From 17dd73149c02b465a008f5ea41a159ca156706db Mon Sep 17 00:00:00 2001 From: royqh1979 Date: Thu, 11 Nov 2021 11:17:15 +0800 Subject: [PATCH 1/4] - enhancement: use lighter color to draw menu seperators - enhancement: differentiate selected and unselected tab bars --- NEWS.md | 4 + RedPandaIDE/systemconsts.h | 2 +- RedPandaIDE/widgets/darkfusionstyle.cpp | 158 ++++++++++++++++++++++++ RedPandaIDE/widgets/darkfusionstyle.h | 2 + 4 files changed, 165 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 90a09e4e..09b168cf 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +Version 0.8.5 For Dev-C++ 7 Beta + - enhancement: use lighter color to draw menu seperators + - enhancement: differentiate selected and unselected tab bars + Version 0.8.4 For Dev-C++ 7 Beta - enhancement: auto save/load the default open folder in the configuration file - fix: shouldn't auto add '()' when char succeeding the completed function name is '(' diff --git a/RedPandaIDE/systemconsts.h b/RedPandaIDE/systemconsts.h index b5431dcb..1502fc1c 100644 --- a/RedPandaIDE/systemconsts.h +++ b/RedPandaIDE/systemconsts.h @@ -3,7 +3,7 @@ #include -#define DEVCPP_VERSION "beta.0.8.4" +#define DEVCPP_VERSION "beta.0.8.5" #define APP_SETTSINGS_FILENAME "redpandacpp.ini" #ifdef Q_OS_WIN diff --git a/RedPandaIDE/widgets/darkfusionstyle.cpp b/RedPandaIDE/widgets/darkfusionstyle.cpp index f05afe04..8a581ac9 100644 --- a/RedPandaIDE/widgets/darkfusionstyle.cpp +++ b/RedPandaIDE/widgets/darkfusionstyle.cpp @@ -793,3 +793,161 @@ QIcon DarkFusionStyle::standardIcon(StandardPixmap standardIcon, const QStyleOpt return QProxyStyle::standardIcon(standardIcon, option, widget); } + +void DarkFusionStyle::drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, + const QWidget *widget) const +{ + QRect rect = option->rect; + QColor outline = calcOutline(option->palette); + QColor highlightedOutline = calcHighlightedOutline(option->palette); + QColor shadow = calcDarkShade(); + + + switch (element) { + case CE_MenuItem: + painter->save(); + // Draws one item in a popup menu. + if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast(option)) { + QColor highlightOutline = highlightedOutline; + QColor highlight = option->palette.highlight().color(); + if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) { + int w = 0; + const int margin = int(QStyleHelper::dpiScaled(5, option)); + if (!menuItem->text.isEmpty()) { + painter->setFont(menuItem->font); + proxy()->drawItemText(painter, menuItem->rect.adjusted(margin, 0, -margin, 0), Qt::AlignLeft | Qt::AlignVCenter, + menuItem->palette, menuItem->state & State_Enabled, menuItem->text, + QPalette::Text); + w = menuItem->fontMetrics.horizontalAdvance(menuItem->text) + margin; + } + painter->setPen(shadow.darker(150)); + bool reverse = menuItem->direction == Qt::RightToLeft; + painter->drawLine(menuItem->rect.left() + margin + (reverse ? 0 : w), menuItem->rect.center().y(), + menuItem->rect.right() - margin - (reverse ? w : 0), menuItem->rect.center().y()); + painter->restore(); + break; + } + } + QProxyStyle::drawControl(element, option, painter, widget); + break; + case CE_TabBarTabShape: + painter->save(); + if (const QStyleOptionTab *tab = qstyleoption_cast(option)) { + + bool rtlHorTabs = (tab->direction == Qt::RightToLeft + && (tab->shape == QTabBar::RoundedNorth + || tab->shape == QTabBar::RoundedSouth)); + bool selected = tab->state & State_Selected; + bool lastTab = ((!rtlHorTabs && tab->position == QStyleOptionTab::End) + || (rtlHorTabs + && tab->position == QStyleOptionTab::Beginning)); + bool onlyOne = tab->position == QStyleOptionTab::OnlyOneTab; + int tabOverlap = pixelMetric(PM_TabBarTabOverlap, option, widget); + rect = option->rect.adjusted(0, 0, (onlyOne || lastTab) ? 0 : tabOverlap, 0); + + QRect r2(rect); + int x1 = r2.left(); + int x2 = r2.right(); + int y1 = r2.top(); + int y2 = r2.bottom(); + + painter->setPen(calcInnerContrastLine()); + + QTransform rotMatrix; + bool flip = false; + painter->setPen(shadow); + + switch (tab->shape) { + case QTabBar::RoundedNorth: + break; + case QTabBar::RoundedSouth: + rotMatrix.rotate(180); + rotMatrix.translate(0, -rect.height() + 1); + rotMatrix.scale(-1, 1); + painter->setTransform(rotMatrix, true); + break; + case QTabBar::RoundedWest: + rotMatrix.rotate(180 + 90); + rotMatrix.scale(-1, 1); + flip = true; + painter->setTransform(rotMatrix, true); + break; + case QTabBar::RoundedEast: + rotMatrix.rotate(90); + rotMatrix.translate(0, - rect.width() + 1); + flip = true; + painter->setTransform(rotMatrix, true); + break; + default: + painter->restore(); + QCommonStyle::drawControl(element, tab, painter, widget); + return; + } + + if (flip) { + QRect tmp = rect; + rect = QRect(tmp.y(), tmp.x(), tmp.height(), tmp.width()); + int temp = x1; + x1 = y1; + y1 = temp; + temp = x2; + x2 = y2; + y2 = temp; + } + + painter->setRenderHint(QPainter::Antialiasing, true); + painter->translate(0.5, 0.5); + + QColor tabFrameColor = tab->features & QStyleOptionTab::HasFrame ? + calcTabFrameColor(option->palette) : + option->palette.window().color(); + + QLinearGradient fillGradient(rect.topLeft(), rect.bottomLeft()); + QLinearGradient outlineGradient(rect.topLeft(), rect.bottomLeft()); + QPen outlinePen = outline.lighter(110); + if (selected) { + fillGradient.setColorAt(0, tabFrameColor.lighter(250)); + // QColor highlight = option->palette.highlight().color(); + // if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange) { + // fillGradient.setColorAt(0, highlight.lighter(130)); + // outlineGradient.setColorAt(0, highlight.darker(130)); + // fillGradient.setColorAt(0.14, highlight); + // outlineGradient.setColorAt(0.14, highlight.darker(130)); + // fillGradient.setColorAt(0.1401, tabFrameColor); + // outlineGradient.setColorAt(0.1401, highlight.darker(130)); + // } + fillGradient.setColorAt(0.85, tabFrameColor.lighter(150)); + fillGradient.setColorAt(1, tabFrameColor); + outlineGradient.setColorAt(1, outline); + outlinePen = QPen(outlineGradient, 1); + } else { + fillGradient.setColorAt(0, tabFrameColor.darker(108)); + fillGradient.setColorAt(0.85, tabFrameColor.darker(108)); + fillGradient.setColorAt(1, tabFrameColor.darker(116)); + } + + QRect drawRect = rect.adjusted(0, selected ? 0 : 2, 0, 3); + painter->setPen(outlinePen); + painter->save(); + painter->setClipRect(rect.adjusted(-1, -1, 1, selected ? -2 : -3)); + painter->setBrush(fillGradient); + painter->drawRoundedRect(drawRect.adjusted(0, 0, -1, -1), 2.0, 2.0); + painter->setBrush(Qt::NoBrush); + painter->setPen(calcInnerContrastLine()); + painter->drawRoundedRect(drawRect.adjusted(1, 1, -2, -1), 2.0, 2.0); + painter->restore(); + + if (selected) { + painter->fillRect(rect.left() + 1, rect.bottom() - 1, rect.width() - 2, rect.bottom() - 1, tabFrameColor); + painter->fillRect(QRect(rect.bottomRight() + QPoint(-2, -1), QSize(1, 1)), calcInnerContrastLine()); + painter->fillRect(QRect(rect.bottomLeft() + QPoint(0, -1), QSize(1, 1)), calcInnerContrastLine()); + painter->fillRect(QRect(rect.bottomRight() + QPoint(-1, -1), QSize(1, 1)), calcInnerContrastLine()); + } + } + painter->restore(); + break; + default: + QProxyStyle::drawControl(element, option, painter, widget); + break; + } +} diff --git a/RedPandaIDE/widgets/darkfusionstyle.h b/RedPandaIDE/widgets/darkfusionstyle.h index acace490..d31c1627 100644 --- a/RedPandaIDE/widgets/darkfusionstyle.h +++ b/RedPandaIDE/widgets/darkfusionstyle.h @@ -12,6 +12,8 @@ public: // QStyle interface public: void drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w) const override; + void drawControl(ControlElement ce, const QStyleOption *option, QPainter *painter, + const QWidget *widget) const override; QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *option = nullptr, const QWidget *widget = nullptr) const override; }; From b3e5ddc94cf2e897117b73549ae3fe241b15083b Mon Sep 17 00:00:00 2001 From: royqh1979 Date: Fri, 12 Nov 2021 02:20:13 +0800 Subject: [PATCH 2/4] - enhancement: greatly reduces memory usage for symbol parsing ( memory needed for bits/stdc++.h reduced from 150m+ to 50m+) - fix: currect compiler set not correctly updated when switch between normal file and project file --- NEWS.md | 4 ++++ RedPandaIDE/mainwindow.cpp | 4 ++-- RedPandaIDE/parser/cppparser.cpp | 19 +++++++++------ RedPandaIDE/parser/cpppreprocessor.cpp | 17 +++++++++++++ RedPandaIDE/parser/cpppreprocessor.h | 33 ++++++++++++++------------ 5 files changed, 53 insertions(+), 24 deletions(-) diff --git a/NEWS.md b/NEWS.md index 09b168cf..da86628b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +Version 0.8.6 For Dev-C++ 7 Beta + - enhancement: greatly reduces memory usage for symbol parsing ( memory needed for bits/stdc++.h reduced from 150m+ to 50m+) + - fix: currect compiler set not correctly updated when switch between normal file and project file + Version 0.8.5 For Dev-C++ 7 Beta - enhancement: use lighter color to draw menu seperators - enhancement: differentiate selected and unselected tab bars diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 396f7314..f9e93de8 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -91,7 +91,7 @@ MainWindow::MainWindow(QWidget *parent) ui->toolbarCompilerSet->addWidget(mCompilerSet); connect(mCompilerSet,QOverload::of(&QComboBox::currentIndexChanged), this, &MainWindow::onCompilerSetChanged); - updateCompilerSet(); + //updateCompilerSet(); mCompilerManager = new CompilerManager(this); mDebugger = new Debugger(this); @@ -399,7 +399,7 @@ void MainWindow::updateEditorActions() } updateCompileActions(); - + updateCompilerSet(); } void MainWindow::updateProjectActions() diff --git a/RedPandaIDE/parser/cppparser.cpp b/RedPandaIDE/parser/cppparser.cpp index 23a2194c..a1be379e 100644 --- a/RedPandaIDE/parser/cppparser.cpp +++ b/RedPandaIDE/parser/cppparser.cpp @@ -61,9 +61,9 @@ void CppParser::addHardDefineByLine(const QString &line) { QMutexLocker locker(&mMutex); if (line.startsWith('#')) { - mPreprocessor.addDefineByLine(line.mid(1).trimmed(), true); + mPreprocessor.addHardDefineByLine(line.mid(1).trimmed()); } else { - mPreprocessor.addDefineByLine(line, true); + mPreprocessor.addHardDefineByLine(line); } } @@ -3127,9 +3127,16 @@ void CppParser::internalParse(const QString &fileName) mPreprocessor.setScanOptions(mParseGlobalHeaders, mParseLocalHeaders); mPreprocessor.preprocess(fileName, buffer); + QStringList prerocessResult = mPreprocessor.result(); + mPreprocessor.clearResult(); +#ifdef QT_DEBUG +// StringsToFile(mPreprocessor.result(),"f:\\preprocess.txt"); +// mPreprocessor.dumpDefinesTo("f:\\defines.txt"); +// mPreprocessor.dumpIncludesListTo("f:\\includes.txt"); +#endif // Tokenize the preprocessed buffer file - mTokenizer.tokenize(mPreprocessor.result()); + mTokenizer.tokenize(prerocessResult); if (mTokenizer.tokenCount() == 0) return; @@ -3147,13 +3154,11 @@ void CppParser::internalParse(const QString &fileName) break; } #ifdef QT_DEBUG -// StringsToFile(mPreprocessor.result(),"f:\\preprocess.txt"); -// mPreprocessor.dumpDefinesTo("f:\\defines.txt"); -// mPreprocessor.dumpIncludesListTo("f:\\includes.txt"); -// mStatementList.dump("f:\\stats.txt"); // mTokenizer.dumpTokens("f:\\tokens.txt"); +// mStatementList.dump("f:\\stats.txt"); // mStatementList.dumpAll("f:\\all-stats.txt"); #endif + mTokenizer.reset(); } } diff --git a/RedPandaIDE/parser/cpppreprocessor.cpp b/RedPandaIDE/parser/cpppreprocessor.cpp index 6967394b..b45b1fbb 100644 --- a/RedPandaIDE/parser/cpppreprocessor.cpp +++ b/RedPandaIDE/parser/cpppreprocessor.cpp @@ -22,6 +22,18 @@ void CppPreprocessor::clear() mCurrentIncludes.reset(); } +void CppPreprocessor::clearResult() +{ + mFileName.clear(); + mBuffer.clear(); + mResult.clear(); + mCurrentIncludes = nullptr; + mIncludes.clear(); // stack of files we've stepped into. last one is current file, first one is source file + mBranchResults.clear();// stack of branch results (boolean). last one is current branch, first one is outermost branch + mDefines.clear(); // working set, editable + mProcessed.clear(); // dictionary to save filename already processed +} + void CppPreprocessor::addDefineByParts(const QString &name, const QString &args, const QString &value, bool hardCoded) { // Check for duplicates @@ -91,6 +103,11 @@ void CppPreprocessor::getDefineParts(const QString &input, QString &name, QStrin value = removeGCCAttributes(s.mid(i+1).trimmed()); } +void CppPreprocessor::addHardDefineByLine(const QString &line) +{ + addDefineByLine(line,true); +} + void CppPreprocessor::addDefineByLine(const QString &line, bool hardCoded) { // Remove define diff --git a/RedPandaIDE/parser/cpppreprocessor.h b/RedPandaIDE/parser/cpppreprocessor.h index 2526bb07..1addf7ba 100644 --- a/RedPandaIDE/parser/cpppreprocessor.h +++ b/RedPandaIDE/parser/cpppreprocessor.h @@ -46,17 +46,12 @@ public: explicit CppPreprocessor(); void clear(); - void addDefineByParts(const QString& name, const QString& args, - const QString& value, bool hardCoded); + void clearResult(); void getDefineParts(const QString& input, QString &name, QString &args, QString &value); - void addDefineByLine(const QString& line, bool hardCoded); - PDefine getDefine(const QString& name); - PDefine getHardDefine(const QString& name); + void addHardDefineByLine(const QString& line); void reset(); //reset but don't clear generated defines - void resetDefines(); void setScanOptions(bool parseSystem, bool parseLocal); void preprocess(const QString& fileName, QStringList buffer = QStringList()); - void invalidDefinesInFile(const QString& fileName); void dumpDefinesTo(const QString& fileName) const; void dumpIncludesListTo(const QString& fileName) const; @@ -97,7 +92,7 @@ private: void expandMacro(const QString& line, QString& newLine, QString& word, int& i, int depth); QString removeGCCAttributes(const QString& line); void removeGCCAttribute(const QString&line, QString& newLine, int &i, const QString& word); - + PDefine getDefine(const QString& name); // current file stuff PParsedFile getInclude(int index); void openInclude(const QString& fileName, QStringList bufferedText=QStringList()); @@ -110,6 +105,12 @@ private: // include stuff PFileIncludes getFileIncludesEntry(const QString& FileName); void addDefinesInFile(const QString& fileName); + void resetDefines(); + void addDefineByParts(const QString& name, const QString& args, + const QString& value, bool hardCoded); + void addDefineByLine(const QString& line, bool hardCoded); + PDefine getHardDefine(const QString& name); + void invalidDefinesInFile(const QString& fileName); void parseArgs(PDefine define); QList tokenizeValue(const QString& value); @@ -181,24 +182,26 @@ private: QStringList mResult; PFileIncludes mCurrentIncludes; int mPreProcIndex; - QHash mIncludesList; - DefineMap mHardDefines; // set by "cpp -dM -E -xc NUL" - DefineMap mDefines; // working set, editable - QHash mFileDefines; //dictionary to save defines for each headerfile; QList mIncludes; // stack of files we've stepped into. last one is current file, first one is source file QList mBranchResults;// stack of branch results (boolean). last one is current branch, first one is outermost branch - //{ List of current compiler set's include path} - QSet mIncludePaths; + DefineMap mDefines; // working set, editable + QSet mProcessed; // dictionary to save filename already processed + + //used by parser even preprocess finished + DefineMap mHardDefines; // set by "cpp -dM -E -xc NUL" + QHash mIncludesList; + QHash mFileDefines; //dictionary to save defines for each headerfile; //{ List of current project's include path } QSet mProjectIncludePaths; //we also need include paths in order (for #include_next) QList mIncludePathList; QList mProjectIncludePathList; + //{ List of current compiler set's include path} + QSet mIncludePaths; bool mParseSystem; bool mParseLocal; QSet mScannedFiles; - QSet mProcessed; // dictionary to save filename already processed }; #endif // CPPPREPROCESSOR_H From 81b524c9ed106e46c610f4a6ae41f523f9100d58 Mon Sep 17 00:00:00 2001 From: royqh1979 Date: Fri, 12 Nov 2021 02:31:45 +0800 Subject: [PATCH 3/4] dont save parser when code/header completion popup hides --- NEWS.md | 2 +- RedPandaIDE/widgets/codecompletionpopup.cpp | 1 + RedPandaIDE/widgets/headercompletionpopup.cpp | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index da86628b..2b9ff2fe 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,5 @@ Version 0.8.6 For Dev-C++ 7 Beta - - enhancement: greatly reduces memory usage for symbol parsing ( memory needed for bits/stdc++.h reduced from 150m+ to 50m+) + - enhancement: greatly reduces memory usage for symbol parsing ( memory needed for bits/stdc++.h reduced from 150m+ to 80m+) - fix: currect compiler set not correctly updated when switch between normal file and project file Version 0.8.5 For Dev-C++ 7 Beta diff --git a/RedPandaIDE/widgets/codecompletionpopup.cpp b/RedPandaIDE/widgets/codecompletionpopup.cpp index 9bc19456..78dbc867 100644 --- a/RedPandaIDE/widgets/codecompletionpopup.cpp +++ b/RedPandaIDE/widgets/codecompletionpopup.cpp @@ -894,6 +894,7 @@ void CodeCompletionPopup::hideEvent(QHideEvent *event) mIncludedFiles.clear(); mUsings.clear(); mAddedStatements.clear(); + mParser = nullptr; QWidget::hideEvent(event); } diff --git a/RedPandaIDE/widgets/headercompletionpopup.cpp b/RedPandaIDE/widgets/headercompletionpopup.cpp index 865ea1ad..3ec95200 100644 --- a/RedPandaIDE/widgets/headercompletionpopup.cpp +++ b/RedPandaIDE/widgets/headercompletionpopup.cpp @@ -227,6 +227,7 @@ void HeaderCompletionPopup::hideEvent(QHideEvent *) { mCompletionList.clear(); mFullCompletionList.clear(); + mParser = nullptr; } bool HeaderCompletionPopup::event(QEvent *event) From 58ba490f32cc4a09da395804892b3e84ff437019 Mon Sep 17 00:00:00 2001 From: royqh1979 Date: Fri, 12 Nov 2021 07:26:13 +0800 Subject: [PATCH 4/4] work save --- RedPandaIDE/parser/cppparser.cpp | 31 +++++++++++++++++++++---------- RedPandaIDE/parser/cppparser.h | 3 +++ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/RedPandaIDE/parser/cppparser.cpp b/RedPandaIDE/parser/cppparser.cpp index a1be379e..03360fe0 100644 --- a/RedPandaIDE/parser/cppparser.cpp +++ b/RedPandaIDE/parser/cppparser.cpp @@ -1297,6 +1297,18 @@ int CppParser::skipBracket(int startAt) return startAt; } +void CppParser::internalClear() +{ + mCurrentScope.clear(); + mCurrentClassScope.clear(); + mIndex = 0; + mClassScope = StatementClassScope::scsNone; + mSkipList.clear(); + mBlockBeginSkips.clear(); + mBlockEndSkips.clear(); + mInlineNamespaceEndSkips.clear(); +} + bool CppParser::checkForCatchBlock() { // return mIndex < mTokenizer.tokenCount() && @@ -3127,7 +3139,8 @@ void CppParser::internalParse(const QString &fileName) mPreprocessor.setScanOptions(mParseGlobalHeaders, mParseLocalHeaders); mPreprocessor.preprocess(fileName, buffer); - QStringList prerocessResult = mPreprocessor.result(); + QStringList preprocessResult = mPreprocessor.result(); + //reduce memory usage mPreprocessor.clearResult(); #ifdef QT_DEBUG // StringsToFile(mPreprocessor.result(),"f:\\preprocess.txt"); @@ -3136,28 +3149,26 @@ void CppParser::internalParse(const QString &fileName) #endif // Tokenize the preprocessed buffer file - mTokenizer.tokenize(prerocessResult); + mTokenizer.tokenize(preprocessResult); + //reduce memory usage + preprocessResult.clear(); if (mTokenizer.tokenCount() == 0) return; // Process the token list - mCurrentScope.clear(); - mCurrentClassScope.clear(); - mIndex = 0; - mClassScope = StatementClassScope::scsNone; - mSkipList.clear(); - mBlockBeginSkips.clear(); - mBlockEndSkips.clear(); - mInlineNamespaceEndSkips.clear(); + internalClear(); while(true) { if (!handleStatement()) break; } + //reduce memory usage + internalClear(); #ifdef QT_DEBUG // mTokenizer.dumpTokens("f:\\tokens.txt"); // mStatementList.dump("f:\\stats.txt"); // mStatementList.dumpAll("f:\\all-stats.txt"); #endif + //reduce memory usage mTokenizer.reset(); } } diff --git a/RedPandaIDE/parser/cppparser.h b/RedPandaIDE/parser/cppparser.h index 4e062440..1bf2f533 100644 --- a/RedPandaIDE/parser/cppparser.h +++ b/RedPandaIDE/parser/cppparser.h @@ -173,6 +173,9 @@ private: void removeScopeLevel(int line); // removes level int skipBraces(int startAt); int skipBracket(int startAt); + + void internalClear(); + bool checkForCatchBlock(); bool checkForEnum(); bool checkForForBlock();