Evaluation mode in the Edit Database Cell editor

Entered expressions are evaluated using SQLite and the result is saved in
the cell.

The SQL Evaluation mode reuses the class used for the "Execute SQL" editor
so syntax highlighting and call-tips are supported.

See issue #2387
This commit is contained in:
mgrojo
2020-11-27 17:37:00 +01:00
parent 9b387d2061
commit 9a70af7973
7 changed files with 60 additions and 17 deletions

View File

@@ -1,6 +1,5 @@
#include "EditDialog.h"
#include "ui_EditDialog.h"
#include "sqlitedb.h"
#include "Settings.h"
#include "qhexedit.h"
#include "docktextedit.h"
@@ -163,6 +162,7 @@ void EditDialog::loadData(const QByteArray& bArrdata)
case TextEditor:
case JsonEditor:
case XmlEditor:
case SqlEvaluator:
// The JSON widget buffer is now the main data source
dataSource = SciBuffer;
@@ -216,6 +216,7 @@ void EditDialog::loadData(const QByteArray& bArrdata)
case TextEditor:
case JsonEditor:
case XmlEditor:
case SqlEvaluator:
setDataInBuffer(bArrdata, SciBuffer);
break;
case RtlTextEditor:
@@ -247,8 +248,9 @@ void EditDialog::loadData(const QByteArray& bArrdata)
// Update the display if in text edit or image viewer mode
switch (editMode) {
case TextEditor:
case XmlEditor:
case JsonEditor:
case XmlEditor:
case SqlEvaluator:
// Disable text editing, and use a warning message as the contents
sciEdit->setText(tr("Image data can't be viewed in this mode.") % '\n' %
tr("Try switching to Image or Binary mode."));
@@ -279,7 +281,7 @@ void EditDialog::loadData(const QByteArray& bArrdata)
case TextEditor:
case JsonEditor:
case XmlEditor:
case SqlEvaluator:
setDataInBuffer(bArrdata, SciBuffer);
break;
@@ -316,6 +318,7 @@ void EditDialog::loadData(const QByteArray& bArrdata)
case TextEditor:
case JsonEditor:
case XmlEditor:
case SqlEvaluator:
// Disable text editing, and use a warning message as the contents
sciEdit->setText(QString(tr("Binary data can't be viewed in this mode.") % '\n' %
tr("Try switching to Binary mode.")));
@@ -367,6 +370,7 @@ void EditDialog::importData(bool asLink)
switch (mode) {
case TextEditor:
case RtlTextEditor:
case SqlEvaluator:
selectedFilter = FILE_FILTER_TXT;
break;
case HexEditor:
@@ -620,6 +624,9 @@ void EditDialog::accept()
emit recordTextUpdated(m_currentIndex, newData.toUtf8(), false);
}
break;
case DockTextEdit::SQL:
emit evaluateText(m_currentIndex, sciEdit->text().toStdString());
break;
}
break;
case HexBuffer:
@@ -632,7 +639,6 @@ void EditDialog::accept()
}
if (!newTextData.isEmpty()) {
QString oldData = m_currentIndex.data(Qt::EditRole).toString();
// Check first for null case, otherwise empty strings cannot overwrite NULL values
if ((m_currentIndex.data(Qt::EditRole).isNull() && dataType != Null) || oldData != newTextData)
@@ -675,6 +681,7 @@ void EditDialog::setDataInBuffer(const QByteArray& bArrdata, DataSources source)
case SciBuffer:
switch (sciEdit->language()) {
case DockTextEdit::PlainText:
case DockTextEdit::SQL:
{
// Load the text into the text editor, remove BOM first if there is one
QByteArray dataWithoutBom = bArrdata;
@@ -756,6 +763,10 @@ void EditDialog::editModeChanged(int newMode)
ui->actionIndent->setEnabled(newMode == JsonEditor || newMode == XmlEditor);
setStackCurrentIndex(newMode);
// Change focus from the mode combo to the editor to start typing.
if (ui->comboMode->hasFocus())
setFocus();
// * If the dataSource is the text buffer, the data is always text *
switch (dataSource) {
case QtBuffer:
@@ -767,7 +778,7 @@ void EditDialog::editModeChanged(int newMode)
case TextEditor: // Switching to one of the Scintilla editor modes
case JsonEditor:
case XmlEditor:
case SqlEvaluator:
setDataInBuffer(ui->qtEdit->toPlainText().toUtf8(), SciBuffer);
break;
@@ -820,9 +831,10 @@ void EditDialog::editModeChanged(int newMode)
}
break;
case TextEditor: // Switching to the text editor
case JsonEditor: // Switching to the JSON editor
case XmlEditor: // Switching to the XML editor
case TextEditor:
case JsonEditor:
case XmlEditor:
case SqlEvaluator:
// The text is already in the Sci buffer but we need to perform the necessary formatting.
setDataInBuffer(sciEdit->text().toUtf8(), SciBuffer);
@@ -1117,6 +1129,11 @@ void EditDialog::setStackCurrentIndex(int editMode)
ui->editorStack->setCurrentIndex(TextEditor);
sciEdit->setLanguage(DockTextEdit::XML);
break;
case SqlEvaluator:
// Scintilla case: switch to the single Scintilla editor and set language
ui->editorStack->setCurrentIndex(TextEditor);
sciEdit->setLanguage(DockTextEdit::SQL);
break;
}
}

View File

@@ -51,6 +51,7 @@ private slots:
signals:
void recordTextUpdated(const QPersistentModelIndex& idx, const QByteArray& bArrdata, bool isBlob);
void evaluateText(const QPersistentModelIndex& idx, const std::string& text);
void requestUrlOrFileOpen(const QString& urlString);
private:
@@ -84,7 +85,7 @@ private:
};
// Edit modes and editor stack (this must be aligned with the UI).
// Note that text modes (plain, JSON and XML) share the Scintilla widget,
// Note that text modes (plain, JSON, XML and SQL evaluator) share the Scintilla widget,
// Consequently the editor stack range is TextEditor..ImageViewer.
enum EditModes {
// Modes with their own widget in the stack:
@@ -94,7 +95,8 @@ private:
ImageEditor = 3,
// Modes in the Scintilla editor:
JsonEditor = 4,
XmlEditor = 5
XmlEditor = 5,
SqlEvaluator = 6
};
int checkDataType(const QByteArray& bArrdata) const;

View File

@@ -88,6 +88,11 @@
<string>XML</string>
</property>
</item>
<item>
<property name="text">
<string>Evaluation</string>
</property>
</item>
</widget>
</item>
<item>
@@ -153,7 +158,9 @@
<property name="whatsThis">
<string>The text editor modes let you edit plain text, as well as JSON or XML data with syntax highlighting, automatic formatting and validation before saving.
Errors are indicated with a red squiggle underline.</string>
Errors are indicated with a red squiggle underline.
In the Evaluation mode, entered SQLite expressions are evaluated and the result applied to the cell.</string>
</property>
</widget>
<widget class="QWidget" name="rtlVerticalLayout">

View File

@@ -428,6 +428,7 @@ void MainWindow::init()
// Connect some more signals and slots
connect(editDock, &EditDialog::recordTextUpdated, this, &MainWindow::updateRecordText);
connect(editDock, &EditDialog::evaluateText, this, &MainWindow::evaluateText);
connect(editDock, &EditDialog::requestUrlOrFileOpen, this, &MainWindow::openUrlOrFile);
connect(ui->dbTreeWidget->selectionModel(), &QItemSelectionModel::currentChanged, this, &MainWindow::changeTreeSelection);
connect(ui->dockEdit, &QDockWidget::visibilityChanged, this, &MainWindow::toggleEditDock);
@@ -986,6 +987,12 @@ void MainWindow::updateRecordText(const QPersistentModelIndex& idx, const QByteA
m_currentTabTableModel->setTypedData(idx, isBlob, text);
}
void MainWindow::evaluateText(const QPersistentModelIndex& idx, const std::string& text)
{
QByteArray value = db.querySingleValueFromDb("SELECT " + text, /* log */ true, DBBrowserDB::Wait);
m_currentTabTableModel->setTypedData(idx, !isTextOnly(value), value);
}
void MainWindow::toggleEditDock(bool visible)
{
if (!visible) {

View File

@@ -175,6 +175,7 @@ private slots:
void helpWhatsThis();
void helpAbout();
void updateRecordText(const QPersistentModelIndex& idx, const QByteArray& text, bool isBlob);
void evaluateText(const QPersistentModelIndex& idx, const std::string& text);
void toggleEditDock(bool visible);
void dataTableSelectionChanged(const QModelIndex& index);
void doubleClickTable(const QModelIndex& index);

View File

@@ -1,5 +1,6 @@
#include "docktextedit.h"
#include "Settings.h"
#include "SqlUiLexer.h"
#include <Qsci/qscistyle.h>
#include <Qsci/qscilexerjson.h>
@@ -9,7 +10,7 @@ QsciLexerJSON* DockTextEdit::jsonLexer = nullptr;
QsciLexerXML* DockTextEdit::xmlLexer = nullptr;
DockTextEdit::DockTextEdit(QWidget* parent) :
ExtendedScintilla(parent)
SqlTextEdit(parent)
{
// Create lexer objects if not done yet
if(jsonLexer == nullptr)
@@ -29,7 +30,8 @@ DockTextEdit::DockTextEdit(QWidget* parent) :
void DockTextEdit::reloadSettings()
{
// Set the parent settings for both lexers
// Set the parent settings for all lexers
SqlTextEdit::reloadSettings();
reloadLexerSettings(jsonLexer);
reloadLexerSettings(xmlLexer);
@@ -94,6 +96,10 @@ void DockTextEdit::setLanguage(Language lang)
setLexer(xmlLexer);
setFolding(QsciScintilla::BoxedTreeFoldStyle);
break;
case SQL:
setLexer(sqlLexer);
setFolding(QsciScintilla::BoxedTreeFoldStyle);
break;
}
}

View File

@@ -1,16 +1,17 @@
#ifndef DOCKTEXTEDIT_H
#define DOCKTEXTEDIT_H
#include "ExtendedScintilla.h"
#include "sqltextedit.h"
class QsciLexerJSON;
class QsciLexerXML;
class SqlUiLexer;
/**
* @brief The DockTextEdit class
* This class is based on our Extended QScintilla widget
* This class extends our QScintilla SQL Text Edit adding XML, JSON and plain text modes.
*/
class DockTextEdit : public ExtendedScintilla
class DockTextEdit : public SqlTextEdit
{
Q_OBJECT
@@ -22,7 +23,8 @@ public:
{
PlainText,
JSON,
XML
XML,
SQL
};
void setLanguage(Language lang);
@@ -40,6 +42,7 @@ public slots:
protected:
static QsciLexerJSON* jsonLexer;
static QsciLexerXML* xmlLexer;
private:
Language m_language;
QFont plainTextFont;