update max line width in background
This commit is contained in:
parent
8faa2c0aa6
commit
8fef396baa
|
@ -25,27 +25,24 @@
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include "qt_utils/charsetinfo.h"
|
#include "qt_utils/charsetinfo.h"
|
||||||
|
#include <QDateTime>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
namespace QSynedit {
|
namespace QSynedit {
|
||||||
|
|
||||||
Document::Document(const QFont& font, QObject *parent):
|
Document::Document(const QFont& font, QObject *parent):
|
||||||
QObject{parent},
|
QObject{parent},
|
||||||
mFontMetrics{font},
|
|
||||||
mTabSize{4},
|
|
||||||
mForceMonospace{false},
|
|
||||||
mSetLineWidthLockCount{0},
|
mSetLineWidthLockCount{0},
|
||||||
mMaxLineChangedInSetLinesWidth{false},
|
mMaxLineChangedInSetLinesWidth{false},
|
||||||
mMutex{}
|
mMutex{},
|
||||||
|
mGlyphCalculator{font}
|
||||||
{
|
{
|
||||||
mAppendNewLineAtEOF = true;
|
mAppendNewLineAtEOF = true;
|
||||||
mNewlineType = NewlineType::Windows;
|
mNewlineType = NewlineType::Windows;
|
||||||
mIndexOfLongestLine = -1;
|
mIndexOfLongestLine = -1;
|
||||||
mUpdateCount = 0;
|
mUpdateCount = 0;
|
||||||
mCharWidth = mFontMetrics.horizontalAdvance("M");
|
mUpdateDocumentLineWidthFunc = std::bind(&GlyphCalculator::calcLineWidth,
|
||||||
mSpaceWidth = mFontMetrics.horizontalAdvance(" ");
|
&mGlyphCalculator,
|
||||||
mUpdateDocumentLineWidthFunc = std::bind(&Document::calcLineWidth,
|
|
||||||
this,
|
|
||||||
std::placeholders::_1,
|
std::placeholders::_1,
|
||||||
std::placeholders::_2,
|
std::placeholders::_2,
|
||||||
std::placeholders::_3);
|
std::placeholders::_3);
|
||||||
|
@ -95,6 +92,22 @@ int Document::lineWidth(int line)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Document::updateLineWidth(int line)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&mMutex);
|
||||||
|
if (line>=0 && line < mLines.size()) {
|
||||||
|
if (mLines[line]->mWidth<0) {
|
||||||
|
int width;
|
||||||
|
QList<int> glyphPositions = mGlyphCalculator.calcLineWidth(
|
||||||
|
mLines[line]->lineText(),
|
||||||
|
mLines[line]->glyphStartCharList(),
|
||||||
|
width);
|
||||||
|
setLineWidth(line, width,glyphPositions);
|
||||||
|
mLines[line]->mIsTempWidth = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int Document::lineWidth(int line, const QString &newText)
|
int Document::lineWidth(int line, const QString &newText)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&mMutex);
|
QMutexLocker locker(&mMutex);
|
||||||
|
@ -104,7 +117,7 @@ int Document::lineWidth(int line, const QString &newText)
|
||||||
if (lineText==newText) {
|
if (lineText==newText) {
|
||||||
return mLines[line]->width();
|
return mLines[line]->width();
|
||||||
} else {
|
} else {
|
||||||
return stringWidth(newText,0);
|
return mGlyphCalculator.stringWidth(newText,0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -571,40 +584,22 @@ void Document::saveUTF32File(QFile &file, QTextCodec* codec)
|
||||||
file.write(codec->fromUnicode(text));
|
file.write(codec->fromUnicode(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Document::forceMonospace() const
|
void Document::setTabSize(int newTabSize)
|
||||||
{
|
{
|
||||||
return mForceMonospace;
|
if (tabSize()!=newTabSize) {
|
||||||
|
mGlyphCalculator.setTabSize(newTabSize);
|
||||||
|
invalidateAllLineWidth();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Document::setForceMonospace(bool newForceMonospace)
|
void Document::setForceMonospace(bool newForceMonospace)
|
||||||
{
|
{
|
||||||
int oldValue = mForceMonospace;
|
int oldValue = forceMonospace();
|
||||||
mForceMonospace = newForceMonospace;
|
mGlyphCalculator.setForceMonospace(newForceMonospace);
|
||||||
if (oldValue != mForceMonospace)
|
if (oldValue != newForceMonospace)
|
||||||
invalidateAllLineWidth();
|
invalidateAllLineWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QFontMetrics &Document::fontMetrics() const
|
|
||||||
{
|
|
||||||
return mFontMetrics;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Document::setFont(const QFont &newFont)
|
|
||||||
{
|
|
||||||
mFontMetrics = QFontMetrics(newFont);
|
|
||||||
mCharWidth = mFontMetrics.horizontalAdvance("M");
|
|
||||||
mSpaceWidth = mFontMetrics.horizontalAdvance(" ");
|
|
||||||
invalidateAllLineWidth();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Document::setTabSize(int newTabSize)
|
|
||||||
{
|
|
||||||
if (mTabSize!=newTabSize) {
|
|
||||||
mTabSize = newTabSize;
|
|
||||||
invalidateAllLineWidth();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Document::loadFromFile(const QString& filename, const QByteArray& encoding, QByteArray& realEncoding)
|
void Document::loadFromFile(const QString& filename, const QByteArray& encoding, QByteArray& realEncoding)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&mMutex);
|
QMutexLocker locker(&mMutex);
|
||||||
|
@ -888,7 +883,7 @@ QList<int> calcGlyphStartCharList(const QString &text)
|
||||||
return glyphStartCharList;
|
return glyphStartCharList;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Document::stringWidth(const QString &str, int left) const
|
int GlyphCalculator::stringWidth(const QString &str, int left) const
|
||||||
{
|
{
|
||||||
QList<int> glyphStartCharList = calcGlyphStartCharList(str);
|
QList<int> glyphStartCharList = calcGlyphStartCharList(str);
|
||||||
int right;
|
int right;
|
||||||
|
@ -896,7 +891,7 @@ int Document::stringWidth(const QString &str, int left) const
|
||||||
return right - left;
|
return right - left;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Document::stringWidth(const QString &str, int left, const QFontMetrics &fontMetrics)
|
int GlyphCalculator::stringWidth(const QString &str, int left, const QFontMetrics &fontMetrics)
|
||||||
{
|
{
|
||||||
QList<int> glyphStartCharList = calcGlyphStartCharList(str);
|
QList<int> glyphStartCharList = calcGlyphStartCharList(str);
|
||||||
int right;
|
int right;
|
||||||
|
@ -944,11 +939,6 @@ int Document::glyphWidth(int line, int glyphIdx)
|
||||||
return mLines[line]->glyphWidth(glyphIdx);
|
return mLines[line]->glyphWidth(glyphIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Document::glyphWidth(const QString &glyph, int left) const
|
|
||||||
{
|
|
||||||
return glyphWidth(glyph,left,mFontMetrics,mForceMonospace);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Document::charToGlyphIndex(int line, int charIdx)
|
int Document::charToGlyphIndex(int line, int charIdx)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&mMutex);
|
QMutexLocker locker(&mMutex);
|
||||||
|
@ -974,12 +964,7 @@ int Document::charToGlyphIndex(const QString& str, QList<int> glyphStartCharList
|
||||||
// return glyphStartCharList.length()-1;
|
// return glyphStartCharList.length()-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<int> Document::calcLineWidth(const QString &lineText, const QList<int> &glyphStartCharList, int &width)
|
QList<int> GlyphCalculator::calcGlyphPositionList(const QString &lineText, const QList<int> &glyphStartCharList, const QFontMetrics &fontMetrics, int left, int &right) const
|
||||||
{
|
|
||||||
return calcGlyphPositionList(lineText,glyphStartCharList,0,width);
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<int> Document::calcGlyphPositionList(const QString &lineText, const QList<int> &glyphStartCharList, const QFontMetrics &fontMetrics, int left, int &right) const
|
|
||||||
{
|
{
|
||||||
right = std::max(0,left);
|
right = std::max(0,left);
|
||||||
int start,end;
|
int start,end;
|
||||||
|
@ -1050,7 +1035,7 @@ int Document::charToGlyphStartPosition(int line, const QString newStr, int charP
|
||||||
QList<int> glyphStartCharList = calcGlyphStartCharList(newStr);
|
QList<int> glyphStartCharList = calcGlyphStartCharList(newStr);
|
||||||
int glyphIdx = charToGlyphIndex(newStr, glyphStartCharList, charPos);
|
int glyphIdx = charToGlyphIndex(newStr, glyphStartCharList, charPos);
|
||||||
int width;
|
int width;
|
||||||
QList<int> glyphStartPositionList = calcGlyphPositionList(newStr, width);
|
QList<int> glyphStartPositionList = mGlyphCalculator.calcGlyphPositionList(newStr, width);
|
||||||
if (glyphIdx<glyphStartCharList.length())
|
if (glyphIdx<glyphStartCharList.length())
|
||||||
return glyphStartPositionList[glyphIdx];
|
return glyphStartPositionList[glyphIdx];
|
||||||
else
|
else
|
||||||
|
@ -1069,7 +1054,7 @@ int Document::xposToGlyphStartChar(int line, const QString newStr, int xpos)
|
||||||
glyphPositionList = mLines[line]->glyphStartPositionList();
|
glyphPositionList = mLines[line]->glyphStartPositionList();
|
||||||
width = mLines[line]->width();
|
width = mLines[line]->width();
|
||||||
} else {
|
} else {
|
||||||
glyphPositionList = calcGlyphPositionList(mLines[line]->lineText(), width);
|
glyphPositionList = mGlyphCalculator.calcGlyphPositionList(mLines[line]->lineText(), width);
|
||||||
}
|
}
|
||||||
int glyphIdx = xposToGlyphIndex(width, glyphPositionList, xpos);
|
int glyphIdx = xposToGlyphIndex(width, glyphPositionList, xpos);
|
||||||
return mLines[line]->glyphStartChar(glyphIdx);
|
return mLines[line]->glyphStartChar(glyphIdx);
|
||||||
|
@ -1206,7 +1191,8 @@ void Document::updateMaxLineWidthChanged()
|
||||||
if (mSetLineWidthLockCount>0) {
|
if (mSetLineWidthLockCount>0) {
|
||||||
mMaxLineChangedInSetLinesWidth = true;
|
mMaxLineChangedInSetLinesWidth = true;
|
||||||
} else {
|
} else {
|
||||||
updateMaxLineWidthAndNotify();
|
//updateMaxLineWidthAndNotify();
|
||||||
|
emit maxLineWidthChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1227,15 +1213,7 @@ void Document::updateMaxLineWidthAndNotify()
|
||||||
emit maxLineWidthChanged();
|
emit maxLineWidthChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<int> Document::calcGlyphPositionList(const QString &lineText, const QList<int> &glyphStartCharList, int left, int &right) const
|
QList<int> GlyphCalculator::calcGlyphPositionList(const QString &lineText, int &width) const
|
||||||
{
|
|
||||||
return calcGlyphPositionList(lineText, glyphStartCharList,
|
|
||||||
mFontMetrics,
|
|
||||||
left,right);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QList<int> Document::calcGlyphPositionList(const QString &lineText, int &width) const
|
|
||||||
{
|
{
|
||||||
QList<int> glyphStartCharList = calcGlyphStartCharList(lineText);
|
QList<int> glyphStartCharList = calcGlyphStartCharList(lineText);
|
||||||
return calcGlyphPositionList(lineText,glyphStartCharList,0,width);
|
return calcGlyphPositionList(lineText,glyphStartCharList,0,width);
|
||||||
|
@ -1290,13 +1268,20 @@ void Document::invalidateAllLineWidth()
|
||||||
line->invalidateWidth();
|
line->invalidateWidth();
|
||||||
}
|
}
|
||||||
mIndexOfLongestLine = -1;
|
mIndexOfLongestLine = -1;
|
||||||
|
FindMaxLineWidthThread *thread = new FindMaxLineWidthThread(mLines, mGlyphCalculator);
|
||||||
|
connect(thread, &FindMaxLineWidthThread::maxWidthLineFound,
|
||||||
|
this, &Document::maxWidthLineFound);
|
||||||
|
connect(thread, &QThread::finished,
|
||||||
|
thread, &QThread::deleteLater);
|
||||||
|
thread->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
DocumentLine::DocumentLine(DocumentLine::UpdateWidthFunc updateWidthFunc):
|
DocumentLine::DocumentLine(DocumentLine::UpdateWidthFunc updateWidthFunc):
|
||||||
mSyntaxState{},
|
mSyntaxState{},
|
||||||
mWidth{-1},
|
mWidth{-1},
|
||||||
mIsTempWidth{true},
|
mIsTempWidth{true},
|
||||||
mUpdateWidthFunc{updateWidthFunc}
|
mUpdateWidthFunc{updateWidthFunc},
|
||||||
|
mTimestamp{QDateTime::currentMSecsSinceEpoch()}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1339,6 +1324,7 @@ int DocumentLine::width()
|
||||||
|
|
||||||
void DocumentLine::setLineText(const QString &newLineText)
|
void DocumentLine::setLineText(const QString &newLineText)
|
||||||
{
|
{
|
||||||
|
mTimestamp = QDateTime::currentMSecsSinceEpoch();
|
||||||
mLineText = newLineText;
|
mLineText = newLineText;
|
||||||
mGlyphStartCharList = calcGlyphStartCharList(newLineText);
|
mGlyphStartCharList = calcGlyphStartCharList(newLineText);
|
||||||
invalidateWidth();
|
invalidateWidth();
|
||||||
|
@ -1697,7 +1683,7 @@ int searchForSegmentIdx(const QList<int> &segList, int minVal, int maxVal, int v
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Document::updateGlyphStartPositionList(
|
int GlyphCalculator::updateGlyphStartPositionList(
|
||||||
const QString &lineText,
|
const QString &lineText,
|
||||||
const QList<int> &glyphStartCharList, int startChar, int endChar,
|
const QList<int> &glyphStartCharList, int startChar, int endChar,
|
||||||
const QFontMetrics &fontMetrics,
|
const QFontMetrics &fontMetrics,
|
||||||
|
@ -1724,7 +1710,7 @@ int Document::updateGlyphStartPositionList(
|
||||||
return right-left;
|
return right-left;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Document::glyphWidth(const QString &glyph, int left, const QFontMetrics &fontMetrics, bool forceMonospace) const
|
int GlyphCalculator::glyphWidth(const QString &glyph, int left, const QFontMetrics &fontMetrics, bool forceMonospace) const
|
||||||
{
|
{
|
||||||
int glyphWidth;
|
int glyphWidth;
|
||||||
if (glyph.length()==0)
|
if (glyph.length()==0)
|
||||||
|
@ -1769,4 +1755,45 @@ int segmentIntervalStart(const QList<int> &segList, int minVal, int maxVal, int
|
||||||
return segList[idx];
|
return segList[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GlyphCalculator::GlyphCalculator(const QFont &font):
|
||||||
|
mFontMetrics{font},
|
||||||
|
mTabSize{4},
|
||||||
|
mForceMonospace{false}
|
||||||
|
{
|
||||||
|
mCharWidth = mFontMetrics.horizontalAdvance("M");
|
||||||
|
mSpaceWidth = mFontMetrics.horizontalAdvance(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlyphCalculator::setFont(const QFont &newFont)
|
||||||
|
{
|
||||||
|
mFontMetrics = QFontMetrics(newFont);
|
||||||
|
mCharWidth = mFontMetrics.horizontalAdvance("M");
|
||||||
|
mSpaceWidth = mFontMetrics.horizontalAdvance(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
FindMaxLineWidthThread::FindMaxLineWidthThread(const DocumentLines &lines, const GlyphCalculator &glyphCalculator, QObject *parent):
|
||||||
|
QThread(parent),
|
||||||
|
mLines{lines},
|
||||||
|
mGlyphCalculator{glyphCalculator}
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void FindMaxLineWidthThread::run()
|
||||||
|
{
|
||||||
|
int maxWidth = 0;
|
||||||
|
int maxWidthLine = -1;
|
||||||
|
for (int i=0;i<mLines.size();i++) {
|
||||||
|
int width = mLines[i]->mWidth;
|
||||||
|
if ( width < 0 )
|
||||||
|
width = mGlyphCalculator.stringWidth(mLines[i]->lineText(),0);
|
||||||
|
if (width > maxWidth) {
|
||||||
|
maxWidth = width;
|
||||||
|
maxWidthLine = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (maxWidthLine >= 0)
|
||||||
|
emit maxWidthLineFound(maxWidthLine);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ QList<int> calcGlyphStartCharList(const QString &text);
|
||||||
void expandGlyphStartCharList(const QString& strAdded, int oldStrLen, QList<int> &glyphStartCharList);
|
void expandGlyphStartCharList(const QString& strAdded, int oldStrLen, QList<int> &glyphStartCharList);
|
||||||
|
|
||||||
class Document;
|
class Document;
|
||||||
|
class FindMaxLineWidthThread;
|
||||||
|
|
||||||
using SearchConfirmAroundProc = std::function<bool ()>;
|
using SearchConfirmAroundProc = std::function<bool ()>;
|
||||||
/**
|
/**
|
||||||
|
@ -178,8 +179,9 @@ private:
|
||||||
int mWidth;
|
int mWidth;
|
||||||
bool mIsTempWidth;
|
bool mIsTempWidth;
|
||||||
UpdateWidthFunc mUpdateWidthFunc;
|
UpdateWidthFunc mUpdateWidthFunc;
|
||||||
|
qint64 mTimestamp;
|
||||||
friend class Document;
|
friend class Document;
|
||||||
|
friend class FindMaxLineWidthThread;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<DocumentLine> PDocumentLine;
|
typedef std::shared_ptr<DocumentLine> PDocumentLine;
|
||||||
|
@ -195,6 +197,105 @@ public:
|
||||||
explicit BinaryFileError (const QString& reason);
|
explicit BinaryFileError (const QString& reason);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GlyphCalculator {
|
||||||
|
public:
|
||||||
|
explicit GlyphCalculator(const QFont& font);
|
||||||
|
|
||||||
|
int tabSize() const {
|
||||||
|
return mTabSize;
|
||||||
|
}
|
||||||
|
void setTabSize(int newTabSize) { mTabSize = newTabSize; }
|
||||||
|
|
||||||
|
|
||||||
|
int tabWidth() const {
|
||||||
|
return mTabSize * spaceWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
int spaceWidth() const {
|
||||||
|
if (mForceMonospace)
|
||||||
|
return mCharWidth;
|
||||||
|
return mSpaceWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool forceMonospace() const { return mForceMonospace; }
|
||||||
|
|
||||||
|
void setForceMonospace(bool newForceMonospace) { mForceMonospace = newForceMonospace; }
|
||||||
|
|
||||||
|
const QFontMetrics &fontMetrics() const { return mFontMetrics; }
|
||||||
|
|
||||||
|
void setFont(const QFont &newFont);
|
||||||
|
|
||||||
|
int glyphWidth(const QString& glyph, int left,
|
||||||
|
const QFontMetrics &fontMetrics,
|
||||||
|
bool forceMonospace) const;
|
||||||
|
|
||||||
|
int glyphWidth(const QString &glyph, int left) const{
|
||||||
|
return glyphWidth(glyph,left,mFontMetrics,mForceMonospace);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<int> calcGlyphPositionList(const QString& lineText, const QList<int> &glyphStartCharList,
|
||||||
|
const QFontMetrics &fontMetrics,
|
||||||
|
int left, int &right) const;
|
||||||
|
|
||||||
|
QList<int> calcGlyphPositionList(const QString& lineText, const QList<int> &glyphStartCharList, int left, int &right) const {
|
||||||
|
return calcGlyphPositionList(lineText, glyphStartCharList,
|
||||||
|
mFontMetrics,
|
||||||
|
left,right);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief calculate display width of a string
|
||||||
|
*
|
||||||
|
* The string may contains the tab char, whose width depends on the tab size and it's position
|
||||||
|
*
|
||||||
|
* @param str the string to be displayed
|
||||||
|
* @param left start x pos of the string
|
||||||
|
* @return width of the string, don't including colsBefore
|
||||||
|
*/
|
||||||
|
int stringWidth(const QString &str, int left) const;
|
||||||
|
|
||||||
|
int stringWidth(const QString &str, int left, const QFontMetrics &fontMetrics);
|
||||||
|
|
||||||
|
QList<int> calcLineWidth(const QString& lineText, const QList<int> &glyphStartCharList, int &width) {
|
||||||
|
return calcGlyphPositionList(lineText,glyphStartCharList,0,width);
|
||||||
|
}
|
||||||
|
QList<int> calcGlyphPositionList(const QString& lineText, int &width) const;
|
||||||
|
|
||||||
|
int updateGlyphStartPositionList(
|
||||||
|
const QString& lineText,
|
||||||
|
const QList<int> &glyphStartCharList,
|
||||||
|
int startChar, int endChar,
|
||||||
|
const QFontMetrics &fontMetrics,
|
||||||
|
QList<int> &glyphStartPositionList,
|
||||||
|
int left, int &right, int &startGlyph, int &endGlyph) const;
|
||||||
|
private:
|
||||||
|
QFontMetrics mFontMetrics;
|
||||||
|
int mTabSize;
|
||||||
|
int mCharWidth;
|
||||||
|
int mSpaceWidth;
|
||||||
|
bool mForceMonospace;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FindMaxLineWidthThread: public QThread {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit FindMaxLineWidthThread(
|
||||||
|
const DocumentLines &lines,
|
||||||
|
const GlyphCalculator& glyphCalculator,
|
||||||
|
QObject* parent=nullptr);
|
||||||
|
FindMaxLineWidthThread(const FindMaxLineWidthThread&) = delete;
|
||||||
|
signals:
|
||||||
|
void maxWidthLineFound(int line);
|
||||||
|
private:
|
||||||
|
DocumentLines mLines;
|
||||||
|
GlyphCalculator mGlyphCalculator;
|
||||||
|
|
||||||
|
// QThread interface
|
||||||
|
protected:
|
||||||
|
void run() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The Document class
|
* @brief The Document class
|
||||||
*
|
*
|
||||||
|
@ -248,6 +349,8 @@ public:
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
int lineWidth(int line);
|
int lineWidth(int line);
|
||||||
|
|
||||||
|
void updateLineWidth(int line);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief get width of the specified text / line
|
* @brief get width of the specified text / line
|
||||||
|
@ -425,20 +528,12 @@ public:
|
||||||
QString glyph(int line, int glyphIdx);
|
QString glyph(int line, int glyphIdx);
|
||||||
QString glyphAt(int line, int charPos);
|
QString glyphAt(int line, int charPos);
|
||||||
|
|
||||||
|
int stringWidth(const QString &str, int left) const {
|
||||||
|
return mGlyphCalculator.stringWidth(str, left);
|
||||||
|
}
|
||||||
|
|
||||||
int charToGlyphStartChar(int line, int charPos);
|
int charToGlyphStartChar(int line, int charPos);
|
||||||
//int columnToGlyphStartColumn(int line, int charPos);
|
//int columnToGlyphStartColumn(int line, int charPos);
|
||||||
/**
|
|
||||||
* @brief calculate display width of a string
|
|
||||||
*
|
|
||||||
* The string may contains the tab char, whose width depends on the tab size and it's position
|
|
||||||
*
|
|
||||||
* @param str the string to be displayed
|
|
||||||
* @param left start x pos of the string
|
|
||||||
* @return width of the string, don't including colsBefore
|
|
||||||
*/
|
|
||||||
int stringWidth(const QString &str, int left) const;
|
|
||||||
|
|
||||||
int stringWidth(const QString &str, int left, const QFontMetrics &fontMetrics);
|
|
||||||
|
|
||||||
int glyphCount(int line);
|
int glyphCount(int line);
|
||||||
/**
|
/**
|
||||||
|
@ -485,7 +580,9 @@ public:
|
||||||
*/
|
*/
|
||||||
int glyphWidth(int line, int glyphIdx);
|
int glyphWidth(int line, int glyphIdx);
|
||||||
|
|
||||||
int glyphWidth(const QString &glyph, int left) const;
|
int glyphWidth(const QString &glyph, int left) const {
|
||||||
|
return mGlyphCalculator.glyphWidth(glyph,left);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief get index of the glyph represented by the specified char
|
* @brief get index of the glyph represented by the specified char
|
||||||
|
@ -514,14 +611,6 @@ public:
|
||||||
int charToGlyphStartPosition(int line, const QString newStr, int charPos);
|
int charToGlyphStartPosition(int line, const QString newStr, int charPos);
|
||||||
int xposToGlyphStartChar(int line, const QString newStr, int xpos);
|
int xposToGlyphStartChar(int line, const QString newStr, int xpos);
|
||||||
|
|
||||||
int updateGlyphStartPositionList(
|
|
||||||
const QString& lineText,
|
|
||||||
const QList<int> &glyphStartCharList,
|
|
||||||
int startChar, int endChar,
|
|
||||||
const QFontMetrics &fontMetrics,
|
|
||||||
QList<int> &glyphStartPositionList,
|
|
||||||
int left, int &right, int &startGlyph, int &endGlyph) const;
|
|
||||||
|
|
||||||
bool getAppendNewLineAtEOF();
|
bool getAppendNewLineAtEOF();
|
||||||
void setAppendNewLineAtEOF(bool appendNewLineAtEOF);
|
void setAppendNewLineAtEOF(bool appendNewLineAtEOF);
|
||||||
|
|
||||||
|
@ -530,26 +619,21 @@ public:
|
||||||
|
|
||||||
bool empty();
|
bool empty();
|
||||||
|
|
||||||
int tabSize() const {
|
int tabSize() const { return mGlyphCalculator.tabSize(); }
|
||||||
return mTabSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tabWidth() const {
|
int tabWidth() const { return mGlyphCalculator.tabWidth(); }
|
||||||
return mTabSize * spaceWidth();
|
|
||||||
}
|
|
||||||
|
|
||||||
int spaceWidth() const {
|
int spaceWidth() const { return mGlyphCalculator.spaceWidth(); }
|
||||||
if (mForceMonospace)
|
|
||||||
return mCharWidth;
|
|
||||||
return mSpaceWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setTabSize(int newTabSize);
|
void setTabSize(int newTabSize);
|
||||||
|
|
||||||
const QFontMetrics &fontMetrics() const;
|
const QFontMetrics &fontMetrics() const { return mGlyphCalculator.fontMetrics(); }
|
||||||
void setFont(const QFont &newFont);
|
void setFont(const QFont &newFont) {
|
||||||
|
mGlyphCalculator.setFont(newFont);
|
||||||
|
invalidateAllLineWidth();
|
||||||
|
}
|
||||||
|
|
||||||
bool forceMonospace() const;
|
bool forceMonospace() const { return mGlyphCalculator.forceMonospace(); }
|
||||||
void setForceMonospace(bool newForceMonospace);
|
void setForceMonospace(bool newForceMonospace);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -563,6 +647,7 @@ signals:
|
||||||
void inserted(int startLine, int count);
|
void inserted(int startLine, int count);
|
||||||
void putted(int line);
|
void putted(int line);
|
||||||
void maxLineWidthChanged();
|
void maxLineWidthChanged();
|
||||||
|
void lineWidthUpdateNeeded(int line);
|
||||||
protected:
|
protected:
|
||||||
QString getTextStr() const;
|
QString getTextStr() const;
|
||||||
void setUpdateState(bool Updating);
|
void setUpdateState(bool Updating);
|
||||||
|
@ -570,6 +655,9 @@ protected:
|
||||||
void addItem(const QString& s);
|
void addItem(const QString& s);
|
||||||
void putTextStr(const QString& text);
|
void putTextStr(const QString& text);
|
||||||
void internalClear();
|
void internalClear();
|
||||||
|
void maxWidthLineFound(int line) {
|
||||||
|
emit lineWidthUpdateNeeded(line);
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
bool lineWidthValid(int line);
|
bool lineWidthValid(int line);
|
||||||
void beginSetLinesWidth();
|
void beginSetLinesWidth();
|
||||||
|
@ -578,18 +666,8 @@ private:
|
||||||
void updateMaxLineWidthChanged();
|
void updateMaxLineWidthChanged();
|
||||||
void updateMaxLineWidthAndNotify();
|
void updateMaxLineWidthAndNotify();
|
||||||
|
|
||||||
int glyphWidth(const QString& glyph, int left,
|
|
||||||
const QFontMetrics &fontMetrics,
|
|
||||||
bool forceMonospace) const;
|
|
||||||
|
|
||||||
int xposToGlyphIndex(int strWidth, QList<int> glyphPositionList, int xpos) const;
|
int xposToGlyphIndex(int strWidth, QList<int> glyphPositionList, int xpos) const;
|
||||||
int charToGlyphIndex(const QString& str, QList<int> glyphStartCharList, int charPos) const;
|
int charToGlyphIndex(const QString& str, QList<int> glyphStartCharList, int charPos) const;
|
||||||
QList<int> calcLineWidth(const QString& lineText, const QList<int> &glyphStartCharList, int &width);
|
|
||||||
QList<int> calcGlyphPositionList(const QString& lineText, const QList<int> &glyphStartCharList,
|
|
||||||
const QFontMetrics &fontMetrics,
|
|
||||||
int left, int &right) const;
|
|
||||||
QList<int> calcGlyphPositionList(const QString& lineText, const QList<int> &glyphStartCharList, int left, int &right) const;
|
|
||||||
QList<int> calcGlyphPositionList(const QString& lineText, int &width) const;
|
|
||||||
QList<int> getGlyphStartCharList(int line, const QString &lineText);
|
QList<int> getGlyphStartCharList(int line, const QString &lineText);
|
||||||
QList<int> getGlyphStartCharList(int line);
|
QList<int> getGlyphStartCharList(int line);
|
||||||
QList<int> getGlyphStartPositionList(int line);
|
QList<int> getGlyphStartPositionList(int line);
|
||||||
|
@ -605,24 +683,17 @@ private:
|
||||||
|
|
||||||
DocumentLine::UpdateWidthFunc mUpdateDocumentLineWidthFunc;
|
DocumentLine::UpdateWidthFunc mUpdateDocumentLineWidthFunc;
|
||||||
|
|
||||||
//SynEdit* mEdit;
|
|
||||||
|
|
||||||
QFontMetrics mFontMetrics;
|
|
||||||
int mTabSize;
|
|
||||||
int mCharWidth;
|
|
||||||
int mSpaceWidth;
|
|
||||||
//int mCount;
|
|
||||||
//int mCapacity;
|
|
||||||
NewlineType mNewlineType;
|
NewlineType mNewlineType;
|
||||||
bool mAppendNewLineAtEOF;
|
bool mAppendNewLineAtEOF;
|
||||||
int mIndexOfLongestLine;
|
int mIndexOfLongestLine;
|
||||||
int mUpdateCount;
|
int mUpdateCount;
|
||||||
bool mForceMonospace;
|
|
||||||
|
|
||||||
int mSetLineWidthLockCount;
|
int mSetLineWidthLockCount;
|
||||||
bool mMaxLineChangedInSetLinesWidth;
|
bool mMaxLineChangedInSetLinesWidth;
|
||||||
QRecursiveMutex mMutex;
|
QRecursiveMutex mMutex;
|
||||||
|
|
||||||
|
GlyphCalculator mGlyphCalculator;
|
||||||
|
|
||||||
friend class QSynEditPainter;
|
friend class QSynEditPainter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -750,7 +750,6 @@ void QSynEditPainter::addHighlightToken(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mIsSpecialLine) {
|
if (mIsSpecialLine) {
|
||||||
QColor oldForeground = foreground;
|
|
||||||
if (mSpecialLineForeground.isValid())
|
if (mSpecialLineForeground.isValid())
|
||||||
foreground = mSpecialLineForeground;
|
foreground = mSpecialLineForeground;
|
||||||
if (mSpecialLineBackground.isValid())
|
if (mSpecialLineBackground.isValid())
|
||||||
|
@ -788,7 +787,7 @@ void QSynEditPainter::addHighlightToken(
|
||||||
}
|
}
|
||||||
//calculate width of the token ( and update it's glyph start positions )
|
//calculate width of the token ( and update it's glyph start positions )
|
||||||
if (calcGlyphPosition) {
|
if (calcGlyphPosition) {
|
||||||
tokenWidth = mEdit->mDocument->updateGlyphStartPositionList(
|
tokenWidth = mEdit->mDocument->mGlyphCalculator.updateGlyphStartPositionList(
|
||||||
lineText,
|
lineText,
|
||||||
glyphStartCharList,
|
glyphStartCharList,
|
||||||
tokenStartChar,
|
tokenStartChar,
|
||||||
|
|
|
@ -44,6 +44,20 @@
|
||||||
|
|
||||||
#define UPDATE_HORIZONTAL_SCROLLBAR_EVENT ((QEvent::Type)(QEvent::User+1))
|
#define UPDATE_HORIZONTAL_SCROLLBAR_EVENT ((QEvent::Type)(QEvent::User+1))
|
||||||
#define UPDATE_VERTICAL_SCROLLBAR_EVENT ((QEvent::Type)(QEvent::User+2))
|
#define UPDATE_VERTICAL_SCROLLBAR_EVENT ((QEvent::Type)(QEvent::User+2))
|
||||||
|
#define UPDATE_LINE_WIDTH_EVENT ((QEvent::Type)(QEvent::User+3))
|
||||||
|
|
||||||
|
class UpdateLineWidthEvent: public QEvent{
|
||||||
|
public:
|
||||||
|
explicit UpdateLineWidthEvent(int line):
|
||||||
|
QEvent{UPDATE_LINE_WIDTH_EVENT},
|
||||||
|
mLine{line}
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
int line() const { return mLine; }
|
||||||
|
private:
|
||||||
|
int mLine;
|
||||||
|
};
|
||||||
|
|
||||||
namespace QSynedit {
|
namespace QSynedit {
|
||||||
QSynEdit::QSynEdit(QWidget *parent) : QAbstractScrollArea(parent),
|
QSynEdit::QSynEdit(QWidget *parent) : QAbstractScrollArea(parent),
|
||||||
|
@ -77,6 +91,7 @@ QSynEdit::QSynEdit(QWidget *parent) : QAbstractScrollArea(parent),
|
||||||
connect(mDocument.get(), &Document::cleared, this, &QSynEdit::updateVScrollbar);
|
connect(mDocument.get(), &Document::cleared, this, &QSynEdit::updateVScrollbar);
|
||||||
connect(mDocument.get(), &Document::deleted, this, &QSynEdit::updateVScrollbar);
|
connect(mDocument.get(), &Document::deleted, this, &QSynEdit::updateVScrollbar);
|
||||||
connect(mDocument.get(), &Document::inserted, this, &QSynEdit::updateVScrollbar);
|
connect(mDocument.get(), &Document::inserted, this, &QSynEdit::updateVScrollbar);
|
||||||
|
connect(mDocument.get(), &Document::lineWidthUpdateNeeded, this, &QSynEdit::onLineWidthUpdateNeeded);
|
||||||
|
|
||||||
mGutterWidth = 0;
|
mGutterWidth = 0;
|
||||||
|
|
||||||
|
@ -1755,6 +1770,12 @@ void QSynEdit::onMaxLineWidthChanged()
|
||||||
updateHScrollBarLater();
|
updateHScrollBarLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QSynEdit::onLineWidthUpdateNeeded(int line)
|
||||||
|
{
|
||||||
|
UpdateLineWidthEvent * event = new UpdateLineWidthEvent(line);
|
||||||
|
qApp->postEvent(this,event);
|
||||||
|
}
|
||||||
|
|
||||||
void QSynEdit::updateHScrollBarLater()
|
void QSynEdit::updateHScrollBarLater()
|
||||||
{
|
{
|
||||||
QEvent * event = new QEvent(UPDATE_HORIZONTAL_SCROLLBAR_EVENT);
|
QEvent * event = new QEvent(UPDATE_HORIZONTAL_SCROLLBAR_EVENT);
|
||||||
|
@ -3143,6 +3164,11 @@ void QSynEdit::doUpdateVScrollbar()
|
||||||
verticalScrollBar()->setSingleStep(mTextHeight);
|
verticalScrollBar()->setSingleStep(mTextHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QSynEdit::doUpdateLineWidth(int line)
|
||||||
|
{
|
||||||
|
mDocument->updateLineWidth(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void QSynEdit::updateCaret()
|
void QSynEdit::updateCaret()
|
||||||
{
|
{
|
||||||
|
@ -5979,10 +6005,17 @@ bool QSynEdit::event(QEvent *event)
|
||||||
{
|
{
|
||||||
switch(event->type()) {
|
switch(event->type()) {
|
||||||
case UPDATE_HORIZONTAL_SCROLLBAR_EVENT:
|
case UPDATE_HORIZONTAL_SCROLLBAR_EVENT:
|
||||||
|
event->setAccepted(true);
|
||||||
doUpdateHScrollbar();
|
doUpdateHScrollbar();
|
||||||
break;
|
break;
|
||||||
|
case UPDATE_LINE_WIDTH_EVENT: {
|
||||||
|
event->setAccepted(true);
|
||||||
|
UpdateLineWidthEvent* updateEvent = dynamic_cast<UpdateLineWidthEvent *>(event);
|
||||||
|
doUpdateLineWidth(updateEvent->line());
|
||||||
|
}
|
||||||
|
break;
|
||||||
case QEvent::KeyPress:{
|
case QEvent::KeyPress:{
|
||||||
QKeyEvent* keyEvent = static_cast<QKeyEvent *>(event);
|
QKeyEvent* keyEvent = dynamic_cast<QKeyEvent *>(event);
|
||||||
if(keyEvent->key() == Qt::Key_Tab || keyEvent->key() == Qt::Key_Backtab)
|
if(keyEvent->key() == Qt::Key_Tab || keyEvent->key() == Qt::Key_Backtab)
|
||||||
{
|
{
|
||||||
// process tab key presse event
|
// process tab key presse event
|
||||||
|
|
|
@ -525,6 +525,7 @@ private:
|
||||||
void doUpdateHScrollbar();
|
void doUpdateHScrollbar();
|
||||||
void updateVScrollbar();
|
void updateVScrollbar();
|
||||||
void doUpdateVScrollbar();
|
void doUpdateVScrollbar();
|
||||||
|
void doUpdateLineWidth(int line);
|
||||||
void updateCaret();
|
void updateCaret();
|
||||||
void recalcCharExtent();
|
void recalcCharExtent();
|
||||||
QString expandAtWideGlyphs(const QString& S);
|
QString expandAtWideGlyphs(const QString& S);
|
||||||
|
@ -645,6 +646,7 @@ private:
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onMaxLineWidthChanged();
|
void onMaxLineWidthChanged();
|
||||||
|
void onLineWidthUpdateNeeded(int line);
|
||||||
void updateHScrollBarLater();
|
void updateHScrollBarLater();
|
||||||
void onBookMarkOptionsChanged();
|
void onBookMarkOptionsChanged();
|
||||||
void onGutterChanged();
|
void onGutterChanged();
|
||||||
|
|
Loading…
Reference in New Issue