* work save

This commit is contained in:
royqh1979@gmail.com 2021-05-24 00:41:00 +08:00
parent 101302255b
commit aee8794305
17 changed files with 519 additions and 262 deletions

View File

@ -12,7 +12,8 @@
#include <QFileDialog>
#include <QMessageBox>
#include <QDebug>
#include <Qsci/qscilexercpp.h>
#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()<<start<<end<<style<<text(start,end);
}
void Editor::onLinesChanged(int startLine, int count) {
this->setMarginWidth(0,QString("0%1").arg(lines()));
qDebug()<<"Editor lines changed"<<lines();
qDebug()<<"Editor lines changed"<<lines()->count();
qDebug()<<startLine<<count;
}
@ -310,7 +270,7 @@ void Editor::updateCaption(const QString& newCaption) {
return;
if (newCaption.isEmpty()) {
QString caption = QFileInfo(mFilename).fileName();
if (this->isModified()) {
if (this->modified()) {
caption.append("[*]");
}
mParentPageControl->setTabText(index,caption);

View File

@ -4,7 +4,7 @@
#include <QObject>
#include <utils.h>
#include <QTabWidget>
#include <Qsci/qsciscintilla.h>
#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:

View File

@ -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"),

View File

@ -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();
}

View File

@ -1,4 +1,5 @@
#include "KeyStrokes.h"
#include <QDebug>
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<SynEditKeyStroke>();
keyStroke->setKey(key);
keyStroke->setKeyModifiers(modifiers);
keyStroke->setCommand(command);
// qDebug()<<"add : 1" ;
// qDebug() << (int)command;
//// PSynEditKeyStroke keyStroke = std::make_shared<SynEditKeyStroke>();
//// 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 ";
}

View File

@ -219,6 +219,7 @@ public:
PSynEditKeyStroke findKeySequence(const QKeySequence& keySeq);
void clear();
void resetDefaults();
private:
SynEditKeyStrokeList mList;
};

View File

@ -5,15 +5,21 @@
#include <cmath>
#include <QScrollBar>
#include <QPaintEvent>
#include <QPainter>
#include <QTimerEvent>
#include "highlighter/base.h"
#include "Constants.h"
#include "TextPainter.h"
#include <QDebug>
SynEdit::SynEdit(QWidget *parent) : QAbstractScrollArea(parent)
{
qDebug()<<"init SynEdit:";
mPaintLock = 0;
mPainterLock = 0;
mPainting = false;
mLines = std::make_shared<SynEditStringList>();
mLines = std::make_shared<SynEditStringList>(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<SynEditUndoList>();
mUndoList->connect(mUndoList.get(), &SynEditUndoList::addedUndo, this, &SynEdit::undoAdded);
mOrigUndoList = mUndoList;
mRedoList = std::make_shared<SynEditUndoList>();
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<QImage>(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"<<caretXY().Char<<caretXY().Line;
return bufferToDisplayPos(caretXY());
}
@ -316,6 +354,14 @@ DisplayCoord SynEdit::pixelsToRowColumn(int aX, int aY)
};
}
QPoint SynEdit::RowColumnToPixels(const DisplayCoord &coord)
{
QPoint result;
result.setX((coord.Column - 1) * mCharWidth + mTextOffset);
result.setY((coord.Row - mTopLine) * mTextHeight);
return result;
}
/**
* @brief takes a position in the text and transforms it into
* the row and column it appears to be on the screen
@ -324,6 +370,7 @@ DisplayCoord SynEdit::pixelsToRowColumn(int aX, int aY)
*/
DisplayCoord SynEdit::bufferToDisplayPos(const BufferCoord &p)
{
qDebug()<<"bufferTodisplayPos"<<p.Char<<p.Line;
DisplayCoord result {p.Char,p.Line};
// Account for tabs and charColumns
result.Column = charToColumn(p.Line,p.Char);
@ -360,11 +407,12 @@ BufferCoord SynEdit::displayToBufferPos(const DisplayCoord &p)
}
Result.Char = i;
}
return Result;
}
int SynEdit::charToColumn(int aLine, int aChar)
{
if (aLine < mLines->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"<<aLine<<aChar;
throw BaseError(SynEdit::tr("Line %1 is out of range").arg(aLine));
}
@ -420,6 +469,7 @@ int SynEdit::rowToLine(int aRow)
int SynEdit::lineToRow(int aLine)
{
qDebug()<<"line to row"<<aLine;
return bufferToDisplayPos({1, aLine}).Row;
}
@ -594,7 +644,7 @@ int SynEdit::charColumns(QChar ch)
{
if (ch == ' ')
return 1;
return std::ceil(fontMetrics().horizontalAdvance(ch) * dpiFactor() / mCharWidth);
return std::ceil((int)(fontMetrics().horizontalAdvance(ch) * dpiFactor()) / (double)mCharWidth);
}
double SynEdit::dpiFactor()
@ -602,6 +652,19 @@ double SynEdit::dpiFactor()
return fontMetrics().fontDpi() / 96.0;
}
void SynEdit::showCaret()
{
m_blinkTimerId = startTimer(100);
}
void SynEdit::hideCaret()
{
if (m_blinkTimerId!=0) {
killTimer(m_blinkTimerId);
m_blinkTimerId = 0;
}
}
void SynEdit::clearAreaList(SynEditingAreaList areaList)
{
areaList.clear();
@ -627,16 +690,16 @@ void SynEdit::computeScroll(int X, int Y)
mLinesInWindow * mTextHeight);
if (X < iScrollBounds.left())
mScrollDeltaX = (X - iScrollBounds.left()) % mCharWidth - 1;
mScrollDeltaX = (X - iScrollBounds.left()) / mCharWidth - 1;
else if (X >= 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; i<mAllFoldRanges.count();i++) {
PSynEditFoldRange range = mAllFoldRanges[i];
if (range->toLine == 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:"<<rcCaret;
qDebug()<<"Clip rect:"<<rcClip;
auto action = finally([&,this] {
//updateCaret();
paintCaret(painter, rcCaret);
mPainting = false;
});
// First paint paint the text area if it was (partly) invalidated.
if (rcClip.right() > 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<QImage> image = std::make_shared<QImage>(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);
}

View File

@ -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<QImage> 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

View File

@ -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<SynEditStringRec>();
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;

View File

@ -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:

View File

@ -2,10 +2,12 @@
#include "SynEdit.h"
#include "Constants.h"
#include <cmath>
#include <QDebug>
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<int> 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;i<Token.length();i++) {
int charCols;
if (Token[i] == SynTabChar) {
charCols = edit->mTabWidth - ((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:"<<rcToken << Token;
painter->setClipRect(rcToken);
int tokenColLen=0;
startPaint = false;
for (int i=0;i<Token.length();i++) {
int charCols;
if (Token[i] == SynTabChar) {
charCols = edit->mTabWidth - ((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;

View File

@ -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);

View File

@ -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;

View File

@ -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() {
}

View File

@ -117,7 +117,7 @@ SynEditCppHighlighter::SynEditCppHighlighter(QObject *parent): SynHighlighter(pa
mCharAttribute = std::make_shared<SynHighlighterAttribute>(SYNS_AttrCharacter);
addAttribute(mCharAttribute);
mCommentAttribute = std::make_shared<SynHighlighterAttribute>(SYNS_AttrComment);
mCommentAttribute->setItalic(true);
mCommentAttribute->setStyles(SynFontStyle::fsItalic);
addAttribute(mCommentAttribute);
mClassAttribute = std::make_shared<SynHighlighterAttribute>(SYNS_AttrClass);
addAttribute(mClassAttribute);
@ -142,7 +142,7 @@ SynEditCppHighlighter::SynEditCppHighlighter(QObject *parent): SynHighlighter(pa
mDirecAttribute = std::make_shared<SynHighlighterAttribute>(SYNS_AttrPreprocessor);
addAttribute(mDirecAttribute);
mKeyAttribute = std::make_shared<SynHighlighterAttribute>(SYNS_AttrReservedWord);
mKeyAttribute->setBold(true);
mCommentAttribute->setStyles(SynFontStyle::fsBold);
addAttribute(mKeyAttribute);
mWhitespaceAttribute = std::make_shared<SynHighlighterAttribute>(SYNS_AttrSpace);
addAttribute(mWhitespaceAttribute);

View File

@ -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();
}
}

View File

@ -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 F>
class final_action