* work save; add rtf exporter

This commit is contained in:
royqh1979@gmail.com 2021-06-10 09:34:59 +08:00
parent 0f0ca96545
commit aea51d21e4
8 changed files with 574 additions and 4 deletions

View File

@ -26,6 +26,7 @@ SOURCES += \
qsynedit/SynEdit.cpp \ qsynedit/SynEdit.cpp \
qsynedit/TextBuffer.cpp \ qsynedit/TextBuffer.cpp \
qsynedit/TextPainter.cpp \ qsynedit/TextPainter.cpp \
qsynedit/exporter/synexporter.cpp \
qsynedit/highlighter/base.cpp \ qsynedit/highlighter/base.cpp \
qsynedit/highlighter/composition.cpp \ qsynedit/highlighter/composition.cpp \
qsynedit/highlighter/cpp.cpp \ qsynedit/highlighter/cpp.cpp \
@ -59,6 +60,7 @@ HEADERS += \
qsynedit/TextBuffer.h \ qsynedit/TextBuffer.h \
qsynedit/TextPainter.h \ qsynedit/TextPainter.h \
qsynedit/Types.h \ qsynedit/Types.h \
qsynedit/exporter/synexporter.h \
qsynedit/highlighter/base.h \ qsynedit/highlighter/base.h \
qsynedit/highlighter/composition.h \ qsynedit/highlighter/composition.h \
qsynedit/highlighter/cpp.h \ qsynedit/highlighter/cpp.h \

View File

@ -73,6 +73,8 @@ Editor::Editor(QWidget *parent, const QString& filename,
} }
applySettings(); applySettings();
connect(this,&SynEdit::statusChanged,this,&Editor::onStatusChanged);
} }
Editor::~Editor() { Editor::~Editor() {
@ -258,6 +260,99 @@ void Editor::onLinesChanged(int startLine, int count) {
qDebug()<<startLine<<count; qDebug()<<startLine<<count;
} }
void Editor::onStatusChanged(SynStatusChanges changes)
{
// if (not (scOpenFile in Changes)) and (fText.Lines.Count <> fLineCount)
// and (fText.Lines.Count <> 0) and ((fLineCount>0) or (fText.Lines.Count>1)) then begin
// if devCodeCompletion.Enabled
// and SameStr(mainForm.ClassBrowser.CurrentFile,FileName) // Don't reparse twice
// then begin
// Reparse;
// end;
// if fText.Focused and devEditor.AutoCheckSyntax and devEditor.CheckSyntaxWhenReturn
// and (fText.Highlighter = dmMain.Cpp) then begin
// mainForm.CheckSyntaxInBack(self);
// end;
// end;
// fLineCount := fText.Lines.Count;
// // scModified is only fired when the modified state changes
if (changes.testFlag(scModified)) {
updateCaption();
}
// if (fTabStopBegin >=0) and (fTabStopY=fText.CaretY) then begin
// if StartsStr(fLineBeforeTabStop,fText.LineText) and EndsStr(fLineAfterTabStop, fText.LineText) then
// fTabStopBegin := Length(fLineBeforeTabStop);
// if fLineAfterTabStop = '' then
// fTabStopEnd := Length(fText.LineText)+1
// else
// fTabStopEnd := Length(fText.LineText) - Length(fLineAfterTabStop);
// fXOffsetSince := fTabStopEnd - fText.CaretX;
// if (fText.CaretX < fTabStopBegin) or (fText.CaretX > (fTabStopEnd+1)) then begin
// fTabStopBegin :=-1;
// end;
// end;
// scSelection includes anything caret related
if (changes.testFlag(SynStatusChange::scSelection)) {
//MainForm.SetStatusbarLineCol;
// // Update the function tip
// fFunctionTip.ForceHide := false;
// if Assigned(fFunctionTipTimer) then begin
// if fFunctionTip.Activated and FunctionTipAllowed then begin
// fFunctionTip.Parser := fParser;
// fFunctionTip.FileName := fFileName;
// fFunctionTip.Show;
// end else begin // Reset the timer
// fFunctionTipTimer.Enabled := false;
// fFunctionTipTimer.Enabled := true;
// end;
}
// // Remove error line colors
// if not fIgnoreCaretChange then begin
// if (fErrorLine <> -1) and not fText.SelAvail then begin
// fText.InvalidateLine(fErrorLine);
// fText.InvalidateGutterLine(fErrorLine);
// fErrorLine := -1;
// end;
// end else
// fIgnoreCaretChange := false;
// if fText.SelAvail then begin
// if fText.GetWordAtRowCol(fText.CaretXY) = fText.SelText then begin
// fSelChanged:=True;
// BeginUpdate;
// EndUpdate;
// end else if fSelChanged then begin
// fSelChanged:=False; //invalidate to unhighlight others
// BeginUpdate;
// EndUpdate;
// end;
// end else if fSelChanged then begin
// fSelChanged:=False; //invalidate to unhighlight others
// BeginUpdate;
// EndUpdate;
// end;
// end;
// if scInsertMode in Changes then begin
// with MainForm.Statusbar do begin
// // Set readonly / insert / overwrite
// if fText.ReadOnly then
// Panels[2].Text := Lang[ID_READONLY]
// else if fText.InsertMode then
// Panels[2].Text := Lang[ID_INSERT]
// else
// Panels[2].Text := Lang[ID_OVERWRITE];
// end;
// end;
// mainForm.CaretList.AddCaret(self,fText.CaretY,fText.CaretX);
}
void Editor::applySettings() void Editor::applySettings()
{ {
SynEditorOptions options = eoAltSetsColumnMode | SynEditorOptions options = eoAltSetsColumnMode |

View File

@ -72,6 +72,7 @@ protected slots:
void onModificationChanged(bool status) ; void onModificationChanged(bool status) ;
void onCursorPositionChanged(int line, int index) ; void onCursorPositionChanged(int line, int index) ;
void onLinesChanged(int startLine, int count) ; void onLinesChanged(int startLine, int count) ;
void onStatusChanged(SynStatusChanges changes);
private: private:
static int newfileCount; static int newfileCount;

View File

@ -143,7 +143,7 @@ void MainWindow::on_actionOpen_triggered()
} }
void MainWindow::closeEvent(QCloseEvent *event) { void MainWindow::closeEvent(QCloseEvent *event) {
if (!mEditorList->closeAll(true)) { if (!mEditorList->closeAll(false)) {
event->ignore(); event->ignore();
return ; return ;
} }

View File

@ -58,8 +58,8 @@ SynEdit::SynEdit(QWidget *parent) : QAbstractScrollArea(parent)
mCaretColor = QColorConstants::Red; mCaretColor = QColorConstants::Red;
mActiveLineColor = QColorConstants::Svg::lightblue; mActiveLineColor = QColorConstants::Svg::lightblue;
mSelectedBackground = QColorConstants::Svg::lightgray; mSelectedBackground = palette().color(QPalette::Highlight);
mSelectedForeground = palette().color(QPalette::Text); mSelectedForeground = palette().color(QPalette::HighlightedText);
mBookMarkOpt.connect(&mBookMarkOpt, &SynBookMarkOpt::changed, this, &SynEdit::bookMarkOptionsChanged); mBookMarkOpt.connect(&mBookMarkOpt, &SynBookMarkOpt::changed, this, &SynEdit::bookMarkOptionsChanged);
// fRightEdge has to be set before FontChanged is called for the first time // fRightEdge has to be set before FontChanged is called for the first time

View File

@ -31,7 +31,7 @@ enum class SynEditCaretType {
ctVerticalLine=0, ctHorizontalLine=1, ctHalfBlock=2, ctBlock=3 ctVerticalLine=0, ctHorizontalLine=1, ctHalfBlock=2, ctBlock=3
}; };
enum class SynStatusChange { enum SynStatusChange {
scNone = 0, scNone = 0,
scAll = 0x0001, scAll = 0x0001,
scCaretX = 0x0002, scCaretX = 0x0002,

View File

@ -0,0 +1,252 @@
#include "synexporter.h"
#include <QClipboard>
#include <QGuiApplication>
#include <QMimeData>
#include <QTextCodec>
SynExporter::SynExporter()
{
mClipboardFormat = "text/plain";
mFont = QGuiApplication::font();
mBackgroundColor = QGuiApplication::palette().color(QPalette::Base);
mForegroundColor = QGuiApplication::palette().color(QPalette::Text);
mUseBackground = false;
mExportAsText = false;
clear();
setTitle("");
}
void SynExporter::clear()
{
mBuffer.clear();
mLastStyle = SynFontStyle::fsNone;
mLastBG = QGuiApplication::palette().color(QPalette::Base);
mLastFG = QGuiApplication::palette().color(QPalette::Text);
}
void SynExporter::CopyToClipboard()
{
if (mExportAsText) {
CopyToClipboardFormat("text/plain");
} else
CopyToClipboardFormat(clipboardFormat());
}
bool SynExporter::exportAsText() const
{
return mExportAsText;
}
void SynExporter::setExportAsText(bool Value)
{
if (mExportAsText != Value) {
mExportAsText = Value;
clear();
}
}
QFont SynExporter::font() const
{
return mFont;
}
void SynExporter::setFont(const QFont &font)
{
mFont = font;
}
PSynHighlighter SynExporter::highlighter() const
{
return mHighlighter;
}
void SynExporter::setHighlighter(PSynHighlighter Value)
{
if (mHighlighter != Value) {
mHighlighter = Value;
clear();
if ((mHighlighter) && (mHighlighter->whitespaceAttribute()) && mUseBackground)
mBackgroundColor = mHighlighter->whitespaceAttribute()->background();
}
}
QString SynExporter::title() const
{
return mTitle;
}
void SynExporter::setTitle(const QString &Value)
{
if (mTitle != Value) {
if (!Value.isEmpty())
mTitle = Value;
else
mTitle = QObject::tr("Untitled");
}
}
bool SynExporter::useBackground() const
{
return mUseBackground;
}
void SynExporter::setUseBackground(bool Value)
{
if (mUseBackground != Value) {
mUseBackground = Value;
clear();
if ((mHighlighter) && (mHighlighter->whitespaceAttribute()) && mUseBackground)
mBackgroundColor = mHighlighter->whitespaceAttribute()->background();
}
}
FileEndingType SynExporter::fileEndingType() const
{
return mFileEndingType;
}
void SynExporter::setFileEndingType(const FileEndingType &fileEndingType)
{
mFileEndingType = fileEndingType;
}
QColor SynExporter::foregroundColor() const
{
return mForegroundColor;
}
void SynExporter::setForegroundColor(const QColor &value)
{
if (mForegroundColor != value) {
mForegroundColor = value;
}
}
QColor SynExporter::backgroundColor() const
{
return mBackgroundColor;
}
void SynExporter::setBackgroundColor(const QColor &value)
{
if (mBackgroundColor != value) {
mBackgroundColor = value;
}
}
QByteArray SynExporter::charset() const
{
return mCharset;
}
void SynExporter::setCharset(const QByteArray &charset)
{
mCharset = charset;
}
void SynExporter::AddData(const QString &AText)
{
if (!AText.isEmpty()) {
QTextCodec* codec = QTextCodec::codecForName(mCharset);
mBuffer.append(codec->fromUnicode(AText));
}
}
void SynExporter::AddDataNewLine(const QString &AText)
{
AddData(AText);
AddNewLine();
}
void SynExporter::AddNewLine()
{
switch(mFileEndingType) {
case FileEndingType::Linux:
AddData("\n");
case FileEndingType::Windows:
AddData("\r\n");
case FileEndingType::Mac:
AddData("\r");
}
}
void SynExporter::CopyToClipboardFormat(QByteArray AFormat)
{
QClipboard* clipboard = QGuiApplication::clipboard();
QMimeData * mimeData = new QMimeData();
mimeData->setData(AFormat,mBuffer);
clipboard->setMimeData(mimeData);
}
void SynExporter::FormatToken(QString &Token)
{
AddData(Token);
}
int SynExporter::GetBufferSize()
{
return mBuffer.size();
}
void SynExporter::InsertData(int APos, const QString &AText)
{
if (!AText.isEmpty()) {
QTextCodec* codec = QTextCodec::codecForName(mCharset);
mBuffer.insert(APos,codec->fromUnicode(AText));
}
}
QString SynExporter::ReplaceReservedChars(QString &AToken)
{
if (AToken.isEmpty())
return "";
QString result;
for (QChar ch:AToken) {
if (mReplaceReserved.contains(ch)) {
result += mReplaceReserved[ch];
} else {
result += ch;
}
}
return result;
}
static QColor ValidatedColor(const QColor& color, const QColor& defaultColor) {
if (color.isValid())
return color;
else
return defaultColor;
}
void SynExporter::SetTokenAttribute(PSynHighlighterAttribute Attri)
{
if (mFirstAttribute) {
mFirstAttribute = false;
mLastBG = ValidatedColor(Attri->background(), mBackgroundColor);
mLastFG = ValidatedColor(Attri->foreground(), mForegroundColor);
mLastStyle = Attri->styles();
FormatBeforeFirstAttribute(
mUseBackground && (mLastBG != mBackgroundColor),
mLastFG != mForegroundColor, Attri->styles());
} else {
bool ChangedBG = mUseBackground &&
(mLastBG != ValidatedColor(Attri->background(), mBackgroundColor));
bool ChangedFG = (mLastFG != ValidatedColor(Attri->foreground(), mForegroundColor));
if (ChangedBG || ChangedFG || (mLastStyle != Attri->styles())) {
// which font style bits are to reset?
SynFontStyles ChangedStyles = mLastStyle & ~(Attri->styles());
FormatAttributeDone(ChangedBG, ChangedFG, ChangedStyles);
// which font style bits are to set?
ChangedStyles = Attri->styles() & ~(mLastStyle);
mLastBG = ValidatedColor(Attri->background(), mBackgroundColor);
mLastFG = ValidatedColor(Attri->foreground(), mForegroundColor);
mLastStyle = Attri->styles();
FormatAttributeInit(ChangedBG, ChangedFG, ChangedStyles);
}
}
}
QByteArray SynExporter::clipboardFormat()
{
return this->mClipboardFormat;
}

View File

@ -0,0 +1,220 @@
#ifndef SYNEXPORTER_H
#define SYNEXPORTER_H
#include <QString>
#include "../SynEdit.h"
using FormatTokenHandler = std::function<void(int Line, int column, QString& token,
PSynHighlighterAttribute attr)>;
class SynExporter
{
public:
explicit SynExporter();
/**
* @brief Clears the output buffer and any internal data that relates to the last
* exported text.
*/
virtual void clear();
/**
* @brief Copies the output buffer contents to the clipboard, as the native format
* or as text depending on the ExportAsText property.
*/
void CopyToClipboard();
/**
* @brief Exports everything in the strings parameter to the output buffer.
* @param ALines
*/
void ExportAll(const SynEditStringList& ALines);
/**
* @brief Exports the given range of the strings parameter to the output buffer.
* @param ALines
* @param Start
* @param Stop
*/
void ExportRange(const SynEditStringList& ALines,
const BufferCoord& Start, const BufferCoord& Stop);
/**
* @brief Saves the contents of the output buffer to a file.
* @param AFileName
*/
void SaveToFile(const QString& AFileName);
/**
* @brief Saves the contents of the output buffer to a stream.
* @param AStream
*/
void SaveToStream(const QIODevice& AStream);
bool exportAsText() const;
void setExportAsText(bool Value);
QFont font() const;
void setFont(const QFont &font);
PSynHighlighter highlighter() const;
void setHighlighter(PSynHighlighter Value);
QString title() const;
void setTitle(const QString &Value);
bool useBackground() const;
void setUseBackground(bool Value);
FileEndingType fileEndingType() const;
void setFileEndingType(const FileEndingType &fileEndingType);
/**
* @brief The clipboard format the exporter creates as native format.
* @return
*/
virtual QByteArray clipboardFormat();
QColor foregroundColor() const;
void setForegroundColor(const QColor &value);
QColor backgroundColor() const;
void setBackgroundColor(const QColor &value);
QByteArray charset() const;
void setCharset(const QByteArray &charset);
protected:
QByteArray mCharset;
QColor mBackgroundColor;
QColor mForegroundColor;
QByteArray mClipboardFormat;
QString mDefaultFilter;
bool mExportAsText;
QFont mFont;
PSynHighlighter mHighlighter;
QColor mLastBG;
QColor mLastFG;
SynFontStyles mLastStyle;
QMap<QChar,QString> mReplaceReserved;
QString mTitle;
bool mUseBackground;
FileEndingType mFileEndingType;
/**
* @brief Adds a string to the output buffer.
* @param AText
*/
void AddData(const QString& AText);
/**
* @brief Adds a string and a trailing newline to the output buffer.
* @param AText
*/
void AddDataNewLine(const QString& AText);
/**
* @brief Adds a newline to the output buffer.
*/
void AddNewLine();
/**
* @brief Copies the data under this format to the clipboard. The clipboard has to
* be opened explicitly when more than one format is to be set.
*/
void CopyToClipboardFormat(QByteArray AFormat);
/**
* @brief Has to be overridden in descendant classes to add the closing format
* strings to the output buffer. The parameters can be used to track what
* changes are made for the next token.
* @param BackgroundChanged
* @param ForegroundChanged
* @param FontStylesChanged
*/
virtual void FormatAttributeDone(bool BackgroundChanged, bool ForegroundChanged,
SynFontStyles FontStylesChanged) = 0;
/**
* @brief Has to be overridden in descendant classes to add the opening format
* strings to the output buffer. The parameters can be used to track what
* changes have been made in respect to the previous token.
* @param BackgroundChanged
* @param ForegroundChanged
* @param FontStylesChanged
*/
virtual void FormatAttributeInit(bool BackgroundChanged, bool ForegroundChanged,
SynFontStyles FontStylesChanged) = 0;
/**
* @brief Has to be overridden in descendant classes to add the closing format
* strings to the output buffer after the last token has been written.
*/
virtual void FormatAfterLastAttribute() = 0;
/**
* @brief Has to be overridden in descendant classes to add the opening format
* strings to the output buffer when the first token is about to be written.
* @param BackgroundChanged
* @param ForegroundChanged
* @param FontStylesChanged
*/
virtual void FormatBeforeFirstAttribute(bool BackgroundChanged, bool ForegroundChanged,
SynFontStyles FontStylesChanged) = 0;
/**
* @brief Can be overridden in descendant classes to add the formatted text of
* the actual token text to the output buffer.
*/
virtual void FormatToken(QString& Token) ;
/**
* @brief Has to be overridden in descendant classes to add a newline in the output
* format to the output buffer.
*/
virtual void FormatNewLine() = 0;
/**
* @brief Returns the size of the formatted text in the output buffer, to be used
* in the format header or footer.
* @return
*/
int GetBufferSize();
/**
* @brief Has to be overridden in descendant classes to return the correct output
* format footer.
* @return
*/
virtual QString GetFooter() = 0;
/**
* @brief Has to be overridden in descendant classes to return the name of the
* output format.
* @return
*/
virtual QString GetFormatName() = 0;
/**
* @brief Has to be overridden in descendant classes to return the correct output
* format header.
* @return
*/
virtual QString GetHeader() = 0;
/**
* @brief Inserts a data block at the given position into the output buffer. Is
* used to insert the format header after the exporting, since some header
* data may be known only after the conversion is done.
* @param APos
* @param AText
*/
void InsertData(int APos, const QString& AText);
/**
* @brief Returns a string that has all the invalid chars of the output format
* replaced with the entries in the replacement array.
*/
QString ReplaceReservedChars(QString &AToken);
/**
* @brief Sets the token attribute of the next token to determine the changes
* of colors and font styles so the properties of the next token can be
* added to the output buffer.
* @param Attri
*/
virtual void SetTokenAttribute(PSynHighlighterAttribute Attri);
private:
QByteArray mBuffer;
bool mFirstAttribute;
FormatTokenHandler mOnFormatToken;
};
#endif // SYNEXPORTER_H