work save

This commit is contained in:
royqh1979@gmail.com 2021-09-30 20:10:48 +08:00
parent a0ea72071c
commit c59e2c6667
12 changed files with 296 additions and 36 deletions

View File

@ -15,13 +15,56 @@ CodeSnippetsManager::CodeSnippetsManager(QObject *parent) : QObject(parent)
void CodeSnippetsManager::load() void CodeSnippetsManager::load()
{ {
//if config file not exists, copy it from data //if config file not exists, copy it from data
QString filename = includeTrailingPathDelimiter(pSettings->dirs().config()) + DEV_CODESNIPPET_FILE;
if (!fileExists(filename)) {
QString defaultFilename = ":/config/codesnippets.json";
if (!QFile::copy(
defaultFilename,
filename)) {
QMessageBox::critical(nullptr,
tr("Load default code snippets failed"),
tr("Can't copy default code snippets '%1' to '%2'.")
.arg(defaultFilename)
.arg(filename));
}
}
//read config file //read config file
QFile file(filename);
if (!file.open(QFile::ReadOnly)) {
QMessageBox::critical(nullptr,
tr("Read code snippets failed"),
tr("Can't open code snippet file '%1' for read.")
.arg(filename));
}
QByteArray json = file.readAll();
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(json,&error);
if (error.error != QJsonParseError::NoError) {
QMessageBox::critical(nullptr,
tr("Read code snippets failed"),
tr("Read code snippet file '%1' failed:%2")
.arg(filename)
.arg(error.errorString()));
}
mSnippets.clear();
QJsonArray array = doc.array();
foreach (const QJsonValue& value,array) {
QJsonObject object = value.toObject();
PCodeSnippet snippet = std::make_shared<CodeSnippet>();
snippet->caption = object["caption"].toString();
snippet->prefix = object["prefix"].toString();
snippet->code = object["code"].toString();
snippet->desc = object["description"].toString();
snippet->section = object["section"].toInt();
mSnippets.append(snippet);
}
} }
void CodeSnippetsManager::save() void CodeSnippetsManager::save()
{ {
QString filename = pSettings->dirs().config() + DEV_CODESNIPPET_FILE; QString filename = includeTrailingPathDelimiter(pSettings->dirs().config()) + DEV_CODESNIPPET_FILE;
QFile file(filename); QFile file(filename);
if (!file.open(QFile::WriteOnly | QFile::Truncate)) { if (!file.open(QFile::WriteOnly | QFile::Truncate)) {
QMessageBox::critical(nullptr, QMessageBox::critical(nullptr,
@ -87,12 +130,18 @@ void CodeSnippetsModel::clear()
endRemoveRows(); endRemoveRows();
} }
int CodeSnippetsModel::rowCount(const QModelIndex &parent) const QModelIndex CodeSnippetsModel::lastSnippetCaption()
{
Q_ASSERT(mSnippets.count()>0);
return createIndex(mSnippets.count()-1,0);
}
int CodeSnippetsModel::rowCount(const QModelIndex &) const
{ {
return mSnippets.count(); return mSnippets.count();
} }
int CodeSnippetsModel::columnCount(const QModelIndex &parent) const int CodeSnippetsModel::columnCount(const QModelIndex &) const
{ {
return 4; return 4;
} }

View File

@ -16,6 +16,7 @@ public:
int menuSection); int menuSection);
void remove(int index); void remove(int index);
void clear(); void clear();
QModelIndex lastSnippetCaption();
// QAbstractItemModel interface // QAbstractItemModel interface
public: public:

View File

@ -1,5 +1,6 @@
<RCC> <RCC>
<qresource prefix="/config"> <qresource prefix="/config">
<file alias="autolink.json">resources/autolink.json</file> <file alias="autolink.json">resources/autolink.json</file>
<file alias="codesnippets.json">resources/codesnippets.json</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -1718,6 +1718,92 @@ void Editor::insertString(const QString &value, bool moveCursor)
} }
} }
void Editor::insertCodeSnippet(const QString &code)
{
clearUserCodeInTabStops();
mXOffsetSince = 0;
mTabStopBegin = -1;
mTabStopEnd = -1;
mTabStopY =0;
mLineBeforeTabStop = "";
mLineAfterTabStop = "";
QStringList sl;
QString newSl;
// prevent lots of repaints
beginUpdate();
auto action = finally([this]{
endUpdate();
});
fText.BeginUpdate;
try
sl.Text:=ParseMacros(Code);
lastI:=0;
spaceCount := Length(Text.GetLeftSpacing(
Text.LeftSpacesEx(fText.LineText,True), True));
for i:=0 to sl.Count -1 do begin
lastPos := 0;
s:= sl[i];
if i>0 then
lastPos := -spaceCount;
while True do begin
insertPos := Pos(USER_CODE_IN_INSERT_POS,s);
if insertPos = 0 then // no %INSERT% macro in this line now
break;
System.new(p);
Delete(s,insertPos,Length(USER_CODE_IN_INSERT_POS));
dec(insertPos);
p.x:=insertPos - lastPos;
p.endX := p.x;
p.y:=i-lastI;
lastPos := insertPos;
lastI:=i;
fUserCodeInTabStops.Add(p);
end;
while True do begin
insertPos := Pos(USER_CODE_IN_REPL_POS_BEGIN,s);
if insertPos = 0 then // no %INSERT% macro in this line now
break;
System.new(p);
Delete(s,insertPos,Length(USER_CODE_IN_REPL_POS_BEGIN));
dec(insertPos);
p.x:=insertPos - lastPos;
insertEndPos := insertPos + Pos(USER_CODE_IN_REPL_POS_END,copy(s,insertPos+1,MaxInt));
if insertEndPos <= insertPos then begin
p.endX := length(s);
end else begin
Delete(s,insertEndPos,Length(USER_CODE_IN_REPL_POS_END));
dec(insertEndPos);
p.endX := insertEndPos - lastPos;
end;
p.y:=i-lastI;
lastPos := insertEndPos;
lastI:=i;
fUserCodeInTabStops.Add(p);
end;
newSl.Add(s);
end;
CursorPos := Text.CaretXY;
s:=newSl.Text;
if EndsStr(#13#10,s) then
Delete(s,Length(s)-1,2)
else if EndsStr(#10, s) then
Delete(s,Length(s),1);
fText.SelText := s;
Text.CaretXY := CursorPos; //restore cursor pos before insert
if fUserCodeInTabStops.Count > 0 then begin
fTabStopBegin :=Text.CaretX;
fTabStopEnd := Text.CaretX;
PopUserCodeInTabStops;
end;
if Code <> '' then
fLastIdCharPressed := 0;
// prevent lots of repaints
finally
fText.EndUpdate;
end;
}
void Editor::showCompletion(bool autoComplete) void Editor::showCompletion(bool autoComplete)
{ {
if (!pSettings->codeCompletion().enabled()) if (!pSettings->codeCompletion().enabled())
@ -1766,7 +1852,10 @@ void Editor::showCompletion(bool autoComplete)
mCompletionPopup->setRecordUsage(pSettings->codeCompletion().recordUsage()); mCompletionPopup->setRecordUsage(pSettings->codeCompletion().recordUsage());
mCompletionPopup->setSortByScope(pSettings->codeCompletion().sortByScope()); mCompletionPopup->setSortByScope(pSettings->codeCompletion().sortByScope());
mCompletionPopup->setShowKeywords(pSettings->codeCompletion().showKeywords()); mCompletionPopup->setShowKeywords(pSettings->codeCompletion().showKeywords());
mCompletionPopup->setShowCodeIns(pSettings->codeCompletion().showCodeIns()); mCompletionPopup->setShowCodeSnippets(pSettings->codeCompletion().showCodeIns());
if (pSettings->codeCompletion().showCodeIns()) {
mCompletionPopup->setCodeSnippets(pMainWindow->codeSnippetManager()->snippets());
}
mCompletionPopup->setIgnoreCase(pSettings->codeCompletion().ignoreCase()); mCompletionPopup->setIgnoreCase(pSettings->codeCompletion().ignoreCase());
mCompletionPopup->resize(pSettings->codeCompletion().width(), mCompletionPopup->resize(pSettings->codeCompletion().width(),
pSettings->codeCompletion().height()); pSettings->codeCompletion().height());
@ -1902,7 +1991,7 @@ void Editor::completionInsert(bool appendFunc)
return; return;
if (pSettings->codeCompletion().recordUsage() if (pSettings->codeCompletion().recordUsage()
&& statement->kind != StatementKind::skUserCodeIn) { && statement->kind != StatementKind::skUserCodeSnippet) {
statement->usageCount+=1; statement->usageCount+=1;
pMainWindow->symbolUsageManager()->updateUsage(statement->fullName, pMainWindow->symbolUsageManager()->updateUsage(statement->fullName,
statement->usageCount); statement->usageCount);
@ -1929,8 +2018,9 @@ void Editor::completionInsert(bool appendFunc)
} }
// ... by replacing the selection // ... by replacing the selection
if (statement->kind == StatementKind::skUserCodeIn) { // it's a user code template if (statement->kind == StatementKind::skUserCodeSnippet) { // it's a user code template
//insertUserCodeIn(Statement->value); // insertUserCodeIn(Statement->value);
insertCodeSnippet(statement->value);
} else { } else {
if ( if (
(statement->kind == StatementKind::skKeyword (statement->kind == StatementKind::skKeyword

View File

@ -371,7 +371,7 @@ void MainWindow::updateEditorColorSchemes()
item = pColorManager->getItem(schemeName, SYNS_AttrReservedWord); item = pColorManager->getItem(schemeName, SYNS_AttrReservedWord);
if (item) { if (item) {
mStatementColors->insert(StatementKind::skKeyword,item->foreground()); mStatementColors->insert(StatementKind::skKeyword,item->foreground());
mStatementColors->insert(StatementKind::skUserCodeIn,item->foreground()); mStatementColors->insert(StatementKind::skUserCodeSnippet,item->foreground());
} }
item = pColorManager->getItem(schemeName, SYNS_AttrString); item = pColorManager->getItem(schemeName, SYNS_AttrString);
if (item) { if (item) {

View File

@ -60,7 +60,7 @@ enum StatementKind {
skNamespace, skNamespace,
skNamespaceAlias, skNamespaceAlias,
skBlock, skBlock,
skUserCodeIn, // user code template skUserCodeSnippet, // user code template
skKeyword, // keywords skKeyword, // keywords
skGlobalVariable, skGlobalVariable,
skLocalVariable, skLocalVariable,

View File

@ -0,0 +1,65 @@
[
{
"caption": "for(;;)",
"code": "for(%REPL_BEGIN%int i=0%REPL_END%;%REPL_BEGIN%i<=0%REPL_END%;%REPL_BEGIN%i++%REPL_END%){\r\n\t%REPL_BEGIN%//TODO%REPL_END%\r\n}",
"description": "",
"prefix": "for(;;)",
"section": -1
},
{
"caption": "if else",
"code": "if(%REPL_BEGIN%1%REPL_END%){\r\n\t%REPL_BEGIN%//TODO%REPL_END%\r\n}else{\r\n\t%REPL_BEGIN%//TODO%REPL_END%\r\n}",
"description": "",
"prefix": "if_else",
"section": -1
},
{
"caption": "if else if",
"code": "if(%REPL_BEGIN%1%REPL_END%){\r\n\t%REPL_BEGIN%//TODO%REPL_END%\r\n}else if(%REPL_BEGIN%1%REPL_END%){\r\n\t%REPL_BEGIN%//TODO%REPL_END%\r\n}else{\r\n\t%REPL_BEGIN%//TODO%REPL_END%\r\n}",
"description": "",
"prefix": "if_else_if",
"section": -1
},
{
"caption": "if()",
"code": "if(%REPL_BEGIN%1%REPL_END%){\r\n\t%REPL_BEGIN%//TODO%REPL_END%\r\n}",
"description": "",
"prefix": "if()",
"section": -1
},
{
"caption": "while()",
"code": "while(%REPL_BEGIN%1%REPL_END%){\r\n\t%REPL_BEGIN%//TODO%REPL_END%\r\n}",
"description": "",
"prefix": "while()",
"section": -1
},
{
"caption": "class{;;}",
"code": "class %REPL_BEGIN%YourClassName%REPL_END% {\r\n\t\t%REPL_BEGIN%int YourVar%REPL_END%;\r\n\tpublic:\r\n\t\t%REPL_BEGIN%YourClassName%REPL_END%() {\r\n\r\n\t\t}\r\n\t\t~%REPL_BEGIN%YourClassName%REPL_END%() {\r\n\r\n\t\t}\r\n\t\t%REPL_BEGIN%void YourMethodOrFunction%REPL_END%() {\r\n\r\n\t\t}\r\n};",
"description": "",
"prefix": "class{;;}",
"section": -1
},
{
"caption": "switch(){}",
"code": "switch (%REPL_BEGIN%1%REPL_END%) {\r\n\tcase %REPL_BEGIN%1%REPL_END%:\r\n\t\t%REPL_BEGIN%//TODO%REPL_END%\r\n\t\tbreak;\r\n\tcase %REPL_BEGIN%2%REPL_END%:\r\n\t\t%REPL_BEGIN%//TODO%REPL_END%\r\n\t\tbreak;\r\n\tdefault:\r\n\t\t%REPL_BEGIN%//TODO%REPL_END%\r\n\t\tbreak;\r\n}",
"description": "",
"prefix": "switch(){}",
"section": -1
},
{
"caption": "do{}while()",
"code": "do{\r\n\t%REPL_BEGIN%//TODO%REPL_END%\r\n}while(%REPL_BEGIN%1%REPL_END%);",
"description": "",
"prefix": "do{}while()",
"section": -1
},
{
"caption": "function()",
"code": "%REPL_BEGIN%int YourFunctionName%REPL_END%(%REPL_BEGIN%int YourParaments%REPL_END%){\r\n\t%REPL_BEGIN%//TODO%REPL_END%\r\n\treturn %REPL_BEGIN%0%REPL_END%;\r\n}",
"description": "",
"prefix": "function()",
"section": -1
}
]

View File

@ -3,6 +3,8 @@
#include "../mainwindow.h" #include "../mainwindow.h"
#include "../codesnippetsmanager.h" #include "../codesnippetsmanager.h"
#include <QItemSelectionModel>
EditorSnippetWidget::EditorSnippetWidget(const QString& name, const QString& group, EditorSnippetWidget::EditorSnippetWidget(const QString& name, const QString& group,
QWidget *parent) : QWidget *parent) :
SettingsWidget(name,group,parent), SettingsWidget(name,group,parent),
@ -20,6 +22,21 @@ EditorSnippetWidget::EditorSnippetWidget(const QString& name, const QString& gro
return; return;
PCodeSnippet snippet = mModel.snippets()[index.row()]; PCodeSnippet snippet = mModel.snippets()[index.row()];
snippet->code = ui->editCode->lines()->text(); snippet->code = ui->editCode->lines()->text();
setSettingsChanged();
});
connect(ui->tblSnippets->selectionModel(), &QItemSelectionModel::currentChanged,
[this] {
QModelIndex index = ui->tblSnippets->currentIndex();
if (!index.isValid()) {
ui->editCode->setEnabled(false);
ui->editCode->lines()->clear();
} else {
mUpdatingCode = true;
ui->editCode->setEnabled(true);
PCodeSnippet snippet = mModel.snippets()[index.row()];
ui->editCode->lines()->setText(snippet->code);
mUpdatingCode = false;
}
}); });
} }
@ -39,32 +56,22 @@ void EditorSnippetWidget::doSave()
pMainWindow->codeSnippetManager()->save(); pMainWindow->codeSnippetManager()->save();
} }
void EditorSnippetWidget::on_tblSnippets_clicked(const QModelIndex &index) void EditorSnippetWidget::on_btnAdd_clicked()
{ {
if (!index.isValid()) mModel.addSnippet(QString("").arg(getNewFileNumber()),
return;
mUpdatingCode = true;
PCodeSnippet snippet = mModel.snippets()[index.row()];
ui->editCode->lines()->setText(snippet->code);
mUpdatingCode = false;
}
void EditorSnippetWidget::on_btnAdd_triggered(QAction *arg1)
{
mModel.addSnippet(QString("Code %1").arg(getNewFileNumber()),
"", "",
"", "",
"", "",
-1); -1);
ui->tblSnippets->setCurrentIndex(mModel.lastSnippetCaption());
ui->tblSnippets->edit(mModel.lastSnippetCaption());
} }
void EditorSnippetWidget::on_btnRemove_triggered(QAction *arg1) void EditorSnippetWidget::on_btnRemove_clicked()
{ {
QModelIndex index = ui->tblSnippets->currentIndex(); QModelIndex index = ui->tblSnippets->currentIndex();
if (!index.isValid()) if (!index.isValid())
return; return;
mModel.remove(index.row()); mModel.remove(index.row());
} }

View File

@ -27,9 +27,8 @@ protected:
void doLoad() override; void doLoad() override;
void doSave() override; void doSave() override;
private slots: private slots:
void on_tblSnippets_clicked(const QModelIndex &index); void on_btnRemove_clicked();
void on_btnAdd_triggered(QAction *arg1); void on_btnAdd_clicked();
void on_btnRemove_triggered(QAction *arg1);
}; };
#endif // EDITORSNIPPETWIDGET_H #endif // EDITORSNIPPETWIDGET_H

View File

@ -21,12 +21,49 @@
</property> </property>
<widget class="QWidget" name="widget" native="true"> <widget class="QWidget" name="widget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_2"> <layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item> <item>
<widget class="QTableView" name="tblSnippets"/> <widget class="QTableView" name="tblSnippets">
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="textElideMode">
<enum>Qt::ElideNone</enum>
</property>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
</widget>
</item> </item>
<item> <item>
<widget class="QWidget" name="widget_2" native="true"> <widget class="QWidget" name="widget_2" native="true">
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item> <item>
<widget class="QToolButton" name="btnAdd"> <widget class="QToolButton" name="btnAdd">
<property name="text"> <property name="text">

View File

@ -32,8 +32,9 @@ void SymbolUsageManager::load()
if (error.error != QJsonParseError::NoError) { if (error.error != QJsonParseError::NoError) {
QMessageBox::critical(nullptr, QMessageBox::critical(nullptr,
tr("Load symbol usage info failed"), tr("Load symbol usage info failed"),
tr("Can't parse symbol usage file '%1'.") tr("Can't parse symbol usage file '%1': %2")
.arg(filename)); .arg(filename)
.arg(error.errorString()));
} }
mUsages.clear(); mUsages.clear();

View File

@ -37,7 +37,7 @@ CodeCompletionPopup::CodeCompletionPopup(QWidget *parent) :
mOnlyGlobals = false; mOnlyGlobals = false;
mShowCount = 1000; mShowCount = 1000;
mShowCodeIns = true; mShowCodeSnippets = true;
mIgnoreCase = false; mIgnoreCase = false;
@ -469,9 +469,9 @@ void CodeCompletionPopup::getCompletionFor(const QString &fileName, const QStrin
int i = mParser->findLastOperator(phrase); int i = mParser->findLastOperator(phrase);
if (i < 0 ) { // don't have any scope prefix if (i < 0 ) { // don't have any scope prefix
if (mShowCodeIns) { if (mShowCodeSnippets) {
//add custom code templates //add custom code templates
foreach (const PCodeSnippet& codeIn,mCodeInsList) { foreach (const PCodeSnippet& codeIn,mCodeSnippets) {
PStatement statement = std::make_shared<Statement>(); PStatement statement = std::make_shared<Statement>();
statement->command = codeIn->prefix; statement->command = codeIn->prefix;
statement->kind = StatementKind::skUserCodeIn; statement->kind = StatementKind::skUserCodeIn;
@ -731,6 +731,16 @@ bool CodeCompletionPopup::isIncluded(const QString &fileName)
return mIncludedFiles.contains(fileName); return mIncludedFiles.contains(fileName);
} }
const QList<PCodeSnippet> &CodeCompletionPopup::codeSnippets() const
{
return mCodeSnippets;
}
void CodeCompletionPopup::setCodeSnippets(const QList<PCodeSnippet> &newCodeSnippets)
{
mCodeSnippets = newCodeSnippets;
}
void CodeCompletionPopup::setColors(const std::shared_ptr<QHash<StatementKind, QColor> > &newColors) void CodeCompletionPopup::setColors(const std::shared_ptr<QHash<StatementKind, QColor> > &newColors)
{ {
mColors = newColors; mColors = newColors;
@ -793,12 +803,12 @@ void CodeCompletionPopup::setIgnoreCase(bool newIgnoreCase)
bool CodeCompletionPopup::showCodeIns() const bool CodeCompletionPopup::showCodeIns() const
{ {
return mShowCodeIns; return mShowCodeSnippets;
} }
void CodeCompletionPopup::setShowCodeIns(bool newShowCodeIns) void CodeCompletionPopup::setShowCodeIns(bool newShowCodeIns)
{ {
mShowCodeIns = newShowCodeIns; mShowCodeSnippets = newShowCodeIns;
} }
bool CodeCompletionPopup::showKeywords() const bool CodeCompletionPopup::showKeywords() const