From aee87943055fcddee394ab0527abbaa3a7551ff6 Mon Sep 17 00:00:00 2001 From: "royqh1979@gmail.com" Date: Mon, 24 May 2021 00:41:00 +0800 Subject: [PATCH] * work save --- RedPandaIDE/editor.cpp | 202 +++++------- RedPandaIDE/editor.h | 4 +- RedPandaIDE/editorlist.cpp | 2 +- RedPandaIDE/mainwindow.cpp | 26 +- RedPandaIDE/qsynedit/KeyStrokes.cpp | 34 +- RedPandaIDE/qsynedit/KeyStrokes.h | 1 + RedPandaIDE/qsynedit/SynEdit.cpp | 300 +++++++++++++++--- RedPandaIDE/qsynedit/SynEdit.h | 35 +- RedPandaIDE/qsynedit/TextBuffer.cpp | 47 ++- RedPandaIDE/qsynedit/TextBuffer.h | 3 + RedPandaIDE/qsynedit/TextPainter.cpp | 98 +++--- RedPandaIDE/qsynedit/TextPainter.h | 2 +- RedPandaIDE/qsynedit/highlighter/base.h | 2 +- .../qsynedit/highlighter/composition.cpp | 5 +- RedPandaIDE/qsynedit/highlighter/cpp.cpp | 4 +- RedPandaIDE/utils.cpp | 15 + RedPandaIDE/utils.h | 1 + 17 files changed, 519 insertions(+), 262 deletions(-) diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index 95fd9b5b..47ef2ae7 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -12,7 +12,8 @@ #include #include #include -#include +#include "qsynedit/highlighter/cpp.h" + using namespace std; @@ -34,7 +35,7 @@ Editor::Editor(QWidget *parent, const QString& filename, const QByteArray& encoding, bool inProject, bool isNew, QTabWidget* parentPageControl): - QsciScintilla(parent), + SynEdit(parent), mFilename(filename), mEncodingOption(encoding), mInProject(inProject), @@ -58,53 +59,8 @@ Editor::Editor(QWidget *parent, const QString& filename, mFileEncoding = mEncodingOption; } - // - QsciLexerCPP *lexer = new QsciLexerCPP(); - lexer->setHighlightEscapeSequences(true); - lexer->setFoldComments(true); - lexer->setDefaultFont(QFont("Consolas",12)); - this->setLexer(lexer); - this->setAutoIndent(pSettings->editor().autoIndent()); - this->setFolding(FoldStyle::BoxedTreeFoldStyle,FoldMargin); - this->setTabWidth(4); + //SynEditCppHighlighter highlighter; - this->setCaretLineVisible(true); - this->setCaretLineBackgroundColor(QColor(0xCCFFFF)); - this->setMatchedBraceForegroundColor(QColor("Red")); - - - this->setBraceMatching(BraceMatch::SloppyBraceMatch); - //行号显示区域 - setMarginType(LineNumberMargin, QsciScintilla::NumberMargin); - setMarginLineNumbers(LineNumberMargin, true); - setMarginWidth(LineNumberMargin,10); - this->onLinesChanged(0,0); - //断点设置区域 - setMarginType(MarkerMargin, QsciScintilla::SymbolMargin); - setMarginLineNumbers(MarkerMargin, false); - setMarginWidth(MarkerMargin,20); - setMarginSensitivity(MarkerMargin, true); //set the margin as a selection margin, which is clickable - -// connect(textEdit, SIGNAL(marginClicked(int, int, Qt::KeyboardModifiers)),this, -// SLOT(on_margin_clicked(int, int, Qt::KeyboardModifiers))); - - //markers -// markerDefine(QsciScintilla::CircledPlus, ErrorMarker); -// setMarkerForegroundColor(QColor("BLACK"),ErrorMarker); -// setMarkerBackgroundColor(QColor("RED"),ErrorMarker); -// markerAdd(1,ErrorMarker); - - // connect will fail if use new function pointer syntax -// connect(this, &QsciScintilla::modificationChanged, -// this, &Editor::onModificationChanged); -// connect(this , &QsciScintilla::cursorPositionChanged, -// this, &Editor::onCursorPositionChanged); - connect(this,SIGNAL(modificationChanged(bool)), - this,SLOT(onModificationChanged(bool))); - connect(this , SIGNAL(cursorPositionChanged(int,int)), - this, SLOT(onCursorPositionChanged(int,int))); - connect(this, SIGNAL(linesChanged(int,int)), - this,SLOT(onLinesChanged(int, int))); } @@ -115,75 +71,77 @@ Editor::~Editor() { } this->setParent(0); - delete this->lexer(); - this->setLexer(NULL); } void Editor::loadFile() { QFile file(mFilename); - if (!file.open(QFile::ReadOnly)) { - QMessageBox::information(pMainWindow, - tr("Error"), - QString(tr("Can't Open File %1:%2")).arg(mFilename).arg(file.errorString())); - } - QByteArray content=file.readAll(); - file.close(); - if (mEncodingOption == ENCODING_AUTO_DETECT) { - mFileEncoding = GuessTextEncoding(content); - } else { - mFileEncoding = mEncodingOption; - } - if (mFileEncoding == ENCODING_UTF8) { - this->setText(QString::fromUtf8(content)); - } else if (mFileEncoding == ENCODING_UTF8_BOM) { - this->setText(QString::fromUtf8(content.mid(3))); - } else if (mFileEncoding == ENCODING_ASCII) { - this->setText(QString::fromLatin1(content)); - } else if (mFileEncoding == ENCODING_SYSTEM_DEFAULT) { - this->setText(QString::fromLocal8Bit(content)); - }else { - QTextCodec*codec = QTextCodec::codecForName(mFileEncoding); - this->setText(codec->toUnicode(content)); - } +// if (!file.open(QFile::ReadOnly)) { +// QMessageBox::information(pMainWindow, +// tr("Error"), +// QString(tr("Can't Open File %1:%2")).arg(mFilename).arg(file.errorString())); +// } + this->lines()->LoadFromFile(file,mEncodingOption,mFileEncoding); +// QByteArray content=file.readAll(); +// file.close(); +// if (mEncodingOption == ENCODING_AUTO_DETECT) { +// mFileEncoding = GuessTextEncoding(content); +// } else { +// mFileEncoding = mEncodingOption; +// } +// if (mFileEncoding == ENCODING_UTF8) { +// this->lines()->load +// this->setText(QString::fromUtf8(content)); +// } else if (mFileEncoding == ENCODING_UTF8_BOM) { +// this->setText(QString::fromUtf8(content.mid(3))); +// } else if (mFileEncoding == ENCODING_ASCII) { +// this->setText(QString::fromLatin1(content)); +// } else if (mFileEncoding == ENCODING_SYSTEM_DEFAULT) { +// this->setText(QString::fromLocal8Bit(content)); +// }else { +// QTextCodec*codec = QTextCodec::codecForName(mFileEncoding); +// this->setText(codec->toUnicode(content)); +// } } void Editor::saveFile(const QString &filename) { - if (mEncodingOption!=ENCODING_AUTO_DETECT && mEncodingOption!=mFileEncoding) { - mFileEncoding = mEncodingOption; - } - if (mEncodingOption == ENCODING_AUTO_DETECT && mFileEncoding == ENCODING_ASCII) { - if (!isTextAllAscii(this->text())) { - mFileEncoding = pSettings->editor().defaultEncoding(); - } - pMainWindow->updateStatusBarForEncoding(); - //todo: update status bar, and set fileencoding using configurations - } +// if (mEncodingOption!=ENCODING_AUTO_DETECT && mEncodingOption!=mFileEncoding) { +// mFileEncoding = mEncodingOption; +// } +// if (mEncodingOption == ENCODING_AUTO_DETECT && mFileEncoding == ENCODING_ASCII) { +// if (!isTextAllAscii(this->text())) { +// mFileEncoding = pSettings->editor().defaultEncoding(); +// } +// pMainWindow->updateStatusBarForEncoding(); +// //todo: update status bar, and set fileencoding using configurations +// } QFile file(filename); - QByteArray ba; - if (mFileEncoding == ENCODING_UTF8) { - ba = this->text().toUtf8(); - } else if (mFileEncoding == ENCODING_UTF8_BOM) { - ba.resize(3); - ba[0]=0xEF; - ba[1]=0xBB; - ba[2]=0xBF; - ba.append(this->text().toUtf8()); - } else if (mFileEncoding == ENCODING_ASCII) { - ba = this->text().toLatin1(); - } else if (mFileEncoding == ENCODING_SYSTEM_DEFAULT) { - ba = this->text().toLocal8Bit(); - } else { - QTextCodec* codec = QTextCodec::codecForName(mFileEncoding); - ba = codec->fromUnicode(this->text()); - } - if (file.open(QFile::WriteOnly)) { - if (file.write(ba)<0) { - throw SaveException(QString(tr("Failed to Save file %1: %2")).arg(filename).arg(file.errorString())); - } - file.close(); - } else { - throw SaveException(QString(tr("Failed to Open file %1: %2")).arg(filename).arg(file.errorString())); - } + this->lines()->SaveToFile(file,mEncodingOption,mFileEncoding); + pMainWindow->updateStatusBarForEncoding(); +// QByteArray ba; +// if (mFileEncoding == ENCODING_UTF8) { +// ba = this->text().toUtf8(); +// } else if (mFileEncoding == ENCODING_UTF8_BOM) { +// ba.resize(3); +// ba[0]=0xEF; +// ba[1]=0xBB; +// ba[2]=0xBF; +// ba.append(this->text().toUtf8()); +// } else if (mFileEncoding == ENCODING_ASCII) { +// ba = this->text().toLatin1(); +// } else if (mFileEncoding == ENCODING_SYSTEM_DEFAULT) { +// ba = this->text().toLocal8Bit(); +// } else { +// QTextCodec* codec = QTextCodec::codecForName(mFileEncoding); +// ba = codec->fromUnicode(this->text()); +// } +// if (file.open(QFile::WriteOnly)) { +// if (file.write(ba)<0) { +// throw SaveException(QString(tr("Failed to Save file %1: %2")).arg(filename).arg(file.errorString())); +// } +// file.close(); +// } else { +// throw SaveException(QString(tr("Failed to Open file %1: %2")).arg(filename).arg(file.errorString())); +// } } bool Editor::save(bool force, bool reparse) { @@ -197,7 +155,7 @@ bool Editor::save(bool force, bool reparse) { QString(QObject::tr("File %s is not writable!"))); return false; } - if (this->isModified() || force) { + if (this->modified()|| force) { try { saveFile(mFilename); setModified(false); @@ -272,10 +230,18 @@ QTabWidget* Editor::pageControl() noexcept{ void Editor::wheelEvent(QWheelEvent *event) { if ( (event->modifiers() & Qt::ControlModifier)!=0) { + QFont oldFont = font(); + int size = oldFont.pointSize(); if (event->angleDelta().y()>0) { - this->zoomIn(); + size = std::max(5,size-1); + oldFont.setPointSize(oldFont.pointSize()); + this->setFont(oldFont); + //this->zoomIn(); } else { - this->zoomOut(); + size = std::min(size+1,50); + oldFont.setPointSize(oldFont.pointSize()); + this->setFont(oldFont); + //this->zoomOut(); } onLinesChanged(0,0); } @@ -286,18 +252,12 @@ void Editor::onModificationChanged(bool) { } void Editor::onCursorPositionChanged(int line, int index) { - pMainWindow->updateStatusBarForEditingInfo(line,index+1,lines(),text().length()); - long pos = getCursorPosition(); - long start = SendScintilla(SCI_WORDSTARTPOSITION,pos,false); - long end = SendScintilla(SCI_WORDENDPOSITION,pos,false); - long style = SendScintilla(SCI_GETSTYLEAT,pos,false); + pMainWindow->updateStatusBarForEditingInfo(line,index+1,lines()->count(),lines()->getTextLength()); - qDebug()<setMarginWidth(0,QString("0%1").arg(lines())); - qDebug()<<"Editor lines changed"<count(); qDebug()<isModified()) { + if (this->modified()) { caption.append("[*]"); } mParentPageControl->setTabText(index,caption); diff --git a/RedPandaIDE/editor.h b/RedPandaIDE/editor.h index 7e70c526..c287ac40 100644 --- a/RedPandaIDE/editor.h +++ b/RedPandaIDE/editor.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include "qsynedit/SynEdit.h" class SaveException: public std::exception { @@ -19,7 +19,7 @@ private: QString mReason; }; -class Editor : public QsciScintilla +class Editor : public SynEdit { Q_OBJECT public: diff --git a/RedPandaIDE/editorlist.cpp b/RedPandaIDE/editorlist.cpp index e282386c..bc6daba8 100644 --- a/RedPandaIDE/editorlist.cpp +++ b/RedPandaIDE/editorlist.cpp @@ -66,7 +66,7 @@ bool EditorList::closeEditor(Editor* editor, bool transferFocus, bool force) { return false; if (force) { editor->save(true,false); - } else if ( (editor->isModified()) && (!editor->text().isEmpty())) { + } else if ( (editor->modified()) && (!editor->empty())) { // ask user if he wants to save QMessageBox::StandardButton reply; reply = QMessageBox::question(pMainWindow,QObject::tr("Save"), diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 7aabd363..117fdba5 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -210,7 +210,7 @@ void MainWindow::on_actionUndo_triggered() { Editor * editor = mEditorList->getEditor(); if (editor != NULL ) { - editor->undo(); + //editor->undo(); } } @@ -218,7 +218,7 @@ void MainWindow::on_actionRedo_triggered() { Editor * editor = mEditorList->getEditor(); if (editor != NULL ) { - editor->redo(); + //editor->redo(); } } @@ -226,7 +226,7 @@ void MainWindow::on_actionCut_triggered() { Editor * editor = mEditorList->getEditor(); if (editor != NULL ) { - editor->cut(); + //editor->cut(); } } @@ -234,7 +234,7 @@ void MainWindow::on_actionSelectAll_triggered() { Editor * editor = mEditorList->getEditor(); if (editor != NULL ) { - editor->selectAll(); + //editor->selectAll(); } } @@ -242,7 +242,7 @@ void MainWindow::on_actionCopy_triggered() { Editor * editor = mEditorList->getEditor(); if (editor != NULL ) { - editor->copy(); + //editor->copy(); } } @@ -250,7 +250,7 @@ void MainWindow::on_actionPaste_triggered() { Editor * editor = mEditorList->getEditor(); if (editor != NULL ) { - editor->paste(); + //editor->paste(); } } @@ -258,7 +258,7 @@ void MainWindow::on_actionIndent_triggered() { Editor * editor = mEditorList->getEditor(); if (editor != NULL ) { - editor->indent(); + //editor->indent(); } } @@ -266,7 +266,7 @@ void MainWindow::on_actionUnIndent_triggered() { Editor * editor = mEditorList->getEditor(); if (editor != NULL ) { - editor->unindent(); + //editor->unindent(); } } @@ -274,7 +274,7 @@ void MainWindow::on_actionToggleComment_triggered() { Editor * editor = mEditorList->getEditor(); if (editor != NULL ) { - editor->toggleComment(); + //editor->toggleComment(); } } @@ -282,7 +282,7 @@ void MainWindow::on_actionUnfoldAll_triggered() { Editor * editor = mEditorList->getEditor(); if (editor != NULL ) { - editor->clearFolds(); + //editor->clearFolds(); } } @@ -290,8 +290,8 @@ void MainWindow::on_actionFoldAll_triggered() { Editor * editor = mEditorList->getEditor(); if (editor != NULL ) { - editor->clearFolds(); - editor->foldAll(); + //editor->clearFolds(); + //editor->foldAll(); } } @@ -305,6 +305,6 @@ void MainWindow::on_tableIssues_doubleClicked(const QModelIndex &index) if (editor == nullptr) return; - editor->setCursorPosition(issue->line-1,issue->column-1); + //editor->setCursorPosition(issue->line-1,issue->column-1); editor->activate(); } diff --git a/RedPandaIDE/qsynedit/KeyStrokes.cpp b/RedPandaIDE/qsynedit/KeyStrokes.cpp index 60d2728d..12a28fc1 100644 --- a/RedPandaIDE/qsynedit/KeyStrokes.cpp +++ b/RedPandaIDE/qsynedit/KeyStrokes.cpp @@ -1,4 +1,5 @@ #include "KeyStrokes.h" +#include SynEditKeyStroke::SynEditKeyStroke() { @@ -88,10 +89,19 @@ SynKeyError::SynKeyError(const QString &reason):BaseError(reason) PSynEditKeyStroke SynEditKeyStrokes::add(SynEditorCommand command, int key, Qt::KeyboardModifiers modifiers) { - PSynEditKeyStroke keyStroke = std::make_shared(); - keyStroke->setKey(key); - keyStroke->setKeyModifiers(modifiers); - keyStroke->setCommand(command); +// qDebug()<<"add : 1" ; +// qDebug() << (int)command; +//// PSynEditKeyStroke keyStroke = std::make_shared(); +//// qDebug()<<"add : 2"; +//// keyStroke->setKey(key); +//// qDebug()<<"add : 3"; +//// keyStroke->setKeyModifiers(modifiers); +//// qDebug()<<"add : 4"; +//// keyStroke->setCommand(command); +// qDebug()<<"add : 5"; +// //mList.append(keyStroke); +// qDebug()<<"add : 6"; + } PSynEditKeyStroke SynEditKeyStrokes::findCommand(SynEditorCommand command) @@ -156,18 +166,33 @@ void SynEditKeyStrokes::clear() void SynEditKeyStrokes::resetDefaults() { + return; + qDebug()<<"SynEditKeyStrokes: resetDefaults "; + qDebug()<<"SynEditKeyStrokes: resetDefaults: clear "; clear(); + qDebug()<<"SynEditKeyStrokes: resetDefaults: add start "; add(SynEditorCommand::ecUp, Qt::Key_Up, Qt::NoModifier); + qDebug()<<"SynEditKeyStrokes: resetDefaults: add start 0"; add(SynEditorCommand::ecSelUp, Qt::Key_Up, Qt::ShiftModifier); + qDebug()<<"SynEditKeyStrokes: resetDefaults: add start 01"; add(SynEditorCommand::ecScrollUp, Qt::Key_Up, Qt::ControlModifier); + qDebug()<<"SynEditKeyStrokes: resetDefaults: add start 02"; add(SynEditorCommand::ecDown, Qt::Key_Down, Qt::NoModifier); + qDebug()<<"SynEditKeyStrokes: resetDefaults: add start 03"; add(SynEditorCommand::ecSelDown, Qt::Key_Down, Qt::ShiftModifier); + qDebug()<<"SynEditKeyStrokes: resetDefaults: add start 04"; add(SynEditorCommand::ecScrollDown, Qt::Key_Down, Qt::ControlModifier); + qDebug()<<"SynEditKeyStrokes: resetDefaults: add start 05"; add(SynEditorCommand::ecLeft, Qt::Key_Left, Qt::NoModifier); + qDebug()<<"SynEditKeyStrokes: resetDefaults: add start 06"; add(SynEditorCommand::ecSelLeft, Qt::Key_Left, Qt::ShiftModifier); add(SynEditorCommand::ecWordLeft, Qt::Key_Left, Qt::ControlModifier); + qDebug()<<"SynEditKeyStrokes: resetDefaults: add start 1"; add(SynEditorCommand::ecSelWordLeft, Qt::Key_Left, Qt::ShiftModifier|Qt::ControlModifier); + qDebug()<<"SynEditKeyStrokes: resetDefaults: add start 2 "; add(SynEditorCommand::ecRight, Qt::Key_Right, Qt::NoModifier); + qDebug()<<"SynEditKeyStrokes: resetDefaults: add start 3"; + add(SynEditorCommand::ecSelRight, Qt::Key_Right, Qt::ShiftModifier); add(SynEditorCommand::ecWordRight, Qt::Key_Right, Qt::ControlModifier); add(SynEditorCommand::ecSelWordRight, Qt::Key_Right, Qt::ShiftModifier|Qt::ControlModifier); @@ -240,4 +265,5 @@ void SynEditKeyStrokes::resetDefaults() add(SynEditorCommand::ecColumnSelect, Qt::Key_C, Qt::ControlModifier | Qt::ShiftModifier); add(SynEditorCommand::ecLineSelect, Qt::Key_L, Qt::ControlModifier | Qt::ShiftModifier); add(SynEditorCommand::ecMatchBracket, Qt::Key_B, Qt::ControlModifier | Qt::ShiftModifier); + qDebug()<<"SynEditKeyStrokes: resetDefaults: add end "; } diff --git a/RedPandaIDE/qsynedit/KeyStrokes.h b/RedPandaIDE/qsynedit/KeyStrokes.h index 0f4d058d..08c111ae 100644 --- a/RedPandaIDE/qsynedit/KeyStrokes.h +++ b/RedPandaIDE/qsynedit/KeyStrokes.h @@ -219,6 +219,7 @@ public: PSynEditKeyStroke findKeySequence(const QKeySequence& keySeq); void clear(); void resetDefaults(); +private: SynEditKeyStrokeList mList; }; diff --git a/RedPandaIDE/qsynedit/SynEdit.cpp b/RedPandaIDE/qsynedit/SynEdit.cpp index 5ede4fad..1fb681ae 100644 --- a/RedPandaIDE/qsynedit/SynEdit.cpp +++ b/RedPandaIDE/qsynedit/SynEdit.cpp @@ -5,15 +5,21 @@ #include #include #include +#include +#include #include "highlighter/base.h" #include "Constants.h" +#include "TextPainter.h" +#include SynEdit::SynEdit(QWidget *parent) : QAbstractScrollArea(parent) { + qDebug()<<"init SynEdit:"; mPaintLock = 0; mPainterLock = 0; mPainting = false; - mLines = std::make_shared(); + mLines = std::make_shared(this); + qDebug()<<"init SynEdit: 1"; mOrigLines = mLines; //fPlugins := TList.Create; mMouseMoved = false; @@ -24,6 +30,8 @@ SynEdit::SynEdit(QWidget *parent) : QAbstractScrollArea(parent) mLines->connect(mLines.get(), &SynEditStringList::deleted, this, &SynEdit::linesDeleted); mLines->connect(mLines.get(), &SynEditStringList::inserted, this, &SynEdit::linesInserted); mLines->connect(mLines.get(), &SynEditStringList::putted, this, &SynEdit::linesPutted); + qDebug()<<"init SynEdit: 2"; + #ifdef Q_OS_WIN mFontDummy = QFont("Consolas",10); #elif Q_OS_LINUX @@ -31,12 +39,17 @@ SynEdit::SynEdit(QWidget *parent) : QAbstractScrollArea(parent) #else #error "Not supported!" #endif + setFont(mFontDummy); + qDebug()<<"init SynEdit:3"; + mUndoList = std::make_shared(); mUndoList->connect(mUndoList.get(), &SynEditUndoList::addedUndo, this, &SynEdit::undoAdded); mOrigUndoList = mUndoList; mRedoList = std::make_shared(); mRedoList->connect(mRedoList.get(), &SynEditUndoList::addedUndo, this, &SynEdit::redoAdded); mOrigRedoList = mRedoList; + qDebug()<<"init SynEdit: 4"; + //DoubleBuffered = false; mActiveLineColor = QColor(); mSelectedBackground = QColor(); @@ -45,6 +58,8 @@ SynEdit::SynEdit(QWidget *parent) : QAbstractScrollArea(parent) mBookMarkOpt.connect(&mBookMarkOpt, &SynBookMarkOpt::changed, this, &SynEdit::bookMarkOptionsChanged); // fRightEdge has to be set before FontChanged is called for the first time mRightEdge = 80; + qDebug()<<"init SynEdit: 5"; + mGutter.setRightOffset(21); mGutter.connect(&mGutter, &SynGutter::changed, this, &SynEdit::gutterChanged); mGutterWidth = mGutter.width(); @@ -57,6 +72,9 @@ SynEdit::SynEdit(QWidget *parent) : QAbstractScrollArea(parent) mInserting = true; mMaxScrollWidth = 1024; mScrollBars = SynScrollStyle::ssBoth; + mExtraLineSpacing = 0; + qDebug()<<"init SynEdit: 6"; + this->setFrameShape(QFrame::Panel); this->setFrameShadow(QFrame::Sunken); this->setLineWidth(1); @@ -64,13 +82,19 @@ SynEdit::SynEdit(QWidget *parent) : QAbstractScrollArea(parent) mOverwriteCaret = SynEditCaretType::ctBlock; mSelectionMode = SynSelectionMode::smNormal; mActiveSelectionMode = SynSelectionMode::smNormal; + qDebug()<<"init SynEdit: 7"; + //stop qt to auto fill background setAutoFillBackground(false); //fFocusList := TList.Create; //fKbdHandler := TSynEditKbdHandler.Create; //fMarkList.OnChange := MarkListChange; + qDebug()<<"init SynEdit: 7-1"; setDefaultKeystrokes(); + qDebug()<<"init SynEdit: 7-2"; mRightEdgeColor = QColorConstants::Svg::silver; + qDebug()<<"init SynEdit: 8"; + /* IME input */ mImeCount = 0; mMBCSStepAside = false; @@ -89,6 +113,8 @@ SynEdit::SynEdit(QWidget *parent) : QAbstractScrollArea(parent) mOptions = eoAutoIndent | eoDragDropEditing | eoEnhanceEndKey | eoScrollPastEol | eoShowScrollHint | eoSmartTabs | eoTabsToSpaces | eoSmartTabDelete| eoGroupUndo; + qDebug()<<"init SynEdit: 9"; + mScrollTimer = new QTimer(this); mScrollTimer->setInterval(100); connect(mScrollTimer, &QTimer::timeout,this, &SynEdit::scrollTimerHandler); @@ -96,16 +122,28 @@ SynEdit::SynEdit(QWidget *parent) : QAbstractScrollArea(parent) mScrollHintColor = QColorConstants::Yellow; mScrollHintFormat = SynScrollHintFormat::shfTopLineOnly; + mContentImage = std::make_shared(clientWidth(),clientHeight(),QImage::Format_ARGB32); + + m_blinkTimerId = 0; + m_bliknStatus = 0; + qDebug()<<"init SynEdit: 10"; + synFontChanged(); + qDebug()<<"init SynEdit: done"; + } int SynEdit::displayLineCount() { + if (mLines->empty()) { + return 0; + } return lineToRow(mLines->count()); } DisplayCoord SynEdit::displayXY() { + qDebug()<<"displayXY"<count()) { + if (aLine <= mLines->count()) { QString s = mLines->getString(aLine - 1); int l = s.length(); int x = 0; @@ -376,6 +424,7 @@ int SynEdit::charToColumn(int aLine, int aChar) } return x+1; } + qDebug()<<"Line outof range"<= iScrollBounds.right()) - mScrollDeltaX = (X - iScrollBounds.right()) % mCharWidth + 1; + mScrollDeltaX = (X - iScrollBounds.right()) / mCharWidth + 1; else mScrollDeltaX = 0; if (Y < iScrollBounds.top()) - mScrollDeltaY = (Y - iScrollBounds.top()) % mTextHeight - 1; + mScrollDeltaY = (Y - iScrollBounds.top()) / mTextHeight - 1; else if (Y >= iScrollBounds.bottom()) - mScrollDeltaY = (Y - iScrollBounds.bottom()) % mTextHeight + 1; + mScrollDeltaY = (Y - iScrollBounds.bottom()) / mTextHeight + 1; else mScrollDeltaY = 0; @@ -940,7 +1003,8 @@ void SynEdit::updateScrollbars() void SynEdit::updateCaret() { mStateFlags.setFlag(SynStateFlag::sfCaretChanged,false); - //do nothing, because we will draw cursor in the paintEvent + //do nothing. Because our caret timer will update the caret periodically +// invalidateRect(QRect(0,0,1,1)); //we use a rect of 1-width & 1-height to signal the paintEvent that we only want to redraw the caret } void SynEdit::recalcCharExtent() @@ -1003,6 +1067,8 @@ void SynEdit::recalcCharExtent() mCharWidth = fm.horizontalAdvance("M"); } mTextHeight += mExtraLineSpacing; + mCharWidth = mCharWidth * dpiFactor(); + mTextHeight = mTextHeight * dpiFactor(); } QString SynEdit::expandAtWideGlyphs(const QString &S) @@ -1352,10 +1418,22 @@ PSynEditFoldRange SynEdit::foldAroundLine(int Line) PSynEditFoldRange SynEdit::foldAroundLineEx(int Line, bool WantCollapsed, bool AcceptFromLine, bool AcceptToLine) { + // Check global list + PSynEditFoldRange Result = checkFoldRange(&mAllFoldRanges, Line, WantCollapsed, AcceptFromLine, AcceptToLine); + // Found an item in the top level list? + if (Result) { + while (true) { + PSynEditFoldRange ResultChild = checkFoldRange(Result->subFoldRanges.get(), Line, WantCollapsed, AcceptFromLine, AcceptToLine); + if (!ResultChild) + break; + Result = ResultChild; // repeat for this one + } + } + return Result; } -PSynEditFoldRange SynEdit::CheckFoldRange(PSynEditFoldRanges FoldRangeToCheck, int Line, bool WantCollapsed, bool AcceptFromLine, bool AcceptToLine) +PSynEditFoldRange SynEdit::checkFoldRange(SynEditFoldRanges *FoldRangeToCheck, int Line, bool WantCollapsed, bool AcceptFromLine, bool AcceptToLine) { for (int i = 0; i< FoldRangeToCheck->count(); i++) { PSynEditFoldRange range = (*FoldRangeToCheck)[i]; @@ -1369,8 +1447,50 @@ PSynEditFoldRange SynEdit::CheckFoldRange(PSynEditFoldRanges FoldRangeToCheck, i return PSynEditFoldRange(); } +PSynEditFoldRange SynEdit::foldEndAtLine(int Line) +{ + for (int i = 0; itoLine == Line ){ + return range; + } else if (range->fromLine>Line) + break; // sorted by line. don't bother scanning further + } + return PSynEditFoldRange(); +} + +void SynEdit::paintCaret(QPainter &painter, const QRect rcClip) +{ + if (m_bliknStatus!=1) + return; + SynEditCaretType ct; + if (this->mInserting) { + ct = mInsertCaret; + } else { + ct =mOverwriteCaret; + } + painter.setPen(QColorConstants::Svg::red); + painter.setBrush(QColorConstants::Svg::red); + switch(ct) { + case SynEditCaretType::ctVerticalLine: + painter.drawLine(rcClip.left()+1,rcClip.top(),rcClip.left()+1,rcClip.bottom()); + break; + case SynEditCaretType::ctHorizontalLine: + painter.drawLine(rcClip.left(),rcClip.bottom()-1,rcClip.right(),rcClip.bottom()-1); + break; + case SynEditCaretType::ctBlock: + painter.drawRect(rcClip); + break; + case SynEditCaretType::ctHalfBlock: + QRect rc=rcClip; + rc.setTop(rcClip.top()+rcClip.height() / 2); + + } +} + void SynEdit::sizeOrFontChanged(bool bFont) { + if (mCharWidth != 0) { mCharsInWindow = std::max(clientWidth() - mGutterWidth - 2, 0) / mCharWidth; mLinesInWindow = clientHeight() / mTextHeight; @@ -1397,17 +1517,42 @@ void SynEdit::doChange() emit Changed(); } +PSynEditStringList SynEdit::lines() const +{ + return mLines; +} + int SynEdit::tabWidth() const { return mTabWidth; } -bool SynEdit::onSpecialLineColors(int, QColor &, QColor &) +bool SynEdit::empty() +{ + return mLines->empty(); +} + +bool SynEdit::onGetSpecialLineColors(int, QColor &, QColor &) { } -void SynEdit::onEditingAreas(int, SynEditingAreaList &) +void SynEdit::onGetEditingAreas(int, SynEditingAreaList &) +{ + +} + +void SynEdit::onGutterGetText(int aLine, QString &aText) +{ + +} + +void SynEdit::onGutterPaint(QPainter &painter, int aLine, int X, int Y) +{ + +} + +void SynEdit::onPaint(QPainter &) { } @@ -1419,45 +1564,114 @@ void SynEdit::paintEvent(QPaintEvent *event) if (mPainting) return; mPainting = true; - QRect rcClip, rcDraw; - int nL1, nL2, nC1, nC2; - // Get the invalidated rect. Compute the invalid area in lines / columns. - rcClip = event->rect(); - // columns - nC1 = mLeftChar; - if (rcClip.left() > mGutterWidth + 2 ) - nC1 += (rcClip.left() - mGutterWidth - 2 ) % mCharWidth; - nC2 = mLeftChar + - (rcClip.right() - mGutterWidth - 2 + mCharWidth - 1) % mCharWidth; - // lines - nL1 = MinMax(mTopLine + rcClip.top() % mTextHeight, mTopLine, displayLineCount()); - nL2 = MinMax(mTopLine + (rcClip.bottom() + mTextHeight - 1) % mTextHeight, 1, displayLineCount()); // Now paint everything while the caret is hidden. + QPainter painter(viewport()); hideCaret(); - auto action = finally([this] { - updateCaret(); + //Get the invalidated rect. + QRect rcClip = event->rect(); + DisplayCoord coord = displayXY(); + QPoint caretPos = RowColumnToPixels(coord); + int caretWidth=mCharWidth; + if (mCaretY <= mLines->count() && mCaretX <= mLines->getString(mCaretY-1).length()) { + caretWidth = charColumns(mLines->getString(mCaretY-1)[mCaretX-1])*mCharWidth; + } + QRect rcCaret(caretPos.x(),caretPos.y(),caretWidth, + mTextHeight); + + qDebug()<<"Painting"; + qDebug()<<"Caret rect:"< mGutterWidth ) { - rcDraw = rcClip; - rcDraw.setLeft( std::max(rcDraw.left(), mGutterWidth)); - paintTextLines(rcDraw, nL1, nL2, nC1, nC2); + if (rcClip.width()==1 && rcClip.height()==1) { + // only update caret + // calculate the needed invalid area for caret + painter.drawImage(rcCaret,*mContentImage); + } else { + QRect rcDraw; + int nL1, nL2, nC1, nC2; + // Compute the invalid area in lines / columns. + // columns + nC1 = mLeftChar; + if (rcClip.left() > mGutterWidth + 2 ) + nC1 += (rcClip.left() - mGutterWidth - 2 ) / mCharWidth; + nC2 = mLeftChar + + (rcClip.right() - mGutterWidth - 2 + mCharWidth - 1) / mCharWidth; + // lines + nL1 = MinMax(mTopLine + rcClip.top() / mTextHeight, mTopLine, displayLineCount()); + nL2 = MinMax(mTopLine + (rcClip.bottom() + mTextHeight - 1) / mTextHeight, 1, displayLineCount()); + + + +// QPainter cachePainter(mContentImage.get()); +// SynEditTextPainter textPainter(this, &cachePainter, +// nL1,nL2,nC1,nC2); + SynEditTextPainter textPainter(this, &painter, + nL1,nL2,nC1,nC2); + // First paint paint the text area if it was (partly) invalidated. + if (rcClip.right() > mGutterWidth ) { + rcDraw = rcClip; + rcDraw.setLeft( std::max(rcDraw.left(), mGutterWidth)); + textPainter.paintTextLines(rcDraw); + //paintTextLines(rcDraw, nL1, nL2, nC1, nC2); + } + + // Then the gutter area if it was (partly) invalidated. + if (rcClip.left() < mGutterWidth) { + rcDraw = rcClip; + rcDraw.setRight(mGutterWidth); + //textPainter.paintGutter(rcDraw); + //paintGutter(rcDraw, nL1, nL2); + } + + //PluginsAfterPaint(Canvas, rcClip, nL1, nL2); + // If there is a custom paint handler call it. + //onPaint(cachePainter); + doOnPaintTransient(SynTransientType::ttAfter); + painter.drawImage(rcClip,*mContentImage); } - // Then the gutter area if it was (partly) invalidated. - if (rcClip.left() < mGutterWidth) { - rcDraw = rcClip; - rcDraw.setRight(mGutterWidth); - paintGutter(rcDraw, nL1, nL2); - } +} - //PluginsAfterPaint(Canvas, rcClip, nL1, nL2); - // If there is a custom paint handler call it. - doOnPaint(); - doOnPaintTransient(SynTransientType::ttAfter); +void SynEdit::resizeEvent(QResizeEvent *event) +{ + //resize the cache image + std::shared_ptr image = std::make_shared(clientWidth(),clientHeight(), + QImage::Format_ARGB32); + + QRect newRect = image->rect().intersected(mContentImage->rect()); + + QPainter painter(image.get()); + + painter.drawImage(newRect,*mContentImage); + + mContentImage = image; + + sizeOrFontChanged(false); +} + +void SynEdit::timerEvent(QTimerEvent *event) +{ + if (event->timerId() == m_blinkTimerId) { + m_bliknStatus = 1- m_bliknStatus; + invalidateRect(QRect(0,0,1,1)); + } +} + +bool SynEdit::event(QEvent *event) +{ + switch(event->type()) { + case QEvent::FontChange: + synFontChanged(); + break; + } + QAbstractScrollArea::event(event); } int SynEdit::maxScrollWidth() const @@ -1588,7 +1802,7 @@ void SynEdit::linesInserted(int index, int count) invalidateLines(index + 1, INT_MAX); invalidateGutterLines(index + 1, INT_MAX); if (mOptions.setFlag(SynEditorOption::eoAutoSizeMaxScrollWidth)) { - int L = mLines->expandedStringLength(index); + int L = mLines->lineColumns(index); if (L > mMaxScrollWidth) setMaxScrollWidth(L); } @@ -1607,7 +1821,7 @@ void SynEdit::linesPutted(int index, int) invalidateLines(index + 1, vEndLine); if (mOptions.setFlag(SynEditorOption::eoAutoSizeMaxScrollWidth)) { - int L = mLines->expandedStringLength(index); + int L = mLines->lineColumns(index); if (L > mMaxScrollWidth) setMaxScrollWidth(L); } diff --git a/RedPandaIDE/qsynedit/SynEdit.h b/RedPandaIDE/qsynedit/SynEdit.h index eedb5a14..acd75287 100644 --- a/RedPandaIDE/qsynedit/SynEdit.h +++ b/RedPandaIDE/qsynedit/SynEdit.h @@ -141,6 +141,10 @@ class SynEdit : public QAbstractScrollArea public: explicit SynEdit(QWidget *parent = nullptr); + /** + * @brief how many rows are there in the editor + * @return + */ int displayLineCount(); DisplayCoord displayXY(); int displayX(); @@ -160,6 +164,7 @@ public: void invalidateGutterLines(int FirstLine, int LastLine); DisplayCoord pixelsToNearestRowColumn(int aX, int aY); DisplayCoord pixelsToRowColumn(int aX, int aY); + QPoint RowColumnToPixels(const DisplayCoord& coord); DisplayCoord bufferToDisplayPos(const BufferCoord& p); BufferCoord displayToBufferPos(const DisplayCoord& p); int charToColumn(int aLine, int aChar); @@ -184,6 +189,8 @@ public: void clearUndo(); int charColumns(QChar ch); double dpiFactor(); + void showCaret(); + void hideCaret(); int topLine() const; void setTopLine(int value); @@ -217,6 +224,9 @@ public: int tabWidth() const; + PSynEditStringList lines() const; + bool empty(); + signals: void Changed(); @@ -243,11 +253,13 @@ signals: void tabSizeChanged(); protected: - virtual bool onSpecialLineColors(int Line, + virtual bool onGetSpecialLineColors(int Line, QColor& foreground, QColor& backgroundColor) ; - virtual void onEditingAreas(int Line, SynEditingAreaList& areaList); + virtual void onGetEditingAreas(int Line, SynEditingAreaList& areaList); virtual void onGutterGetText(int aLine, QString& aText); - virtual void onGutterPaint(int aLine, int X, int Y); + virtual void onGutterPaint(QPainter& painter, int aLine, int X, int Y); + virtual void onPaint(QPainter& painter); + @@ -301,7 +313,9 @@ private: QString substringByColumns(const QString& s, int startColumn, int& colLen); PSynEditFoldRange foldAroundLine(int Line); PSynEditFoldRange foldAroundLineEx(int Line, bool WantCollapsed, bool AcceptFromLine, bool AcceptToLine); - PSynEditFoldRange CheckFoldRange(PSynEditFoldRanges FoldRangeToCheck,int Line, bool WantCollapsed, bool AcceptFromLine, bool AcceptToLine); + PSynEditFoldRange checkFoldRange(SynEditFoldRanges* FoldRangeToCheck,int Line, bool WantCollapsed, bool AcceptFromLine, bool AcceptToLine); + PSynEditFoldRange foldEndAtLine(int Line); + void paintCaret(QPainter& painter, const QRect rcClip); private slots: void bookMarkOptionsChanged(); @@ -319,6 +333,7 @@ private slots: void doChange(); private: + std::shared_ptr mContentImage; SynEditFoldRanges mAllFoldRanges; SynEditCodeFolding mCodeFolding; bool mUseCodeFolding; @@ -431,6 +446,18 @@ protected: void paintEvent(QPaintEvent *event) override; friend class SynEditTextPainter; + +// QWidget interface +protected: +void resizeEvent(QResizeEvent *event) override; + +// QObject interface +protected: +void timerEvent(QTimerEvent *event) override; + +// QObject interface +public: +bool event(QEvent *event) override; }; #endif // SYNEDIT_H diff --git a/RedPandaIDE/qsynedit/TextBuffer.cpp b/RedPandaIDE/qsynedit/TextBuffer.cpp index 0ca7fdba..72d87930 100644 --- a/RedPandaIDE/qsynedit/TextBuffer.cpp +++ b/RedPandaIDE/qsynedit/TextBuffer.cpp @@ -108,6 +108,16 @@ void SynEditStringList::InsertItem(int Index, const QString &s) endUpdate(); } +void SynEditStringList::addItem(const QString &s) +{ + beginUpdate(); + PSynEditStringRec line = std::make_shared(); + line->fString = s; + mIndexOfLongestLine = -1; + mList.append(line); + endUpdate(); +} + ConvertTabsProcEx SynEditStringList::getConvertTabsProc() const { return mConvertTabsProc; @@ -232,7 +242,7 @@ int SynEditStringList::addStrings(const QStringList &Strings) int FirstAdded = mList.count(); for (const QString& s:Strings) { - add(s); + addItem(s); } emit inserted(FirstAdded,Strings.count()); } @@ -439,8 +449,8 @@ void SynEditStringList::LoadFromFile(QFile &file, const QByteArray& encoding, QB { if (!file.open(QFile::ReadOnly | QFile::Text)) throw FileError(tr("Can't open file '%1' for read!").arg(file.fileName())); - if (!file.canReadLine()) - throw FileError(tr("Can't read from file '%1'!").arg(file.fileName())); +// if (!file.canReadLine()) +// throw FileError(tr("Can't read from file '%1'!").arg(file.fileName())); beginUpdate(); auto action = finally([this]{ endUpdate(); @@ -448,16 +458,16 @@ void SynEditStringList::LoadFromFile(QFile &file, const QByteArray& encoding, QB //test for utf8 / utf 8 bom if (encoding == ENCODING_AUTO_DETECT) { - QByteArray line = file.readLine(); - QTextCodec* codec; - QTextCodec::ConverterState * state; - bool needReread = false; - bool allAscii = true; - //test for BOM - if (line.isEmpty()) { + if (file.atEnd()) { realEncoding = ENCODING_ASCII; return; } + QByteArray line = file.readLine(); + QTextCodec* codec; + QTextCodec::ConverterState state; + bool needReread = false; + bool allAscii = true; + //test for BOM if ((line.length()>=3) && ((unsigned char)line[0]==0xEF) && ((unsigned char)line[1]==0xBB) && ((unsigned char)line[2]==0xBF) ) { realEncoding = ENCODING_UTF8_BOM; line = line.mid(3); @@ -472,14 +482,14 @@ void SynEditStringList::LoadFromFile(QFile &file, const QByteArray& encoding, QB allAscii = isTextAllAscii(line); } if (allAscii) { - add(QString::fromLatin1(line)); + addItem(removeLineEnds(QString::fromLatin1(line))); } else { - QString newLine = codec->toUnicode(line.constData(),line.length(),state); - if (state->invalidChars>0) { + QString newLine = codec->toUnicode(line.constData(),line.length(),&state); + if (state.invalidChars>0) { needReread = true; break; } - add(newLine); + addItem(removeLineEnds(newLine)); } line = file.readLine(); } while (!file.atEnd()); @@ -508,7 +518,7 @@ void SynEditStringList::LoadFromFile(QFile &file, const QByteArray& encoding, QB QString line; clear(); while (textStream.readLineInto(&line)) { - add(line); + addItem(removeLineEnds(line)); } } @@ -525,7 +535,7 @@ void SynEditStringList::SaveToFile(QFile &file, const QByteArray& encoding, QByt QTextCodec* codec; if (realEncoding == ENCODING_UTF8_BOM) { codec = QTextCodec::codecForName(ENCODING_UTF8_BOM); - } else if (realEncoding == ENCODING_ASCII) { + } else if (realEncoding == ENCODING_SYSTEM_DEFAULT) { codec = QTextCodec::codecForLocale(); } for (PSynEditStringRec& line:mList) { @@ -592,6 +602,11 @@ void SynEditStringList::setFileEndingType(const FileEndingType &fileEndingType) mFileEndingType = fileEndingType; } +bool SynEditStringList::empty() +{ + return count()==0; +} + void SynEditStringList::invalidAllLineColumns() { mIndexOfLongestLine = -1; diff --git a/RedPandaIDE/qsynedit/TextBuffer.h b/RedPandaIDE/qsynedit/TextBuffer.h index 7ab67e3e..14f57634 100644 --- a/RedPandaIDE/qsynedit/TextBuffer.h +++ b/RedPandaIDE/qsynedit/TextBuffer.h @@ -95,6 +95,8 @@ public: FileEndingType getFileEndingType() const; void setFileEndingType(const FileEndingType &fileEndingType); + + bool empty(); public slots: void invalidAllLineColumns(); @@ -109,6 +111,7 @@ protected: QString GetTextStr(); void SetUpdateState(bool Updating); void InsertItem(int Index, const QString& s); + void addItem(const QString& s); void PutTextStr(const QString& text); private: diff --git a/RedPandaIDE/qsynedit/TextPainter.cpp b/RedPandaIDE/qsynedit/TextPainter.cpp index 464b05fb..c8192bcc 100644 --- a/RedPandaIDE/qsynedit/TextPainter.cpp +++ b/RedPandaIDE/qsynedit/TextPainter.cpp @@ -2,10 +2,12 @@ #include "SynEdit.h" #include "Constants.h" #include +#include -SynEditTextPainter::SynEditTextPainter(SynEdit *edit, int FirstRow, int LastRow, int FirstCol, int LastCol) +SynEditTextPainter::SynEditTextPainter(SynEdit *edit, QPainter *painter, int FirstRow, int LastRow, int FirstCol, int LastCol) { this->edit = edit; + this->painter = painter; this->aFirstRow = FirstRow; this->aLastRow = LastRow; this->FirstCol = FirstCol; @@ -75,20 +77,12 @@ void SynEditTextPainter::paintTextLines(const QRect& clip) void SynEditTextPainter::paintGutter(const QRect& clip) { int cRow; - int cMark; QRect rcLine, rcFold; QList aGutterOffs; - bool bHasOtherMarks; QString s; - int vFirstLine; - int vLastLine; int vLine; - int vMarkRow; - int vGutterRow; int vLineTop; - QSize TextSize; int x; - PSynEditFoldRange FoldRange; AClip = clip; @@ -133,15 +127,12 @@ void SynEditTextPainter::paintGutter(const QRect& clip) s = edit->mGutter.formatLineNumber(vLine); - if (edit->mOnGutterGetText) { - edit->mOnGutterGetText(vLine,s); - } - + edit->onGutterGetText(vLine,s); QRectF textRect; textRect = painter->boundingRect(textRect, Qt::AlignLeft,s); painter->drawText( (edit->mGutterWidth - edit->mGutter.rightOffset() - 2) - textRect.width(), - rcLine.top() + ((edit->mTextHeight - int(textRect.height())) % 2), + rcLine.top() + ((edit->mTextHeight - int(textRect.height())) / 2), s ); } @@ -166,33 +157,33 @@ void SynEditTextPainter::paintGutter(const QRect& clip) // Need to paint a line? if (edit->foldAroundLine(vLine)) { - x = rcFold.left() + (rcFold.width() % 2); + x = rcFold.left() + (rcFold.width() / 2); painter->drawLine(x,rcFold.top(), x, rcFold.bottom()); } // Need to paint a line end? if (edit->foldEndAtLine(vLine)) { - x = rcFold.left() + (rcFold.width() % 2); - painter->drawLine(x,rcFold.top(), x, rcFold.top() + rcFold.height() % 2); + x = rcFold.left() + (rcFold.width() / 2); + painter->drawLine(x,rcFold.top(), x, rcFold.top() + rcFold.height() / 2); painter->drawLine(x, - rcFold.top() + rcFold.height() % 2, + rcFold.top() + rcFold.height() / 2, rcFold.right() - 2 , - rcFold.top() + rcFold.height() % 2); + rcFold.top() + rcFold.height() / 2); } // Any fold ranges beginning on this line? - FoldRange = edit->foldStartAtLine(vLine); + PSynEditFoldRange FoldRange = edit->foldStartAtLine(vLine); if (FoldRange) { // Draw the bottom part of a line if (!FoldRange->collapsed) { - x = rcFold.left() + (rcFold.width() % 2); - painter->drawLine(x, rcFold.top() + rcFold.height() % 2, + x = rcFold.left() + (rcFold.width() / 2); + painter->drawLine(x, rcFold.top() + rcFold.height() / 2, x, rcFold.bottom()); } // make a square rect inflateRect(rcFold,-2, 0); rcFold.setTop( - rcFold.top() + ((edit->mTextHeight - rcFold.width()) % 2)); + rcFold.top() + ((edit->mTextHeight - rcFold.width()) / 2)); rcFold.setBottom(rcFold.top() + rcFold.width()); // Paint the square the user can click on @@ -202,11 +193,11 @@ void SynEditTextPainter::paintGutter(const QRect& clip) // Paint minus sign painter->drawLine( - rcFold.left() + 2, rcFold.top() + (rcFold.height() % 2 ), - rcFold.right() - 2, rcFold.top() + (rcFold.height() % 2 )); + rcFold.left() + 2, rcFold.top() + (rcFold.height() / 2 ), + rcFold.right() - 2, rcFold.top() + (rcFold.height() / 2 )); // Paint vertical line of plus sign if (FoldRange->collapsed) { - x = rcFold.left() + (rcFold.width() % 2); + x = rcFold.left() + (rcFold.width() / 2); painter->drawLine(x, rcFold.top() + 2, x, rcFold.bottom() + 2); } @@ -271,7 +262,7 @@ void SynEditTextPainter::paintGutter(const QRect& clip) // end; for (cRow = aFirstRow; cRow <=aLastRow; cRow++) { vLine = edit->rowToLine(cRow); - edit->onGutterPaint(vLine, 0, (cRow - edit->mTopLine) * edit->mTextHeight); + edit->onGutterPaint(*painter,vLine, 0, (cRow - edit->mTopLine) * edit->mTextHeight); } } @@ -325,6 +316,7 @@ void SynEditTextPainter::ComputeSelectionInfo() bAnySelection = (vEnd.Line >= vFirstLine) and (vStart.Line <= vLastLine); if (bAnySelection) { // Transform the selection from text space into screen space + qDebug()<<"ComputeSelectionInfo"; vSelStart = edit->bufferToDisplayPos(vStart); vSelEnd = edit->bufferToDisplayPos(vEnd); // In the column selection mode sort the begin and end of the selection, @@ -365,29 +357,30 @@ void SynEditTextPainter::PaintToken(const QString &Token, int TokenCols, int Col Last -= ColumnsBefore; if (First > TokenCols) { } else { - painter->setClipRect(rcToken); - int tokenColLen=0; - startPaint = false; - for (int i=0;imTabWidth - ((ColumnsBefore+tokenColLen) % edit->mTabWidth); - } else { - charCols = edit->charColumns(Token[i]); - } - if (tokenColLen+charCols>=First) { - startPaint = true; - if (tokenColLen+1!=First) { - nX-= (First - tokenColLen - 1) * edit->mCharWidth; - } - } - painter->drawText(nX,rcToken.bottom(), Token[i]); + qDebug()<<"token clip rect:"<setClipRect(rcToken); + int tokenColLen=0; + startPaint = false; + for (int i=0;imTabWidth - ((ColumnsBefore+tokenColLen) % edit->mTabWidth); + } else { + charCols = edit->charColumns(Token[i]); + } + if (tokenColLen+charCols>=First) { + if (!startPaint && (tokenColLen+1!=First)) { + nX-= (First - tokenColLen - 1) * edit->mCharWidth; + } + startPaint = true; + } + painter->drawText(nX,rcToken.bottom()-painter->fontMetrics().descent()*edit->dpiFactor() , Token[i]); - tokenColLen += charCols; - nX += charCols * edit->mCharWidth; - if (tokenColLen > Last) - break; - } + tokenColLen += charCols; + nX += charCols * edit->mCharWidth; + if (tokenColLen > Last) + break; + } } rcToken.setLeft(rcToken.right()); @@ -722,9 +715,8 @@ void SynEditTextPainter::PaintLines() int vFirstChar; int vLastChar; SynEditingAreaList areaList; - QColor colBorder; PSynEditFoldRange foldRange; - int nC1,nC2,nFold; + int nFold; QString sFold; // Initialize rcLine for drawing. Note that Top and Bottom are updated @@ -747,7 +739,7 @@ void SynEditTextPainter::PaintLines() // use special values for them. colFG = edit->palette().color(QPalette::Text); colBG = colEditorBG(); - bSpecialLine = edit->onSpecialLineColors(vLine, colFG, colBG); + bSpecialLine = edit->onGetSpecialLineColors(vLine, colFG, colBG); if (bSpecialLine) { // The selection colors are just swapped, like seen in Delphi. colSelFG = colBG; @@ -756,7 +748,7 @@ void SynEditTextPainter::PaintLines() colSelFG = edit->mSelectedForeground; colSelBG = edit->mSelectedBackground; } - edit->onEditingAreas(vLine, areaList); + edit->onGetEditingAreas(vLine, areaList); // Removed word wrap support vFirstChar = FirstCol; vLastChar = LastCol; diff --git a/RedPandaIDE/qsynedit/TextPainter.h b/RedPandaIDE/qsynedit/TextPainter.h index 26ab2ab9..93fca6e1 100644 --- a/RedPandaIDE/qsynedit/TextPainter.h +++ b/RedPandaIDE/qsynedit/TextPainter.h @@ -22,7 +22,7 @@ class SynEditTextPainter }; public: - SynEditTextPainter(SynEdit * edit,int FirstRow, int LastRow, + SynEditTextPainter(SynEdit * edit,QPainter* painter,int FirstRow, int LastRow, int FirstCol, int LastCol); void paintTextLines(const QRect& clip); void paintGutter(const QRect& clip); diff --git a/RedPandaIDE/qsynedit/highlighter/base.h b/RedPandaIDE/qsynedit/highlighter/base.h index e86749a6..ae4dadcf 100644 --- a/RedPandaIDE/qsynedit/highlighter/base.h +++ b/RedPandaIDE/qsynedit/highlighter/base.h @@ -109,7 +109,7 @@ public: virtual void setLine(const QString& newLine, int lineNumber) = 0; virtual void resetState() = 0; - virtual QString languageName(); + virtual QString languageName() = 0; static bool isSpaceChar(const QChar& ch); bool enabled() const; diff --git a/RedPandaIDE/qsynedit/highlighter/composition.cpp b/RedPandaIDE/qsynedit/highlighter/composition.cpp index d8a16a96..576b5ffb 100644 --- a/RedPandaIDE/qsynedit/highlighter/composition.cpp +++ b/RedPandaIDE/qsynedit/highlighter/composition.cpp @@ -25,7 +25,7 @@ SynScheme::SynScheme(QObject *parent): connect(mMarkerAttribute.get(),&SynHighlighterAttribute::changed, this, &SynScheme::MarkerAttriChanged); mMarkerAttribute->setBackground(QColorConstants::Yellow); - mMarkerAttribute->setBold(true); + mMarkerAttribute->setStyles(SynFontStyle::fsBold); } QString SynScheme::endExpr() const @@ -91,3 +91,6 @@ QString SynScheme::ConvertExpression(const QString &Value) return Value; } } + +void SynScheme::MarkerAttriChanged() { +} diff --git a/RedPandaIDE/qsynedit/highlighter/cpp.cpp b/RedPandaIDE/qsynedit/highlighter/cpp.cpp index 95caa4d3..b8185c14 100644 --- a/RedPandaIDE/qsynedit/highlighter/cpp.cpp +++ b/RedPandaIDE/qsynedit/highlighter/cpp.cpp @@ -117,7 +117,7 @@ SynEditCppHighlighter::SynEditCppHighlighter(QObject *parent): SynHighlighter(pa mCharAttribute = std::make_shared(SYNS_AttrCharacter); addAttribute(mCharAttribute); mCommentAttribute = std::make_shared(SYNS_AttrComment); - mCommentAttribute->setItalic(true); + mCommentAttribute->setStyles(SynFontStyle::fsItalic); addAttribute(mCommentAttribute); mClassAttribute = std::make_shared(SYNS_AttrClass); addAttribute(mClassAttribute); @@ -142,7 +142,7 @@ SynEditCppHighlighter::SynEditCppHighlighter(QObject *parent): SynHighlighter(pa mDirecAttribute = std::make_shared(SYNS_AttrPreprocessor); addAttribute(mDirecAttribute); mKeyAttribute = std::make_shared(SYNS_AttrReservedWord); - mKeyAttribute->setBold(true); + mCommentAttribute->setStyles(SynFontStyle::fsBold); addAttribute(mKeyAttribute); mWhitespaceAttribute = std::make_shared(SYNS_AttrSpace); addAttribute(mWhitespaceAttribute); diff --git a/RedPandaIDE/utils.cpp b/RedPandaIDE/utils.cpp index 59d900b9..e60e0ce8 100644 --- a/RedPandaIDE/utils.cpp +++ b/RedPandaIDE/utils.cpp @@ -363,3 +363,18 @@ void inflateRect(QRect &rect, int dx, int dy) rect.setTop(rect.top()-dy); rect.setBottom(rect.bottom()+dy); } + +QString removeLineEnds(const QString &s) +{ + if (s.isEmpty()) + return s; + int i = s.length()-1; + while ((i>=0) && ((s[i] == '\r') || (s[i]=='\n'))) { + i--; + }; + if (i>=0) { + return s.left(i+1); + } else { + return QString(); + } +} diff --git a/RedPandaIDE/utils.h b/RedPandaIDE/utils.h index 4475b28f..52d794c9 100644 --- a/RedPandaIDE/utils.h +++ b/RedPandaIDE/utils.h @@ -95,6 +95,7 @@ void decodeKey(int combinedKey, int& key, Qt::KeyboardModifiers& modifiers); void inflateRect(QRect& rect, int delta); void inflateRect(QRect& rect, int dx, int dy); +QString removeLineEnds(const QString& s); template class final_action