aboutsummaryrefslogtreecommitdiffstats
path: root/SQLiteStudio3/guiSQLiteStudio/windows/codesnippeteditor.cpp
diff options
context:
space:
mode:
authorLibravatarUnit 193 <unit193@unit193.net>2023-04-30 18:30:36 -0400
committerLibravatarUnit 193 <unit193@unit193.net>2023-04-30 18:30:36 -0400
commit3565aad630864ecdbe53fdaa501ea708555b3c7c (patch)
treec743e4ad0bad39ebdb2f514c7cc52d34a257ebbe /SQLiteStudio3/guiSQLiteStudio/windows/codesnippeteditor.cpp
parent1fdc150116cad39aae5c5da407c3312b47a59e3a (diff)
New upstream version 3.4.4+dfsg.upstream/3.4.4+dfsg
Diffstat (limited to 'SQLiteStudio3/guiSQLiteStudio/windows/codesnippeteditor.cpp')
-rw-r--r--SQLiteStudio3/guiSQLiteStudio/windows/codesnippeteditor.cpp350
1 files changed, 350 insertions, 0 deletions
diff --git a/SQLiteStudio3/guiSQLiteStudio/windows/codesnippeteditor.cpp b/SQLiteStudio3/guiSQLiteStudio/windows/codesnippeteditor.cpp
new file mode 100644
index 0000000..82cade7
--- /dev/null
+++ b/SQLiteStudio3/guiSQLiteStudio/windows/codesnippeteditor.cpp
@@ -0,0 +1,350 @@
+#include "codesnippeteditor.h"
+#include "common/unused.h"
+#include "ui_codesnippeteditor.h"
+#include "uiconfig.h"
+#include "windows/codesnippeteditormodel.h"
+#include "sqlitestudio.h"
+#include "iconmanager.h"
+#include "uiutils.h"
+#include "codesnippeteditormodel.h"
+#include <QSortFilterProxyModel>
+#include <QItemSelection>
+#include <QDesktopServices>
+#include <QStyleFactory>
+
+CFG_KEYS_DEFINE(CodeSnippetEditor)
+
+CodeSnippetEditor::CodeSnippetEditor(QWidget *parent) :
+ MdiChild(parent),
+ ui(new Ui::CodeSnippetEditor)
+{
+ init();
+}
+
+CodeSnippetEditor::~CodeSnippetEditor()
+{
+ delete ui;
+}
+
+bool CodeSnippetEditor::restoreSessionNextTime()
+{
+ return false;
+}
+
+bool CodeSnippetEditor::isUncommitted() const
+{
+ return model->isModified() || currentModified;
+}
+
+QString CodeSnippetEditor::getQuitUncommittedConfirmMessage() const
+{
+ return tr("Code Snippets editor window has uncommitted modifications.");
+}
+
+QVariant CodeSnippetEditor::saveSession()
+{
+ return QVariant();
+}
+
+bool CodeSnippetEditor::restoreSession(const QVariant& sessionValue)
+{
+ UNUSED(sessionValue);
+ return true;
+}
+
+Icon* CodeSnippetEditor::getIconNameForMdiWindow()
+{
+ return ICONS.CODE_SNIPPET;
+}
+
+QString CodeSnippetEditor::getTitleForMdiWindow()
+{
+ return tr("Code Snippets editor");
+}
+
+void CodeSnippetEditor::createActions()
+{
+ createAction(COMMIT, ICONS.COMMIT, tr("Commit all snippet changes"), this, SLOT(commit()), ui->toolBar, this);
+ createAction(ROLLBACK, ICONS.ROLLBACK, tr("Rollback all snippet changes"), this, SLOT(rollback()), ui->toolBar, this);
+ ui->toolBar->addSeparator();
+ createAction(ADD, ICONS.NEW_FUNCTION, tr("Create new snippet"), this, SLOT(newSnippet()), ui->toolBar, this);
+ createAction(DELETE, ICONS.DELETE_FUNCTION, tr("Delete selected snippet"), this, SLOT(deleteSnippet()), ui->toolBar, this);
+ ui->toolBar->addSeparator();
+ createAction(MOVE_UP, ICONS.MOVE_UP, tr("Move the snippet up"), this, SLOT(moveSnippetUp()), ui->toolBar, this);
+ createAction(MOVE_DOWN, ICONS.MOVE_DOWN, tr("Move the snippet down"), this, SLOT(moveSnippetDown()), ui->toolBar, this);
+ ui->toolBar->addSeparator();
+ createAction(HELP, ICONS.HELP, tr("Code snippets manual"), this, SLOT(help()), ui->toolBar, this);
+
+#ifdef Q_OS_MACX
+ QStyle *fusion = QStyleFactory::create("Fusion");
+ ui->toolBar->setStyle(fusion);
+#endif
+}
+
+void CodeSnippetEditor::setupDefShortcuts()
+{
+ // Widget context
+ setShortcutContext({COMMIT, ROLLBACK}, Qt::WidgetWithChildrenShortcut);
+ BIND_SHORTCUTS(CodeSnippetEditor, Action);
+}
+
+QToolBar* CodeSnippetEditor::getToolBar(int toolbar) const
+{
+ UNUSED(toolbar);
+ return ui->toolBar;
+}
+
+void CodeSnippetEditor::init()
+{
+ ui->setupUi(this);
+ clearEdits();
+
+ ui->mainCodeEdit->setFont(CFG_UI.Fonts.SqlEditor.get());
+
+ model = new CodeSnippetEditorModel(this);
+ snippetFilterModel = new QSortFilterProxyModel(this);
+ snippetFilterModel->setSourceModel(model);
+ ui->list->setModel(snippetFilterModel);
+
+ initActions();
+
+ connect(ui->list->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(snippetSelected(QItemSelection,QItemSelection)));
+ connect(ui->list->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(updateState()));
+ connect(ui->assistantShortcutEdit, SIGNAL(keySequenceChanged(QKeySequence)), this, SLOT(updateModified()));
+ connect(ui->mainCodeEdit, SIGNAL(textChanged()), this, SLOT(updateModified()));
+ connect(ui->nameEdit, SIGNAL(textChanged(QString)), this, SLOT(updateModified()));
+ connect(CFG_UI.Fonts.SqlEditor, SIGNAL(changed(QVariant)), this, SLOT(changeFont(QVariant)));
+ connect(ui->clearAssistantShortcutButton, SIGNAL(clicked(bool)), this, SLOT(clearAssistantShortcutPressed()));
+
+ model->setData(CODESNIPPETS->getSnippets());
+
+ updateCurrentSnippetState();
+}
+
+int CodeSnippetEditor::getCurrentSnippetRow() const
+{
+ QModelIndexList idxList = ui->list->selectionModel()->selectedIndexes();
+ if (idxList.size() == 0)
+ return -1;
+
+ return idxList.first().row();
+}
+
+void CodeSnippetEditor::snippetDeselected(int row)
+{
+ model->setName(row, ui->nameEdit->text());
+ model->setCode(row, ui->mainCodeEdit->toPlainText());
+ model->setHotkey(row, ui->assistantShortcutEdit->keySequence());
+ model->setModified(row, currentModified);
+ model->validateNames();
+}
+
+void CodeSnippetEditor::snippetSelected(int row)
+{
+ updatesForSelection = true;
+ ui->nameEdit->setText(model->getName(row));
+ ui->mainCodeEdit->setPlainText(model->getCode(row));
+ ui->assistantShortcutEdit->setKeySequence(model->getHotkey(row));
+
+ updatesForSelection = false;
+ currentModified = model->isModified(row);
+
+ updateCurrentSnippetState();
+}
+
+void CodeSnippetEditor::selectSnippet(int row, bool skipModelUpdates)
+{
+ if (!model->isValidRowIndex(row))
+ return;
+
+ if (skipModelUpdates)
+ skipModelUpdatesDuringSelection = true;
+
+ ui->list->selectionModel()->setCurrentIndex(model->index(row), QItemSelectionModel::Clear|QItemSelectionModel::SelectCurrent);
+
+ if (skipModelUpdates)
+ skipModelUpdatesDuringSelection = false;
+}
+
+void CodeSnippetEditor::clearEdits()
+{
+ ui->nameEdit->clear();
+ ui->assistantShortcutEdit->clear();
+ ui->mainCodeEdit->setPlainText(QString());
+}
+
+void CodeSnippetEditor::commit()
+{
+ int row = getCurrentSnippetRow();
+ if (model->isValidRowIndex(row))
+ snippetDeselected(row);
+
+ QList<CodeSnippetManager::CodeSnippet*> snippets = model->generateSnippets();
+
+ CODESNIPPETS->setSnippets(snippets);
+ model->clearModified();
+ currentModified = false;
+
+ if (model->isValidRowIndex(row))
+ selectSnippet(row);
+
+ updateState();
+}
+
+void CodeSnippetEditor::rollback()
+{
+ int selectedBefore = getCurrentSnippetRow();
+
+ model->setData(CODESNIPPETS->getSnippets());
+ currentModified = false;
+ clearEdits();
+
+ if (model->isValidRowIndex(selectedBefore))
+ selectSnippet(selectedBefore);
+
+ updateState();
+}
+
+void CodeSnippetEditor::newSnippet()
+{
+ CodeSnippetManager::CodeSnippet* snip = new CodeSnippetManager::CodeSnippet();
+ snip->name = generateUniqueName("snippet", model->getSnippetNames());
+
+ model->addSnippet(snip);
+
+ selectSnippet(model->rowCount() - 1);
+}
+
+void CodeSnippetEditor::deleteSnippet()
+{
+ int row = getCurrentSnippetRow();
+ model->deleteSnippet(row);
+ clearEdits();
+
+ row = getCurrentSnippetRow();
+ if (model->isValidRowIndex(row))
+ snippetSelected(row);
+
+ updateState();
+}
+
+void CodeSnippetEditor::moveSnippetUp()
+{
+ int row = getCurrentSnippetRow();
+ int newRow = model->moveUp(row);
+ if (row != newRow)
+ selectSnippet(newRow, true);
+}
+
+void CodeSnippetEditor::moveSnippetDown()
+{
+ int row = getCurrentSnippetRow();
+ int newRow = model->moveDown(row);
+ if (row != newRow)
+ selectSnippet(newRow, true);
+}
+
+void CodeSnippetEditor::updateModified()
+{
+ if (updatesForSelection)
+ return;
+
+ int row = getCurrentSnippetRow();
+ if (model->isValidRowIndex(row))
+ {
+ bool nameDiff = model->getName(row) != ui->nameEdit->text();
+ bool codeDiff = model->getCode(row) != ui->mainCodeEdit->toPlainText();
+ bool hotkeyDiff = model->getHotkey(row) != ui->assistantShortcutEdit->keySequence();
+ currentModified = (nameDiff || codeDiff || hotkeyDiff);
+ }
+
+ updateCurrentSnippetState();
+}
+
+void CodeSnippetEditor::updateCurrentSnippetState()
+{
+ int row = getCurrentSnippetRow();
+ bool validRow = model->isValidRowIndex(row);
+ ui->rightWidget->setEnabled(validRow);
+ if (!validRow)
+ {
+ setValidState(ui->nameEdit, true);
+ setValidState(ui->mainCodeEdit, true);
+ setValidState(ui->assistantShortcutEdit, true);
+ updateState();
+ return;
+ }
+
+ QString name = ui->nameEdit->text();
+ bool nameOk = !name.trimmed().isEmpty() && model->isAllowedName(row, name);
+ setValidState(ui->nameEdit, nameOk, tr("Enter a non-empty, unique name of the snippet."));
+
+ bool codeOk = !ui->mainCodeEdit->toPlainText().trimmed().isEmpty();
+ setValidState(ui->mainCodeEdit, codeOk, tr("Enter a non-empty snippet content."));
+
+ QKeySequence assistantHotkey = ui->assistantShortcutEdit->keySequence();
+ bool hotkeyOk = assistantHotkey.isEmpty() || model->isAllowedHotkey(row, assistantHotkey);
+ setValidState(ui->assistantShortcutWidget, hotkeyOk, tr("This hotkey is not unique in context of a code assistant."));
+
+ model->setValid(row, codeOk && nameOk && hotkeyOk);
+ updateState();
+}
+
+void CodeSnippetEditor::updateState()
+{
+ bool modified = model->isModified() || currentModified;
+ bool valid = model->isValid();
+
+ actionMap[COMMIT]->setEnabled(modified && valid);
+ actionMap[ROLLBACK]->setEnabled(modified);
+ actionMap[DELETE]->setEnabled(ui->list->selectionModel()->selectedIndexes().size() > 0);
+}
+
+void CodeSnippetEditor::snippetSelected(const QItemSelection& selected, const QItemSelection& deselected)
+{
+ if (skipModelUpdatesDuringSelection)
+ return;
+
+ int deselCnt = deselected.indexes().size();
+ int selCnt = selected.indexes().size();
+
+ if (deselCnt > 0)
+ snippetDeselected(deselected.indexes().first().row());
+
+ if (selCnt > 0)
+ snippetSelected(selected.indexes().first().row());
+
+ if (deselCnt > 0 && selCnt == 0)
+ {
+ currentModified = false;
+ clearEdits();
+ }
+}
+
+void CodeSnippetEditor::applyFilter(const QString& value)
+{
+ // The selection hack (clear & set) below is described in more details in FunctionsEditor::applyFilter().
+ int row = getCurrentSnippetRow();
+ ui->list->selectionModel()->clearSelection();
+
+ snippetFilterModel->setFilterFixedString(value);
+
+ selectSnippet(row);
+}
+
+void CodeSnippetEditor::changeFont(const QVariant& font)
+{
+ ui->mainCodeEdit->setFont(font.value<QFont>());
+}
+
+void CodeSnippetEditor::clearAssistantShortcutPressed()
+{
+ ui->assistantShortcutEdit->clear();
+ ui->assistantShortcutEdit->setFocus();
+}
+
+void CodeSnippetEditor::help()
+{
+ static const QString url = QStringLiteral("https://github.com/pawelsalawa/sqlitestudio/wiki/User_Manual#code-snippets");
+ QDesktopServices::openUrl(QUrl(url, QUrl::StrictMode));
+}