- implement: export as rtf / export as html

- fix: the contents copied/exported are not correctly syntax colored
 - fix: stop execution if the source file is not compiled and user choose not to compile it
This commit is contained in:
royqh1979@gmail.com 2021-10-12 09:47:58 +08:00
parent 80be584700
commit bb8b711376
12 changed files with 234 additions and 26 deletions

View File

@ -1,3 +1,8 @@
Version 0.6.5
- implement: export as rtf / export as html
- fix: the contents copied/exported are not correctly syntax colored
- fix: stop execution if the source file is not compiled and user choose not to compile it
Version 0.6.4 Version 0.6.4
- fix: code completion popup not show after '->' inputted - fix: code completion popup not show after '->' inputted
- fix: font styles in the color scheme settings not in effect - fix: font styles in the color scheme settings not in effect

View File

@ -57,7 +57,7 @@ PSynHighlighter HighlighterManager::getCppHighlighter()
highlighter->localVarAttribute()->setForeground(QColorConstants::Black); highlighter->localVarAttribute()->setForeground(QColorConstants::Black);
highlighter->numberAttribute()->setForeground(0x1750EB); highlighter->numberAttribute()->setForeground(0x1750EB);
highlighter->octAttribute()->setForeground(QColorConstants::Svg::purple); highlighter->octAttribute()->setForeground(QColorConstants::Svg::purple);
highlighter->direcAttribute()->setForeground(0x1f542e); highlighter->preprocessorAttribute()->setForeground(0x1f542e);
highlighter->keywordAttribute()->setForeground(0x0033b3); highlighter->keywordAttribute()->setForeground(0x0033b3);
highlighter->whitespaceAttribute()->setForeground(QColorConstants::Svg::silver); highlighter->whitespaceAttribute()->setForeground(QColorConstants::Svg::silver);
highlighter->stringAttribute()->setForeground(0x007d17); highlighter->stringAttribute()->setForeground(0x007d17);

View File

@ -827,7 +827,7 @@ void Editor::onPreparePaintHighlightToken(int line, int aChar, const QString &to
// qDebug()<<token<<"-"<<attr->name()<<" - "<<line<<" : "<<aChar; // qDebug()<<token<<"-"<<attr->name()<<" - "<<line<<" : "<<aChar;
if (mParser && mCompletionPopup && (attr == highlighter()->identifierAttribute())) { if (mParser && (attr == highlighter()->identifierAttribute())) {
BufferCoord p{aChar,line}; BufferCoord p{aChar,line};
BufferCoord pBeginPos,pEndPos; BufferCoord pBeginPos,pEndPos;
QString s= getWordAtPosition(this,p, pBeginPos,pEndPos, WordPurpose::wpInformation); QString s= getWordAtPosition(this,p, pBeginPos,pEndPos, WordPurpose::wpInformation);
@ -1123,26 +1123,34 @@ void Editor::copyAsHTML()
{ {
if (!selAvail()) if (!selAvail())
return; return;
SynHTMLExporter SynExporterHTML(tabWidth()); SynHTMLExporter exporter(tabWidth());
SynExporterHTML.setTitle(QFileInfo(mFilename).fileName()); exporter.setTitle(QFileInfo(mFilename).fileName());
SynExporterHTML.setExportAsText(false); exporter.setExportAsText(false);
SynExporterHTML.setUseBackground(pSettings->editor().copyHTMLUseBackground()); exporter.setUseBackground(pSettings->editor().copyHTMLUseBackground());
SynExporterHTML.setFont(font()); exporter.setFont(font());
PSynHighlighter hl = highlighter(); PSynHighlighter hl = highlighter();
if (!pSettings->editor().copyHTMLUseEditorColor()) { if (!pSettings->editor().copyHTMLUseEditorColor()) {
hl = highlighterManager.copyHighlighter(highlighter()); hl = highlighterManager.copyHighlighter(highlighter());
highlighterManager.applyColorScheme(hl,pSettings->editor().copyHTMLColorScheme()); highlighterManager.applyColorScheme(hl,pSettings->editor().copyHTMLColorScheme());
} }
SynExporterHTML.setHighlighter(hl); exporter.setHighlighter(hl);
SynExporterHTML.setCreateHTMLFragment(true); exporter.setOnFormatToken(std::bind(&Editor::onExportedFormatToken,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5
));
exporter.setCreateHTMLFragment(true);
SynExporterHTML.ExportRange(lines(),blockBegin(),blockEnd()); exporter.ExportRange(lines(),blockBegin(),blockEnd());
QMimeData * mimeData = new QMimeData; QMimeData * mimeData = new QMimeData;
//sethtml will convert buffer to QString , which will cause encoding trouble //sethtml will convert buffer to QString , which will cause encoding trouble
mimeData->setData(SynExporterHTML.clipboardFormat(),SynExporterHTML.buffer()); mimeData->setData(exporter.clipboardFormat(),exporter.buffer());
mimeData->setText(selText()); mimeData->setText(selText());
QGuiApplication::clipboard()->clear(); QGuiApplication::clipboard()->clear();
@ -2057,6 +2065,56 @@ void Editor::print()
} }
void Editor::exportAsRTF(const QString &rtfFilename)
{
SynRTFExporter exporter;
exporter.setTitle(extractFileName(rtfFilename));
exporter.setExportAsText(true);
exporter.setUseBackground(pSettings->editor().copyRTFUseBackground());
exporter.setFont(font());
PSynHighlighter hl = highlighter();
if (!pSettings->editor().copyRTFUseEditorColor()) {
hl = highlighterManager.copyHighlighter(highlighter());
highlighterManager.applyColorScheme(hl,pSettings->editor().copyRTFColorScheme());
}
exporter.setHighlighter(hl);
exporter.setOnFormatToken(std::bind(&Editor::onExportedFormatToken,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5
));
exporter.ExportAll(lines());
exporter.SaveToFile(rtfFilename);
}
void Editor::exportAsHTML(const QString &htmlFilename)
{
SynHTMLExporter exporter(tabWidth());
exporter.setTitle(extractFileName(htmlFilename));
exporter.setExportAsText(false);
exporter.setUseBackground(pSettings->editor().copyHTMLUseBackground());
exporter.setFont(font());
PSynHighlighter hl = highlighter();
if (!pSettings->editor().copyHTMLUseEditorColor()) {
hl = highlighterManager.copyHighlighter(highlighter());
highlighterManager.applyColorScheme(hl,pSettings->editor().copyHTMLColorScheme());
}
exporter.setHighlighter(hl);
exporter.setOnFormatToken(std::bind(&Editor::onExportedFormatToken,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5
));
exporter.ExportAll(lines());
exporter.SaveToFile(htmlFilename);
}
void Editor::showCompletion(bool autoComplete) void Editor::showCompletion(bool autoComplete)
{ {
if (!pSettings->codeCompletion().enabled()) if (!pSettings->codeCompletion().enabled())
@ -2852,6 +2910,74 @@ void Editor::popUserCodeInTabStops()
} }
} }
void Editor::onExportedFormatToken(PSynHighlighter syntaxHighlighter, int Line, int column, const QString &token, PSynHighlighterAttribute& attr)
{
if (!syntaxHighlighter)
return;
if (token.isEmpty())
return;
//don't do this
if (mCompletionPopup->isVisible() || mHeaderCompletionPopup->isVisible())
return;
if (mParser && (attr == syntaxHighlighter->identifierAttribute())) {
BufferCoord p{column,Line};
BufferCoord pBeginPos,pEndPos;
QString s= getWordAtPosition(this,p, pBeginPos,pEndPos, WordPurpose::wpInformation);
// qDebug()<<s;
PStatement statement = mParser->findStatementOf(mFilename,
s , p.Line);
StatementKind kind = mParser->getKindOfStatement(statement);
if (kind == StatementKind::skUnknown) {
if ((pEndPos.Line>=1)
&& (pEndPos.Char>=0)
&& (pEndPos.Char < lines()->getString(pEndPos.Line-1).length())
&& (lines()->getString(pEndPos.Line-1)[pEndPos.Char] == '(')) {
kind = StatementKind::skFunction;
} else {
kind = StatementKind::skVariable;
}
}
SynEditCppHighlighter* cppHighlighter = dynamic_cast<SynEditCppHighlighter*>(syntaxHighlighter.get());
switch(kind) {
case StatementKind::skFunction:
case StatementKind::skConstructor:
case StatementKind::skDestructor:
attr = cppHighlighter->functionAttribute();
break;
case StatementKind::skClass:
case StatementKind::skTypedef:
case StatementKind::skAlias:
attr = cppHighlighter->classAttribute();
break;
case StatementKind::skEnumClassType:
case StatementKind::skEnumType:
break;
case StatementKind::skLocalVariable:
case StatementKind::skParameter:
attr = cppHighlighter->localVarAttribute();
break;
case StatementKind::skVariable:
attr = cppHighlighter->variableAttribute();
break;
case StatementKind::skGlobalVariable:
attr = cppHighlighter->globalVarAttribute();
break;
case StatementKind::skEnum:
case StatementKind::skPreprocessor:
attr = cppHighlighter->preprocessorAttribute();
break;
case StatementKind::skKeyword:
attr = cppHighlighter->keywordAttribute();
break;
case StatementKind::skNamespace:
case StatementKind::skNamespaceAlias:
attr = cppHighlighter->stringAttribute();
break;
}
}
}
void Editor::setInProject(bool newInProject) void Editor::setInProject(bool newInProject)
{ {
if (mInProject == newInProject) if (mInProject == newInProject)

View File

@ -159,6 +159,8 @@ public:
void insertString(const QString& value, bool moveCursor); void insertString(const QString& value, bool moveCursor);
void insertCodeSnippet(const QString& code); void insertCodeSnippet(const QString& code);
void print(); void print();
void exportAsRTF(const QString& rtfFilename);
void exportAsHTML(const QString& htmlFilename);
const PCppParser &parser(); const PCppParser &parser();
@ -218,7 +220,8 @@ private:
void updateFunctionTip(); void updateFunctionTip();
void clearUserCodeInTabStops(); void clearUserCodeInTabStops();
void popUserCodeInTabStops(); void popUserCodeInTabStops();
void onExportedFormatToken(PSynHighlighter syntaxHighlighter, int Line, int column, const QString& token,
PSynHighlighterAttribute &attr);
private: private:
QByteArray mEncodingOption; // the encoding type set by the user QByteArray mEncodingOption; // the encoding type set by the user
QByteArray mFileEncoding; // the real encoding of the file (auto detected) QByteArray mFileEncoding; // the real encoding of the file (auto detected)

View File

@ -101,6 +101,11 @@ MainWindow::MainWindow(QWidget *parent)
mMenuNew->addAction(ui->actionNew_Project); mMenuNew->addAction(ui->actionNew_Project);
ui->menuFile->insertMenu(ui->actionOpen,mMenuNew); ui->menuFile->insertMenu(ui->actionOpen,mMenuNew);
mMenuExport = new QMenu(tr("Export"));
mMenuExport->addAction(ui->actionExport_As_RTF);
mMenuExport->addAction(ui->actionExport_As_HTML);
ui->menuFile->insertMenu(ui->actionPrint,mMenuExport);
buildEncodingMenu(); buildEncodingMenu();
mMenuRecentProjects = new QMenu(); mMenuRecentProjects = new QMenu();
@ -241,6 +246,8 @@ void MainWindow::updateEditorActions()
ui->actionRedo->setEnabled(false); ui->actionRedo->setEnabled(false);
ui->actionSave->setEnabled(false); ui->actionSave->setEnabled(false);
ui->actionSaveAs->setEnabled(false); ui->actionSaveAs->setEnabled(false);
ui->actionExport_As_HTML->setEnabled(false);
ui->actionExport_As_RTF->setEnabled(false);
ui->actionPrint->setEnabled(false); ui->actionPrint->setEnabled(false);
ui->actionSelectAll->setEnabled(false); ui->actionSelectAll->setEnabled(false);
ui->actionToggleComment->setEnabled(false); ui->actionToggleComment->setEnabled(false);
@ -274,6 +281,8 @@ void MainWindow::updateEditorActions()
ui->actionUndo->setEnabled(e->canUndo()); ui->actionUndo->setEnabled(e->canUndo());
ui->actionSave->setEnabled(e->modified()); ui->actionSave->setEnabled(e->modified());
ui->actionSaveAs->setEnabled(true); ui->actionSaveAs->setEnabled(true);
ui->actionExport_As_HTML->setEnabled(true);
ui->actionExport_As_RTF->setEnabled(true);
ui->actionPrint->setEnabled(true); ui->actionPrint->setEnabled(true);
ui->actionSelectAll->setEnabled(e->lines()->count()>0); ui->actionSelectAll->setEnabled(e->lines()->count()>0);
ui->actionToggleComment->setEnabled(!e->readOnly() && e->lines()->count()>0); ui->actionToggleComment->setEnabled(!e->readOnly() && e->lines()->count()>0);
@ -960,8 +969,8 @@ void MainWindow::runExecutable(const QString &exeName,const QString &filename)
+"<br /><br />"+tr("Compile now?"), +"<br /><br />"+tr("Compile now?"),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
ui->actionCompile_Run->trigger(); ui->actionCompile_Run->trigger();
return;
} }
return;
} else { } else {
QMessageBox::critical(this,"Error", QMessageBox::critical(this,"Error",
tr("Source file is not compiled.")); tr("Source file is not compiled."));
@ -977,6 +986,9 @@ void MainWindow::runExecutable(const QString &exeName,const QString &filename)
ui->actionCompile_Run->trigger(); ui->actionCompile_Run->trigger();
return; return;
} }
} else {
QMessageBox::warning(this,"Error",
tr("Source file is more recent than executable."));
} }
} }
} }
@ -4159,3 +4171,47 @@ const PToolsManager &MainWindow::toolsManager() const
return mToolsManager; return mToolsManager;
} }
void MainWindow::on_actionExport_As_RTF_triggered()
{
Editor * editor = mEditorList->getEditor();
if (!editor)
return;
QString rtfFile = QFileDialog::getSaveFileName(editor,
tr("Export As RTF"),
extractFilePath(editor->filename()),
tr("Rich Text Format Files (*.rtf)")
);
if (rtfFile.isEmpty())
return;
try {
editor->exportAsRTF(rtfFile);
} catch (FileError e) {
QMessageBox::critical(editor,
"Error",
e.reason());
}
}
void MainWindow::on_actionExport_As_HTML_triggered()
{
Editor * editor = mEditorList->getEditor();
if (!editor)
return;
QString htmlFile = QFileDialog::getSaveFileName(editor,
tr("Export As HTML"),
extractFilePath(editor->filename()),
tr("HTML Files (*.html)")
);
if (htmlFile.isEmpty())
return;
try {
editor->exportAsHTML(htmlFile);
} catch (FileError e) {
QMessageBox::critical(editor,
"Error",
e.reason());
}
}

View File

@ -392,6 +392,10 @@ private slots:
void on_actionPrint_triggered(); void on_actionPrint_triggered();
void on_actionExport_As_RTF_triggered();
void on_actionExport_As_HTML_triggered();
private: private:
Ui::MainWindow *ui; Ui::MainWindow *ui;
EditorList *mEditorList; EditorList *mEditorList;
@ -399,6 +403,7 @@ private:
QLabel *mFileEncodingStatus; QLabel *mFileEncodingStatus;
QLabel *mFileModeStatus; QLabel *mFileModeStatus;
QMenu *mMenuEncoding; QMenu *mMenuEncoding;
QMenu *mMenuExport;
QMenu *mMenuEncodingList; QMenu *mMenuEncodingList;
QMenu *mMenuRecentFiles; QMenu *mMenuRecentFiles;
QMenu *mMenuRecentProjects; QMenu *mMenuRecentProjects;

View File

@ -1822,6 +1822,16 @@
<string>Ctrl+P</string> <string>Ctrl+P</string>
</property> </property>
</action> </action>
<action name="actionExport_As_RTF">
<property name="text">
<string>Export As RTF</string>
</property>
</action>
<action name="actionExport_As_HTML">
<property name="text">
<string>Export As HTML</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>

View File

@ -94,7 +94,7 @@ void SynExporter::ExportRange(PSynEditStringList ALines, BufferCoord Start, Buff
QString Token = ReplaceReservedChars(token); QString Token = ReplaceReservedChars(token);
if (mOnFormatToken) if (mOnFormatToken)
mOnFormatToken(i, mHighlighter->getTokenPos(), mHighlighter->getToken(),attri); mOnFormatToken(mHighlighter, i, mHighlighter->getTokenPos()+1, mHighlighter->getToken(),attri);
SetTokenAttribute(attri); SetTokenAttribute(attri);
FormatToken(Token); FormatToken(Token);
mHighlighter->next(); mHighlighter->next();
@ -115,13 +115,16 @@ void SynExporter::SaveToFile(const QString &AFileName)
QFile file(AFileName); QFile file(AFileName);
if (file.open(QIODevice::WriteOnly)) { if (file.open(QIODevice::WriteOnly)) {
SaveToStream(file); SaveToStream(file);
file.close(); } else {
throw FileError(QObject::tr("Can't open file '%1' to write!"));
} }
} }
void SynExporter::SaveToStream(QIODevice &AStream) void SynExporter::SaveToStream(QIODevice &AStream)
{ {
AStream.write(mBuffer); if (AStream.write(mBuffer)<0) {
throw FileError(QObject::tr("Failed to write data."));
}
} }
bool SynExporter::exportAsText() const bool SynExporter::exportAsText() const

View File

@ -6,8 +6,8 @@
using FormatTokenHandler = std::function<void(int Line, int column, const QString& token, using FormatTokenHandler = std::function<void(PSynHighlighter syntaxHighlighter, int Line, int column, const QString& token,
PSynHighlighterAttribute attr)>; PSynHighlighterAttribute& attr)>;
class SynExporter class SynExporter
{ {

View File

@ -138,8 +138,8 @@ SynEditCppHighlighter::SynEditCppHighlighter(): SynHighlighter()
addAttribute(mNumberAttribute); addAttribute(mNumberAttribute);
mOctAttribute = std::make_shared<SynHighlighterAttribute>(SYNS_AttrOctal); mOctAttribute = std::make_shared<SynHighlighterAttribute>(SYNS_AttrOctal);
addAttribute(mOctAttribute); addAttribute(mOctAttribute);
mDirecAttribute = std::make_shared<SynHighlighterAttribute>(SYNS_AttrPreprocessor); mPreprocessorAttribute = std::make_shared<SynHighlighterAttribute>(SYNS_AttrPreprocessor);
addAttribute(mDirecAttribute); addAttribute(mPreprocessorAttribute);
mKeywordAttribute = std::make_shared<SynHighlighterAttribute>(SYNS_AttrReservedWord); mKeywordAttribute = std::make_shared<SynHighlighterAttribute>(SYNS_AttrReservedWord);
addAttribute(mKeywordAttribute); addAttribute(mKeywordAttribute);
mWhitespaceAttribute = std::make_shared<SynHighlighterAttribute>(SYNS_AttrSpace); mWhitespaceAttribute = std::make_shared<SynHighlighterAttribute>(SYNS_AttrSpace);
@ -168,9 +168,9 @@ PSynHighlighterAttribute SynEditCppHighlighter::asmAttribute() const
return mAsmAttribute; return mAsmAttribute;
} }
PSynHighlighterAttribute SynEditCppHighlighter::direcAttribute() const PSynHighlighterAttribute SynEditCppHighlighter::preprocessorAttribute() const
{ {
return mDirecAttribute; return mPreprocessorAttribute;
} }
PSynHighlighterAttribute SynEditCppHighlighter::invalidAttribute() const PSynHighlighterAttribute SynEditCppHighlighter::invalidAttribute() const
@ -1369,7 +1369,7 @@ PSynHighlighterAttribute SynEditCppHighlighter::getTokenAttribute() const
case TokenKind::Comment: case TokenKind::Comment:
return mCommentAttribute; return mCommentAttribute;
case TokenKind::Directive: case TokenKind::Directive:
return mDirecAttribute; return mPreprocessorAttribute;
case TokenKind::Identifier: case TokenKind::Identifier:
return mIdentifierAttribute; return mIdentifierAttribute;
case TokenKind::Key: case TokenKind::Key:

View File

@ -53,7 +53,7 @@ public:
PSynHighlighterAttribute asmAttribute() const; PSynHighlighterAttribute asmAttribute() const;
PSynHighlighterAttribute direcAttribute() const; PSynHighlighterAttribute preprocessorAttribute() const;
PSynHighlighterAttribute invalidAttribute() const; PSynHighlighterAttribute invalidAttribute() const;
@ -144,7 +144,7 @@ private:
int mRightBraces; int mRightBraces;
PSynHighlighterAttribute mAsmAttribute; PSynHighlighterAttribute mAsmAttribute;
PSynHighlighterAttribute mDirecAttribute; PSynHighlighterAttribute mPreprocessorAttribute;
PSynHighlighterAttribute mInvalidAttribute; PSynHighlighterAttribute mInvalidAttribute;
PSynHighlighterAttribute mNumberAttribute; PSynHighlighterAttribute mNumberAttribute;
PSynHighlighterAttribute mFloatAttribute; PSynHighlighterAttribute mFloatAttribute;

View File

@ -3,7 +3,7 @@
#include <QStringList> #include <QStringList>
#define DEVCPP_VERSION "0.6.4" #define DEVCPP_VERSION "0.6.5"
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
#define APP_SETTSINGS_FILENAME "redpandacpp.ini" #define APP_SETTSINGS_FILENAME "redpandacpp.ini"