diff --git a/NEWS.md b/NEWS.md index 2b9ff2fe..d62addf8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,15 @@ +Version 0.8.7 For Dev-C++ 7 Beta + - enhancement: auto indent line to column 1 when enter '#' at beginning of line + - fix: when enter '{' or '}' at beginning of line, auto indent will remove all contents of the line + - fix: auto indent should be turned off when reformat code + - fix: auto indent should be turned off when replace in code + 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 80m+) - fix: currect compiler set not correctly updated when switch between normal file and project file + - fix: editor auto save settings not saved and applied + - fix: only auto save files that has new modifications + - fix: correctly auto save files with it's own name Version 0.8.5 For Dev-C++ 7 Beta - enhancement: use lighter color to draw menu seperators diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index 3ccc4dfb..25941177 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -151,10 +151,12 @@ Editor::Editor(QWidget *parent, const QString& filename, connect(this, &QWidget::customContextMenuRequested, pMainWindow, &MainWindow::onEditorContextMenu); + mCanAutoSave = false; if (isNew && parentPageControl!=nullptr) { QString fileTemplate = pMainWindow->codeSnippetManager()->newFileTemplate(); if (!fileTemplate.isEmpty()) { insertCodeSnippet(fileTemplate); + mCanAutoSave = true; } } if (!isNew && parentPageControl!=nullptr) { @@ -1390,6 +1392,8 @@ void Editor::onStatusChanged(SynStatusChanges changes) } if (changes.testFlag(scModified)) { mCurrentLineModified = true; + if (mParentPageControl!=nullptr) + mCanAutoSave = true; } if (changes.testFlag(SynStatusChange::scCaretX) @@ -3120,6 +3124,16 @@ void Editor::onExportedFormatToken(PSynHighlighter syntaxHighlighter, int Line, } } +bool Editor::canAutoSave() const +{ + return mCanAutoSave; +} + +void Editor::setCanAutoSave(bool newCanAutoSave) +{ + mCanAutoSave = newCanAutoSave; +} + const QDateTime &Editor::hideTime() const { return mHideTime; @@ -3514,7 +3528,12 @@ void Editor::reformat() content); selectAll(); + SynEditorOptions oldOptions = getOptions(); + SynEditorOptions newOptions = oldOptions; + newOptions.setFlag(SynEditorOption::eoAutoIndent,false); + setOptions(newOptions); setSelText(QString::fromUtf8(newContent)); + setOptions(oldOptions); reparse(); checkSyntaxInBack(); reparseTodo(); diff --git a/RedPandaIDE/editor.h b/RedPandaIDE/editor.h index 52b07f33..70e44cfb 100644 --- a/RedPandaIDE/editor.h +++ b/RedPandaIDE/editor.h @@ -269,6 +269,7 @@ private: int mTabStopBegin; int mTabStopEnd; int mTabStopY; + bool mCanAutoSave; QString mLineBeforeTabStop; QString mLineAfterTabStop; QList mUserCodeInTabStops; @@ -312,6 +313,9 @@ public: const QDateTime &hideTime() const; void setHideTime(const QDateTime &newHideTime); + bool canAutoSave() const; + void setCanAutoSave(bool newCanAutoSave); + protected: void mouseReleaseEvent(QMouseEvent *event) override; diff --git a/RedPandaIDE/gdbmiresultparser.cpp b/RedPandaIDE/gdbmiresultparser.cpp index 0e3e23fa..19521d55 100644 --- a/RedPandaIDE/gdbmiresultparser.cpp +++ b/RedPandaIDE/gdbmiresultparser.cpp @@ -146,7 +146,7 @@ bool GDBMIResultParser::parseArray(char *&p, ParseValue &value) if (*p!=']') { while (*p!=0) { skipSpaces(p); - QObject obj; + ParseObject obj; bool result = parseObject(p,obj); if (result) { array.append(obj); @@ -202,7 +202,7 @@ const QString &GDBMIResultParser::ParseValue::value() const return mValue; } -const QList &GDBMIResultParser::ParseValue::array() const +const QList<::GDBMIResultParser::ParseObject> &GDBMIResultParser::ParseValue::array() const { return mArray; } @@ -228,25 +228,18 @@ GDBMIResultParser::ParseValue::ParseValue(const QString &value): { } -GDBMIResultParser::ParseValue::ParseValue(const PParseObject &object): +GDBMIResultParser::ParseValue::ParseValue(const ParseObject &object): mObject(object), mType(ParseValueType::Object) { } -GDBMIResultParser::ParseValue::ParseValue(const QList &array): +GDBMIResultParser::ParseValue::ParseValue(const QList &array): mArray(array), mType(ParseValueType::Array) { } -void GDBMIResultParser::ParseValue::addObject(const PParseObject &object) -{ - Q_ASSERT(mType == ParseValueType::Array || mType == ParseValueType::NotAssigned); - mType = ParseValueType::Array; - mArray.append(object); -} - GDBMIResultParser::ParseValue &GDBMIResultParser::ParseValue::operator=(const QString &value) { Q_ASSERT(mType == ParseValueType::NotAssigned); diff --git a/RedPandaIDE/gdbmiresultparser.h b/RedPandaIDE/gdbmiresultparser.h index 0842134a..3009fe96 100644 --- a/RedPandaIDE/gdbmiresultparser.h +++ b/RedPandaIDE/gdbmiresultparser.h @@ -2,6 +2,7 @@ #define GDBMIRESULTPARSER_H #include +#include #include @@ -38,10 +39,9 @@ class GDBMIResultParser explicit ParseValue(const ParseObject &object); explicit ParseValue(const QList& array); ParseValue(const ParseValue&) = delete; - void addObject(const PParseObject& object); const QString &value() const; - QList &array() const; - const PParseObject &object() const; + const QList &array() const; + const ParseObject &object() const; ParseValueType type() const; ParseValue& operator=(const QString& value); ParseValue& operator=(const ParseObject& object); diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 3c633bdb..72ccf83f 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -799,8 +799,10 @@ void MainWindow::updateClassBrowserForEditor(Editor *editor) void MainWindow::resetAutoSaveTimer() { if (pSettings->editor().enableAutoSave()) { + mAutoSaveTimer.stop(); //minute to milliseconds mAutoSaveTimer.start(pSettings->editor().autoSaveInterval()*60*1000); + onAutoSaveTimeout(); } else { mAutoSaveTimer.stop(); } @@ -1544,35 +1546,47 @@ void MainWindow::prepareDebugger() void MainWindow::doAutoSave(Editor *e) { - if (!e) - return; - if (!e->modified()) + + if (!e || !e->canAutoSave()) return; QString filename = e->filename(); - QFileInfo fileInfo(filename); - QDir parent = fileInfo.absoluteDir(); - QString baseName = fileInfo.completeBaseName(); - QString suffix = fileInfo.suffix(); - switch(pSettings->editor().autoSaveStrategy()) { - case assOverwrite: - break; - case assAppendUnixTimestamp: - filename = parent.filePath( - QString("%1.%2.%3") - .arg(baseName) - .arg(QDateTime::currentSecsSinceEpoch()) - .arg(suffix)); - break; - case assAppendFormatedTimeStamp: { - QDateTime time = QDateTime::currentDateTime(); - filename = parent.filePath( - QString("%1.%2.%3") - .arg(baseName) - .arg(time.toString("yyyy.MM.dd.hh.mm.ss")) - .arg(suffix)); + try { + QFileInfo fileInfo(filename); + QDir parent = fileInfo.absoluteDir(); + QString baseName = fileInfo.completeBaseName(); + QString suffix = fileInfo.suffix(); + switch(pSettings->editor().autoSaveStrategy()) { + case assOverwrite: + e->save(); + return; + case assAppendUnixTimestamp: + filename = parent.filePath( + QString("%1.%2.%3") + .arg(baseName) + .arg(QDateTime::currentSecsSinceEpoch()) + .arg(suffix)); + break; + case assAppendFormatedTimeStamp: { + QDateTime time = QDateTime::currentDateTime(); + filename = parent.filePath( + QString("%1.%2.%3") + .arg(baseName) + .arg(time.toString("yyyy.MM.dd.hh.mm.ss")) + .arg(suffix)); + } + } + if (e->isNew()) { + e->saveAs(); + } else { + e->saveFile(filename); + e->setCanAutoSave(false); + } + } catch (FileError& error) { + QMessageBox::critical(e, + tr("Auto Save Error"), + tr("Auto save \"%1\" to \"%2\" failed:%3") + .arg(e->filename(), filename, error.reason())); } - } - e->saveFile(filename); } //static void limitActionShortCutScope(QAction* action,QWidget* scopeWidget) { diff --git a/RedPandaIDE/qsynedit/SynEdit.cpp b/RedPandaIDE/qsynedit/SynEdit.cpp index 024365ef..cbaed964 100644 --- a/RedPandaIDE/qsynedit/SynEdit.cpp +++ b/RedPandaIDE/qsynedit/SynEdit.cpp @@ -1,4 +1,5 @@ #include "SynEdit.h" +#include "highlighter/cpp.h" #include #include #include @@ -1473,7 +1474,14 @@ int SynEdit::calcIndentSpaces(int line, const QString& lineText, bool addIndent) matchingIndents = rangeAfterFirstToken.matchingIndents; dontAddIndent = true; l = startLine; - } else if (mHighlighter->isLastLineCommentNotFinished(rangePreceeding.state) + } else if (mHighlighter->getClass() == SynHighlighterClass::CppHighlighter + && trimmedLineText.startsWith('#') + && attr == ((SynEditCppHighlighter *)mHighlighter.get())->preprocessorAttribute()) { + dontAddIndent = true; + indentSpaces=0; + l=0; + } else if (mHighlighter->getClass() == SynHighlighterClass::CppHighlighter + && mHighlighter->isLastLineCommentNotFinished(rangePreceeding.state) && (trimmedLineText.startsWith("*")) ) { // last line is a not finished comment, and this line start with "*" @@ -1785,7 +1793,7 @@ void SynEdit::doDeleteLastChar() mLines->deleteAt(mCaretY); doLinesDeleted(mCaretY+1, 1); if (mOptions.testFlag(eoTrimTrailingSpaces)) - Temp = trimRight(Temp); + Temp = TrimRight(Temp); setLineText(lineText() + Temp); helper = lineBreak(); //"/r/n" } @@ -2119,7 +2127,7 @@ void SynEdit::insertLine(bool moveCaret) rightLineText,mOptions.testFlag(eoAutoIndent) && notInComment); if (mOptions.testFlag(eoAutoIndent)) { - rightLineText=trimLeft(rightLineText); + rightLineText=TrimLeft(rightLineText); } QString indentSpacesForRightLineText = GetLeftSpacing(indentSpaces,true); mLines->insert(mCaretY, indentSpacesForRightLineText+rightLineText); @@ -2624,17 +2632,21 @@ void SynEdit::doAddChar(QChar AChar) } mUndoList->BeginBlock(); - if (mOptions.testFlag(eoAutoIndent) && mHighlighter - && (oldCaretY<=mLines->count())) { + // auto + if (mOptions.testFlag(eoAutoIndent) + && mHighlighter + && mHighlighter->getClass()==SynHighlighterClass::CppHighlighter + && (oldCaretY<=mLines->count()) ) { + //unindent if ':' at end of the line if (AChar == ':') { QString line = mLines->getString(oldCaretY-1); if (line.length() < oldCaretX) { int indentSpaces = calcIndentSpaces(oldCaretY,line+":", true); if (indentSpaces != leftSpaces(line)) { - QString temp = GetLeftSpacing(indentSpaces,true) + trimLeft(line); - int i = temp.length(); - mLines->putString(oldCaretY-1,temp); + QString newLine = GetLeftSpacing(indentSpaces,true) + TrimLeft(line); + int i = newLine.length(); + mLines->putString(oldCaretY-1,newLine); internalSetCaretXY(BufferCoord{i+1,oldCaretY}); mUndoList->AddChange( SynChangeReason::crDelete, @@ -2646,66 +2658,35 @@ void SynEdit::doAddChar(QChar AChar) mUndoList->AddChange( SynChangeReason::crInsert, BufferCoord{1, oldCaretY}, - BufferCoord{temp.length()+1, oldCaretY}, - "", + BufferCoord{newLine.length()+1, oldCaretY}, + newLine, SynSelectionMode::smNormal ); } } - } - //unindent if '{' is after an statement like 'if' 'for' - if (AChar == '{') { - QString temp = mLines->getString(oldCaretY-1).mid(0,oldCaretX-1); + } else if (AChar == '{' || AChar == '}' || AChar == '#') { + //Reindent line when add '{' '}' and '#' at the beginning + QString left = mLines->getString(oldCaretY-1).mid(0,oldCaretX-1); // and the first nonblank char is this new { - if (temp.trimmed().isEmpty()) { - int indentSpaces = calcIndentSpaces(oldCaretY,"{", true); - QString line = mLines->getString(oldCaretY-1); - if (indentSpaces != leftSpaces(line)) { - QString temp = GetLeftSpacing(indentSpaces,true); - int i = temp.length(); - mLines->putString(oldCaretY-1,temp); - internalSetCaretXY(BufferCoord{i+1,oldCaretY}); + if (left.trimmed().isEmpty()) { + int indentSpaces = calcIndentSpaces(oldCaretY,AChar, true); + if (indentSpaces != leftSpaces(left)) { + QString right = mLines->getString(oldCaretY-1).mid(oldCaretX); + QString newLeft = GetLeftSpacing(indentSpaces,true); + mLines->putString(oldCaretY-1,newLeft+right); + internalSetCaretXY(BufferCoord{newLeft.length()+1,oldCaretY}); mUndoList->AddChange( SynChangeReason::crDelete, BufferCoord{1, oldCaretY}, - BufferCoord{line.length()+1, oldCaretY}, - line, + BufferCoord{left.length()+1, oldCaretY}, + left, SynSelectionMode::smNormal ); mUndoList->AddChange( SynChangeReason::crInsert, BufferCoord{1, oldCaretY}, - BufferCoord{temp.length()+1, oldCaretY}, - "", - SynSelectionMode::smNormal - ); - } - } - } - // Remove TabWidth of indent of the current line when typing a } - if (AChar == '}') { - QString temp = mLines->getString(oldCaretY-1).mid(0,oldCaretX-1); - // and the first nonblank char is this new } - if (temp.trimmed().isEmpty()) { - int indentSpaces = calcIndentSpaces(oldCaretY,"}", true); - QString line = mLines->getString(oldCaretY-1); - if (indentSpaces != leftSpaces(line)) { - QString temp = GetLeftSpacing(indentSpaces,true); - int i = temp.length(); - mLines->putString(oldCaretY-1,temp); - internalSetCaretXY(BufferCoord{i+1,oldCaretY}); - mUndoList->AddChange( - SynChangeReason::crDelete, - BufferCoord{1, oldCaretY}, - BufferCoord{line.length()+1, oldCaretY}, - line, - SynSelectionMode::smNormal - ); - mUndoList->AddChange( - SynChangeReason::crInsert, - BufferCoord{1, oldCaretY}, - BufferCoord{temp.length()+1, oldCaretY}, - "", + BufferCoord{newLeft.length()+1, oldCaretY}, + newLeft, SynSelectionMode::smNormal ); } @@ -4881,6 +4862,8 @@ int SynEdit::searchReplace(const QString &sSearch, const QString &sReplace, SynS mUndoList->BeginBlock(); dobatchReplace = true; } + bool oldAutoIndent = mOptions.testFlag(SynEditorOption::eoAutoIndent); + mOptions.setFlag(SynEditorOption::eoAutoIndent,false); doSetSelText(replaceText); nReplaceLen = caretX() - nFound; // fix the caret position and the remaining results @@ -4894,6 +4877,7 @@ int SynEdit::searchReplace(const QString &sSearch, const QString &sReplace, SynS } } } + mOptions.setFlag(SynEditorOption::eoAutoIndent,oldAutoIndent); } } // search next / previous line @@ -4941,7 +4925,7 @@ void SynEdit::doLinesInserted(int firstLine, int count) void SynEdit::properSetLine(int ALine, const QString &ALineText) { if (mOptions.testFlag(eoTrimTrailingSpaces)) - mLines->putString(ALine,trimRight(ALineText)); + mLines->putString(ALine,TrimRight(ALineText)); else mLines->putString(ALine,ALineText); } @@ -5047,7 +5031,7 @@ int SynEdit::insertTextByNormalMode(const QString &Value) int Result = 0; sLeftSide = lineText().mid(0, mCaretX - 1); if (mCaretX - 1 > sLeftSide.length()) { - if (stringIsBlank(sLeftSide)) + if (StringIsBlank(sLeftSide)) sLeftSide = GetLeftSpacing(displayX() - 1, true); else sLeftSide += QString(mCaretX - 1 - sLeftSide.length(),' '); @@ -5063,7 +5047,7 @@ int SynEdit::insertTextByNormalMode(const QString &Value) Start = 0; P = GetEOL(Value,Start); if (Peditor().load(); //font - ui->chkEnableAutoSave->setChecked(pSettings->editor().enableAutoSave()); + ui->grpEnableAutoSave->setChecked(pSettings->editor().enableAutoSave()); ui->spinInterval->setValue(pSettings->editor().autoSaveInterval()); switch(pSettings->editor().autoSaveTarget()) { case astCurrentFile: @@ -60,7 +60,7 @@ void EditorAutoSaveWidget::doLoad() void EditorAutoSaveWidget::doSave() { - pSettings->editor().setEnableAutoSave(ui->chkEnableAutoSave->isChecked()); + pSettings->editor().setEnableAutoSave(ui->grpEnableAutoSave->isChecked()); pSettings->editor().setAutoSaveInterval(ui->spinInterval->value()); if (ui->rbCurrentFile->isChecked()) pSettings->editor().setAutoSaveTarget(astCurrentFile); @@ -74,6 +74,8 @@ void EditorAutoSaveWidget::doSave() pSettings->editor().setAutoSaveStrategy(assAppendUnixTimestamp); else pSettings->editor().setAutoSaveStrategy(assAppendFormatedTimeStamp); + pSettings->editor().save(); + pMainWindow->resetAutoSaveTimer(); } void EditorAutoSaveWidget::on_rbOverwrite_toggled(bool) diff --git a/RedPandaIDE/settingsdialog/editorautosavewidget.ui b/RedPandaIDE/settingsdialog/editorautosavewidget.ui index 5f36b260..7e6634dc 100644 --- a/RedPandaIDE/settingsdialog/editorautosavewidget.ui +++ b/RedPandaIDE/settingsdialog/editorautosavewidget.ui @@ -15,7 +15,7 @@ - + Enable auto save diff --git a/RedPandaIDE/systemconsts.h b/RedPandaIDE/systemconsts.h index 1502fc1c..de3b4b01 100644 --- a/RedPandaIDE/systemconsts.h +++ b/RedPandaIDE/systemconsts.h @@ -3,7 +3,7 @@ #include -#define DEVCPP_VERSION "beta.0.8.5" +#define DEVCPP_VERSION "beta.0.8.6" #define APP_SETTSINGS_FILENAME "redpandacpp.ini" #ifdef Q_OS_WIN diff --git a/RedPandaIDE/widgets/darkfusionstyle.cpp b/RedPandaIDE/widgets/darkfusionstyle.cpp index 8a581ac9..ac5560fc 100644 --- a/RedPandaIDE/widgets/darkfusionstyle.cpp +++ b/RedPandaIDE/widgets/darkfusionstyle.cpp @@ -805,12 +805,12 @@ void DarkFusionStyle::drawControl(ControlElement element, const QStyleOption *op 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) { + painter->save(); int w = 0; const int margin = int(QStyleHelper::dpiScaled(5, option)); if (!menuItem->text.isEmpty()) {