Files
sqlitebrowser/src/sqltextedit.cpp
mgrojo 33266b7707 Improvement and fixes to the un/comment block feature
The last line of the selection is considered part of the block, even if it
is not completely selected. At the same time, we have to discard this last
line of the selection, if the index is 0, since in that case there is no
actual selected character in the line.

Additionally all the steps in the replacement are considered a single
action for history, so that user can undo the change in a single undo
action.

See issue #1614
2018-11-21 21:13:40 +01:00

133 lines
4.8 KiB
C++

#include "sql/sqlitetypes.h"
#include "sqltextedit.h"
#include "Settings.h"
#include "SqlUiLexer.h"
#include <Qsci/qscicommandset.h>
#include <Qsci/qscicommand.h>
#include <QShortcut>
#include <QRegExp>
SqlUiLexer* SqlTextEdit::sqlLexer = nullptr;
SqlTextEdit::SqlTextEdit(QWidget* parent) :
ExtendedScintilla(parent)
{
// Create lexer object if not done yet
if(sqlLexer == nullptr)
sqlLexer = new SqlUiLexer(this);
// Set the SQL lexer
setLexer(sqlLexer);
// Set icons for auto completion
registerImage(SqlUiLexer::ApiCompleterIconIdKeyword, QImage(":/icons/keyword"));
registerImage(SqlUiLexer::ApiCompleterIconIdFunction, QImage(":/icons/function"));
registerImage(SqlUiLexer::ApiCompleterIconIdTable, QImage(":/icons/table"));
registerImage(SqlUiLexer::ApiCompleterIconIdColumn, QImage(":/icons/field"));
registerImage(SqlUiLexer::ApiCompleterIconIdSchema, QImage(":/icons/database"));
// Remove command bindings that would interfere with our shortcutToggleComment
QsciCommand * command = standardCommands()->boundTo(Qt::ControlModifier+Qt::Key_Slash);
command->setKey(0);
command = standardCommands()->boundTo(Qt::ControlModifier+Qt::ShiftModifier+Qt::Key_Slash);
command->setKey(0);
QShortcut* shortcutToggleComment = new QShortcut(QKeySequence(tr("Ctrl+/")), this, nullptr, nullptr, Qt::WidgetShortcut);
connect(shortcutToggleComment, &QShortcut::activated, this, &SqlTextEdit::toggleBlockComment);
// Do rest of initialisation
reloadSettings();
}
SqlTextEdit::~SqlTextEdit()
{
}
void SqlTextEdit::reloadSettings()
{
// Enable auto completion if it hasn't been disabled
if(Settings::getValue("editor", "auto_completion").toBool())
{
setAutoCompletionThreshold(3);
setAutoCompletionCaseSensitivity(true);
setAutoCompletionShowSingle(true);
setAutoCompletionSource(QsciScintilla::AcsAPIs);
} else {
setAutoCompletionThreshold(0);
}
ExtendedScintilla::reloadSettings();
setupSyntaxHighlightingFormat(sqlLexer, "comment", QsciLexerSQL::Comment);
setupSyntaxHighlightingFormat(sqlLexer, "comment", QsciLexerSQL::CommentLine);
setupSyntaxHighlightingFormat(sqlLexer, "comment", QsciLexerSQL::CommentDoc);
setupSyntaxHighlightingFormat(sqlLexer, "keyword", QsciLexerSQL::Keyword);
setupSyntaxHighlightingFormat(sqlLexer, "table", QsciLexerSQL::KeywordSet6);
setupSyntaxHighlightingFormat(sqlLexer, "function", QsciLexerSQL::KeywordSet7);
setupSyntaxHighlightingFormat(sqlLexer, "string", QsciLexerSQL::SingleQuotedString);
// Highlight double quote strings as identifier or as literal string depending on user preference
switch(static_cast<sqlb::escapeQuoting>(Settings::getValue("editor", "identifier_quotes").toInt())) {
case sqlb::DoubleQuotes:
setupSyntaxHighlightingFormat(sqlLexer, "identifier", QsciLexerSQL::DoubleQuotedString);
sqlLexer->setQuotedIdentifiers(false);
break;
case sqlb::GraveAccents:
sqlLexer->setQuotedIdentifiers(true);
// Fall through, treat quoted string as literal string
case sqlb::SquareBrackets:
setupSyntaxHighlightingFormat(sqlLexer, "string", QsciLexerSQL::DoubleQuotedString);
break;
}
setupSyntaxHighlightingFormat(sqlLexer, "identifier", QsciLexerSQL::Identifier);
setupSyntaxHighlightingFormat(sqlLexer, "identifier", QsciLexerSQL::QuotedIdentifier);
}
void SqlTextEdit::toggleBlockComment()
{
int lineFrom, indexFrom, lineTo, indexTo;
// If there is no selection, select the current line
if (!hasSelectedText()) {
getCursorPosition(&lineFrom, &indexFrom);
// Windows lines requires an adjustment, otherwise the selection would
// end in the next line.
indexTo = text(lineFrom).endsWith("\r\n") ? lineLength(lineFrom)-1 : lineLength(lineFrom);
setSelection(lineFrom, 0, lineFrom, indexTo);
}
getSelection(&lineFrom, &indexFrom, &lineTo, &indexTo);
bool uncomment = text(lineFrom).contains(QRegExp("^[ \t]*--"));
// If the selection ends before the first character of a line, don't
// take this line into account for un/commenting.
if (indexTo==0)
lineTo--;
beginUndoAction();
// Iterate over the selected lines, get line text, make
// replacement depending on whether the first line was commented
// or uncommented, and replace the line text. All in a single undo action.
for (int line=lineFrom; line<=lineTo; line++) {
QString lineText = text(line);
if (uncomment)
lineText.replace(QRegExp("^([ \t]*)-- ?"), "\\1");
else
lineText.replace(QRegExp("^"), "-- ");
indexTo = lineText.endsWith("\r\n") ? lineLength(line)-1 : lineLength(line);
setSelection(line, 0, line, indexTo);
replaceSelectedText(lineText);
}
endUndoAction();
}