From f1ae5bfdfdb162db214d31fb0efc979d149997a3 Mon Sep 17 00:00:00 2001 From: "royqh1979@gmail.com" Date: Sun, 29 Aug 2021 00:48:23 +0800 Subject: [PATCH] work save: header completion --- RedPandaIDE/RedPandaIDE.pro | 10 +- RedPandaIDE/editor.cpp | 2 +- RedPandaIDE/editor.h | 4 +- RedPandaIDE/mainwindow.cpp | 8 +- RedPandaIDE/mainwindow.h | 1 - RedPandaIDE/parser/cppparser.cpp | 140 +++++++---- RedPandaIDE/parser/cppparser.h | 72 +++--- RedPandaIDE/parser/cpppreprocessor.cpp | 37 ++- RedPandaIDE/parser/cpptokenizer.cpp | 6 +- RedPandaIDE/parser/parserutils.cpp | 9 +- RedPandaIDE/parser/parserutils.h | 4 +- RedPandaIDE/parser/statementmodel.cpp | 10 +- RedPandaIDE/parser/statementmodel.h | 10 +- RedPandaIDE/settings.cpp | 34 ++- RedPandaIDE/systemconsts.h | 2 +- .../widgets/codecompletionlistview.cpp | 29 +++ RedPandaIDE/widgets/codecompletionlistview.h | 26 ++ ...letionview.cpp => codecompletionpopup.cpp} | 139 +++++------ ...completionview.h => codecompletionpopup.h} | 34 +-- RedPandaIDE/widgets/headercompletionpopup.cpp | 236 ++++++++++++++++++ RedPandaIDE/widgets/headercompletionpopup.h | 64 +++++ 21 files changed, 623 insertions(+), 254 deletions(-) create mode 100644 RedPandaIDE/widgets/codecompletionlistview.cpp create mode 100644 RedPandaIDE/widgets/codecompletionlistview.h rename RedPandaIDE/widgets/{codecompletionview.cpp => codecompletionpopup.cpp} (87%) rename RedPandaIDE/widgets/{codecompletionview.h => codecompletionpopup.h} (78%) create mode 100644 RedPandaIDE/widgets/headercompletionpopup.cpp create mode 100644 RedPandaIDE/widgets/headercompletionpopup.h diff --git a/RedPandaIDE/RedPandaIDE.pro b/RedPandaIDE/RedPandaIDE.pro index c52859bb..704a245c 100644 --- a/RedPandaIDE/RedPandaIDE.pro +++ b/RedPandaIDE/RedPandaIDE.pro @@ -29,7 +29,8 @@ SOURCES += \ qsynedit/SearchRegex.cpp \ settingsdialog/debuggeneralwidget.cpp \ widgets/classbrowser.cpp \ - widgets/codecompletionview.cpp \ + widgets/codecompletionlistview.cpp \ + widgets/codecompletionpopup.cpp \ widgets/cpudialog.cpp \ debugger.cpp \ editor.cpp \ @@ -69,7 +70,7 @@ SOURCES += \ utils.cpp \ widgets/coloredit.cpp \ widgets/consolewidget.cpp \ - widgets/elidedlabel.cpp \ + widgets/headercompletionpopup.cpp \ widgets/issuestable.cpp \ widgets/qconsole.cpp \ widgets/qpatchedcombobox.cpp \ @@ -94,7 +95,8 @@ HEADERS += \ qsynedit/SearchRegex.h \ settingsdialog/debuggeneralwidget.h \ widgets/classbrowser.h \ - widgets/codecompletionview.h \ + widgets/codecompletionlistview.h \ + widgets/codecompletionpopup.h \ widgets/cpudialog.h \ debugger.h \ editor.h \ @@ -135,7 +137,7 @@ HEADERS += \ common.h \ widgets/coloredit.h \ widgets/consolewidget.h \ - widgets/elidedlabel.h \ + widgets/headercompletionpopup.h \ widgets/issuestable.h \ widgets/qconsole.h \ widgets/qpatchedcombobox.h \ diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index a8f83fc2..0c13f432 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -97,7 +97,7 @@ Editor::Editor(QWidget *parent, const QString& filename, } else { initParser(); } - mCompletionPopup = std::make_shared(); + mCompletionPopup = std::make_shared(); applySettings(); applyColorScheme(pSettings->editor().colorScheme()); diff --git a/RedPandaIDE/editor.h b/RedPandaIDE/editor.h index e41e886c..0c17342b 100644 --- a/RedPandaIDE/editor.h +++ b/RedPandaIDE/editor.h @@ -8,7 +8,7 @@ #include "colorscheme.h" #include "common.h" #include "parser/cppparser.h" -#include "widgets/codecompletionview.h" +#include "widgets/codecompletionpopup.h" class SaveException: public std::exception { @@ -192,7 +192,7 @@ private: QSet mBreakpointLines; int mActiveBreakpointLine; PCppParser mParser; - std::shared_ptr mCompletionPopup; + std::shared_ptr mCompletionPopup; int mLastIdCharPressed; bool mUseCppSyntax; diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 075805b4..9533bbef 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -121,6 +121,8 @@ MainWindow::MainWindow(QWidget *parent) //class browser ui->classBrowser->setModel(&mClassBrowserModel); + + updateAppTitle(); } MainWindow::~MainWindow() @@ -340,8 +342,8 @@ void MainWindow::updateAppTitle() // Application.Title := Format('%s - %s', [fProject.Name, appName]); // end; else { - setWindowTitle(QString("%s %s").arg(appName).arg(DEVCPP_VERSION)); - app->setApplicationName(QString("%s").arg(appName)); + setWindowTitle(QString("%1 %2").arg(appName).arg(DEVCPP_VERSION)); + app->setApplicationName(QString("%1").arg(appName)); } } @@ -1598,7 +1600,7 @@ void MainWindow::onStartParsing() void MainWindow::onEndParsing(int total, int) { - double parseTime = mParserTimer.elapsed() / 1000; + double parseTime = mParserTimer.elapsed() / 1000.0; double parsingFrequency; diff --git a/RedPandaIDE/mainwindow.h b/RedPandaIDE/mainwindow.h index f8d63e0a..fdde4479 100644 --- a/RedPandaIDE/mainwindow.h +++ b/RedPandaIDE/mainwindow.h @@ -5,7 +5,6 @@ #include "common.h" #include "widgets/searchresultview.h" #include "widgets/classbrowser.h" -#include "widgets/elidedlabel.h" QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } diff --git a/RedPandaIDE/parser/cppparser.cpp b/RedPandaIDE/parser/cppparser.cpp index 7ae52513..48e9f461 100644 --- a/RedPandaIDE/parser/cppparser.cpp +++ b/RedPandaIDE/parser/cppparser.cpp @@ -104,7 +104,7 @@ void CppParser::fillListOfFunctions(const QString &fileName, const QString &phra if (parentScope && parentScope->kind == StatementKind::skNamespace) { PStatementList namespaceStatementsList = findNamespace(parentScope->command); if (namespaceStatementsList) { - for (PStatement namespaceStatement : *namespaceStatementsList) { + for (PStatement& namespaceStatement : *namespaceStatementsList) { fillListOfFunctions(fileName,line,statement,namespaceStatement,list); } } @@ -135,10 +135,9 @@ PFileIncludes CppParser::findFileIncludes(const QString &filename, bool deleteIt return fileIncludes; } -QString CppParser::findFirstTemplateParamOf(const QString &fileName, const QString &phrase, PStatement currentScope) +QString CppParser::findFirstTemplateParamOf(const QString &fileName, const QString &phrase, const PStatement& currentScope) { QMutexLocker locker(&mMutex); - QString result = ""; if (mParsing) return ""; // Remove pointer stuff from type @@ -168,7 +167,7 @@ PStatement CppParser::findFunctionAt(const QString &fileName, int line) PFileIncludes fileIncludes = mPreprocessor.includesList().value(fileName); if (!fileIncludes) return PStatement(); - for (PStatement statement : fileIncludes->statements) { + for (PStatement& statement : fileIncludes->statements) { if (statement->kind != StatementKind::skFunction && statement->kind != StatementKind::skConstructor && statement->kind != StatementKind::skDestructor) @@ -209,7 +208,7 @@ PStatement CppParser::findStatementOf(const QString &fileName, const QString &ph return findStatementOf(fileName,phrase,findAndScanBlockAt(fileName,line)); } -PStatement CppParser::findStatementOf(const QString &fileName, const QString &phrase, PStatement currentScope, PStatement &parentScopeType, bool force) +PStatement CppParser::findStatementOf(const QString &fileName, const QString &phrase, const PStatement& currentScope, PStatement &parentScopeType, bool force) { QMutexLocker locker(&mMutex); PStatement result; @@ -233,7 +232,7 @@ PStatement CppParser::findStatementOf(const QString &fileName, const QString &ph remainder = splitPhrase(remainder,nextScopeWord,operatorToken,memberName); - for (PStatement currentNamespace: *namespaceList) { + for (PStatement& currentNamespace: *namespaceList) { statement = findMemberOfStatement(nextScopeWord,currentNamespace); if (statement) break; @@ -259,7 +258,7 @@ PStatement CppParser::findStatementOf(const QString &fileName, const QString &ph PStatementList namespaceList = mNamespaces.value(currentScope->fullName); if (!namespaceList || namespaceList->isEmpty()) return PStatement(); - for (PStatement currentNamespace:*namespaceList){ + for (PStatement& currentNamespace:*namespaceList){ statement = findMemberOfStatement(nextScopeWord,currentNamespace); if (statement) break; @@ -359,13 +358,13 @@ PStatement CppParser::findStatementOf(const QString &fileName, const QString &ph return statement; } -PStatement CppParser::findStatementOf(const QString &fileName, const QString &phrase, PStatement currentClass, bool force) +PStatement CppParser::findStatementOf(const QString &fileName, const QString &phrase, const PStatement& currentClass, bool force) { PStatement statementParentType; return findStatementOf(fileName,phrase,currentClass,statementParentType,force); } -PStatement CppParser::findStatementStartingFrom(const QString &fileName, const QString &phrase, PStatement startScope, bool force) +PStatement CppParser::findStatementStartingFrom(const QString &fileName, const QString &phrase, const PStatement& startScope, bool force) { QMutexLocker locker(&mMutex); if (mParsing && !force) @@ -382,7 +381,7 @@ PStatement CppParser::findStatementStartingFrom(const QString &fileName, const Q return result; // not found // search members of all usings (in current scope ) - for (QString namespaceName:scopeStatement->usingList) { + for (const QString& namespaceName:scopeStatement->usingList) { result = findStatementInNamespace(phrase,namespaceName); if (result) return result; @@ -398,7 +397,7 @@ PStatement CppParser::findStatementStartingFrom(const QString &fileName, const Q //Find in all global usings const QSet& fileUsings = getFileUsings(fileName); // add members of all fusings - for (QString namespaceName:fileUsings) { + for (const QString& namespaceName:fileUsings) { result = findStatementInNamespace(phrase,namespaceName); if (result) return result; @@ -406,7 +405,7 @@ PStatement CppParser::findStatementStartingFrom(const QString &fileName, const Q return PStatement(); } -PStatement CppParser::findTypeDefinitionOf(const QString &fileName, const QString &aType, PStatement currentClass) +PStatement CppParser::findTypeDefinitionOf(const QString &fileName, const QString &aType, const PStatement& currentClass) { QMutexLocker locker(&mMutex); @@ -463,17 +462,16 @@ bool CppParser::freeze(const QString &serialId) QStringList CppParser::getClassesList() { QMutexLocker locker(&mMutex); - if (mParsing) - return QStringList(); QStringList list; + return list; // fills List with a list of all the known classes QQueue queue; queue.enqueue(PStatement()); while (!queue.isEmpty()) { PStatement statement = queue.dequeue(); StatementMap statementMap = mStatementList.childrenStatements(statement); - for (PStatement child:statementMap) { + for (PStatement& child:statementMap) { if (child->kind == StatementKind::skClass) list.append(child->command); if (!child->children.isEmpty()) @@ -516,7 +514,7 @@ QSet CppParser::getFileIncludes(const QString &filename) PFileIncludes fileIncludes = mPreprocessor.includesList().value(filename,PFileIncludes()); if (fileIncludes) { - for (QString file: fileIncludes->includeFiles.keys()) { + for (const QString& file: fileIncludes->includeFiles.keys()) { list.insert(file); } } @@ -544,7 +542,7 @@ QString CppParser::getHeaderFileName(const QString &relativeTo, const QString &l mPreprocessor.projectIncludePaths()); } -StatementKind CppParser::getKindOfStatement(PStatement statement) +StatementKind CppParser::getKindOfStatement(const PStatement& statement) { if (!statement) return StatementKind::skUnknown; @@ -638,7 +636,7 @@ void CppParser::parseFile(const QString &fileName, bool inProject, bool onlyIfNo mFilesScannedCount = 0; // parse header files in the first parse - for (QString file:files) { + for (const QString& file:files) { if (isHfile(file)) { mFilesScannedCount++; emit onProgress(file,mFilesToScanCount,mFilesScannedCount); @@ -648,7 +646,7 @@ void CppParser::parseFile(const QString &fileName, bool inProject, bool onlyIfNo } } //we only parse CFile in the second parse - for (QString file:files) { + for (const QString& file:files) { if (isCfile(file)) { mFilesScannedCount++; emit onProgress(file,mFilesToScanCount,mFilesScannedCount); @@ -686,7 +684,7 @@ void CppParser::parseFileList(bool updateView) mFilesScannedCount = 0; mFilesToScanCount = mFilesToScan.count(); // parse header files in the first parse - for (QString file:mFilesToScan) { + for (const QString& file:mFilesToScan) { if (isHfile(file)) { mFilesScannedCount++; emit onProgress(mCurrentFile,mFilesToScanCount,mFilesScannedCount); @@ -696,7 +694,7 @@ void CppParser::parseFileList(bool updateView) } } //we only parse CFile in the second parse - for (QString file:mFilesToScan) { + for (const QString& file:mFilesToScan) { if (isCfile(file)) { mFilesScannedCount++; emit onProgress(mCurrentFile,mFilesToScanCount,mFilesScannedCount); @@ -722,7 +720,7 @@ void CppParser::parseHardDefines() mParsing = false; mIsSystemHeader=oldIsSystemHeader; }); - for (PDefine define:mPreprocessor.hardDefines()) { + for (const PDefine& define:mPreprocessor.hardDefines()) { QString hintText = "#define"; if (define->name != "") hintText += ' ' + define->name; @@ -813,13 +811,16 @@ void CppParser::unFreeze() mLockCount--; } -QString CppParser::prettyPrintStatement(PStatement statement, int line) +QString CppParser::prettyPrintStatement(const PStatement& statement, int line) { //TODO: implement it return "not implemented yet"; } -QString CppParser::getFirstTemplateParam(PStatement statement, const QString& filename, const QString& phrase, PStatement currentScope) +QString CppParser::getFirstTemplateParam(const PStatement& statement, + const QString& filename, + const QString& phrase, + const PStatement& currentScope) { if (!statement) return ""; @@ -852,7 +853,7 @@ int CppParser::getFirstTemplateParamEnd(const QString &s, int startAt) return startAt; } -void CppParser::addFileToScan(QString value, bool inProject) +void CppParser::addFileToScan(const QString& value, bool inProject) { QMutexLocker locker(&mMutex); //value.replace('/','\\'); // only accept full file names @@ -868,7 +869,7 @@ void CppParser::addFileToScan(QString value, bool inProject) } -PStatement CppParser::addInheritedStatement(PStatement derived, PStatement inherit, StatementClassScope access) +PStatement CppParser::addInheritedStatement(const PStatement& derived, const PStatement& inherit, StatementClassScope access) { PStatement statement = addStatement( @@ -890,7 +891,12 @@ PStatement CppParser::addInheritedStatement(PStatement derived, PStatement inher return statement; } -PStatement CppParser::addChildStatement(PStatement parent, const QString &fileName, const QString &hintText, const QString &aType, const QString &command, const QString &args, const QString &value, int line, StatementKind kind, StatementScope scope, StatementClassScope classScope, bool isDefinition, bool isStatic) +PStatement CppParser::addChildStatement(const PStatement& parent, const QString &fileName, + const QString &hintText, const QString &aType, + const QString &command, const QString &args, + const QString &value, int line, StatementKind kind, + const StatementScope& scope, const StatementClassScope& classScope, + bool isDefinition, bool isStatic) { return addStatement( parent, @@ -908,7 +914,16 @@ PStatement CppParser::addChildStatement(PStatement parent, const QString &fileNa isStatic); } -PStatement CppParser::addStatement(PStatement parent, const QString &fileName, const QString &hintText, const QString &aType, const QString &command, const QString &args, const QString &value, int line, StatementKind kind, StatementScope scope, StatementClassScope classScope, bool isDefinition, bool isStatic) +PStatement CppParser::addStatement(const PStatement& parent, + const QString &fileName, + const QString &hintText, + const QString &aType, + const QString &command, + const QString &args, + const QString &value, + int line, StatementKind kind, + const StatementScope& scope, + const StatementClassScope& classScope, bool isDefinition, bool isStatic) { // Move '*', '&' to type rather than cmd (it's in the way for code-completion) QString newType = aType; @@ -1002,7 +1017,7 @@ PStatement CppParser::addStatement(PStatement parent, const QString &fileName, c return result; } -void CppParser::setInheritance(int index, PStatement classStatement, bool isStruct) +void CppParser::setInheritance(int index, const PStatement& classStatement, bool isStruct) { // Clear it. Assume it is assigned classStatement->inheritanceList.clear(); @@ -1054,7 +1069,7 @@ bool CppParser::isCurrentScope(const QString &command) return (statement->command == s); } -void CppParser::addSoloScopeLevel(PStatement statement, int line) +void CppParser::addSoloScopeLevel(PStatement& statement, int line) { // Add class list @@ -1542,7 +1557,7 @@ void CppParser::getFullNamespace(const QString &phrase, QString &sNamespace, QSt } } -QString CppParser::getFullStatementName(const QString &command, PStatement parent) +QString CppParser::getFullStatementName(const QString &command, const PStatement& parent) { PStatement scopeStatement=parent; while (scopeStatement && !isNamedScope(scopeStatement->kind)) @@ -1553,7 +1568,7 @@ QString CppParser::getFullStatementName(const QString &command, PStatement paren return command; } -PStatement CppParser::getIncompleteClass(const QString &command, PStatement parentScope) +PStatement CppParser::getIncompleteClass(const QString &command, const PStatement& parentScope) { QString s=command; //remove template parameter @@ -1586,7 +1601,8 @@ QString CppParser::getStatementKey(const QString &sName, const QString &sType, c return sName + "--" + sType + "--" + sNoNameArgs; } -PStatement CppParser::getTypeDef(PStatement statement, const QString& fileName, const QString& aType) +PStatement CppParser::getTypeDef(const PStatement& statement, + const QString& fileName, const QString& aType) { if (!statement) { return PStatement(); @@ -2975,7 +2991,8 @@ void CppParser::internalParse(const QString &fileName) } } -void CppParser::inheritClassStatement(PStatement derived, bool isStruct, PStatement base, StatementClassScope access) +void CppParser::inheritClassStatement(const PStatement& derived, bool isStruct, + const PStatement& base, StatementClassScope access) { PFileIncludes fileIncludes1=mPreprocessor.includesList().value(derived->fileName); PFileIncludes fileIncludes2=mPreprocessor.includesList().value(base->fileName); @@ -2991,7 +3008,7 @@ void CppParser::inheritClassStatement(PStatement derived, bool isStruct, PStatem else access = StatementClassScope::scsPrivate; } - for (PStatement statement : base->children) { + for (const PStatement& statement : base->children) { if (statement->classScope == StatementClassScope::scsPrivate || statement->kind == StatementKind::skConstructor || statement->kind == StatementKind::skDestructor) @@ -3021,10 +3038,12 @@ QString CppParser::expandMacroType(const QString &name) return name; } -void CppParser::fillListOfFunctions(const QString& fileName, int line,PStatement statement, PStatement scopeStatement, QStringList &list) +void CppParser::fillListOfFunctions(const QString& fileName, int line, + const PStatement& statement, + const PStatement& scopeStatement, QStringList &list) { StatementMap children = mStatementList.childrenStatements(scopeStatement); - for (PStatement child:children) { + for (const PStatement& child:children) { if ((statement->command == child->command) #ifdef Q_OS_WIN || (statement->command +'A' == child->command) @@ -3038,7 +3057,8 @@ void CppParser::fillListOfFunctions(const QString& fileName, int line,PStatement } } -PStatement CppParser::findMemberOfStatement(const QString &phrase, PStatement scopeStatement) +PStatement CppParser::findMemberOfStatement(const QString &phrase, + const PStatement& scopeStatement) { const StatementMap& statementMap =mStatementList.childrenStatements(scopeStatement); if (statementMap.isEmpty()) @@ -3058,13 +3078,14 @@ PStatement CppParser::findMemberOfStatement(const QString &phrase, PStatement sc return statementMap.value(s,PStatement()); } -PStatement CppParser::findStatementInScope(const QString &name, const QString &noNameArgs, StatementKind kind, PStatement scope) +PStatement CppParser::findStatementInScope(const QString &name, const QString &noNameArgs, + StatementKind kind, const PStatement& scope) { if (scope && scope->kind == StatementKind::skNamespace) { PStatementList namespaceStatementsList = findNamespace(scope->command); if (!namespaceStatementsList) return PStatement(); - for (PStatement namespaceStatement: *namespaceStatementsList) { + for (const PStatement& namespaceStatement: *namespaceStatementsList) { PStatement result=doFindStatementInScope(name,noNameArgs,kind,namespaceStatement); if (result) return result; @@ -3075,7 +3096,7 @@ PStatement CppParser::findStatementInScope(const QString &name, const QString &n return PStatement(); } -PStatement CppParser::findStatementInScope(const QString &name, PStatement scope) +PStatement CppParser::findStatementInScope(const QString &name, const PStatement& scope) { if (!scope) return findMemberOfStatement(name,scope); @@ -3091,7 +3112,7 @@ PStatement CppParser::findStatementInNamespace(const QString &name, const QStrin PStatementList namespaceStatementsList=findNamespace(namespaceName); if (!namespaceStatementsList) return PStatement(); - for (PStatement namespaceStatement:*namespaceStatementsList) { + for (const PStatement& namespaceStatement:*namespaceStatementsList) { PStatement result = findMemberOfStatement(name,namespaceStatement); if (result) return result; @@ -3118,15 +3139,14 @@ int CppParser::getBracketEnd(const QString &s, int startAt) return startAt; } -PStatement CppParser::doFindStatementInScope(const QString &name, const QString &noNameArgs, StatementKind kind, PStatement scope) +PStatement CppParser::doFindStatementInScope(const QString &name, + const QString &noNameArgs, + StatementKind kind, + const PStatement& scope) { const StatementMap& statementMap =mStatementList.childrenStatements(scope); - if (statementMap.isEmpty()) - return PStatement(); - QList statementList = statementMap.values(name); - - for (PStatement statement: statementList) { + for (const PStatement& statement: statementMap.values(name)) { if (statement->kind == kind && statement->noNameArgs == noNameArgs) { return statement; } @@ -3140,8 +3160,8 @@ void CppParser::internalInvalidateFile(const QString &fileName) return; //remove all statements in the file - QList keys=mNamespaces.keys(); - for (QString key:keys) { + const QList& keys=mNamespaces.keys(); + for (const QString& key:keys) { PStatementList statements = mNamespaces.value(key); for (int i=statements->size()-1;i>=0;i--) { PStatement statement = statements->at(i); @@ -3163,7 +3183,7 @@ void CppParser::internalInvalidateFile(const QString &fileName) //fPreprocessor.InvalidDefinesInFile(FileName); //we don't need this, since we reset defines after each parse //p->includeFiles.clear(); //p->usings.clear(); - for (PStatement statement:p->statements) { + for (PStatement& statement:p->statements) { if ((statement->kind == StatementKind::skFunction || statement->kind == StatementKind::skConstructor || statement->kind == StatementKind::skDestructor @@ -3173,7 +3193,7 @@ void CppParser::internalInvalidateFile(const QString &fileName) } } - for (PStatement statement:p->declaredStatements) { + for (PStatement& statement:p->declaredStatements) { mStatementList.deleteStatement(statement); } @@ -3204,7 +3224,7 @@ QSet CppParser::calculateFilesToBeReparsed(const QString &fileName) PFileIncludes p=mPreprocessor.includesList().value(name); if (!p) continue; - for (QString s:p->dependedFiles) { + for (const QString& s:p->dependedFiles) { if (!processed.contains(s)) { queue.enqueue(s); } @@ -3223,7 +3243,7 @@ int CppParser::calcKeyLenForStruct(const QString &word) return -1; } -void CppParser::scanMethodArgs(PStatement functionStatement, const QString &argStr) +void CppParser::scanMethodArgs(const PStatement& functionStatement, const QString &argStr) { // Split up argument string by , int i = 1; // assume it starts with ( and ends with ) @@ -3596,6 +3616,16 @@ void CppParser::setParseGlobalHeaders(bool newParseGlobalHeaders) mParseGlobalHeaders = newParseGlobalHeaders; } +const QSet &CppParser::includePaths() +{ + return mPreprocessor.includePaths(); +} + +const QSet &CppParser::projectIncludePaths() +{ + return mPreprocessor.projectIncludePaths(); +} + bool CppParser::parseLocalHeaders() const { return mParseLocalHeaders; @@ -3680,7 +3710,7 @@ void CppFileListParserThread::run() } } -void parseFile(PCppParser parser, QString fileName, bool inProject, bool onlyIfNotParsed, bool updateView) +void parseFile(PCppParser parser, const QString& fileName, bool inProject, bool onlyIfNotParsed, bool updateView) { CppFileParserThread* thread = new CppFileParserThread(parser,fileName,inProject,onlyIfNotParsed,updateView); thread->connect(thread, diff --git a/RedPandaIDE/parser/cppparser.h b/RedPandaIDE/parser/cppparser.h index 9a79a4ac..d1494243 100644 --- a/RedPandaIDE/parser/cppparser.h +++ b/RedPandaIDE/parser/cppparser.h @@ -18,7 +18,7 @@ public: ~CppParser(); void addHardDefineByLine(const QString& line); - void addFileToScan(QString value, bool inProject = false); + void addFileToScan(const QString& value, bool inProject = false); void addIncludePath(const QString& value); void addProjectIncludePath(const QString& value); void clearIncludePaths(); @@ -32,7 +32,7 @@ public: PFileIncludes findFileIncludes(const QString &filename, bool deleteIt = false); QString findFirstTemplateParamOf(const QString& fileName, const QString& phrase, - PStatement currentScope); + const PStatement& currentScope); PStatement findFunctionAt(const QString& fileName, int line); int findLastOperator(const QString& phrase) const; @@ -42,21 +42,21 @@ public: int line); PStatement findStatementOf(const QString& fileName, const QString& phrase, - PStatement currentScope, + const PStatement& currentScope, PStatement& parentScopeType, bool force = false); PStatement findStatementOf(const QString& fileName, const QString& phrase, - PStatement currentClass, + const PStatement& currentClass, bool force = false); //{Find statement starting from startScope} PStatement findStatementStartingFrom(const QString& fileName, const QString& phrase, - PStatement startScope, + const PStatement& startScope, bool force = false); PStatement findTypeDefinitionOf(const QString& fileName, const QString& aType, - PStatement currentClass); + const PStatement& currentClass); bool freeze(); // Freeze/Lock (stop reparse while searching) bool freeze(const QString& serialId); // Freeze/Lock (stop reparse while searching) QStringList getClassesList(); @@ -65,7 +65,7 @@ public: QSet getFileUsings(const QString& filename); QString getHeaderFileName(const QString& relativeTo, const QString& line);// both - StatementKind getKindOfStatement(PStatement statement); + StatementKind getKindOfStatement(const PStatement& statement); void invalidateFile(const QString& fileName); bool isIncludeLine(const QString &line); bool isProjectHeaderFile(const QString& fileName); @@ -78,6 +78,8 @@ public: void reset(); void unFreeze(); // UnFree/UnLock (reparse while searching) + + //void getSourcePair(const QString& fName, QString& CFile, QString& HFile); // int suggestMemberInsertionLine(PStatement parentStatement, @@ -91,7 +93,7 @@ public: //QString statementKindStr(StatementKind value); //QString statementClassScopeStr(StatementClassScope value); - QString prettyPrintStatement(PStatement statement, int line = -1); + QString prettyPrintStatement(const PStatement& statement, int line = -1); @@ -119,6 +121,9 @@ public: bool parseGlobalHeaders() const; void setParseGlobalHeaders(bool newParseGlobalHeaders); + const QSet& includePaths(); + const QSet& projectIncludePaths(); + const StatementModel &statementList() const; signals: @@ -128,13 +133,13 @@ signals: void onEndParsing(int total, int updateView); private: PStatement addInheritedStatement( - PStatement derived, - PStatement inherit, + const PStatement& derived, + const PStatement& inherit, StatementClassScope access); PStatement addChildStatement( // support for multiple parents (only typedef struct/union use multiple parents) - PStatement parent, + const PStatement& parent, const QString& fileName, const QString& hintText, const QString& aType, // "Type" is already in use @@ -143,12 +148,12 @@ private: const QString& value, int line, StatementKind kind, - StatementScope scope, - StatementClassScope classScope, + const StatementScope& scope, + const StatementClassScope& classScope, bool isDefinition, bool isStatic); // TODO: InheritanceList not supported PStatement addStatement( - PStatement parent, + const PStatement& parent, const QString &fileName, const QString &hintText, const QString &aType, // "Type" is already in use @@ -157,13 +162,13 @@ private: const QString& value, int line, StatementKind kind, - StatementScope scope, - StatementClassScope classScope, + const StatementScope& scope, + const StatementClassScope& classScope, bool isDefinition, bool isStatic); - void setInheritance(int index, PStatement classStatement, bool isStruct); + void setInheritance(int index, const PStatement& classStatement, bool isStruct); bool isCurrentScope(const QString& command); - void addSoloScopeLevel(PStatement statement, int line); // adds new solo level + void addSoloScopeLevel(PStatement& statement, int line); // adds new solo level void removeScopeLevel(int line); // removes level int skipBraces(int startAt); int skipBracket(int startAt); @@ -185,18 +190,20 @@ private: bool checkForVar(); QString expandMacroType(const QString& name); //{procedure ResetDefines;} - void fillListOfFunctions(const QString& fileName, int line,PStatement statement, PStatement scopeStatement, QStringList& list); + void fillListOfFunctions(const QString& fileName, int line, + const PStatement& statement, + const PStatement& scopeStatement, QStringList& list); PStatement findMemberOfStatement( const QString& phrase, - PStatement scopeStatement); + const PStatement& scopeStatement); PStatement findStatementInScope( const QString& name, const QString& noNameArgs, StatementKind kind, - PStatement scope); + const PStatement& scope); PStatement findStatementInScope( const QString& name, - PStatement scope); + const PStatement& scope); PStatement findStatementInNamespace( const QString& name, const QString& namespaceName); @@ -206,8 +213,8 @@ private: int getCurrentBlockEndSkip(); int getCurrentInlineNamespaceEndSkip(); PStatement getCurrentScope(); // gets last item from last level - QString getFirstTemplateParam(PStatement statement, const QString& filename, - const QString& phrase, PStatement currentScope); + QString getFirstTemplateParam(const PStatement& statement, const QString& filename, + const QString& phrase, const PStatement& currentScope); int getFirstTemplateParamEnd(const QString& s, int startAt); void getFullNamespace( @@ -216,15 +223,16 @@ private: QString& member); QString getFullStatementName( const QString& command, - PStatement parent); + const PStatement& parent); PStatement getIncompleteClass( const QString& command, - PStatement parentScope); + const PStatement& parentScope); StatementScope getScope(); QString getStatementKey(const QString& sName, const QString& sType, const QString& sNoNameArgs); - PStatement getTypeDef(PStatement statement, const QString& fileName, const QString& aType); + PStatement getTypeDef(const PStatement& statement, + const QString& fileName, const QString& aType); void handleCatchBlock(); void handleEnum(); void handleForBlock(); @@ -246,14 +254,14 @@ private: void internalParse(const QString& fileName); // function FindMacroDefine(const Command: AnsiString): PStatement; void inheritClassStatement( - PStatement derived, + const PStatement& derived, bool isStruct, - PStatement base, + const PStatement& base, StatementClassScope access); PStatement doFindStatementInScope(const QString& name, const QString& noNameArgs, StatementKind kind, - PStatement scope); + const PStatement& scope); void internalInvalidateFile(const QString& fileName); void internalInvalidateFiles(const QSet& files); QSet calculateFilesToBeReparsed(const QString& fileName); @@ -265,7 +273,7 @@ private: // function GetRemainder(const Phrase: AnsiString): AnsiString; // } void scanMethodArgs( - PStatement functionStatement, + const PStatement& functionStatement, const QString& argStr); QString splitPhrase(const QString& phrase, QString& sClazz, QString &sMember, QString& sOperator); @@ -401,7 +409,7 @@ protected: void parseFile( PCppParser parser, - QString fileName, + const QString& fileName, bool inProject, bool onlyIfNotParsed = false, bool updateView = true); diff --git a/RedPandaIDE/parser/cpppreprocessor.cpp b/RedPandaIDE/parser/cpppreprocessor.cpp index 12af512c..64844b55 100644 --- a/RedPandaIDE/parser/cpppreprocessor.cpp +++ b/RedPandaIDE/parser/cpppreprocessor.cpp @@ -154,8 +154,8 @@ void CppPreprocessor::invalidDefinesInFile(const QString &fileName) { PDefineMap defineMap = mFileDefines.value(fileName,PDefineMap()); if (defineMap) { - for (PDefine define:*defineMap) { - PDefine p = mDefines.value(define->name); + for (const PDefine& define:*defineMap) { + const PDefine& p = mDefines.value(define->name); if (p == define) { mDefines.remove(define->name); } @@ -169,10 +169,10 @@ void CppPreprocessor::dumpDefinesTo(const QString &fileName) const QFile file(fileName); if (file.open(QIODevice::WriteOnly|QIODevice::Truncate)) { QTextStream stream(&file); - for (PDefine define:mDefines) { - stream<name) - .arg(define->args).arg(define->value) - .arg(define->hardCoded).arg(define->formatValue) + for (const PDefine& define:mDefines) { + stream<name,define->args,define->value) + .arg(define->hardCoded).arg(define->formatValue) <baseFile<<" : "<includeFiles.keys()) { + for (const QString& s:fileIncludes->includeFiles.keys()) { stream<<"\t--"+s<dependingFiles) { + for (const QString& s:fileIncludes->dependingFiles) { stream<<"\t^^"+s<dependedFiles) { + for (const QString& s:fileIncludes->dependedFiles) { stream<<"\t&&"+s<usings) { + for (const QString& s:fileIncludes->usings) { stream<<"\t++"+s< p:fileIncludes->statements) { - PStatement statement = p.lock(); + for (PStatement& statement:fileIncludes->statements) { if (statement) { stream<command) .arg(statement->fullName)<fileIncludes->includeFiles.contains(fileName)) { return; //already included } - for (PParsedFile parsedFile:mIncludes) { + for (PParsedFile& parsedFile:mIncludes) { parsedFile->fileIncludes->includeFiles.insert(fileName,false); } } @@ -611,7 +610,7 @@ void CppPreprocessor::openInclude(const QString &fileName, QStringList bufferedT //add defines of already parsed including headers; addDefinesInFile(fileName); PFileIncludes fileIncludes = getFileIncludesEntry(fileName); - for (PParsedFile file:mIncludes) { + for (PParsedFile& file:mIncludes) { file->fileIncludes->includeFiles.insert(fileIncludes->includeFiles); } } @@ -710,7 +709,7 @@ void CppPreprocessor::addDefinesInFile(const QString &fileName) //first add the defines in the files it included PFileIncludes fileIncludes = getFileIncludesEntry(fileName); if (fileIncludes) { - for (QString s:fileIncludes->includeFiles.keys()) { + for (const QString& s:fileIncludes->includeFiles.keys()) { addDefinesInFile(s); } } @@ -718,7 +717,7 @@ void CppPreprocessor::addDefinesInFile(const QString &fileName) // then add the defines defined in it PDefineMap defineList = mFileDefines.value(fileName, PDefineMap()); if (defineList) { - for (PDefine define: defineList->values()) { + for (const PDefine& define: defineList->values()) { mDefines.insert(define->name,define); } } @@ -740,7 +739,7 @@ void CppPreprocessor::parseArgs(PDefine define) QString formatStr = ""; DefineArgTokenType lastTokenType=DefineArgTokenType::Other; int index; - for (PDefineArgToken token: tokens) { + for (const PDefineArgToken& token: tokens) { switch(token->type) { case DefineArgTokenType::Identifier: index = define->argList.indexOf(token->value); @@ -851,7 +850,7 @@ QStringList CppPreprocessor::removeComments(const QStringList &text) ContentType currentType = ContentType::Other; QString delimiter; - for (QString line:text) { + for (const QString& line:text) { QString s; int pos = 0; bool stopProcess=false; diff --git a/RedPandaIDE/parser/cpptokenizer.cpp b/RedPandaIDE/parser/cpptokenizer.cpp index d8a53ba4..75401983 100644 --- a/RedPandaIDE/parser/cpptokenizer.cpp +++ b/RedPandaIDE/parser/cpptokenizer.cpp @@ -50,7 +50,7 @@ void CppTokenizer::dumpTokens(const QString &fileName) if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { QTextStream stream(&file); - for (PToken token:mTokenList) { + for (const PToken& token:mTokenList) { stream<line).arg(token->text)<& in { // Search compiler include directories - for (QString path:includePaths) { + for (const QString& path:includePaths) { QDir dir(path); if (dir.exists(fileName)) return dir.absoluteFilePath(fileName); @@ -373,7 +373,7 @@ bool isSystemHeaderFile(const QString &fileName, const QSet &includePat } } else { //check if it's in the include dir - for (QString includePath: includePaths) { + for (const QString& includePath: includePaths) { QDir dir(includePath); if (dir.exists(fileName)) return true; @@ -387,7 +387,7 @@ bool isKeyword(const QString &word) return CppKeywords.contains(word); } -bool isHfile(const QString filename) +bool isHfile(const QString& filename) { if (filename.isEmpty()) return false; @@ -397,7 +397,7 @@ bool isHfile(const QString filename) } -bool isCfile(const QString filename) +bool isCfile(const QString& filename) { if (filename.isEmpty()) return false; @@ -464,7 +464,6 @@ void CppScopes::clear() MemberOperatorType getOperatorType(const QString &phrase, int index) { - MemberOperatorType result=MemberOperatorType::otOther; if (index>=phrase.length()) return MemberOperatorType::otOther; if (phrase[index] == '.') diff --git a/RedPandaIDE/parser/parserutils.h b/RedPandaIDE/parser/parserutils.h index 6c349d2f..cc2f2af8 100644 --- a/RedPandaIDE/parser/parserutils.h +++ b/RedPandaIDE/parser/parserutils.h @@ -200,8 +200,8 @@ QString getLocalHeaderFilename(const QString& relativeTo, const QString& fileNam QString getSystemHeaderFilename(const QString& fileName, const QSet& includePaths); bool isSystemHeaderFile(const QString& fileName, const QSet& includePaths); -bool isHfile(const QString filename); -bool isCfile(const QString filename); +bool isHfile(const QString& filename); +bool isCfile(const QString& filename); bool isKeyword(const QString& word); bool isScopeTypeKind(StatementKind kind); MemberOperatorType getOperatorType(const QString& phrase, int index); diff --git a/RedPandaIDE/parser/statementmodel.cpp b/RedPandaIDE/parser/statementmodel.cpp index b49cbba2..91458b90 100644 --- a/RedPandaIDE/parser/statementmodel.cpp +++ b/RedPandaIDE/parser/statementmodel.cpp @@ -8,7 +8,7 @@ StatementModel::StatementModel(QObject *parent) : QObject(parent) mCount = 0; } -void StatementModel::add(PStatement statement) +void StatementModel::add(const PStatement& statement) { if (!statement) { return ; @@ -26,7 +26,7 @@ void StatementModel::add(PStatement statement) } -void StatementModel::deleteStatement(PStatement statement) +void StatementModel::deleteStatement(const PStatement& statement) { if (!statement) { return ; @@ -45,7 +45,7 @@ void StatementModel::deleteStatement(PStatement statement) } -const StatementMap &StatementModel::childrenStatements(PStatement statement) const +const StatementMap &StatementModel::childrenStatements(const PStatement& statement) const { if (!statement) { return mGlobalStatements; @@ -97,7 +97,7 @@ void StatementModel::dumpAll(const QString &logFile) } #endif -void StatementModel::addMember(StatementMap &map, PStatement statement) +void StatementModel::addMember(StatementMap &map, const PStatement& statement) { if (!statement) return ; @@ -110,7 +110,7 @@ void StatementModel::addMember(StatementMap &map, PStatement statement) // lst->append(statement); } -int StatementModel::deleteMember(StatementMap &map, PStatement statement) +int StatementModel::deleteMember(StatementMap &map, const PStatement& statement) { if (!statement) return 0; diff --git a/RedPandaIDE/parser/statementmodel.h b/RedPandaIDE/parser/statementmodel.h index 373b3616..3077b568 100644 --- a/RedPandaIDE/parser/statementmodel.h +++ b/RedPandaIDE/parser/statementmodel.h @@ -11,11 +11,11 @@ class StatementModel : public QObject public: explicit StatementModel(QObject *parent = nullptr); - void add(PStatement statement); + void add(const PStatement& statement); // function DeleteFirst: Integer; // function DeleteLast: Integer; - void deleteStatement(PStatement statement); - const StatementMap& childrenStatements(PStatement statement = PStatement()) const; + void deleteStatement(const PStatement& statement); + const StatementMap& childrenStatements(const PStatement& statement = PStatement()) const; const StatementMap& childrenStatements(std::weak_ptr statement) const; void clear(); void dump(const QString& logFile); @@ -25,8 +25,8 @@ public: signals: private: - void addMember(StatementMap& map, PStatement statement); - int deleteMember(StatementMap& map, PStatement statement); + void addMember(StatementMap& map, const PStatement& statement); + int deleteMember(StatementMap& map, const PStatement& statement); void dumpStatementMap(StatementMap& map, QTextStream& out, int level); private: int mCount; diff --git a/RedPandaIDE/settings.cpp b/RedPandaIDE/settings.cpp index 48c079a9..52d8cd37 100644 --- a/RedPandaIDE/settings.cpp +++ b/RedPandaIDE/settings.cpp @@ -1965,15 +1965,14 @@ void Settings::CompilerSets::loadSets() .arg(pCurrentSet->name()) +"

" +msg - +"Would you like Dev-C++ to remove them for you and add the default paths to the valid paths?

Leaving those directories will lead to problems during compilation.

Unless you know exactly what you're doing, it is recommended that you click Yes.", - QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { - findSets(); - saveSets(); - if ( mList.size() <= mDefaultIndex) - mDefaultIndex = mList.size()-1; - } else { + +"Would you like Red Panda C++ to remove them for you and add the default paths to the valid paths?

Leaving those directories will lead to problems during compilation.

Unless you know exactly what you're doing, it is recommended that you click Yes.", + QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) { return; } + findSets(); + saveSets(); + if ( mList.size() <= mDefaultIndex) + mDefaultIndex = mList.size()-1; pCurrentSet = defaultSet(); if (!pCurrentSet) { return; @@ -1982,8 +1981,29 @@ void Settings::CompilerSets::loadSets() if (pCurrentSet->binDirs().count()>0) { pCurrentSet->setProperties(pCurrentSet->binDirs()[0]); } + } else { + return; } + } else { + if (QMessageBox::warning(nullptr,tr("Confirm"), + QObject::tr("Compiler set not configuared.") + +"

" + +QObject::tr("Would you like Red Panda C++ to search for compilers in the following locations:
'%1'
'%2'? ") + .arg(includeTrailingPathDelimiter(pSettings->dirs().app()) + "MinGW32") + .arg(includeTrailingPathDelimiter(pSettings->dirs().app()) + "MinGW64"), + QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) { + return; + } + clearSets(); + findSets(); + mDefaultIndex = mList.size()-1; + pCurrentSet = defaultSet(); + if (!pCurrentSet) { + return; + } + saveSets(); } + } void Settings::CompilerSets::saveDefaultIndex() diff --git a/RedPandaIDE/systemconsts.h b/RedPandaIDE/systemconsts.h index f23a65bb..9ae7082f 100644 --- a/RedPandaIDE/systemconsts.h +++ b/RedPandaIDE/systemconsts.h @@ -30,7 +30,7 @@ #error "Only support windows and linux now!" #endif -#define DEVCPP_VERSION "0.01" +#define DEVCPP_VERSION "0.05" class SystemConsts { diff --git a/RedPandaIDE/widgets/codecompletionlistview.cpp b/RedPandaIDE/widgets/codecompletionlistview.cpp new file mode 100644 index 00000000..675e58de --- /dev/null +++ b/RedPandaIDE/widgets/codecompletionlistview.cpp @@ -0,0 +1,29 @@ +#include "codecompletionlistview.h" + +CodeCompletionListView::CodeCompletionListView(QWidget *parent) : QListView(parent) +{ + +} + +void CodeCompletionListView::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_Up + || event->key() == Qt::Key_Down) { + QListView::keyPressEvent(event); + return; + } + if (!mKeypressedCallback || !mKeypressedCallback(event)) { + QListView::keyPressEvent(event); + } +} + +const KeyPressedCallback &CodeCompletionListView::keypressedCallback() const +{ + return mKeypressedCallback; +} + +void CodeCompletionListView::setKeypressedCallback(const KeyPressedCallback &newKeypressedCallback) +{ + mKeypressedCallback = newKeypressedCallback; +} + diff --git a/RedPandaIDE/widgets/codecompletionlistview.h b/RedPandaIDE/widgets/codecompletionlistview.h new file mode 100644 index 00000000..cc939a66 --- /dev/null +++ b/RedPandaIDE/widgets/codecompletionlistview.h @@ -0,0 +1,26 @@ +#ifndef CODECOMPLETIONLISTVIEW_H +#define CODECOMPLETIONLISTVIEW_H + +#include +#include +#include "../parser/parserutils.h" +using KeyPressedCallback = std::function; + +class CodeCompletionListView: public QListView { + Q_OBJECT +public: + explicit CodeCompletionListView(QWidget *parent = nullptr); + + // QWidget interface + const KeyPressedCallback &keypressedCallback() const; + void setKeypressedCallback(const KeyPressedCallback &newKeypressedCallback); + +protected: + void keyPressEvent(QKeyEvent *event) override; +private: + KeyPressedCallback mKeypressedCallback; +}; + +using ColorCallback = std::function; + +#endif // CODECOMPLETIONLISTVIEW_H diff --git a/RedPandaIDE/widgets/codecompletionview.cpp b/RedPandaIDE/widgets/codecompletionpopup.cpp similarity index 87% rename from RedPandaIDE/widgets/codecompletionview.cpp rename to RedPandaIDE/widgets/codecompletionpopup.cpp index 7948b768..088de2d5 100644 --- a/RedPandaIDE/widgets/codecompletionview.cpp +++ b/RedPandaIDE/widgets/codecompletionpopup.cpp @@ -1,4 +1,4 @@ -#include "codecompletionview.h" +#include "codecompletionpopup.h" #include "../utils.h" #include @@ -6,7 +6,7 @@ #include #include -CodeCompletionView::CodeCompletionView(QWidget *parent) : +CodeCompletionPopup::CodeCompletionPopup(QWidget *parent) : QWidget(parent) { setWindowFlags(Qt::Popup); @@ -39,18 +39,18 @@ CodeCompletionView::CodeCompletionView(QWidget *parent) : } -CodeCompletionView::~CodeCompletionView() +CodeCompletionPopup::~CodeCompletionPopup() { delete mListView; delete mModel; } -void CodeCompletionView::setKeypressedCallback(const KeyPressedCallback &newKeypressedCallback) +void CodeCompletionPopup::setKeypressedCallback(const KeyPressedCallback &newKeypressedCallback) { mListView->setKeypressedCallback(newKeypressedCallback); } -void CodeCompletionView::prepareSearch(const QString &phrase, const QString &filename, int line) +void CodeCompletionPopup::prepareSearch(const QString &phrase, const QString &filename, int line) { QMutexLocker locker(&mMutex); if (!isEnabled()) @@ -71,7 +71,7 @@ void CodeCompletionView::prepareSearch(const QString &phrase, const QString &fil setCursor(oldCursor); } -bool CodeCompletionView::search(const QString &phrase, bool autoHideOnSingleResult) +bool CodeCompletionPopup::search(const QString &phrase, bool autoHideOnSingleResult) { QMutexLocker locker(&mMutex); @@ -118,7 +118,7 @@ bool CodeCompletionView::search(const QString &phrase, bool autoHideOnSingleResu return false; } -PStatement CodeCompletionView::selectedStatement() +PStatement CodeCompletionPopup::selectedStatement() { if (isEnabled()) { int index = mListView->currentIndex().row(); @@ -135,7 +135,7 @@ PStatement CodeCompletionView::selectedStatement() return PStatement(); } -void CodeCompletionView::addChildren(PStatement scopeStatement, const QString &fileName, int line) +void CodeCompletionPopup::addChildren(PStatement scopeStatement, const QString &fileName, int line) { if (scopeStatement && !isIncluded(scopeStatement->fileName) && !isIncluded(scopeStatement->definitionFileName)) @@ -145,7 +145,7 @@ void CodeCompletionView::addChildren(PStatement scopeStatement, const QString &f return; if (!scopeStatement) { //Global scope - for (PStatement childStatement: children) { + for (const PStatement& childStatement: children) { if (childStatement->fileName.isEmpty()) { // hard defines addStatement(childStatement,fileName,-1); @@ -163,7 +163,7 @@ void CodeCompletionView::addChildren(PStatement scopeStatement, const QString &f } } } else { - for (PStatement childStatement: children) { + for (const PStatement& childStatement: children) { if (!( childStatement->kind == StatementKind::skConstructor || childStatement->kind == StatementKind::skDestructor || childStatement->kind == StatementKind::skBlock) @@ -173,7 +173,7 @@ void CodeCompletionView::addChildren(PStatement scopeStatement, const QString &f } } -void CodeCompletionView::addStatement(PStatement statement, const QString &fileName, int line) +void CodeCompletionPopup::addStatement(PStatement statement, const QString &fileName, int line) { if (mAddedStatements.contains(statement->command)) return; @@ -303,7 +303,7 @@ static bool sortByScopeWithUsageComparator(PStatement statement1,PStatement stat return statement1->command < statement2->command; } -void CodeCompletionView::filterList(const QString &member) +void CodeCompletionPopup::filterList(const QString &member) { QMutexLocker locker(&mMutex); mCompletionStatementList.clear(); @@ -326,7 +326,7 @@ void CodeCompletionView::filterList(const QString &member) mCompletionStatementList.clear(); if (!member.isEmpty()) { // filter mCompletionStatementList.reserve(mFullCompletionStatementList.size()); - for (PStatement statement:mFullCompletionStatementList) { + foreach (const PStatement& statement, mFullCompletionStatementList) { Qt::CaseSensitivity cs = (mIgnoreCase? Qt::CaseInsensitive: Qt::CaseSensitive); @@ -340,7 +340,7 @@ void CodeCompletionView::filterList(const QString &member) int secondCount = 0; int thirdCount = 0; int usageCount; - for (PStatement statement:mCompletionStatementList) { + foreach (const PStatement& statement,mCompletionStatementList) { if (statement->usageCount == 0) { usageCount = mSymbolUsage.value(statement->fullName,0); if (usageCount == 0) @@ -363,7 +363,7 @@ void CodeCompletionView::filterList(const QString &member) thirdCount = usageCount; } } - for (PStatement statement:mCompletionStatementList) { + foreach (const PStatement& statement, mCompletionStatementList) { if (statement->usageCount == 0) { statement->freqTop = 0; } else if (statement->usageCount == topCount) { @@ -395,7 +395,7 @@ void CodeCompletionView::filterList(const QString &member) // } } -void CodeCompletionView::getCompletionFor(const QString &fileName, const QString &phrase, int line) +void CodeCompletionPopup::getCompletionFor(const QString &fileName, const QString &phrase, int line) { if(!mParser) return; @@ -412,7 +412,7 @@ void CodeCompletionView::getCompletionFor(const QString &fileName, const QString //C++ preprocessor directives if (phrase.startsWith('#')) { if (mShowKeywords) { - for (QString keyword:CppDirectives) { + foreach (const QString& keyword, CppDirectives) { PStatement statement = std::make_shared(); statement->command = keyword; statement->kind = StatementKind::skKeyword; @@ -428,7 +428,7 @@ void CodeCompletionView::getCompletionFor(const QString &fileName, const QString //docstring tags (javadoc style) if (phrase.startsWith('@')) { if (mShowKeywords) { - for (QString keyword:JavadocTags) { + foreach (const QString& keyword,JavadocTags) { PStatement statement = std::make_shared(); statement->command = keyword; statement->kind = StatementKind::skKeyword; @@ -448,7 +448,7 @@ void CodeCompletionView::getCompletionFor(const QString &fileName, const QString if (mShowCodeIns) { //add custom code templates - for (PCodeIns codeIn:mCodeInsList) { + foreach (const PCodeIns& codeIn,mCodeInsList) { PStatement statement = std::make_shared(); statement->command = codeIn->prefix; statement->kind = StatementKind::skUserCodeIn; @@ -462,7 +462,7 @@ void CodeCompletionView::getCompletionFor(const QString &fileName, const QString if (mShowKeywords) { //add keywords if (mUseCppKeyword) { - for (QString keyword:CppKeywords.keys()) { + foreach (const QString& keyword,CppKeywords.keys()) { PStatement statement = std::make_shared(); statement->command = keyword; statement->kind = StatementKind::skKeyword; @@ -472,7 +472,7 @@ void CodeCompletionView::getCompletionFor(const QString &fileName, const QString mFullCompletionStatementList.append(statement); } } else { - for (QString keyword:CKeywords) { + foreach (const QString& keyword,CKeywords) { PStatement statement = std::make_shared(); statement->command = keyword; statement->kind = StatementKind::skKeyword; @@ -495,12 +495,12 @@ void CodeCompletionView::getCompletionFor(const QString &fileName, const QString } // add members of all usings (in current scope ) and not added before - for (QString namespaceName:scopeStatement->usingList) { + foreach (const QString& namespaceName,scopeStatement->usingList) { PStatementList namespaceStatementsList = mParser->findNamespace(namespaceName); if (!namespaceStatementsList) continue; - for (PStatement namespaceStatement:*namespaceStatementsList) { + foreach (const PStatement& namespaceStatement,*namespaceStatementsList) { addChildren(namespaceStatement, fileName, line); } } @@ -512,12 +512,12 @@ void CodeCompletionView::getCompletionFor(const QString &fileName, const QString // add members of all fusings mUsings = mParser->getFileUsings(fileName); - for (QString namespaceName:mUsings) { + foreach (const QString& namespaceName, mUsings) { PStatementList namespaceStatementsList = mParser->findNamespace(namespaceName); if (!namespaceStatementsList) continue; - for (PStatement namespaceStatement:*namespaceStatementsList) { + foreach (const PStatement& namespaceStatement, *namespaceStatementsList) { addChildren(namespaceStatement, fileName, line); } } @@ -535,7 +535,7 @@ void CodeCompletionView::getCompletionFor(const QString &fileName, const QString PStatementList namespaceStatementsList = mParser->findNamespace(scopeName); if (namespaceStatementsList) { - for (PStatement namespaceStatement:*namespaceStatementsList) { + foreach (const PStatement& namespaceStatement, *namespaceStatementsList) { addChildren(namespaceStatement, fileName, line); } return; @@ -633,7 +633,7 @@ void CodeCompletionView::getCompletionFor(const QString &fileName, const QString const StatementMap& children = mParser->statementList().childrenStatements(classTypeStatement); if (children.isEmpty()) return; - for (PStatement childStatement:children) { + foreach (const PStatement& childStatement, children) { if ((childStatement->classScope==StatementClassScope::scsPublic) && !( childStatement->kind == StatementKind::skConstructor @@ -654,7 +654,7 @@ void CodeCompletionView::getCompletionFor(const QString &fileName, const QString return; const StatementMap& children = mParser->statementList().childrenStatements(classTypeStatement); - for (PStatement child:children) { + foreach (const PStatement& child,children) { addStatement(child,fileName,line); } } else if ((opType == MemberOperatorType::otDColon) @@ -667,7 +667,7 @@ void CodeCompletionView::getCompletionFor(const QString &fileName, const QString //we can use all static members const StatementMap& children = mParser->statementList().childrenStatements(classTypeStatement); - for (PStatement childStatement: children) { + foreach (const PStatement& childStatement, children) { if ( (childStatement->isStatic) || (childStatement->kind == StatementKind::skTypedef @@ -683,7 +683,7 @@ void CodeCompletionView::getCompletionFor(const QString &fileName, const QString // we can only use public static members const StatementMap& children = mParser->statementList().childrenStatements(classTypeStatement); - for (PStatement childStatement: children) { + foreach (const PStatement& childStatement,children) { if ( (childStatement->isStatic) || (childStatement->kind == StatementKind::skTypedef @@ -703,122 +703,122 @@ void CodeCompletionView::getCompletionFor(const QString &fileName, const QString } } -bool CodeCompletionView::isIncluded(const QString &fileName) +bool CodeCompletionPopup::isIncluded(const QString &fileName) { return mIncludedFiles.contains(fileName); } -void CodeCompletionView::showEvent(QShowEvent *) +void CodeCompletionPopup::showEvent(QShowEvent *) { mListView->setFocus(); } -const PStatement &CodeCompletionView::currentStatement() const +const PStatement &CodeCompletionPopup::currentStatement() const { return mCurrentStatement; } -void CodeCompletionView::setCurrentStatement(const PStatement &newCurrentStatement) +void CodeCompletionPopup::setCurrentStatement(const PStatement &newCurrentStatement) { mCurrentStatement = newCurrentStatement; } -QHash &CodeCompletionView::colors() +QHash &CodeCompletionPopup::colors() { return mColors; } -bool CodeCompletionView::useCppKeyword() const +bool CodeCompletionPopup::useCppKeyword() const { return mUseCppKeyword; } -void CodeCompletionView::setUseCppKeyword(bool newUseCppKeyword) +void CodeCompletionPopup::setUseCppKeyword(bool newUseCppKeyword) { mUseCppKeyword = newUseCppKeyword; } -bool CodeCompletionView::sortByScope() const +bool CodeCompletionPopup::sortByScope() const { return mSortByScope; } -void CodeCompletionView::setSortByScope(bool newSortByScope) +void CodeCompletionPopup::setSortByScope(bool newSortByScope) { mSortByScope = newSortByScope; } -bool CodeCompletionView::ignoreCase() const +bool CodeCompletionPopup::ignoreCase() const { return mIgnoreCase; } -void CodeCompletionView::setIgnoreCase(bool newIgnoreCase) +void CodeCompletionPopup::setIgnoreCase(bool newIgnoreCase) { mIgnoreCase = newIgnoreCase; } -bool CodeCompletionView::showCodeIns() const +bool CodeCompletionPopup::showCodeIns() const { return mShowCodeIns; } -void CodeCompletionView::setShowCodeIns(bool newShowCodeIns) +void CodeCompletionPopup::setShowCodeIns(bool newShowCodeIns) { mShowCodeIns = newShowCodeIns; } -bool CodeCompletionView::showKeywords() const +bool CodeCompletionPopup::showKeywords() const { return mShowKeywords; } -void CodeCompletionView::setShowKeywords(bool newShowKeywords) +void CodeCompletionPopup::setShowKeywords(bool newShowKeywords) { mShowKeywords = newShowKeywords; } -bool CodeCompletionView::recordUsage() const +bool CodeCompletionPopup::recordUsage() const { return mRecordUsage; } -void CodeCompletionView::setRecordUsage(bool newRecordUsage) +void CodeCompletionPopup::setRecordUsage(bool newRecordUsage) { mRecordUsage = newRecordUsage; } -bool CodeCompletionView::onlyGlobals() const +bool CodeCompletionPopup::onlyGlobals() const { return mOnlyGlobals; } -void CodeCompletionView::setOnlyGlobals(bool newOnlyGlobals) +void CodeCompletionPopup::setOnlyGlobals(bool newOnlyGlobals) { mOnlyGlobals = newOnlyGlobals; } -int CodeCompletionView::showCount() const +int CodeCompletionPopup::showCount() const { return mShowCount; } -void CodeCompletionView::setShowCount(int newShowCount) +void CodeCompletionPopup::setShowCount(int newShowCount) { mShowCount = newShowCount; } -const PCppParser &CodeCompletionView::parser() const +const PCppParser &CodeCompletionPopup::parser() const { return mParser; } -void CodeCompletionView::setParser(const PCppParser &newParser) +void CodeCompletionPopup::setParser(const PCppParser &newParser) { mParser = newParser; } -void CodeCompletionView::hideEvent(QHideEvent *event) +void CodeCompletionPopup::hideEvent(QHideEvent *event) { QMutexLocker locker(&mMutex); mListView->setKeypressedCallback(nullptr); @@ -830,7 +830,7 @@ void CodeCompletionView::hideEvent(QHideEvent *event) QWidget::hideEvent(event); } -bool CodeCompletionView::event(QEvent *event) +bool CodeCompletionPopup::event(QEvent *event) { bool result = QWidget::event(event); if (event->type() == QEvent::FontChange) { @@ -839,34 +839,7 @@ bool CodeCompletionView::event(QEvent *event) return result; } -CodeCompletionListView::CodeCompletionListView(QWidget *parent) : QListView(parent) -{ - -} - -void CodeCompletionListView::keyPressEvent(QKeyEvent *event) -{ - if (event->key() == Qt::Key_Up - || event->key() == Qt::Key_Down) { - QListView::keyPressEvent(event); - return; - } - if (!mKeypressedCallback || !mKeypressedCallback(event)) { - QListView::keyPressEvent(event); - } -} - -const KeyPressedCallback &CodeCompletionListView::keypressedCallback() const -{ - return mKeypressedCallback; -} - -void CodeCompletionListView::setKeypressedCallback(const KeyPressedCallback &newKeypressedCallback) -{ - mKeypressedCallback = newKeypressedCallback; -} - -CodeCompletionListModel::CodeCompletionListModel(StatementList *statements, QObject *parent): +CodeCompletionListModel::CodeCompletionListModel(const StatementList *statements, QObject *parent): QAbstractListModel(parent), mStatements(statements) { diff --git a/RedPandaIDE/widgets/codecompletionview.h b/RedPandaIDE/widgets/codecompletionpopup.h similarity index 78% rename from RedPandaIDE/widgets/codecompletionview.h rename to RedPandaIDE/widgets/codecompletionpopup.h index c1aee6cb..bc602cca 100644 --- a/RedPandaIDE/widgets/codecompletionview.h +++ b/RedPandaIDE/widgets/codecompletionpopup.h @@ -1,33 +1,15 @@ -#ifndef CODECOMPLETIONVIEW_H -#define CODECOMPLETIONVIEW_H +#ifndef CODECOMPLETIONPOPUP_H +#define CODECOMPLETIONPOPUP_H #include #include #include "parser/cppparser.h" - -using KeyPressedCallback = std::function; - -class CodeCompletionListView: public QListView { - Q_OBJECT -public: - explicit CodeCompletionListView(QWidget *parent = nullptr); - - // QWidget interface - const KeyPressedCallback &keypressedCallback() const; - void setKeypressedCallback(const KeyPressedCallback &newKeypressedCallback); - -protected: - void keyPressEvent(QKeyEvent *event) override; -private: - KeyPressedCallback mKeypressedCallback; -}; - -using ColorCallback = std::function; +#include "codecompletionlistview.h" class CodeCompletionListModel : public QAbstractListModel { Q_OBJECT public: - explicit CodeCompletionListModel(StatementList* statements,QObject *parent = nullptr); + explicit CodeCompletionListModel(const StatementList* statements,QObject *parent = nullptr); int rowCount(const QModelIndex &parent) const override; QVariant data(const QModelIndex &index, int role) const override; void notifyUpdated(); @@ -39,13 +21,13 @@ private: ColorCallback mColorCallback; }; -class CodeCompletionView : public QWidget +class CodeCompletionPopup : public QWidget { Q_OBJECT public: - explicit CodeCompletionView(QWidget *parent = nullptr); - ~CodeCompletionView(); + explicit CodeCompletionPopup(QWidget *parent = nullptr); + ~CodeCompletionPopup(); void setKeypressedCallback(const KeyPressedCallback &newKeypressedCallback); void prepareSearch(const QString& phrase, const QString& filename, int line); @@ -127,4 +109,4 @@ public: bool event(QEvent *event) override; }; -#endif // CODECOMPLETIONVIEW_H +#endif // CODECOMPLETIONPOPUP_H diff --git a/RedPandaIDE/widgets/headercompletionpopup.cpp b/RedPandaIDE/widgets/headercompletionpopup.cpp new file mode 100644 index 00000000..4b19ddb6 --- /dev/null +++ b/RedPandaIDE/widgets/headercompletionpopup.cpp @@ -0,0 +1,236 @@ +#include "headercompletionpopup.h" + +#include +#include +#include +#include + +HeaderCompletionPopup::HeaderCompletionPopup(QWidget* parent):QWidget(parent) +{ + setWindowFlags(Qt::Popup); + mListView = new CodeCompletionListView(this); + mModel=new HeaderCompletionListModel(&mCompletionList); + mListView->setModel(mModel); + setLayout(new QVBoxLayout()); + layout()->addWidget(mListView); + layout()->setMargin(0); + + mSearchLocal = false; + mCurrentFile = ""; + mPhrase = ""; + mIgnoreCase = false; +} + +HeaderCompletionPopup::~HeaderCompletionPopup() +{ + delete mModel; +} + +void HeaderCompletionPopup::prepareSearch(const QString &phrase, const QString &fileName) +{ + QCursor oldCursor = cursor(); + setCursor(Qt::WaitCursor); + mCurrentFile = fileName; + mPhrase = phrase; + getCompletionFor(phrase); + setCursor(oldCursor); +} + +bool HeaderCompletionPopup::search(const QString &phrase, bool autoHideOnSingleResult) +{ + mPhrase = phrase; + if (mPhrase.isEmpty()) { + hide(); + return false; + } + if(!isEnabled()) + return false; + + QCursor oldCursor = cursor(); + setCursor(Qt::WaitCursor); + + int i = mPhrase.lastIndexOf('\\'); + if (i<0) { + i = mPhrase.lastIndexOf('/'); + } + QString symbol = mPhrase; + if (i>=0) { + symbol = mPhrase.mid(i+1); + } + + // filter fFullCompletionList to fCompletionList + filterList(symbol); + mModel->notifyUpdated(); + setCursor(oldCursor); + + if (!mCompletionList.isEmpty()) { + if (mCompletionList.count() == 1) { + // if only one suggestion and auto hide , don't show the frame + if (autoHideOnSingleResult) + return true; + // if only one suggestion, and is exactly the symbol to search, hide the frame (the search is over) + if (symbol == mCompletionList.front()) + return true; + } + } else { + hide(); + } + return false; +} + +void HeaderCompletionPopup::setKeypressedCallback(const KeyPressedCallback &newKeypressedCallback) +{ + mListView->setKeypressedCallback(newKeypressedCallback); +} + +void HeaderCompletionPopup::setSuggestionColor(const QColor &color) +{ + mModel->setColor(color); +} + +void HeaderCompletionPopup::filterList(const QString &member) +{ + mCompletionList.clear(); + if (member.isEmpty()) { + foreach (const QString& s,mFullCompletionList) { + mCompletionList.append(s); + } + } else { + foreach (const QString& s,mFullCompletionList) { + if (mIgnoreCase && s.startsWith(member, Qt::CaseInsensitive)) { + mCompletionList.append(s); + } else if (s.startsWith(member, Qt::CaseSensitive)){ + mCompletionList.append(s); + } + } + } + std::sort(mCompletionList.begin(),mCompletionList.end()); +} + +void HeaderCompletionPopup::getCompletionFor(const QString &phrase) +{ + int idx = phrase.lastIndexOf('\\'); + if (idx<0) { + idx = phrase.lastIndexOf('/'); + } + mFullCompletionList.clear(); + if (idx < 0) { // dont have basedir + if (mSearchLocal) { + QFileInfo fileInfo(mCurrentFile); + addFilesInPath(fileInfo.absolutePath()); + }; + + for (const QString& path: mParser->includePaths()) { + addFilesInPath(path); + } + + for (const QString& path: mParser->projectIncludePaths()) { + addFilesInPath(path); + } + } else { + QString current = phrase.mid(0,idx); + if (mSearchLocal) { + QFileInfo fileInfo(mCurrentFile); + addFilesInSubDir(fileInfo.absolutePath(),current); + } + for (const QString& path: mParser->includePaths()) { + addFilesInSubDir(path,current); + } + + for (const QString& path: mParser->projectIncludePaths()) { + addFilesInSubDir(path,current); + } + } +} + +void HeaderCompletionPopup::addFilesInPath(const QString &path) +{ + QDir dir(path); + if (!dir.exists()) + return; + foreach (const QFileInfo& fileInfo, dir.entryInfoList()) { + QString suffix = fileInfo.suffix().toLower(); + if (suffix == ".h" || suffix == ".hpp" || suffix == "") { + addFile(fileInfo.fileName()); + } + } +} + +void HeaderCompletionPopup::addFile(const QString &fileName) +{ + if (fileName.isEmpty()) + return; + if (fileName.startsWith('.')) + return; + mFullCompletionList.insert(fileName); +} + +void HeaderCompletionPopup::addFilesInSubDir(const QString &baseDirPath, const QString &subDirName) +{ + QDir baseDir(baseDirPath); + QString subDirPath = baseDir.filePath(subDirName); + addFilesInPath(subDirPath); +} + +void HeaderCompletionPopup::showEvent(QShowEvent *) +{ + mListView->setFocus(); +} + +void HeaderCompletionPopup::hideEvent(QHideEvent *) +{ + mCompletionList.clear(); + mFullCompletionList.clear(); +} + +bool HeaderCompletionPopup::event(QEvent *event) +{ + bool result = QWidget::event(event); + switch (event->type()) { + case QEvent::FontChange: + mListView->setFont(font()); + break; + } + return result; +} + +HeaderCompletionListModel::HeaderCompletionListModel(const QStringList *files, QObject *parent): + QAbstractListModel(parent), + mFiles(files) +{ + +} + +int HeaderCompletionListModel::rowCount(const QModelIndex &) const +{ + return mFiles->count(); +} + +QVariant HeaderCompletionListModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + if (index.row()>=mFiles->count()) + return QVariant(); + + switch(role) { + case Qt::DisplayRole: { + return mFiles->at(index.row()); + } + case Qt::ForegroundRole: + return mColor; + break; + } + return QVariant(); +} + +void HeaderCompletionListModel::notifyUpdated() +{ + beginResetModel(); + endResetModel(); +} + +void HeaderCompletionListModel::setColor(const QColor &newColor) +{ + mColor = newColor; +} diff --git a/RedPandaIDE/widgets/headercompletionpopup.h b/RedPandaIDE/widgets/headercompletionpopup.h new file mode 100644 index 00000000..bb8058b5 --- /dev/null +++ b/RedPandaIDE/widgets/headercompletionpopup.h @@ -0,0 +1,64 @@ +#ifndef HEADERCOMPLETIONPOPUP_H +#define HEADERCOMPLETIONPOPUP_H + +#include +#include "codecompletionlistview.h" +#include "../parser/cppparser.h" + +class HeaderCompletionListModel: public QAbstractListModel { + Q_OBJECT +public: + explicit HeaderCompletionListModel(const QStringList* files,QObject *parent = nullptr); + int rowCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role) const override; + void notifyUpdated(); + void setColor(const QColor &newColor); + +private: + const QStringList* mFiles; + QColor mColor; +}; + +class HeaderCompletionPopup : public QWidget +{ + Q_OBJECT +public: + HeaderCompletionPopup(QWidget* parent=nullptr); + ~HeaderCompletionPopup(); + void prepareSearch(const QString& phrase, const QString& fileName); + bool search(const QString& phrase, bool autoHideOnSingleResult); + void setKeypressedCallback(const KeyPressedCallback &newKeypressedCallback); + void setSuggestionColor(const QColor& color); + +private: + void filterList(const QString& member); + void getCompletionFor(const QString& phrase); + void addFilesInPath(const QString& path); + void addFile(const QString& fileName); + void addFilesInSubDir(const QString& baseDirPath, const QString& subDirName); +private: + + CodeCompletionListView* mListView; + HeaderCompletionListModel* mModel; + QSet mFullCompletionList; + QStringList mCompletionList; + int mShowCount; + QSet mAddedFileNames; + + PCppParser mParser; + QString mPhrase; + bool mIgnoreCase; + bool mSearchLocal; + QString mCurrentFile; + + // QWidget interface +protected: + void showEvent(QShowEvent *event) override; + void hideEvent(QHideEvent *event) override; + + // QObject interface +public: + bool event(QEvent *event) override; +}; + +#endif // HEADERCOMPLETIONPOPUP_H