* work save
This commit is contained in:
parent
8feda5d762
commit
1dddfc6fea
|
@ -21,6 +21,7 @@ SOURCES += \
|
|||
qsynedit/Constants.cpp \
|
||||
qsynedit/MiscClasses.cpp \
|
||||
qsynedit/MiscProcs.cpp \
|
||||
qsynedit/SynEdit.cpp \
|
||||
qsynedit/TextBuffer.cpp \
|
||||
qsynedit/highlighter/base.cpp \
|
||||
qsynedit/highlighter/composition.cpp \
|
||||
|
@ -46,7 +47,9 @@ HEADERS += \
|
|||
qsynedit/Constants.h \
|
||||
qsynedit/MiscClasses.h \
|
||||
qsynedit/MiscProcs.h \
|
||||
qsynedit/SynEdit.h \
|
||||
qsynedit/TextBuffer.h \
|
||||
qsynedit/Types.h \
|
||||
qsynedit/highlighter/base.h \
|
||||
qsynedit/highlighter/composition.h \
|
||||
qsynedit/highlighter/cpp.h \
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "MiscProcs.h"
|
||||
#include <QFile>
|
||||
#include <QPainter>
|
||||
#include <QTextStream>
|
||||
#include <algorithm>
|
||||
|
||||
int MinMax(int x, int mi, int ma)
|
||||
|
@ -437,7 +439,7 @@ bool InternalEnumHighlighterAttris(PSynHighlighter Highlighter,
|
|||
QString UniqueAttriName = Highlighter->getName()
|
||||
+ HighlighterList.indexOf(Highlighter) + '.'
|
||||
+ pAttr->name();
|
||||
Result = (*highlighterAttriProc)(Highlighter, pAttr,
|
||||
Result = highlighterAttriProc(Highlighter, pAttr,
|
||||
UniqueAttriName, Params);
|
||||
if (!Result)
|
||||
break;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <QSet>
|
||||
#include "highlighter/base.h"
|
||||
#include <QPaintDevice>
|
||||
#include <QTextStream>
|
||||
#include <QVector>
|
||||
#include <initializer_list>
|
||||
//#include <QRect>
|
||||
|
@ -31,14 +32,14 @@ void InternalFillRect(QPainter* painter, const QRect& rcPaint, const QColor& col
|
|||
|
||||
// Converting tabs to spaces: To use the function several times it's better
|
||||
// to use a function pointer that is set to the fastest conversion function.
|
||||
using ConvertTabsProc = QString (*)(const QString& Line, int TabWidth);
|
||||
using ConvertTabsProc = std::function<QString(const QString&, int)>;
|
||||
|
||||
ConvertTabsProc GetBestConvertTabsProc(int TabWidth);
|
||||
|
||||
// This is the slowest conversion function which can handle TabWidth <> 2^n.
|
||||
QString ConvertTabs(const QString& Line, int TabWidth);
|
||||
|
||||
using ConvertTabsProcEx = QString (*)(const QString& Line, int TabWidth, bool& HasTabs);
|
||||
using ConvertTabsProcEx = std::function<QString(const QString&, int, bool& )>;
|
||||
|
||||
ConvertTabsProcEx GetBestConvertTabsProcEx(int TabWidth);
|
||||
// This is the slowest conversion function which can handle TabWidth <> 2^n.
|
||||
|
@ -68,9 +69,9 @@ QString EncodeString(const QString & s);
|
|||
// Decodes string, encoded with EncodeString.
|
||||
QString DecodeString(const QString& s);
|
||||
|
||||
using HighlighterAttriProc = bool (*) (PSynHighlighter Highlighter,
|
||||
using HighlighterAttriProc = std::function<bool(PSynHighlighter Highlighter,
|
||||
PSynHighlighterAttribute Attri, const QString& UniqueAttriName,
|
||||
std::initializer_list<void *> Params);
|
||||
std::initializer_list<void *> Params)>;
|
||||
|
||||
// Enums all child highlighters and their attributes of a TSynMultiSyn through a
|
||||
// callback function.
|
||||
|
@ -85,4 +86,5 @@ uint16_t CalcFCS(unsigned char* ABuf, int ABufSize);
|
|||
|
||||
void SynDrawGradient(QPaintDevice* ACanvas, const QColor& AStartColor, const QColor& AEndColor,
|
||||
int ASteps, const QRect& ARect, bool AHorizontal);
|
||||
|
||||
#endif // MISCPROCS_H
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
#include "SynEdit.h"
|
||||
|
||||
SynEdit::SynEdit(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef SYNEDIT_H
|
||||
#define SYNEDIT_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class SynEdit : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SynEdit(QWidget *parent = nullptr);
|
||||
|
||||
signals:
|
||||
|
||||
};
|
||||
|
||||
#endif // SYNEDIT_H
|
|
@ -1,16 +1,24 @@
|
|||
#include "TextBuffer.h"
|
||||
#include <QDataStream>
|
||||
#include <QFile>
|
||||
#include <QTextCodec>
|
||||
#include <QTextStream>
|
||||
#include <stdexcept>
|
||||
#include "../utils.h"
|
||||
|
||||
SynEditStringList::SynEditStringList()
|
||||
{
|
||||
mAppendNewLineAtEOF = true;
|
||||
mFileFormat = SynEditFileFormat::Windows;
|
||||
mFileEndingType = FileEndingType::Windows;
|
||||
mIndexOfLongestLine = -1;
|
||||
mUpdateCount = 0;
|
||||
setTabWidth(8);
|
||||
}
|
||||
|
||||
static void ListIndexOutOfBounds(int index) {
|
||||
throw IndexOutOfRange(index);
|
||||
}
|
||||
|
||||
int SynEditStringList::parenthesisLevels(int Index)
|
||||
{
|
||||
if (Index>=0 && Index < mList.size()) {
|
||||
|
@ -89,15 +97,8 @@ SynRangeState SynEditStringList::ranges(int Index)
|
|||
void SynEditStringList::InsertItem(int Index, const QString &s)
|
||||
{
|
||||
beginUpdate();
|
||||
PSynEditStringRec line;
|
||||
line->fString=s;
|
||||
line->fObject = nullptr;
|
||||
line->fRange = {0,0};
|
||||
line->fExpandedLength = -1;
|
||||
line->fParenthesisLevel = 0;
|
||||
line->fBracketLevel = 0;
|
||||
line->fBraceLevel = 0;
|
||||
line->fFlags = SynEditStringFlag::sfExpandedLengthUnknown;
|
||||
PSynEditStringRec line = std::make_shared<SynEditStringRec>();
|
||||
line->fString = s;
|
||||
mIndexOfLongestLine = -1;
|
||||
mList.insert(Index,line);
|
||||
endUpdate();
|
||||
|
@ -121,7 +122,7 @@ void SynEditStringList::setAppendNewLineAtEOF(bool appendNewLineAtEOF)
|
|||
void SynEditStringList::setRange(int Index, SynRangeState ARange)
|
||||
{
|
||||
if (Index<0 || Index>=mList.count()) {
|
||||
throw new std::out_of_range(QObject::tr("Index % s out of range").arg(Index).toLocal8Bit());
|
||||
ListIndexOutOfBounds(Index);
|
||||
}
|
||||
beginUpdate();
|
||||
mList[Index]->fRange = ARange;
|
||||
|
@ -131,7 +132,7 @@ void SynEditStringList::setRange(int Index, SynRangeState ARange)
|
|||
void SynEditStringList::setParenthesisLevel(int Index, int level)
|
||||
{
|
||||
if (Index<0 || Index>=mList.count()) {
|
||||
throw new std::out_of_range(QObject::tr("Index % s out of range").arg(Index).toLocal8Bit());
|
||||
ListIndexOutOfBounds(Index);
|
||||
}
|
||||
beginUpdate();
|
||||
mList[Index]->fParenthesisLevel = level;
|
||||
|
@ -141,7 +142,7 @@ void SynEditStringList::setParenthesisLevel(int Index, int level)
|
|||
void SynEditStringList::setBracketLevel(int Index, int level)
|
||||
{
|
||||
if (Index<0 || Index>=mList.count()) {
|
||||
throw new std::out_of_range(QObject::tr("Index % s out of range").arg(Index).toLocal8Bit());
|
||||
ListIndexOutOfBounds(Index);
|
||||
}
|
||||
beginUpdate();
|
||||
mList[Index]->fBracketLevel = level;
|
||||
|
@ -151,7 +152,7 @@ void SynEditStringList::setBracketLevel(int Index, int level)
|
|||
void SynEditStringList::setBraceLevel(int Index, int level)
|
||||
{
|
||||
if (Index<0 || Index>=mList.count()) {
|
||||
throw new std::out_of_range(QObject::tr("Index % s out of range").arg(Index).toLocal8Bit());
|
||||
ListIndexOutOfBounds(Index);
|
||||
}
|
||||
beginUpdate();
|
||||
mList[Index]->fBraceLevel = level;
|
||||
|
@ -184,6 +185,11 @@ QString SynEditStringList::text()
|
|||
return GetTextStr();
|
||||
}
|
||||
|
||||
void SynEditStringList::setText(const QString &text)
|
||||
{
|
||||
PutTextStr(text);
|
||||
}
|
||||
|
||||
void SynEditStringList::beginUpdate()
|
||||
{
|
||||
if (mUpdateCount == 0) {
|
||||
|
@ -194,7 +200,7 @@ void SynEditStringList::beginUpdate()
|
|||
|
||||
void SynEditStringList::endUpdate()
|
||||
{
|
||||
FUpdateCount--;
|
||||
mUpdateCount--;
|
||||
if (mUpdateCount == 0) {
|
||||
SetUpdateState(false);
|
||||
}
|
||||
|
@ -218,7 +224,7 @@ void SynEditStringList::setTabWidth(int value)
|
|||
}
|
||||
}
|
||||
|
||||
int SynEditStringList::Add(const QString &s)
|
||||
int SynEditStringList::add(const QString &s)
|
||||
{
|
||||
beginUpdate();
|
||||
int Result = mList.count();
|
||||
|
@ -228,7 +234,7 @@ int SynEditStringList::Add(const QString &s)
|
|||
return Result;
|
||||
}
|
||||
|
||||
int SynEditStringList::AddStrings(const QStringList &Strings)
|
||||
int SynEditStringList::addStrings(const QStringList &Strings)
|
||||
{
|
||||
if (Strings.count() > 0) {
|
||||
mIndexOfLongestLine = -1;
|
||||
|
@ -239,7 +245,7 @@ int SynEditStringList::AddStrings(const QStringList &Strings)
|
|||
int FirstAdded = mList.count();
|
||||
|
||||
for (const QString& s:Strings) {
|
||||
Add(s);
|
||||
add(s);
|
||||
}
|
||||
emit inserted(FirstAdded,Strings.count());
|
||||
}
|
||||
|
@ -250,7 +256,7 @@ int SynEditStringList::getTextLength()
|
|||
int Result = 0;
|
||||
for (const PSynEditStringRec& line: mList ) {
|
||||
Result += line->fString.length();
|
||||
if (mFileFormat == SynEditFileFormat::Windows) {
|
||||
if (mFileEndingType == FileEndingType::Windows) {
|
||||
Result += 2;
|
||||
} else {
|
||||
Result += 1;
|
||||
|
@ -258,7 +264,7 @@ int SynEditStringList::getTextLength()
|
|||
}
|
||||
}
|
||||
|
||||
void SynEditStringList::Clear()
|
||||
void SynEditStringList::clear()
|
||||
{
|
||||
if (!mList.isEmpty()) {
|
||||
beginUpdate();
|
||||
|
@ -268,14 +274,66 @@ void SynEditStringList::Clear()
|
|||
}
|
||||
}
|
||||
|
||||
void SynEditStringList::Delete(int Index)
|
||||
void SynEditStringList::deleteLines(int Index, int NumLines)
|
||||
{
|
||||
if (NumLines<=0)
|
||||
return;
|
||||
if ((Index < 0) || (Index >= mList.count())) {
|
||||
throw new std::out_of_range(QObject::tr("Index % s out of range").arg(Index).toLocal8Bit());
|
||||
ListIndexOutOfBounds(Index);
|
||||
}
|
||||
beginUpdate();
|
||||
auto action = finally([this]{
|
||||
endUpdate();
|
||||
});
|
||||
if (mIndexOfLongestLine>=Index && (mIndexOfLongestLine <Index+NumLines)) {
|
||||
mIndexOfLongestLine = - 1;
|
||||
}
|
||||
int LinesAfter = mList.count() - (Index + NumLines);
|
||||
if (LinesAfter < 0) {
|
||||
NumLines = mList.count() - Index;
|
||||
}
|
||||
mList.remove(Index,NumLines);
|
||||
emit deleted(Index,NumLines);
|
||||
}
|
||||
|
||||
void SynEditStringList::Exchange(int Index1, int Index2)
|
||||
{
|
||||
if ((Index1 < 0) || (Index1 >= mList.count())) {
|
||||
ListIndexOutOfBounds(Index1);
|
||||
}
|
||||
if ((Index2 < 0) || (Index2 >= mList.count())) {
|
||||
ListIndexOutOfBounds(Index2);
|
||||
}
|
||||
beginUpdate();
|
||||
mList.swapItemsAt(Index1,Index2);
|
||||
if (mIndexOfLongestLine == Index1) {
|
||||
mIndexOfLongestLine = Index2;
|
||||
} else if (mIndexOfLongestLine == Index2) {
|
||||
mIndexOfLongestLine = Index1;
|
||||
}
|
||||
endUpdate();
|
||||
}
|
||||
|
||||
void SynEditStringList::Insert(int Index, const QString &s)
|
||||
{
|
||||
if ((Index < 0) || (Index > mList.count())) {
|
||||
ListIndexOutOfBounds(Index);
|
||||
}
|
||||
beginUpdate();
|
||||
InsertItem(Index, s);
|
||||
emit inserted(Index,1);
|
||||
endUpdate();
|
||||
}
|
||||
|
||||
void SynEditStringList::deleteAt(int Index)
|
||||
{
|
||||
if ((Index < 0) || (Index >= mList.count())) {
|
||||
ListIndexOutOfBounds(Index);
|
||||
}
|
||||
beginUpdate();
|
||||
if (mIndexOfLongestLine == Index)
|
||||
mIndexOfLongestLine = -1;
|
||||
mList.removeAt(Index);
|
||||
mIndexOfLongestLine = -1;
|
||||
emit deleted(Index,1);
|
||||
endUpdate();
|
||||
}
|
||||
|
@ -285,24 +343,24 @@ QString SynEditStringList::GetTextStr()
|
|||
QString Result;
|
||||
for (PSynEditStringRec& line:mList) {
|
||||
Result.append(line->fString);
|
||||
switch(mFileFormat) {
|
||||
case SynEditFileFormat::Linux:
|
||||
switch(mFileEndingType) {
|
||||
case FileEndingType::Linux:
|
||||
Result.append('\n');
|
||||
case SynEditFileFormat::Windows:
|
||||
case FileEndingType::Windows:
|
||||
Result.append("\r\n");
|
||||
case SynEditFileFormat::Mac:
|
||||
case FileEndingType::Mac:
|
||||
Result.append("\r");
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
void SynEditStringList::put(int Index, const QString &s)
|
||||
{
|
||||
void SynEditStringList::put(int Index, const QString &s) {
|
||||
if (Index == mList.count()) {
|
||||
Add(s);
|
||||
add(s);
|
||||
} else {
|
||||
if (Index<0 || Index>=mList.count()) {
|
||||
throw new std::out_of_range(QObject::tr("Index % s out of range").arg(Index).toLocal8Bit());
|
||||
ListIndexOutOfBounds(Index);
|
||||
}
|
||||
beginUpdate();
|
||||
mIndexOfLongestLine = -1;
|
||||
|
@ -316,7 +374,7 @@ void SynEditStringList::put(int Index, const QString &s)
|
|||
void SynEditStringList::putObject(int Index, void *AObject)
|
||||
{
|
||||
if (Index<0 || Index>=mList.count()) {
|
||||
throw new std::out_of_range(QObject::tr("Index % s out of range").arg(Index).toLocal8Bit());
|
||||
ListIndexOutOfBounds(Index);
|
||||
}
|
||||
beginUpdate();
|
||||
mList[Index]->fObject = AObject;
|
||||
|
@ -350,3 +408,496 @@ QString SynEditStringList::ExpandString(int Index)
|
|||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
void SynEditStringList::InsertLines(int Index, int NumLines)
|
||||
{
|
||||
if (Index<0 || Index>=mList.count()) {
|
||||
ListIndexOutOfBounds(Index);
|
||||
}
|
||||
if (NumLines<=0)
|
||||
return;
|
||||
beginUpdate();
|
||||
auto action = finally([this]{
|
||||
endUpdate();
|
||||
});
|
||||
PSynEditStringRec line;
|
||||
mList.insert(Index,NumLines,line);
|
||||
for (int i=Index;i<Index+NumLines;i++) {
|
||||
line = std::make_shared<SynEditStringRec>();
|
||||
mList[i]=line;
|
||||
}
|
||||
emit inserted(Index,NumLines);
|
||||
}
|
||||
|
||||
void SynEditStringList::InsertStrings(int Index, const QStringList &NewStrings)
|
||||
{
|
||||
if (Index<0 || Index>=mList.count()) {
|
||||
ListIndexOutOfBounds(Index);
|
||||
}
|
||||
if (NewStrings.isEmpty())
|
||||
return;
|
||||
beginUpdate();
|
||||
auto action = finally([this]{
|
||||
endUpdate();
|
||||
});
|
||||
PSynEditStringRec line;
|
||||
mList.insert(Index,NewStrings.length(),line);
|
||||
for (int i=0;i<NewStrings.length();i++) {
|
||||
line = std::make_shared<SynEditStringRec>();
|
||||
line->fString = NewStrings[i];
|
||||
mList[i+Index]=line;
|
||||
}
|
||||
emit inserted(Index,NewStrings.length());
|
||||
}
|
||||
|
||||
void SynEditStringList::InsertText(int Index, const QString &NewText)
|
||||
{
|
||||
if (Index<0 || Index>=mList.count()) {
|
||||
ListIndexOutOfBounds(Index);
|
||||
}
|
||||
if (NewText.isEmpty())
|
||||
return;
|
||||
QStringList lines = TextToLines(NewText);
|
||||
InsertStrings(Index,lines);
|
||||
}
|
||||
|
||||
void SynEditStringList::LoadFromFile(QFile &file, const QByteArray& encoding, QByteArray& realEncoding)
|
||||
{
|
||||
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()));
|
||||
beginUpdate();
|
||||
auto action = finally([this]{
|
||||
endUpdate();
|
||||
});
|
||||
|
||||
//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()) {
|
||||
realEncoding = ENCODING_ASCII;
|
||||
return;
|
||||
}
|
||||
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);
|
||||
codec = QTextCodec::codecForName(ENCODING_UTF8);
|
||||
} else {
|
||||
realEncoding = ENCODING_UTF8;
|
||||
codec = QTextCodec::codecForName(ENCODING_UTF8);
|
||||
}
|
||||
clear();
|
||||
do {
|
||||
if (allAscii) {
|
||||
allAscii = isTextAllAscii(line);
|
||||
}
|
||||
if (allAscii) {
|
||||
add(QString::fromLatin1(line));
|
||||
} else {
|
||||
QString newLine = codec->toUnicode(line.constData(),line.length(),state);
|
||||
if (state->invalidChars>0) {
|
||||
needReread = true;
|
||||
break;
|
||||
}
|
||||
add(newLine);
|
||||
}
|
||||
line = file.readLine();
|
||||
} while (!file.atEnd());
|
||||
if (!needReread) {
|
||||
if (allAscii)
|
||||
realEncoding = ENCODING_ASCII;
|
||||
return;
|
||||
}
|
||||
realEncoding = ENCODING_SYSTEM_DEFAULT;
|
||||
} else {
|
||||
realEncoding = encoding;
|
||||
}
|
||||
|
||||
if (realEncoding == ENCODING_SYSTEM_DEFAULT) {
|
||||
realEncoding = QTextCodec::codecForLocale()->name();
|
||||
}
|
||||
file.reset();
|
||||
QTextStream textStream(&file);
|
||||
if (realEncoding == ENCODING_UTF8_BOM) {
|
||||
textStream.setAutoDetectUnicode(true);
|
||||
textStream.setCodec(ENCODING_UTF8);
|
||||
} else {
|
||||
textStream.setAutoDetectUnicode(false);
|
||||
textStream.setCodec(realEncoding);
|
||||
}
|
||||
QString line;
|
||||
clear();
|
||||
while (textStream.readLineInto(&line)) {
|
||||
add(line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SynEditStringList::SaveToFile(QFile &file, const QByteArray& encoding, QByteArray& realEncoding)
|
||||
{
|
||||
if (!file.open(QFile::WriteOnly | QFile::Truncate | QFile::Text))
|
||||
throw FileError(tr("Can't open file '%1' for save!").arg(file.fileName()));
|
||||
if (mList.isEmpty())
|
||||
return;
|
||||
bool allAscii = true;
|
||||
|
||||
QTextCodec* codec;
|
||||
if (realEncoding == ENCODING_UTF8_BOM) {
|
||||
codec = QTextCodec::codecForName(ENCODING_UTF8_BOM);
|
||||
} else if (realEncoding == ENCODING_ASCII) {
|
||||
codec = QTextCodec::codecForLocale();
|
||||
}
|
||||
for (PSynEditStringRec& line:mList) {
|
||||
if (allAscii) {
|
||||
allAscii = isTextAllAscii(line->fString);
|
||||
}
|
||||
if (!allAscii) {
|
||||
file.write(codec->fromUnicode(line->fString));
|
||||
} else {
|
||||
file.write(line->fString.toLatin1());
|
||||
}
|
||||
switch (mFileEndingType) {
|
||||
case FileEndingType::Windows:
|
||||
file.write("\r\n");
|
||||
break;
|
||||
case FileEndingType::Linux:
|
||||
file.write("\n");
|
||||
break;
|
||||
case FileEndingType::Mac:
|
||||
file.write("\r");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (encoding == ENCODING_AUTO_DETECT && allAscii) {
|
||||
realEncoding = ENCODING_ASCII;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SynEditStringList::PutTextStr(const QString &text)
|
||||
{
|
||||
beginUpdate();
|
||||
auto action = finally([this]{
|
||||
endUpdate();
|
||||
});
|
||||
clear();
|
||||
int pos = 0;
|
||||
int start;
|
||||
while (pos < text.length()) {
|
||||
start = pos;
|
||||
while (pos<text.length()) {
|
||||
if (text[pos] == '\r' || text[pos] == '\n') {
|
||||
break;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
add(text.mid(start,pos-start));
|
||||
if (pos>=text.length())
|
||||
break;
|
||||
if (text[pos] == '\r')
|
||||
pos++;
|
||||
if (text[pos] == '\n')
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
FileEndingType SynEditStringList::getFileEndingType() const
|
||||
{
|
||||
return mFileEndingType;
|
||||
}
|
||||
|
||||
void SynEditStringList::setFileEndingType(const FileEndingType &fileEndingType)
|
||||
{
|
||||
mFileEndingType = fileEndingType;
|
||||
}
|
||||
|
||||
SynEditStringRec::SynEditStringRec():
|
||||
fString(),
|
||||
fObject(nullptr),
|
||||
fRange{0,0},
|
||||
fExpandedLength(-1),
|
||||
fParenthesisLevel(0),
|
||||
fBracketLevel(0),
|
||||
fBraceLevel(0),
|
||||
fFlags(SynEditStringFlag::sfExpandedLengthUnknown)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
SynEditUndoList::SynEditUndoList()
|
||||
{
|
||||
mMaxUndoActions = 1024;
|
||||
mNextChangeNumber = 1;
|
||||
mInsideRedo = false;
|
||||
|
||||
mBlockChangeNumber=0;
|
||||
mBlockCount=0;
|
||||
mFullUndoImposible=false;
|
||||
mLockCount = 0;
|
||||
mInitialChangeNumber = 0;
|
||||
}
|
||||
|
||||
void SynEditUndoList::AddChange(SynChangeReason AReason, const BufferCoord &AStart, const BufferCoord &AEnd, const QString &ChangeText, SynSelectionMode SelMode)
|
||||
{
|
||||
if (mLockCount != 0)
|
||||
return;
|
||||
int changeNumber;
|
||||
if (mBlockChangeNumber != 0) {
|
||||
changeNumber = mBlockChangeNumber;
|
||||
} else {
|
||||
changeNumber = mNextChangeNumber;
|
||||
if (mBlockCount == 0) {
|
||||
mNextChangeNumber++;
|
||||
if (mNextChangeNumber == 0) {
|
||||
mNextChangeNumber++;
|
||||
}
|
||||
}
|
||||
}
|
||||
PSynEditUndoItem NewItem = std::make_shared<SynEditUndoItem>(AReason,
|
||||
SelMode,AStart,AEnd,ChangeText,
|
||||
changeNumber);
|
||||
PushItem(NewItem);
|
||||
}
|
||||
|
||||
void SynEditUndoList::AddGroupBreak()
|
||||
{
|
||||
//Add the GroupBreak even if ItemCount = 0. Since items are stored in
|
||||
//reverse order in TCustomSynEdit.fRedoList, a GroupBreak could be lost.
|
||||
if (LastChangeReason() != SynChangeReason::crGroupBreak) {
|
||||
AddChange(SynChangeReason::crGroupBreak, {0,0}, {0,0}, "", SynSelectionMode::smNormal);
|
||||
}
|
||||
}
|
||||
|
||||
void SynEditUndoList::BeginBlock()
|
||||
{
|
||||
mBlockCount++;
|
||||
mBlockChangeNumber = mNextChangeNumber;
|
||||
}
|
||||
|
||||
void SynEditUndoList::Clear()
|
||||
{
|
||||
mItems.clear();
|
||||
mFullUndoImposible = false;
|
||||
}
|
||||
|
||||
void SynEditUndoList::DeleteItem(int index)
|
||||
{
|
||||
if (index <0 || index>=mItems.count()) {
|
||||
ListIndexOutOfBounds(index);
|
||||
}
|
||||
mItems.removeAt(index);
|
||||
}
|
||||
|
||||
void SynEditUndoList::EndBlock()
|
||||
{
|
||||
if (mBlockCount > 0) {
|
||||
mBlockCount--;
|
||||
if (mBlockCount == 0) {
|
||||
int iBlockID = mBlockChangeNumber;
|
||||
mBlockChangeNumber = 0;
|
||||
mNextChangeNumber++;
|
||||
if (mNextChangeNumber == 0)
|
||||
mNextChangeNumber++;
|
||||
if (mItems.count() > 0 && PeekItem()->changeNumber() == iBlockID)
|
||||
emit addedUndo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SynChangeReason SynEditUndoList::LastChangeReason()
|
||||
{
|
||||
if (mItems.count() == 0)
|
||||
return SynChangeReason::crNothing;
|
||||
else
|
||||
mItems.last()->changeReason();
|
||||
}
|
||||
|
||||
void SynEditUndoList::Lock()
|
||||
{
|
||||
mLockCount++;
|
||||
}
|
||||
|
||||
PSynEditUndoItem SynEditUndoList::PeekItem()
|
||||
{
|
||||
if (mItems.count() == 0)
|
||||
return PSynEditUndoItem();
|
||||
else
|
||||
return mItems.last();
|
||||
}
|
||||
|
||||
PSynEditUndoItem SynEditUndoList::PopItem()
|
||||
{
|
||||
if (mItems.count() == 0)
|
||||
return PSynEditUndoItem();
|
||||
else {
|
||||
PSynEditUndoItem item = mItems.last();
|
||||
mItems.removeLast();
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
void SynEditUndoList::PushItem(PSynEditUndoItem Item)
|
||||
{
|
||||
if (!Item)
|
||||
return;
|
||||
mItems.append(Item);
|
||||
EnsureMaxEntries();
|
||||
if (Item->changeReason()!= SynChangeReason::crGroupBreak)
|
||||
addedUndo();
|
||||
}
|
||||
|
||||
void SynEditUndoList::Unlock()
|
||||
{
|
||||
if (mLockCount > 0)
|
||||
mLockCount--;
|
||||
}
|
||||
|
||||
bool SynEditUndoList::CanUndo()
|
||||
{
|
||||
return mItems.count()>0;
|
||||
}
|
||||
|
||||
int SynEditUndoList::ItemCount()
|
||||
{
|
||||
return mItems.count();
|
||||
}
|
||||
|
||||
int SynEditUndoList::maxUndoActions() const
|
||||
{
|
||||
return mMaxUndoActions;
|
||||
}
|
||||
|
||||
void SynEditUndoList::setMaxUndoActions(int maxUndoActions)
|
||||
{
|
||||
mMaxUndoActions = maxUndoActions;
|
||||
}
|
||||
|
||||
bool SynEditUndoList::initialState()
|
||||
{
|
||||
if (ItemCount() == 0) {
|
||||
return mInitialChangeNumber == 0;
|
||||
} else {
|
||||
return PeekItem()->changeNumber() == mInitialChangeNumber;
|
||||
}
|
||||
}
|
||||
|
||||
PSynEditUndoItem SynEditUndoList::item(int index)
|
||||
{
|
||||
if (index <0 || index>=mItems.count()) {
|
||||
ListIndexOutOfBounds(index);
|
||||
}
|
||||
return mItems[index];
|
||||
}
|
||||
|
||||
void SynEditUndoList::setInitialState(const bool Value)
|
||||
{
|
||||
if (Value) {
|
||||
if (ItemCount() == 0)
|
||||
mInitialChangeNumber = 0;
|
||||
else
|
||||
mInitialChangeNumber = PeekItem()->changeNumber();
|
||||
} else if (ItemCount() == 0) {
|
||||
if (mInitialChangeNumber == 0) {
|
||||
mInitialChangeNumber = -1;
|
||||
}
|
||||
} else if (PeekItem()->changeNumber() == mInitialChangeNumber) {
|
||||
mInitialChangeNumber = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void SynEditUndoList::setItem(int index, PSynEditUndoItem Value)
|
||||
{
|
||||
if (index <0 || index>=mItems.count()) {
|
||||
ListIndexOutOfBounds(index);
|
||||
}
|
||||
mItems[index]=Value;
|
||||
}
|
||||
|
||||
int SynEditUndoList::blockChangeNumber() const
|
||||
{
|
||||
return mBlockChangeNumber;
|
||||
}
|
||||
|
||||
void SynEditUndoList::setBlockChangeNumber(int blockChangeNumber)
|
||||
{
|
||||
mBlockChangeNumber = blockChangeNumber;
|
||||
}
|
||||
|
||||
int SynEditUndoList::blockCount() const
|
||||
{
|
||||
return mBlockCount;
|
||||
}
|
||||
|
||||
bool SynEditUndoList::insideRedo() const
|
||||
{
|
||||
return mInsideRedo;
|
||||
}
|
||||
|
||||
void SynEditUndoList::setInsideRedo(bool insideRedo)
|
||||
{
|
||||
mInsideRedo = insideRedo;
|
||||
}
|
||||
|
||||
bool SynEditUndoList::fullUndoImposible() const
|
||||
{
|
||||
return mFullUndoImposible;
|
||||
}
|
||||
|
||||
void SynEditUndoList::EnsureMaxEntries()
|
||||
{
|
||||
if (mItems.count() > mMaxUndoActions){
|
||||
mFullUndoImposible = true;
|
||||
while (mItems.count() > mMaxUndoActions) {
|
||||
mItems.removeFirst();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SynSelectionMode SynEditUndoItem::changeSelMode() const
|
||||
{
|
||||
return mChangeSelMode;
|
||||
}
|
||||
|
||||
BufferCoord SynEditUndoItem::changeStartPos() const
|
||||
{
|
||||
return mChangeStartPos;
|
||||
}
|
||||
|
||||
BufferCoord SynEditUndoItem::changeEndPos() const
|
||||
{
|
||||
return mChangeEndPos;
|
||||
}
|
||||
|
||||
QString SynEditUndoItem::changeStr() const
|
||||
{
|
||||
return mChangeStr;
|
||||
}
|
||||
|
||||
int SynEditUndoItem::changeNumber() const
|
||||
{
|
||||
return mChangeNumber;
|
||||
}
|
||||
|
||||
SynEditUndoItem::SynEditUndoItem(SynChangeReason reason, SynSelectionMode selMode,
|
||||
BufferCoord startPos, BufferCoord endPos,
|
||||
const QString &str, int number)
|
||||
{
|
||||
mChangeReason = reason;
|
||||
mChangeSelMode = selMode;
|
||||
mChangeStartPos = startPos;
|
||||
mChangeEndPos = endPos;
|
||||
mChangeStr = str;
|
||||
mChangeNumber = number;
|
||||
}
|
||||
|
||||
SynChangeReason SynEditUndoItem::changeReason() const
|
||||
{
|
||||
return mChangeReason;
|
||||
}
|
||||
|
|
|
@ -3,9 +3,11 @@
|
|||
|
||||
#include <QStringList>
|
||||
#include "highlighter/base.h"
|
||||
#include <QList>
|
||||
#include <QVector>
|
||||
#include <memory>
|
||||
#include "MiscProcs.h"
|
||||
#include "../utils.h"
|
||||
#include "Types.h"
|
||||
|
||||
enum SynEditStringFlag {
|
||||
sfHasTabs = 0x0001,
|
||||
|
@ -24,11 +26,14 @@ struct SynEditStringRec {
|
|||
int fParenthesisLevel;
|
||||
int fBracketLevel;
|
||||
int fBraceLevel;
|
||||
|
||||
public:
|
||||
explicit SynEditStringRec();
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<SynEditStringRec> PSynEditStringRec;
|
||||
|
||||
typedef QList<PSynEditStringRec> SynEditStringRecList;
|
||||
typedef QVector<PSynEditStringRec> SynEditStringRecList;
|
||||
|
||||
typedef std::shared_ptr<SynEditStringRecList> PSynEditStringRecList;
|
||||
|
||||
|
@ -36,15 +41,9 @@ class SynEditStringList;
|
|||
|
||||
typedef std::shared_ptr<SynEditStringList> PSynEditStringList;
|
||||
|
||||
using StringListChangeCallback = void (*) (PSynEditStringList* object, int index, int count);
|
||||
|
||||
enum class SynEditFileFormat {
|
||||
Windows,
|
||||
Linux,
|
||||
Mac
|
||||
};// Windows: CRLF, UNIX: LF, Mac: CR
|
||||
|
||||
using StringListChangeCallback = std::function<void(PSynEditStringList* object, int index, int count)>;
|
||||
|
||||
class QFile;
|
||||
class SynEditStringList : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -66,6 +65,7 @@ public:
|
|||
int count();
|
||||
void* getObject(int Index);
|
||||
QString text();
|
||||
void setText(const QString& text);
|
||||
|
||||
void put(int Index, const QString& s);
|
||||
void putObject(int Index, void * AObject);
|
||||
|
@ -75,46 +75,29 @@ public:
|
|||
|
||||
int tabWidth();
|
||||
void setTabWidth(int value);
|
||||
int Add(const QString& s);
|
||||
int AddStrings(const QStringList& Strings);
|
||||
int add(const QString& s);
|
||||
int addStrings(const QStringList& Strings);
|
||||
|
||||
int getTextLength();
|
||||
void Clear();
|
||||
void Delete(int Index);
|
||||
procedure DeleteLines(Index, NumLines: integer);
|
||||
procedure Exchange(Index1, Index2: integer); override;
|
||||
procedure Insert(Index: integer; const S: string); override;
|
||||
procedure InsertLines(Index, NumLines: integer);
|
||||
procedure InsertStrings(Index: integer; NewStrings: TStrings);
|
||||
procedure InsertText(Index: integer; NewText: string);
|
||||
procedure LoadFromFile(const FileName: string); override;
|
||||
procedure SaveToFile(const FileName: string); override;
|
||||
procedure SaveToStream(Stream: TStream); override;
|
||||
procedure LoadFromStream(Stream: TStream); override;
|
||||
property AppendNewLineAtEOF: Boolean read fAppendNewLineAtEOF write fAppendNewLineAtEOF;
|
||||
property FileFormat: TSynEditFileFormat read fFileFormat write fFileFormat;
|
||||
property ExpandedStrings[Index: integer]: string read expandedStrings;
|
||||
property ExpandedStringLengths[Index: integer]: integer read expandedStringLength;
|
||||
property LengthOfLongestLine: integer read lengthOfLongestLine;
|
||||
property Ranges[Index: integer]: TSynEditRange read GetRange write setRange;
|
||||
property ParenthesisLevels[Index: integer]: integer read GetParenthesisLevel write setParenthesisLevel;
|
||||
property BracketLevels[Index: integer]: integer read GetBracketLevel write setBracketLevel;
|
||||
property BraceLevels[Index: integer]: integer read GetBraceLevel write setBraceLevel;
|
||||
property TabWidth: integer read fTabWidth write setTabWidth;
|
||||
property OnChange: TNotifyEvent read fOnChange write fOnChange;
|
||||
property OnChanging: TNotifyEvent read fOnChanging write fOnChanging;
|
||||
property OnCleared: TNotifyEvent read fOnCleared write fOnCleared;
|
||||
property OnDeleted: TStringListChangeEvent read fOnDeleted write fOnDeleted;
|
||||
property OnInserted: TStringListChangeEvent read fOnInserted
|
||||
write fOnInserted;
|
||||
property OnPutted: TStringListChangeEvent read fOnPutted write fOnPutted;
|
||||
property ConvertTabsProc: TConvertTabsProcEx read fConvertTabsProc;
|
||||
void clear();
|
||||
void deleteAt(int Index);
|
||||
void deleteLines(int Index, int NumLines);
|
||||
void Exchange(int Index1, int Index2);
|
||||
void Insert(int Index, const QString& s);
|
||||
void InsertLines(int Index, int NumLines);
|
||||
void InsertStrings(int Index, const QStringList& NewStrings);
|
||||
void InsertText(int Index,const QString& NewText);
|
||||
void LoadFromFile(QFile& file, const QByteArray& encoding, QByteArray& realEncoding);
|
||||
void SaveToFile(QFile& file, const QByteArray& encoding, QByteArray& realEncoding);
|
||||
|
||||
bool getAppendNewLineAtEOF() const;
|
||||
void setAppendNewLineAtEOF(bool appendNewLineAtEOF);
|
||||
|
||||
ConvertTabsProcEx getConvertTabsProc() const;
|
||||
|
||||
FileEndingType getFileEndingType() const;
|
||||
void setFileEndingType(const FileEndingType &fileEndingType);
|
||||
|
||||
signals:
|
||||
void changed();
|
||||
void changing();
|
||||
|
@ -126,22 +109,117 @@ protected:
|
|||
QString GetTextStr();
|
||||
void SetUpdateState(bool Updating);
|
||||
void InsertItem(int Index, const QString& s);
|
||||
|
||||
void PutTextStr(const QString& text);
|
||||
|
||||
private:
|
||||
SynEditStringRecList mList;
|
||||
|
||||
//int mCount;
|
||||
//int mCapacity;
|
||||
SynEditFileFormat mFileFormat;
|
||||
FileEndingType mFileEndingType;
|
||||
bool mAppendNewLineAtEOF;
|
||||
ConvertTabsProcEx mConvertTabsProc;
|
||||
int mIndexOfLongestLine;
|
||||
int mTabWidth;
|
||||
int mUpdateCount;
|
||||
|
||||
QString ExpandString(int Index);
|
||||
};
|
||||
|
||||
enum class SynChangeReason {crInsert, crPaste, crDragDropInsert,
|
||||
//several undo entries can be chained together via the ChangeNumber
|
||||
//see also TCustomSynEdit.[Begin|End]UndoBlock methods
|
||||
crDeleteAfterCursor, crDelete,
|
||||
crLineBreak, crIndent, crUnindent,
|
||||
crSilentDelete, crSilentDeleteAfterCursor,
|
||||
crAutoCompleteBegin, crAutoCompleteEnd,
|
||||
crPasteBegin, crPasteEnd, //for pasting, since it might do a lot of operations
|
||||
crSpecial1Begin, crSpecial1End,
|
||||
crSpecial2Begin, crSpecial2End,
|
||||
crCaret, //just restore the Caret, allowing better Undo behavior
|
||||
crSelection, //restore Selection
|
||||
crNothing,
|
||||
crGroupBreak,
|
||||
crDeleteAll
|
||||
};
|
||||
class SynEditUndoItem {
|
||||
private:
|
||||
SynChangeReason mChangeReason;
|
||||
SynSelectionMode mChangeSelMode;
|
||||
BufferCoord mChangeStartPos;
|
||||
BufferCoord mChangeEndPos;
|
||||
QString mChangeStr;
|
||||
int mChangeNumber;
|
||||
public:
|
||||
SynEditUndoItem(SynChangeReason reason,
|
||||
SynSelectionMode selMode,
|
||||
BufferCoord startPos,
|
||||
BufferCoord endPos,
|
||||
const QString& str,
|
||||
int number);
|
||||
|
||||
SynChangeReason changeReason() const;
|
||||
SynSelectionMode changeSelMode() const;
|
||||
BufferCoord changeStartPos() const;
|
||||
BufferCoord changeEndPos() const;
|
||||
QString changeStr() const;
|
||||
int changeNumber() const;
|
||||
};
|
||||
using PSynEditUndoItem = std::shared_ptr<SynEditUndoItem>;
|
||||
|
||||
class SynEditUndoList {
|
||||
public:
|
||||
explicit SynEditUndoList();
|
||||
|
||||
void AddChange(SynChangeReason AReason, const BufferCoord& AStart, const BufferCoord& AEnd,
|
||||
const QString& ChangeText, SynSelectionMode SelMode);
|
||||
|
||||
void AddGroupBreak();
|
||||
void BeginBlock();
|
||||
void Clear();
|
||||
void DeleteItem(int index);
|
||||
void EndBlock();
|
||||
SynChangeReason LastChangeReason();
|
||||
void Lock();
|
||||
PSynEditUndoItem PeekItem();
|
||||
PSynEditUndoItem PopItem();
|
||||
void PushItem(PSynEditUndoItem Item);
|
||||
void Unlock();
|
||||
|
||||
bool CanUndo();
|
||||
int ItemCount();
|
||||
|
||||
int maxUndoActions() const;
|
||||
void setMaxUndoActions(int maxUndoActions);
|
||||
bool initialState();
|
||||
PSynEditUndoItem item(int index);
|
||||
void setInitialState(const bool Value);
|
||||
void setItem(int index, PSynEditUndoItem Value);
|
||||
|
||||
int blockChangeNumber() const;
|
||||
void setBlockChangeNumber(int blockChangeNumber);
|
||||
|
||||
int blockCount() const;
|
||||
|
||||
bool insideRedo() const;
|
||||
void setInsideRedo(bool insideRedo);
|
||||
|
||||
bool fullUndoImposible() const;
|
||||
|
||||
signals:
|
||||
void addedUndo();
|
||||
|
||||
protected:
|
||||
int mBlockChangeNumber;
|
||||
int mBlockCount;
|
||||
bool mFullUndoImposible;
|
||||
QVector<PSynEditUndoItem> mItems;
|
||||
int mLockCount;
|
||||
int mMaxUndoActions;
|
||||
int mNextChangeNumber;
|
||||
int mInitialChangeNumber;
|
||||
bool mInsideRedo;
|
||||
void EnsureMaxEntries();
|
||||
};
|
||||
|
||||
#endif // SYNEDITSTRINGLIST_H
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef TYPES_H
|
||||
#define TYPES_H
|
||||
enum class SynSelectionMode {smNormal, smLine, smColumn};
|
||||
|
||||
struct BufferCoord {
|
||||
int Char;
|
||||
int Line;
|
||||
};
|
||||
|
||||
struct DisplayCoord {
|
||||
int Column;
|
||||
int Row;
|
||||
};
|
||||
#endif // TYPES_H
|
|
@ -7,6 +7,7 @@
|
|||
#include <QMap>
|
||||
#include <QSet>
|
||||
#include <QVector>
|
||||
#include <QVector>
|
||||
|
||||
typedef struct {
|
||||
int state;
|
||||
|
@ -151,6 +152,6 @@ private:
|
|||
};
|
||||
|
||||
using PSynHighlighter = std::shared_ptr<SynHighlighter>;
|
||||
using SynHighlighterList = QList<PSynHighlighter>;
|
||||
using SynHighlighterList = QVector<PSynHighlighter>;
|
||||
|
||||
#endif // SYNHIGHLIGTERBASE_H
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
class SynSchema;
|
||||
using PSynSchema = std::shared_ptr<SynSchema>;
|
||||
|
||||
using OnCheckMarker = void (*)(PSynSchema Sender,int &StartPos, int &MarkerLen,
|
||||
std::shared_ptr<QString>& MarkerText , int Line);
|
||||
using OnCheckMarker = std::function<void(PSynSchema Sender,int &StartPos, int &MarkerLen,
|
||||
std::shared_ptr<QString>& MarkerText , int Line)>;
|
||||
|
||||
class SynScheme : public QObject {
|
||||
Q_OBJECT
|
||||
|
|
|
@ -253,3 +253,79 @@ QString toLocalPath(const QString &filename)
|
|||
newPath.replace("/",QDir::separator());
|
||||
return newPath;
|
||||
}
|
||||
|
||||
QStringList TextToLines(const QString &text)
|
||||
{
|
||||
QTextStream stream(&((QString&)text),QIODevice::ReadOnly);
|
||||
return ReadStreamToLines(&stream);
|
||||
}
|
||||
|
||||
QStringList ReadFileToLines(const QString& fileName, QTextCodec* codec)
|
||||
{
|
||||
QFile file(fileName);
|
||||
if (file.open(QFile::ReadOnly)) {
|
||||
QTextStream stream(&file);
|
||||
stream.setCodec(codec);
|
||||
stream.setAutoDetectUnicode(false);
|
||||
return ReadStreamToLines(&stream);
|
||||
}
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
QStringList ReadStreamToLines(QTextStream *stream)
|
||||
{
|
||||
QStringList list;
|
||||
QString s;
|
||||
while (stream->readLineInto(&s)) {
|
||||
list.append(s);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
void ReadStreamToLines(QTextStream *stream,
|
||||
LineProcessFunc lineFunc)
|
||||
{
|
||||
QString s;
|
||||
while (stream->readLineInto(&s)) {
|
||||
lineFunc(s);
|
||||
}
|
||||
}
|
||||
|
||||
void TextToLines(const QString &text, LineProcessFunc lineFunc)
|
||||
{
|
||||
QTextStream stream(&((QString&)text),QIODevice::ReadOnly);
|
||||
ReadStreamToLines(&stream,lineFunc);
|
||||
}
|
||||
|
||||
void ReadFileToLines(const QString &fileName, QTextCodec *codec, LineProcessFunc lineFunc)
|
||||
{
|
||||
QFile file(fileName);
|
||||
if (file.open(QFile::ReadOnly)) {
|
||||
QTextStream stream(&file);
|
||||
stream.setCodec(codec);
|
||||
stream.setAutoDetectUnicode(false);
|
||||
ReadStreamToLines(&stream, lineFunc);
|
||||
}
|
||||
}
|
||||
|
||||
BaseError::BaseError(const QString &reason):
|
||||
mReason(reason)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString BaseError::reason() const
|
||||
{
|
||||
return mReason;
|
||||
}
|
||||
|
||||
IndexOutOfRange::IndexOutOfRange(int Index):
|
||||
BaseError(QObject::tr("Index %1 out of range").arg(Index))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
FileError::FileError(const QString &reason): BaseError(reason)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
@ -3,10 +3,14 @@
|
|||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <functional>
|
||||
#include <QString>
|
||||
|
||||
class QByteArray;
|
||||
class QString;
|
||||
class QStringList;
|
||||
class QTextStream;
|
||||
class QTextCodec;
|
||||
|
||||
#define ENCODING_AUTO_DETECT "AUTO"
|
||||
#define ENCODING_UTF8 "UTF-8"
|
||||
|
@ -23,6 +27,31 @@ enum class FileType{
|
|||
Other // any others
|
||||
};
|
||||
|
||||
enum class FileEndingType {
|
||||
Windows,
|
||||
Linux,
|
||||
Mac
|
||||
};// Windows: CRLF, UNIX: LF, Mac: CR
|
||||
|
||||
class BaseError{
|
||||
public:
|
||||
explicit BaseError(const QString& reason);
|
||||
QString reason() const;
|
||||
|
||||
protected:
|
||||
QString mReason;
|
||||
};
|
||||
|
||||
class IndexOutOfRange:public BaseError {
|
||||
public:
|
||||
explicit IndexOutOfRange(int Index);
|
||||
};
|
||||
|
||||
class FileError: public BaseError {
|
||||
public:
|
||||
explicit FileError(const QString& reason);
|
||||
};
|
||||
|
||||
typedef void (*LineOutputFunc) (const QString& line);
|
||||
typedef bool (*CheckAbortFunc) ();
|
||||
bool isGreenEdition();
|
||||
|
@ -46,6 +75,21 @@ void splitStringArguments(const QString& arguments, QStringList& argumentList);
|
|||
bool programHasConsole(const QString& filename);
|
||||
QString toLocalPath(const QString& filename);
|
||||
|
||||
using LineProcessFunc = std::function<void(const QString&)>;
|
||||
|
||||
QStringList ReadStreamToLines(QTextStream* stream);
|
||||
|
||||
void ReadStreamToLines(QTextStream* stream, LineProcessFunc lineFunc);
|
||||
|
||||
|
||||
QStringList TextToLines(const QString& text);
|
||||
|
||||
void TextToLines(const QString& text, LineProcessFunc lineFunc);
|
||||
|
||||
QStringList ReadFileToLines(const QString& fileName, QTextCodec* codec);
|
||||
|
||||
void ReadFileToLines(const QString& fileName, QTextCodec* codec, LineProcessFunc lineFunc);
|
||||
|
||||
template <class F>
|
||||
class final_action
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue