work save
This commit is contained in:
parent
a0ea72071c
commit
c59e2c6667
|
@ -16,12 +16,55 @@ CodeSnippetsManager::CodeSnippetsManager(QObject *parent) : QObject(parent)
|
|||
void CodeSnippetsManager::load()
|
||||
{
|
||||
//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
|
||||
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()
|
||||
{
|
||||
QString filename = pSettings->dirs().config() + DEV_CODESNIPPET_FILE;
|
||||
QString filename = includeTrailingPathDelimiter(pSettings->dirs().config()) + DEV_CODESNIPPET_FILE;
|
||||
QFile file(filename);
|
||||
if (!file.open(QFile::WriteOnly | QFile::Truncate)) {
|
||||
QMessageBox::critical(nullptr,
|
||||
|
@ -87,12 +130,18 @@ void CodeSnippetsModel::clear()
|
|||
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();
|
||||
}
|
||||
|
||||
int CodeSnippetsModel::columnCount(const QModelIndex &parent) const
|
||||
int CodeSnippetsModel::columnCount(const QModelIndex &) const
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ public:
|
|||
int menuSection);
|
||||
void remove(int index);
|
||||
void clear();
|
||||
QModelIndex lastSnippetCaption();
|
||||
|
||||
// QAbstractItemModel interface
|
||||
public:
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<RCC>
|
||||
<qresource prefix="/config">
|
||||
<file alias="autolink.json">resources/autolink.json</file>
|
||||
<file alias="codesnippets.json">resources/codesnippets.json</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
if (!pSettings->codeCompletion().enabled())
|
||||
|
@ -1766,7 +1852,10 @@ void Editor::showCompletion(bool autoComplete)
|
|||
mCompletionPopup->setRecordUsage(pSettings->codeCompletion().recordUsage());
|
||||
mCompletionPopup->setSortByScope(pSettings->codeCompletion().sortByScope());
|
||||
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->resize(pSettings->codeCompletion().width(),
|
||||
pSettings->codeCompletion().height());
|
||||
|
@ -1902,7 +1991,7 @@ void Editor::completionInsert(bool appendFunc)
|
|||
return;
|
||||
|
||||
if (pSettings->codeCompletion().recordUsage()
|
||||
&& statement->kind != StatementKind::skUserCodeIn) {
|
||||
&& statement->kind != StatementKind::skUserCodeSnippet) {
|
||||
statement->usageCount+=1;
|
||||
pMainWindow->symbolUsageManager()->updateUsage(statement->fullName,
|
||||
statement->usageCount);
|
||||
|
@ -1929,8 +2018,9 @@ void Editor::completionInsert(bool appendFunc)
|
|||
}
|
||||
|
||||
// ... by replacing the selection
|
||||
if (statement->kind == StatementKind::skUserCodeIn) { // it's a user code template
|
||||
//insertUserCodeIn(Statement->value);
|
||||
if (statement->kind == StatementKind::skUserCodeSnippet) { // it's a user code template
|
||||
// insertUserCodeIn(Statement->value);
|
||||
insertCodeSnippet(statement->value);
|
||||
} else {
|
||||
if (
|
||||
(statement->kind == StatementKind::skKeyword
|
||||
|
|
|
@ -371,7 +371,7 @@ void MainWindow::updateEditorColorSchemes()
|
|||
item = pColorManager->getItem(schemeName, SYNS_AttrReservedWord);
|
||||
if (item) {
|
||||
mStatementColors->insert(StatementKind::skKeyword,item->foreground());
|
||||
mStatementColors->insert(StatementKind::skUserCodeIn,item->foreground());
|
||||
mStatementColors->insert(StatementKind::skUserCodeSnippet,item->foreground());
|
||||
}
|
||||
item = pColorManager->getItem(schemeName, SYNS_AttrString);
|
||||
if (item) {
|
||||
|
|
|
@ -60,7 +60,7 @@ enum StatementKind {
|
|||
skNamespace,
|
||||
skNamespaceAlias,
|
||||
skBlock,
|
||||
skUserCodeIn, // user code template
|
||||
skUserCodeSnippet, // user code template
|
||||
skKeyword, // keywords
|
||||
skGlobalVariable,
|
||||
skLocalVariable,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
]
|
|
@ -3,6 +3,8 @@
|
|||
#include "../mainwindow.h"
|
||||
#include "../codesnippetsmanager.h"
|
||||
|
||||
#include <QItemSelectionModel>
|
||||
|
||||
EditorSnippetWidget::EditorSnippetWidget(const QString& name, const QString& group,
|
||||
QWidget *parent) :
|
||||
SettingsWidget(name,group,parent),
|
||||
|
@ -20,6 +22,21 @@ EditorSnippetWidget::EditorSnippetWidget(const QString& name, const QString& gro
|
|||
return;
|
||||
PCodeSnippet snippet = mModel.snippets()[index.row()];
|
||||
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();
|
||||
}
|
||||
|
||||
void EditorSnippetWidget::on_tblSnippets_clicked(const QModelIndex &index)
|
||||
void EditorSnippetWidget::on_btnAdd_clicked()
|
||||
{
|
||||
if (!index.isValid())
|
||||
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()),
|
||||
mModel.addSnippet(QString("").arg(getNewFileNumber()),
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
-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();
|
||||
if (!index.isValid())
|
||||
return;
|
||||
mModel.remove(index.row());
|
||||
}
|
||||
|
||||
|
|
|
@ -27,9 +27,8 @@ protected:
|
|||
void doLoad() override;
|
||||
void doSave() override;
|
||||
private slots:
|
||||
void on_tblSnippets_clicked(const QModelIndex &index);
|
||||
void on_btnAdd_triggered(QAction *arg1);
|
||||
void on_btnRemove_triggered(QAction *arg1);
|
||||
void on_btnRemove_clicked();
|
||||
void on_btnAdd_clicked();
|
||||
};
|
||||
|
||||
#endif // EDITORSNIPPETWIDGET_H
|
||||
|
|
|
@ -21,12 +21,49 @@
|
|||
</property>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<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>
|
||||
<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>
|
||||
<widget class="QWidget" name="widget_2" native="true">
|
||||
<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>
|
||||
<widget class="QToolButton" name="btnAdd">
|
||||
<property name="text">
|
||||
|
|
|
@ -32,8 +32,9 @@ void SymbolUsageManager::load()
|
|||
if (error.error != QJsonParseError::NoError) {
|
||||
QMessageBox::critical(nullptr,
|
||||
tr("Load symbol usage info failed"),
|
||||
tr("Can't parse symbol usage file '%1'.")
|
||||
.arg(filename));
|
||||
tr("Can't parse symbol usage file '%1': %2")
|
||||
.arg(filename)
|
||||
.arg(error.errorString()));
|
||||
}
|
||||
|
||||
mUsages.clear();
|
||||
|
|
|
@ -37,7 +37,7 @@ CodeCompletionPopup::CodeCompletionPopup(QWidget *parent) :
|
|||
|
||||
mOnlyGlobals = false;
|
||||
mShowCount = 1000;
|
||||
mShowCodeIns = true;
|
||||
mShowCodeSnippets = true;
|
||||
|
||||
mIgnoreCase = false;
|
||||
|
||||
|
@ -469,9 +469,9 @@ void CodeCompletionPopup::getCompletionFor(const QString &fileName, const QStrin
|
|||
int i = mParser->findLastOperator(phrase);
|
||||
if (i < 0 ) { // don't have any scope prefix
|
||||
|
||||
if (mShowCodeIns) {
|
||||
if (mShowCodeSnippets) {
|
||||
//add custom code templates
|
||||
foreach (const PCodeSnippet& codeIn,mCodeInsList) {
|
||||
foreach (const PCodeSnippet& codeIn,mCodeSnippets) {
|
||||
PStatement statement = std::make_shared<Statement>();
|
||||
statement->command = codeIn->prefix;
|
||||
statement->kind = StatementKind::skUserCodeIn;
|
||||
|
@ -731,6 +731,16 @@ bool CodeCompletionPopup::isIncluded(const QString &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)
|
||||
{
|
||||
mColors = newColors;
|
||||
|
@ -793,12 +803,12 @@ void CodeCompletionPopup::setIgnoreCase(bool newIgnoreCase)
|
|||
|
||||
bool CodeCompletionPopup::showCodeIns() const
|
||||
{
|
||||
return mShowCodeIns;
|
||||
return mShowCodeSnippets;
|
||||
}
|
||||
|
||||
void CodeCompletionPopup::setShowCodeIns(bool newShowCodeIns)
|
||||
{
|
||||
mShowCodeIns = newShowCodeIns;
|
||||
mShowCodeSnippets = newShowCodeIns;
|
||||
}
|
||||
|
||||
bool CodeCompletionPopup::showKeywords() const
|
||||
|
|
Loading…
Reference in New Issue