mirror of
https://github.com/sqlitebrowser/sqlitebrowser.git
synced 2026-05-06 20:09:54 -05:00
Refactoring and find/replace dialog in the JSON editor.
SQL and JSON text editor classes have been refactored. A new parent class for both editors have been added for the common logic implementable without depending on the specific lexer. The only visible effect of this change should be that the JSON editor (issue #1173) now has the same find/replace dialog as the SQL editor. This prepares for the implementation of the XML editor (issue #1253).
This commit is contained in:
@@ -121,6 +121,7 @@ set(SQLB_MOC_HDR
|
||||
src/RemoteModel.h
|
||||
src/RemotePushDialog.h
|
||||
src/FindReplaceDialog.h
|
||||
src/ExtendedScintilla.h
|
||||
)
|
||||
|
||||
set(SQLB_SRC
|
||||
@@ -161,6 +162,7 @@ set(SQLB_SRC
|
||||
src/RemoteModel.cpp
|
||||
src/RemotePushDialog.cpp
|
||||
src/FindReplaceDialog.cpp
|
||||
src/ExtendedScintilla.cpp
|
||||
)
|
||||
|
||||
set(SQLB_FORMS
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
#include "ExtendedScintilla.h"
|
||||
#include "FindReplaceDialog.h"
|
||||
#include "Settings.h"
|
||||
#include "Qsci/qscilexer.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QDropEvent>
|
||||
#include <QUrl>
|
||||
#include <QMimeData>
|
||||
#include <QShortcut>
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
#include <cmath>
|
||||
|
||||
|
||||
ExtendedScintilla::ExtendedScintilla(QWidget* parent) :
|
||||
QsciScintilla(parent),
|
||||
findReplaceDialog(new FindReplaceDialog(this))
|
||||
{
|
||||
// This class does not set any lexer, that must be done in the child classes.
|
||||
|
||||
// Enable UTF8
|
||||
setUtf8(true);
|
||||
|
||||
// Enable brace matching
|
||||
setBraceMatching(QsciScintilla::SloppyBraceMatch);
|
||||
|
||||
// Enable auto indentation
|
||||
setAutoIndent(true);
|
||||
|
||||
// Enable folding
|
||||
setFolding(QsciScintilla::BoxedTreeFoldStyle);
|
||||
|
||||
// Create error indicator
|
||||
errorIndicatorNumber = indicatorDefine(QsciScintilla::SquiggleIndicator);
|
||||
setIndicatorForegroundColor(Qt::red, errorIndicatorNumber);
|
||||
|
||||
// Set a sensible scroll width, so the scroll bar is avoided in
|
||||
// most cases.
|
||||
setScrollWidth(80);
|
||||
|
||||
// Scroll width is adjusted to ensure that all of the lines
|
||||
// currently displayed can be completely scrolled. This mode never
|
||||
// adjusts the scroll width to be narrower.
|
||||
setScrollWidthTracking(true);
|
||||
|
||||
// Connect signals
|
||||
connect(this, SIGNAL(linesChanged()), this, SLOT(updateLineNumberAreaWidth()));
|
||||
|
||||
// The shortcut is constrained to the Widget context so it does not conflict with other SqlTextEdit widgets in the Main Window.
|
||||
QShortcut* shortcutFindReplace = new QShortcut(QKeySequence(tr("Ctrl+H")), this, nullptr, nullptr, Qt::WidgetShortcut);
|
||||
connect(shortcutFindReplace, SIGNAL(activated()), this, SLOT(openFindReplaceDialog()));
|
||||
|
||||
// Prepare for adding the find/replace option to the QScintilla context menu
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showContextMenu(const QPoint &)));
|
||||
}
|
||||
|
||||
ExtendedScintilla::~ExtendedScintilla()
|
||||
{
|
||||
}
|
||||
|
||||
void ExtendedScintilla::updateLineNumberAreaWidth()
|
||||
{
|
||||
// Calculate number of digits of the current number of lines
|
||||
int digits = std::floor(std::log10(lines())) + 1;
|
||||
|
||||
// Calculate the width of this number if it was all zeros (this is because a 1 might require less space than a 0 and this could
|
||||
// cause some flickering depending on the font) and set the new margin width.
|
||||
QFont font = lexer()->defaultFont();
|
||||
setMarginWidth(0, QFontMetrics(font).width(QString("0").repeated(digits)) + 5);
|
||||
}
|
||||
|
||||
void ExtendedScintilla::dropEvent(QDropEvent* e)
|
||||
{
|
||||
QList<QUrl> urls = e->mimeData()->urls();
|
||||
if(urls.isEmpty())
|
||||
return QsciScintilla::dropEvent(e);
|
||||
|
||||
QString file = urls.first().toLocalFile();
|
||||
if(!QFile::exists(file))
|
||||
return;
|
||||
|
||||
QFile f(file);
|
||||
f.open(QIODevice::ReadOnly);
|
||||
setText(f.readAll());
|
||||
f.close();
|
||||
}
|
||||
|
||||
void ExtendedScintilla::setupSyntaxHighlightingFormat(const QString& settings_name, int style)
|
||||
{
|
||||
lexer()->setColor(QColor(Settings::getValue("syntaxhighlighter", settings_name + "_colour").toString()), style);
|
||||
|
||||
QFont font(Settings::getValue("editor", "font").toString());
|
||||
font.setPointSize(Settings::getValue("editor", "fontsize").toInt());
|
||||
font.setBold(Settings::getValue("syntaxhighlighter", settings_name + "_bold").toBool());
|
||||
font.setItalic(Settings::getValue("syntaxhighlighter", settings_name + "_italic").toBool());
|
||||
font.setUnderline(Settings::getValue("syntaxhighlighter", settings_name + "_underline").toBool());
|
||||
lexer()->setFont(font, style);
|
||||
}
|
||||
|
||||
void ExtendedScintilla::reloadKeywords()
|
||||
{
|
||||
// Set lexer again to reload the updated keywords list
|
||||
setLexer(lexer());
|
||||
}
|
||||
|
||||
void ExtendedScintilla::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);
|
||||
}
|
||||
|
||||
// Set syntax highlighting settings
|
||||
QFont defaultfont(Settings::getValue("editor", "font").toString());
|
||||
defaultfont.setStyleHint(QFont::TypeWriter);
|
||||
defaultfont.setPointSize(Settings::getValue("editor", "fontsize").toInt());
|
||||
lexer()->setDefaultColor(Qt::black);
|
||||
lexer()->setFont(defaultfont);
|
||||
|
||||
// Set font
|
||||
QFont font(Settings::getValue("editor", "font").toString());
|
||||
font.setStyleHint(QFont::TypeWriter);
|
||||
font.setPointSize(Settings::getValue("editor", "fontsize").toInt());
|
||||
setFont(font);
|
||||
|
||||
// Show line numbers
|
||||
QFont marginsfont(QFont(Settings::getValue("editor", "font").toString()));
|
||||
marginsfont.setPointSize(font.pointSize());
|
||||
setMarginsFont(marginsfont);
|
||||
setMarginLineNumbers(0, true);
|
||||
setMarginsBackgroundColor(Qt::lightGray);
|
||||
updateLineNumberAreaWidth();
|
||||
|
||||
// Highlight current line
|
||||
setCaretLineVisible(true);
|
||||
setCaretLineBackgroundColor(QColor(Settings::getValue("syntaxhighlighter", "currentline_colour").toString()));
|
||||
|
||||
// Set tab width
|
||||
setTabWidth(Settings::getValue("editor", "tabsize").toInt());
|
||||
lexer()->refreshProperties();
|
||||
|
||||
// Check if error indicators are enabled and clear them if they just got disabled
|
||||
showErrorIndicators = Settings::getValue("editor", "error_indicators").toBool();
|
||||
if(!showErrorIndicators)
|
||||
clearErrorIndicators();
|
||||
|
||||
}
|
||||
|
||||
void ExtendedScintilla::clearErrorIndicators()
|
||||
{
|
||||
// Clear any error indicators from position (0,0) to the last column of the last line
|
||||
clearIndicatorRange(0, 0, lines(), lineLength(lines()), errorIndicatorNumber);
|
||||
}
|
||||
|
||||
void ExtendedScintilla::setErrorIndicator(int fromRow, int fromIndex, int toRow, int toIndex)
|
||||
{
|
||||
// Set error indicator for the specified range but only if they're enabled
|
||||
if(showErrorIndicators)
|
||||
fillIndicatorRange(fromRow, fromIndex, toRow, toIndex, errorIndicatorNumber);
|
||||
}
|
||||
|
||||
void ExtendedScintilla::setErrorIndicator(int position)
|
||||
{
|
||||
// Set error indicator for the position until end of line, but only if they're enabled
|
||||
if(showErrorIndicators) {
|
||||
|
||||
int column = SendScintilla(QsciScintillaBase::SCI_GETCOLUMN, position);
|
||||
int line = SendScintilla(QsciScintillaBase::SCI_LINEFROMPOSITION, position);
|
||||
|
||||
fillIndicatorRange(line, column, line+1, 0, errorIndicatorNumber);
|
||||
}
|
||||
}
|
||||
|
||||
bool ExtendedScintilla::findText(QString text, bool regexp, bool caseSensitive, bool words, bool wrap, bool forward) {
|
||||
|
||||
// For finding the previous occurrence, we need to skip the current
|
||||
// selection, otherwise we'd always found the same occurrence.
|
||||
if (!forward && hasSelectedText()) {
|
||||
int lineFrom, indexFrom;
|
||||
int lineTo, indexTo;
|
||||
getSelection(&lineFrom, &indexFrom, &lineTo, &indexTo);
|
||||
setCursorPosition(lineFrom, indexFrom);
|
||||
}
|
||||
|
||||
return findFirst(text, regexp, caseSensitive, words, wrap, forward);
|
||||
}
|
||||
|
||||
void ExtendedScintilla::clearSelection()
|
||||
{
|
||||
setSelection(-1,-1,-1,-1);
|
||||
}
|
||||
|
||||
void ExtendedScintilla::openFindReplaceDialog()
|
||||
{
|
||||
findReplaceDialog->setExtendedScintilla(this);
|
||||
findReplaceDialog->show();
|
||||
}
|
||||
|
||||
void ExtendedScintilla::showContextMenu(const QPoint &pos)
|
||||
{
|
||||
|
||||
QAction* findReplaceAction = new QAction(QIcon(":/icons/text_replace"), tr("Find and Replace..."), this);
|
||||
findReplaceAction->setShortcut(QKeySequence(tr("Ctrl+H")));
|
||||
connect(findReplaceAction, &QAction::triggered, [&]() {
|
||||
openFindReplaceDialog();
|
||||
});
|
||||
|
||||
// This has to be created here, otherwise the set of enabled options would not update accordingly.
|
||||
QMenu* editContextMenu = createStandardContextMenu();
|
||||
editContextMenu->addSeparator();
|
||||
editContextMenu->addAction(findReplaceAction);
|
||||
|
||||
editContextMenu->exec(mapToGlobal(pos));
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef EXTENDEDSCINTILLA_H
|
||||
#define EXTENDEDSCINTILLA_H
|
||||
|
||||
#include "Qsci/qsciscintilla.h"
|
||||
|
||||
class FindReplaceDialog;
|
||||
|
||||
/**
|
||||
* @brief The ExtendedScintilla class
|
||||
* This class extends the QScintilla widget for the application
|
||||
*/
|
||||
class ExtendedScintilla : public QsciScintilla
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ExtendedScintilla(QWidget *parent = nullptr);
|
||||
virtual ~ExtendedScintilla();
|
||||
|
||||
bool findText(QString text, bool regexp, bool caseSensitive, bool words, bool wrap, bool forward);
|
||||
void clearSelection();
|
||||
|
||||
public slots:
|
||||
void reloadKeywords();
|
||||
void reloadSettings();
|
||||
void clearErrorIndicators();
|
||||
void setErrorIndicator(int fromRow, int fromIndex, int toRow, int toIndex);
|
||||
// Set error indicator from position to end of line
|
||||
void setErrorIndicator(int position);
|
||||
void openFindReplaceDialog();
|
||||
|
||||
protected:
|
||||
void dropEvent(QDropEvent* e);
|
||||
|
||||
void setupSyntaxHighlightingFormat(const QString& settings_name, int style);
|
||||
|
||||
int errorIndicatorNumber;
|
||||
bool showErrorIndicators;
|
||||
FindReplaceDialog* findReplaceDialog;
|
||||
|
||||
private slots:
|
||||
void updateLineNumberAreaWidth();
|
||||
void showContextMenu(const QPoint &pos);
|
||||
};
|
||||
|
||||
#endif
|
||||
+20
-19
@@ -17,28 +17,28 @@ FindReplaceDialog::~FindReplaceDialog()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void FindReplaceDialog::setSqlTextEdit(SqlTextEdit* sqlTextEdit)
|
||||
void FindReplaceDialog::setExtendedScintilla(ExtendedScintilla* scintilla)
|
||||
{
|
||||
m_sqlTextEdit = sqlTextEdit;
|
||||
m_scintilla = scintilla;
|
||||
|
||||
// Create indicator for find-all and replace-all occurrences
|
||||
foundIndicatorNumber = m_sqlTextEdit->indicatorDefine(QsciScintilla::StraightBoxIndicator);
|
||||
m_sqlTextEdit->setIndicatorForegroundColor(Qt::magenta, foundIndicatorNumber);
|
||||
m_sqlTextEdit->setIndicatorDrawUnder(true, foundIndicatorNumber);
|
||||
foundIndicatorNumber = m_scintilla->indicatorDefine(QsciScintilla::StraightBoxIndicator);
|
||||
m_scintilla->setIndicatorForegroundColor(Qt::magenta, foundIndicatorNumber);
|
||||
m_scintilla->setIndicatorDrawUnder(true, foundIndicatorNumber);
|
||||
|
||||
bool isWriteable = ! m_sqlTextEdit->isReadOnly();
|
||||
bool isWriteable = ! m_scintilla->isReadOnly();
|
||||
ui->replaceWithText->setEnabled(isWriteable);
|
||||
ui->replaceButton->setEnabled(isWriteable);
|
||||
ui->replaceAllButton->setEnabled(isWriteable);
|
||||
|
||||
connect(m_sqlTextEdit, SIGNAL(destroyed()), this, SLOT(hide()));
|
||||
connect(m_scintilla, SIGNAL(destroyed()), this, SLOT(hide()));
|
||||
}
|
||||
|
||||
bool FindReplaceDialog::findNext()
|
||||
{
|
||||
clearIndicators();
|
||||
|
||||
bool found = m_sqlTextEdit->findText
|
||||
bool found = m_scintilla->findText
|
||||
(ui->findText->text(),
|
||||
ui->regexpCheckBox->isChecked(),
|
||||
ui->caseCheckBox->isChecked(),
|
||||
@@ -61,23 +61,23 @@ void FindReplaceDialog::show()
|
||||
|
||||
void FindReplaceDialog::replace()
|
||||
{
|
||||
m_sqlTextEdit->replace(ui->replaceWithText->text());
|
||||
m_scintilla->replace(ui->replaceWithText->text());
|
||||
findNext();
|
||||
}
|
||||
|
||||
void FindReplaceDialog::indicateSelection()
|
||||
{
|
||||
int fromRow, fromIndex, toRow, toIndex;
|
||||
m_sqlTextEdit->getSelection(&fromRow, &fromIndex, &toRow, &toIndex);
|
||||
m_sqlTextEdit->fillIndicatorRange(fromRow, fromIndex, toRow, toIndex, foundIndicatorNumber);
|
||||
m_scintilla->getSelection(&fromRow, &fromIndex, &toRow, &toIndex);
|
||||
m_scintilla->fillIndicatorRange(fromRow, fromIndex, toRow, toIndex, foundIndicatorNumber);
|
||||
|
||||
}
|
||||
void FindReplaceDialog::findAll()
|
||||
{
|
||||
clearIndicators();
|
||||
int occurrences = 0;
|
||||
m_sqlTextEdit->setCursorPosition(0, 0);
|
||||
while (m_sqlTextEdit->findText
|
||||
m_scintilla->setCursorPosition(0, 0);
|
||||
while (m_scintilla->findText
|
||||
(ui->findText->text(),
|
||||
ui->regexpCheckBox->isChecked(),
|
||||
ui->caseCheckBox->isChecked(),
|
||||
@@ -87,7 +87,7 @@ void FindReplaceDialog::findAll()
|
||||
indicateSelection();
|
||||
++occurrences;
|
||||
}
|
||||
m_sqlTextEdit->clearSelection();
|
||||
m_scintilla->clearSelection();
|
||||
|
||||
QString message;
|
||||
switch (occurrences) {
|
||||
@@ -109,19 +109,19 @@ void FindReplaceDialog::replaceAll()
|
||||
{
|
||||
clearIndicators();
|
||||
int occurrences = 0;
|
||||
m_sqlTextEdit->setCursorPosition(0, 0);
|
||||
while (m_sqlTextEdit->findText
|
||||
m_scintilla->setCursorPosition(0, 0);
|
||||
while (m_scintilla->findText
|
||||
(ui->findText->text(),
|
||||
ui->regexpCheckBox->isChecked(),
|
||||
ui->caseCheckBox->isChecked(),
|
||||
ui->wholeWordsCheckBox->isChecked(),
|
||||
false,
|
||||
true)) {
|
||||
m_sqlTextEdit->replace(ui->replaceWithText->text());
|
||||
m_scintilla->replace(ui->replaceWithText->text());
|
||||
indicateSelection();
|
||||
++occurrences;
|
||||
}
|
||||
m_sqlTextEdit->clearSelection();
|
||||
m_scintilla->clearSelection();
|
||||
|
||||
QString message;
|
||||
switch (occurrences) {
|
||||
@@ -147,12 +147,13 @@ void FindReplaceDialog::help()
|
||||
|
||||
void FindReplaceDialog::clearIndicators()
|
||||
{
|
||||
m_sqlTextEdit->clearIndicatorRange(0, 0, m_sqlTextEdit->lines(), m_sqlTextEdit->lineLength(m_sqlTextEdit->lines()), foundIndicatorNumber);
|
||||
m_scintilla->clearIndicatorRange(0, 0, m_scintilla->lines(), m_scintilla->lineLength(m_scintilla->lines()), foundIndicatorNumber);
|
||||
ui->messageLabel->setText("");
|
||||
}
|
||||
|
||||
void FindReplaceDialog::close()
|
||||
{
|
||||
m_scintilla->clearSelection();
|
||||
clearIndicators();
|
||||
QDialog::close();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef FindReplaceDialog_H
|
||||
#define FindReplaceDialog_H
|
||||
|
||||
#include <sqltextedit.h>
|
||||
#include <ExtendedScintilla.h>
|
||||
|
||||
#include <QDialog>
|
||||
#include <QAbstractButton>
|
||||
@@ -18,7 +18,7 @@ public:
|
||||
|
||||
explicit FindReplaceDialog(QWidget* parent = nullptr);
|
||||
~FindReplaceDialog();
|
||||
void setSqlTextEdit(SqlTextEdit* sqlTextEdit);
|
||||
void setExtendedScintilla(ExtendedScintilla* scintilla);
|
||||
void show();
|
||||
|
||||
private slots:
|
||||
@@ -35,7 +35,7 @@ private:
|
||||
void indicateSelection();
|
||||
void clearIndicators();
|
||||
Ui::FindReplaceDialog* ui;
|
||||
SqlTextEdit* m_sqlTextEdit;
|
||||
ExtendedScintilla* m_scintilla;
|
||||
int foundIndicatorNumber;
|
||||
};
|
||||
|
||||
|
||||
+3
-149
@@ -1,125 +1,32 @@
|
||||
#include "jsontextedit.h"
|
||||
#include "Settings.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QDropEvent>
|
||||
#include <QUrl>
|
||||
#include <QMimeData>
|
||||
#include <QDebug>
|
||||
#include <cmath>
|
||||
|
||||
QsciLexerJSON* JsonTextEdit::jsonLexer = nullptr;
|
||||
|
||||
JsonTextEdit::JsonTextEdit(QWidget* parent) :
|
||||
QsciScintilla(parent)
|
||||
ExtendedScintilla(parent)
|
||||
{
|
||||
// Create lexer object if not done yet
|
||||
if(jsonLexer == nullptr)
|
||||
jsonLexer = new QsciLexerJSON(this);
|
||||
|
||||
// Set the lexer
|
||||
// Set the JSON lexer
|
||||
setLexer(jsonLexer);
|
||||
|
||||
// Enable UTF8
|
||||
setUtf8(true);
|
||||
|
||||
// Enable brace matching
|
||||
setBraceMatching(QsciScintilla::SloppyBraceMatch);
|
||||
|
||||
// Enable auto indentation
|
||||
setAutoIndent(true);
|
||||
|
||||
// Enable folding
|
||||
setFolding(QsciScintilla::BoxedTreeFoldStyle);
|
||||
jsonLexer->setFoldCompact(false);
|
||||
|
||||
// Create error indicator
|
||||
errorIndicatorNumber = indicatorDefine(QsciScintilla::SquiggleIndicator);
|
||||
setIndicatorForegroundColor(Qt::red, errorIndicatorNumber);
|
||||
|
||||
// Set a sensible scroll width, so the scroll bar is avoided in
|
||||
// most cases.
|
||||
setScrollWidth(80);
|
||||
|
||||
// Scroll width is adjusted to ensure that all of the lines
|
||||
// currently displayed can be completely scrolled. This mode never
|
||||
// adjusts the scroll width to be narrower.
|
||||
setScrollWidthTracking(true);
|
||||
|
||||
// Do rest of initialisation
|
||||
reloadSettings();
|
||||
|
||||
// Connect signals
|
||||
connect(this, SIGNAL(linesChanged()), this, SLOT(updateLineNumberAreaWidth()));
|
||||
}
|
||||
|
||||
JsonTextEdit::~JsonTextEdit()
|
||||
{
|
||||
}
|
||||
|
||||
void JsonTextEdit::updateLineNumberAreaWidth()
|
||||
{
|
||||
// Calculate number of digits of the current number of lines
|
||||
int digits = std::floor(std::log10(lines())) + 1;
|
||||
|
||||
// Calculate the width of this number if it was all zeros (this is because a 1 might require less space than a 0 and this could
|
||||
// cause some flickering depending on the font) and set the new margin width.
|
||||
QFont font = lexer()->font(QsciLexerJSON::Default);
|
||||
setMarginWidth(0, QFontMetrics(font).width(QString("0").repeated(digits)) + 5);
|
||||
}
|
||||
|
||||
void JsonTextEdit::dropEvent(QDropEvent* e)
|
||||
{
|
||||
QList<QUrl> urls = e->mimeData()->urls();
|
||||
if(urls.isEmpty())
|
||||
return QsciScintilla::dropEvent(e);
|
||||
|
||||
QString file = urls.first().toLocalFile();
|
||||
if(!QFile::exists(file))
|
||||
return;
|
||||
|
||||
QFile f(file);
|
||||
f.open(QIODevice::ReadOnly);
|
||||
setText(f.readAll());
|
||||
f.close();
|
||||
}
|
||||
|
||||
void JsonTextEdit::setupSyntaxHighlightingFormat(const QString& settings_name, int style)
|
||||
{
|
||||
jsonLexer->setColor(QColor(Settings::getValue("syntaxhighlighter", settings_name + "_colour").toString()), style);
|
||||
|
||||
QFont font(Settings::getValue("editor", "font").toString());
|
||||
font.setPointSize(Settings::getValue("editor", "fontsize").toInt());
|
||||
font.setBold(Settings::getValue("syntaxhighlighter", settings_name + "_bold").toBool());
|
||||
font.setItalic(Settings::getValue("syntaxhighlighter", settings_name + "_italic").toBool());
|
||||
font.setUnderline(Settings::getValue("syntaxhighlighter", settings_name + "_underline").toBool());
|
||||
jsonLexer->setFont(font, style);
|
||||
}
|
||||
|
||||
void JsonTextEdit::reloadKeywords()
|
||||
{
|
||||
// Set lexer again to reload the updated keywords list
|
||||
setLexer(lexer());
|
||||
}
|
||||
|
||||
void JsonTextEdit::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();
|
||||
|
||||
// Set syntax highlighting settings
|
||||
QFont defaultfont(Settings::getValue("editor", "font").toString());
|
||||
defaultfont.setStyleHint(QFont::TypeWriter);
|
||||
defaultfont.setPointSize(Settings::getValue("editor", "fontsize").toInt());
|
||||
jsonLexer->setFont(defaultfont);
|
||||
setupSyntaxHighlightingFormat("comment", QsciLexerJSON::CommentLine);
|
||||
setupSyntaxHighlightingFormat("comment", QsciLexerJSON::CommentBlock);
|
||||
setupSyntaxHighlightingFormat("keyword", QsciLexerJSON::Keyword);
|
||||
@@ -144,57 +51,4 @@ void JsonTextEdit::reloadSettings()
|
||||
jsonLexer->setFont(errorFont, QsciLexerJSON::UnclosedString);
|
||||
jsonLexer->setPaper(jsonLexer->defaultPaper(QsciLexerJSON::String), QsciLexerJSON::Error);
|
||||
jsonLexer->setPaper(jsonLexer->defaultPaper(QsciLexerJSON::String), QsciLexerJSON::UnclosedString);
|
||||
|
||||
// Set font
|
||||
QFont font(Settings::getValue("editor", "font").toString());
|
||||
font.setStyleHint(QFont::TypeWriter);
|
||||
font.setPointSize(Settings::getValue("editor", "fontsize").toInt());
|
||||
setFont(font);
|
||||
|
||||
// Show line numbers
|
||||
QFont marginsfont(QFont(Settings::getValue("editor", "font").toString()));
|
||||
marginsfont.setPointSize(font.pointSize());
|
||||
setMarginsFont(marginsfont);
|
||||
setMarginLineNumbers(0, true);
|
||||
setMarginsBackgroundColor(Qt::lightGray);
|
||||
updateLineNumberAreaWidth();
|
||||
|
||||
// Highlight current line
|
||||
setCaretLineVisible(true);
|
||||
setCaretLineBackgroundColor(QColor(Settings::getValue("syntaxhighlighter", "currentline_colour").toString()));
|
||||
|
||||
// Set tab width
|
||||
setTabWidth(Settings::getValue("editor", "tabsize").toInt());
|
||||
jsonLexer->refreshProperties();
|
||||
|
||||
// Check if error indicators are enabled and clear them if they just got disabled
|
||||
showErrorIndicators = Settings::getValue("editor", "error_indicators").toBool();
|
||||
if(!showErrorIndicators)
|
||||
clearErrorIndicators();
|
||||
|
||||
}
|
||||
|
||||
void JsonTextEdit::clearErrorIndicators()
|
||||
{
|
||||
// Clear any error indicators from position (0,0) to the last column of the last line
|
||||
clearIndicatorRange(0, 0, lines(), lineLength(lines()), errorIndicatorNumber);
|
||||
}
|
||||
|
||||
void JsonTextEdit::setErrorIndicator(int fromRow, int fromIndex, int toRow, int toIndex)
|
||||
{
|
||||
// Set error indicator for the specified range but only if they're enabled
|
||||
if(showErrorIndicators)
|
||||
fillIndicatorRange(fromRow, fromIndex, toRow, toIndex, errorIndicatorNumber);
|
||||
}
|
||||
|
||||
void JsonTextEdit::setErrorIndicator(int position)
|
||||
{
|
||||
// Set error indicator for the position until end of line, but only if they're enabled
|
||||
if(showErrorIndicators) {
|
||||
|
||||
int column = SendScintilla(QsciScintillaBase::SCI_GETCOLUMN, position);
|
||||
int line = SendScintilla(QsciScintillaBase::SCI_LINEFROMPOSITION, position);
|
||||
|
||||
fillIndicatorRange(line, column, line+1, 0, errorIndicatorNumber);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-20
@@ -1,14 +1,14 @@
|
||||
#ifndef JSONTEXTEDIT_H
|
||||
#define JSONTEXTEDIT_H
|
||||
|
||||
#include "Qsci/qsciscintilla.h"
|
||||
#include "ExtendedScintilla.h"
|
||||
#include <Qsci/qscilexerjson.h>
|
||||
|
||||
/**
|
||||
* @brief The JsonTextEdit class
|
||||
* This class is based on the QScintilla widget
|
||||
* This class is based on our Extended QScintilla widget
|
||||
*/
|
||||
class JsonTextEdit : public QsciScintilla
|
||||
class JsonTextEdit : public ExtendedScintilla
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -19,24 +19,7 @@ public:
|
||||
static QsciLexerJSON* jsonLexer;
|
||||
|
||||
public slots:
|
||||
void reloadKeywords();
|
||||
void reloadSettings();
|
||||
void clearErrorIndicators();
|
||||
void setErrorIndicator(int fromRow, int fromIndex, int toRow, int toIndex);
|
||||
// Set error indicator from position to end of line
|
||||
void setErrorIndicator(int position);
|
||||
|
||||
protected:
|
||||
void dropEvent(QDropEvent* e);
|
||||
|
||||
private:
|
||||
void setupSyntaxHighlightingFormat(const QString& settings_name, int style);
|
||||
|
||||
int errorIndicatorNumber;
|
||||
bool showErrorIndicators;
|
||||
|
||||
private slots:
|
||||
void updateLineNumberAreaWidth();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+3
-191
@@ -1,28 +1,17 @@
|
||||
#include "sqltextedit.h"
|
||||
#include "Settings.h"
|
||||
#include "SqlUiLexer.h"
|
||||
#include "FindReplaceDialog.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QDropEvent>
|
||||
#include <QUrl>
|
||||
#include <QMimeData>
|
||||
#include <QShortcut>
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
#include <cmath>
|
||||
|
||||
SqlUiLexer* SqlTextEdit::sqlLexer = nullptr;
|
||||
|
||||
SqlTextEdit::SqlTextEdit(QWidget* parent) :
|
||||
QsciScintilla(parent),
|
||||
findReplaceDialog(new FindReplaceDialog(this))
|
||||
ExtendedScintilla(parent)
|
||||
{
|
||||
// Create lexer object if not done yet
|
||||
if(sqlLexer == nullptr)
|
||||
sqlLexer = new SqlUiLexer(this);
|
||||
|
||||
// Set the lexer
|
||||
// Set the SQL lexer
|
||||
setLexer(sqlLexer);
|
||||
|
||||
// Set icons for auto completion
|
||||
@@ -31,114 +20,18 @@ SqlTextEdit::SqlTextEdit(QWidget* parent) :
|
||||
registerImage(SqlUiLexer::ApiCompleterIconIdTable, QImage(":/icons/table"));
|
||||
registerImage(SqlUiLexer::ApiCompleterIconIdColumn, QImage(":/icons/field"));
|
||||
|
||||
// Enable UTF8
|
||||
setUtf8(true);
|
||||
|
||||
// Enable brace matching
|
||||
setBraceMatching(QsciScintilla::SloppyBraceMatch);
|
||||
|
||||
// Enable auto indentation
|
||||
setAutoIndent(true);
|
||||
|
||||
// Enable folding
|
||||
setFolding(QsciScintilla::BoxedTreeFoldStyle);
|
||||
|
||||
// Create error indicator
|
||||
errorIndicatorNumber = indicatorDefine(QsciScintilla::SquiggleIndicator);
|
||||
setIndicatorForegroundColor(Qt::red, errorIndicatorNumber);
|
||||
|
||||
// Set a sensible scroll width, so the scroll bar is avoided in
|
||||
// most cases.
|
||||
setScrollWidth(80);
|
||||
|
||||
// Scroll width is adjusted to ensure that all of the lines
|
||||
// currently displayed can be completely scrolled. This mode never
|
||||
// adjusts the scroll width to be narrower.
|
||||
setScrollWidthTracking(true);
|
||||
|
||||
// Do rest of initialisation
|
||||
reloadSettings();
|
||||
|
||||
// Connect signals
|
||||
connect(this, SIGNAL(linesChanged()), this, SLOT(updateLineNumberAreaWidth()));
|
||||
|
||||
// The shortcut is constrained to the Widget context so it does not conflict with other SqlTextEdit widgets in the Main Window.
|
||||
QShortcut* shortcutFindReplace = new QShortcut(QKeySequence(tr("Ctrl+H")), this, nullptr, nullptr, Qt::WidgetShortcut);
|
||||
connect(shortcutFindReplace, SIGNAL(activated()), this, SLOT(openFindReplaceDialog()));
|
||||
|
||||
// Prepare for adding the find/replace option to the QScintilla context menu
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showContextMenu(const QPoint &)));
|
||||
}
|
||||
|
||||
SqlTextEdit::~SqlTextEdit()
|
||||
{
|
||||
}
|
||||
|
||||
void SqlTextEdit::updateLineNumberAreaWidth()
|
||||
{
|
||||
// Calculate number of digits of the current number of lines
|
||||
int digits = std::floor(std::log10(lines())) + 1;
|
||||
|
||||
// Calculate the width of this number if it was all zeros (this is because a 1 might require less space than a 0 and this could
|
||||
// cause some flickering depending on the font) and set the new margin width.
|
||||
QFont font = lexer()->font(QsciLexerSQL::Default);
|
||||
setMarginWidth(0, QFontMetrics(font).width(QString("0").repeated(digits)) + 5);
|
||||
}
|
||||
|
||||
void SqlTextEdit::dropEvent(QDropEvent* e)
|
||||
{
|
||||
QList<QUrl> urls = e->mimeData()->urls();
|
||||
if(urls.isEmpty())
|
||||
return QsciScintilla::dropEvent(e);
|
||||
|
||||
QString file = urls.first().toLocalFile();
|
||||
if(!QFile::exists(file))
|
||||
return;
|
||||
|
||||
QFile f(file);
|
||||
f.open(QIODevice::ReadOnly);
|
||||
setText(f.readAll());
|
||||
f.close();
|
||||
}
|
||||
|
||||
void SqlTextEdit::setupSyntaxHighlightingFormat(const QString& settings_name, int style)
|
||||
{
|
||||
sqlLexer->setColor(QColor(Settings::getValue("syntaxhighlighter", settings_name + "_colour").toString()), style);
|
||||
|
||||
QFont font(Settings::getValue("editor", "font").toString());
|
||||
font.setPointSize(Settings::getValue("editor", "fontsize").toInt());
|
||||
font.setBold(Settings::getValue("syntaxhighlighter", settings_name + "_bold").toBool());
|
||||
font.setItalic(Settings::getValue("syntaxhighlighter", settings_name + "_italic").toBool());
|
||||
font.setUnderline(Settings::getValue("syntaxhighlighter", settings_name + "_underline").toBool());
|
||||
sqlLexer->setFont(font, style);
|
||||
}
|
||||
|
||||
void SqlTextEdit::reloadKeywords()
|
||||
{
|
||||
// Set lexer again to reload the updated keywords list
|
||||
setLexer(lexer());
|
||||
}
|
||||
|
||||
void SqlTextEdit::reloadSettings()
|
||||
{
|
||||
// Enable auto completion if it hasn't been disabled
|
||||
if(Settings::getValue("editor", "auto_completion").toBool())
|
||||
{
|
||||
setAutoCompletionThreshold(3);
|
||||
setAutoCompletionCaseSensitivity(false);
|
||||
setAutoCompletionShowSingle(true);
|
||||
setAutoCompletionSource(QsciScintilla::AcsAPIs);
|
||||
} else {
|
||||
setAutoCompletionThreshold(0);
|
||||
}
|
||||
ExtendedScintilla::reloadSettings();
|
||||
|
||||
// Set syntax highlighting settings
|
||||
QFont defaultfont(Settings::getValue("editor", "font").toString());
|
||||
defaultfont.setStyleHint(QFont::TypeWriter);
|
||||
defaultfont.setPointSize(Settings::getValue("editor", "fontsize").toInt());
|
||||
sqlLexer->setColor(Qt::black, QsciLexerSQL::Default);
|
||||
sqlLexer->setFont(defaultfont);
|
||||
setupSyntaxHighlightingFormat("comment", QsciLexerSQL::Comment);
|
||||
setupSyntaxHighlightingFormat("comment", QsciLexerSQL::CommentLine);
|
||||
setupSyntaxHighlightingFormat("comment", QsciLexerSQL::CommentDoc);
|
||||
@@ -149,85 +42,4 @@ void SqlTextEdit::reloadSettings()
|
||||
setupSyntaxHighlightingFormat("string", QsciLexerSQL::SingleQuotedString);
|
||||
setupSyntaxHighlightingFormat("identifier", QsciLexerSQL::Identifier);
|
||||
setupSyntaxHighlightingFormat("identifier", QsciLexerSQL::QuotedIdentifier);
|
||||
|
||||
// Set font
|
||||
QFont font(Settings::getValue("editor", "font").toString());
|
||||
font.setStyleHint(QFont::TypeWriter);
|
||||
font.setPointSize(Settings::getValue("editor", "fontsize").toInt());
|
||||
setFont(font);
|
||||
|
||||
// Show line numbers
|
||||
QFont marginsfont(QFont(Settings::getValue("editor", "font").toString()));
|
||||
marginsfont.setPointSize(font.pointSize());
|
||||
setMarginsFont(marginsfont);
|
||||
setMarginLineNumbers(0, true);
|
||||
setMarginsBackgroundColor(Qt::lightGray);
|
||||
updateLineNumberAreaWidth();
|
||||
|
||||
// Highlight current line
|
||||
setCaretLineVisible(true);
|
||||
setCaretLineBackgroundColor(QColor(Settings::getValue("syntaxhighlighter", "currentline_colour").toString()));
|
||||
|
||||
// Set tab width
|
||||
setTabWidth(Settings::getValue("editor", "tabsize").toInt());
|
||||
|
||||
// Check if error indicators are enabled and clear them if they just got disabled
|
||||
showErrorIndicators = Settings::getValue("editor", "error_indicators").toBool();
|
||||
if(!showErrorIndicators)
|
||||
clearErrorIndicators();
|
||||
}
|
||||
|
||||
void SqlTextEdit::clearErrorIndicators()
|
||||
{
|
||||
// Clear any error indicators from position (0,0) to the last column of the last line
|
||||
clearIndicatorRange(0, 0, lines(), lineLength(lines()), errorIndicatorNumber);
|
||||
}
|
||||
|
||||
void SqlTextEdit::setErrorIndicator(int fromRow, int fromIndex, int toRow, int toIndex)
|
||||
{
|
||||
// Set error indicator for the specified range but only if they're enabled
|
||||
if(showErrorIndicators)
|
||||
fillIndicatorRange(fromRow, fromIndex, toRow, toIndex, errorIndicatorNumber);
|
||||
}
|
||||
|
||||
bool SqlTextEdit::findText(QString text, bool regexp, bool caseSensitive, bool words, bool wrap, bool forward) {
|
||||
|
||||
// For finding the previous occurrence, we need to skip the current
|
||||
// selection, otherwise we'd always found the same occurrence.
|
||||
if (!forward && hasSelectedText()) {
|
||||
int lineFrom, indexFrom;
|
||||
int lineTo, indexTo;
|
||||
getSelection(&lineFrom, &indexFrom, &lineTo, &indexTo);
|
||||
setCursorPosition(lineFrom, indexFrom);
|
||||
}
|
||||
|
||||
return findFirst(text, regexp, caseSensitive, words, wrap, forward);
|
||||
}
|
||||
|
||||
void SqlTextEdit::clearSelection()
|
||||
{
|
||||
setSelection(-1,-1,-1,-1);
|
||||
}
|
||||
|
||||
void SqlTextEdit::openFindReplaceDialog()
|
||||
{
|
||||
findReplaceDialog->setSqlTextEdit(this);
|
||||
findReplaceDialog->show();
|
||||
}
|
||||
|
||||
void SqlTextEdit::showContextMenu(const QPoint &pos)
|
||||
{
|
||||
|
||||
QAction* findReplaceAction = new QAction(QIcon(":/icons/text_replace"), tr("Find and Replace..."), this);
|
||||
findReplaceAction->setShortcut(QKeySequence(tr("Ctrl+H")));
|
||||
connect(findReplaceAction, &QAction::triggered, [&]() {
|
||||
openFindReplaceDialog();
|
||||
});
|
||||
|
||||
// This has to be created here, otherwise the set of enabled options would not update accordingly.
|
||||
QMenu* editContextMenu = createStandardContextMenu();
|
||||
editContextMenu->addSeparator();
|
||||
editContextMenu->addAction(findReplaceAction);
|
||||
|
||||
editContextMenu->exec(mapToGlobal(pos));
|
||||
}
|
||||
|
||||
+2
-21
@@ -1,7 +1,7 @@
|
||||
#ifndef SQLTEXTEDIT_H
|
||||
#define SQLTEXTEDIT_H
|
||||
|
||||
#include "Qsci/qsciscintilla.h"
|
||||
#include "ExtendedScintilla.h"
|
||||
|
||||
class FindReplaceDialog;
|
||||
class SqlUiLexer;
|
||||
@@ -10,7 +10,7 @@ class SqlUiLexer;
|
||||
* @brief The SqlTextEdit class
|
||||
* This class is based on the QScintilla widget
|
||||
*/
|
||||
class SqlTextEdit : public QsciScintilla
|
||||
class SqlTextEdit : public ExtendedScintilla
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -18,30 +18,11 @@ public:
|
||||
explicit SqlTextEdit(QWidget *parent = nullptr);
|
||||
virtual ~SqlTextEdit();
|
||||
|
||||
bool findText(QString text, bool regexp, bool caseSensitive, bool words, bool wrap, bool forward);
|
||||
void clearSelection();
|
||||
static SqlUiLexer* sqlLexer;
|
||||
|
||||
public slots:
|
||||
void reloadKeywords();
|
||||
void reloadSettings();
|
||||
void clearErrorIndicators();
|
||||
void setErrorIndicator(int fromRow, int fromIndex, int toRow, int toIndex);
|
||||
void openFindReplaceDialog();
|
||||
|
||||
protected:
|
||||
void dropEvent(QDropEvent* e);
|
||||
|
||||
private:
|
||||
void setupSyntaxHighlightingFormat(const QString& settings_name, int style);
|
||||
|
||||
int errorIndicatorNumber;
|
||||
bool showErrorIndicators;
|
||||
FindReplaceDialog* findReplaceDialog;
|
||||
|
||||
private slots:
|
||||
void updateLineNumberAreaWidth();
|
||||
void showContextMenu(const QPoint &pos);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+4
-2
@@ -60,7 +60,8 @@ HEADERS += \
|
||||
RemoteModel.h \
|
||||
RemotePushDialog.h \
|
||||
jsontextedit.h \
|
||||
FindReplaceDialog.h
|
||||
FindReplaceDialog.h \
|
||||
ExtendedScintilla.h
|
||||
|
||||
SOURCES += \
|
||||
sqlitedb.cpp \
|
||||
@@ -98,7 +99,8 @@ SOURCES += \
|
||||
RemoteModel.cpp \
|
||||
RemotePushDialog.cpp \
|
||||
jsontextedit.cpp \
|
||||
FindReplaceDialog.cpp
|
||||
FindReplaceDialog.cpp \
|
||||
ExtendedScintilla.cpp
|
||||
|
||||
RESOURCES += icons/icons.qrc \
|
||||
translations/flags/flags.qrc \
|
||||
|
||||
Reference in New Issue
Block a user