mirror of
https://github.com/sqlitebrowser/sqlitebrowser.git
synced 2026-02-06 19:48:28 -06:00
Merge pull request #1275 from sqlitebrowser/xml_cell_edit
XML mode for the cell editor
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include "sqlitedb.h"
|
||||
#include "Settings.h"
|
||||
#include "src/qhexedit.h"
|
||||
#include "docktextedit.h"
|
||||
#include "FileDialog.h"
|
||||
#include "Data.h"
|
||||
|
||||
@@ -13,6 +14,7 @@
|
||||
#include <QBuffer>
|
||||
#include <QModelIndex>
|
||||
#include <QJsonDocument>
|
||||
#include <QDomDocument>
|
||||
#include <QMessageBox>
|
||||
|
||||
EditDialog::EditDialog(QWidget* parent)
|
||||
@@ -21,7 +23,6 @@ EditDialog::EditDialog(QWidget* parent)
|
||||
currentIndex(QModelIndex()),
|
||||
dataSource(TextBuffer),
|
||||
dataType(Null),
|
||||
textNullSet(false),
|
||||
isReadOnly(true)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
@@ -34,17 +35,18 @@ EditDialog::EditDialog(QWidget* parent)
|
||||
hexLayout->addWidget(hexEdit);
|
||||
hexEdit->setOverwriteMode(false);
|
||||
|
||||
QHBoxLayout* jsonLayout = new QHBoxLayout(ui->editorJSON);
|
||||
jsonEdit = new JsonTextEdit(this);
|
||||
jsonLayout->addWidget(jsonEdit);
|
||||
QHBoxLayout* sciLayout = new QHBoxLayout(ui->editorSci);
|
||||
sciEdit = new DockTextEdit(this);
|
||||
sciLayout->addWidget(sciEdit);
|
||||
|
||||
QShortcut* ins = new QShortcut(QKeySequence(Qt::Key_Insert), this);
|
||||
connect(ins, SIGNAL(activated()), this, SLOT(toggleOverwriteMode()));
|
||||
|
||||
connect(ui->editorText, SIGNAL(textChanged()), this, SLOT(updateApplyButton()));
|
||||
connect(hexEdit, SIGNAL(dataChanged()), this, SLOT(updateApplyButton()));
|
||||
connect(jsonEdit, SIGNAL(textChanged()), this, SLOT(updateApplyButton()));
|
||||
connect(jsonEdit, SIGNAL(textChanged()), this, SLOT(editTextChanged()));
|
||||
|
||||
connect(sciEdit, SIGNAL(textChanged()), this, SLOT(updateApplyButton()));
|
||||
connect(sciEdit, SIGNAL(textChanged()), this, SLOT(editTextChanged()));
|
||||
|
||||
mustIndentAndCompact = Settings::getValue("databrowser", "indent_compact").toBool();
|
||||
ui->buttonIndent->setChecked(mustIndentAndCompact);
|
||||
@@ -99,15 +101,15 @@ void EditDialog::loadData(const QByteArray& data)
|
||||
// Determine the data type, saving that info in the class variable
|
||||
dataType = checkDataType(data);
|
||||
|
||||
// Get the current editor mode (eg text, hex, or image mode)
|
||||
int editMode = ui->editorStack->currentIndex();
|
||||
// Get the current editor mode (eg text, hex, image, json or xml mode)
|
||||
int editMode = ui->comboMode->currentIndex();
|
||||
|
||||
// Data type specific handling
|
||||
switch (dataType) {
|
||||
case Null:
|
||||
// Set enabled any of the text widgets
|
||||
ui->editorText->setEnabled(true);
|
||||
jsonEdit->setEnabled(true);
|
||||
sciEdit->setEnabled(true);
|
||||
switch (editMode) {
|
||||
case TextEditor:
|
||||
// The text widget buffer is now the main data source
|
||||
@@ -119,15 +121,16 @@ void EditDialog::loadData(const QByteArray& data)
|
||||
break;
|
||||
|
||||
case JsonEditor:
|
||||
case XmlEditor:
|
||||
|
||||
// The JSON widget buffer is now the main data source
|
||||
dataSource = JsonBuffer;
|
||||
dataSource = SciBuffer;
|
||||
|
||||
// Empty the text editor contents, then enable text editing
|
||||
jsonEdit->clear();
|
||||
sciEdit->clear();
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case HexEditor:
|
||||
// The hex widget buffer is now the main data source
|
||||
dataSource = HexBuffer;
|
||||
@@ -153,78 +156,27 @@ void EditDialog::loadData(const QByteArray& data)
|
||||
|
||||
case Text:
|
||||
case JSON:
|
||||
// Set enabled any of the text widgets
|
||||
ui->editorText->setEnabled(true);
|
||||
jsonEdit->setEnabled(true);
|
||||
// Can be stored in any widget, except the ImageViewer
|
||||
|
||||
switch (editMode) {
|
||||
case TextEditor:
|
||||
{
|
||||
// The text widget buffer is now the main data source
|
||||
dataSource = TextBuffer;
|
||||
|
||||
// Load the text into the text editor, remove BOM first if there is one
|
||||
QByteArray dataWithoutBom = data;
|
||||
removedBom = removeBom(dataWithoutBom);
|
||||
|
||||
textData = QString::fromUtf8(dataWithoutBom.constData(), dataWithoutBom.size());
|
||||
ui->editorText->setPlainText(textData);
|
||||
|
||||
// Select all of the text by default
|
||||
ui->editorText->selectAll();
|
||||
|
||||
setDataInBuffer(data, TextBuffer);
|
||||
break;
|
||||
}
|
||||
case JsonEditor:
|
||||
// The JSON widget buffer is now the main data source
|
||||
dataSource = JsonBuffer;
|
||||
{
|
||||
QJsonParseError parseError;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(QByteArray(data.constData(), data.size()), &parseError);
|
||||
|
||||
if (mustIndentAndCompact && !jsonDoc.isNull()) {
|
||||
// Load indented JSON into the JSON editor
|
||||
textData = QString(jsonDoc.toJson(QJsonDocument::Indented));
|
||||
jsonEdit->setText(textData);
|
||||
} else {
|
||||
// Fallback case. The data is not yet valid JSON.
|
||||
textData = QString::fromUtf8(data.constData(), data.size());
|
||||
jsonEdit->setText(textData);
|
||||
}
|
||||
|
||||
jsonEdit->clearErrorIndicators();
|
||||
if (parseError.error != QJsonParseError::NoError)
|
||||
jsonEdit->setErrorIndicator(parseError.offset-1);
|
||||
|
||||
}
|
||||
|
||||
case XmlEditor:
|
||||
setDataInBuffer(data, SciBuffer);
|
||||
break;
|
||||
|
||||
case HexEditor:
|
||||
// The hex widget buffer is now the main data source
|
||||
dataSource = HexBuffer;
|
||||
|
||||
// Load the text into the hex editor
|
||||
hexEdit->setData(data);
|
||||
|
||||
setDataInBuffer(data, HexBuffer);
|
||||
break;
|
||||
|
||||
case ImageViewer:
|
||||
// The text widget buffer is now the main data source
|
||||
dataSource = TextBuffer;
|
||||
// The image viewer cannot hold data nor display text.
|
||||
|
||||
// Clear any image from the image viewing widget
|
||||
ui->editorImage->setPixmap(QPixmap(0,0));
|
||||
|
||||
// Load the text into the text editor
|
||||
textData = QString::fromUtf8(data.constData(), data.size());
|
||||
ui->editorText->setPlainText(textData);
|
||||
|
||||
// Enable text editing
|
||||
ui->editorText->setEnabled(true);
|
||||
|
||||
// Select all of the text by default
|
||||
ui->editorText->selectAll();
|
||||
setDataInBuffer(data, TextBuffer);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -235,10 +187,7 @@ void EditDialog::loadData(const QByteArray& data)
|
||||
// stored it in the editorImage widget instead, it would be a pixmap
|
||||
// and there's no good way to restore that back to the original
|
||||
// (pristine) image data. eg image metadata would be lost
|
||||
hexEdit->setData(data);
|
||||
|
||||
// The hex widget buffer is now the main data source
|
||||
dataSource = HexBuffer;
|
||||
setDataInBuffer(data, HexBuffer);
|
||||
|
||||
// Update the display if in text edit or image viewer mode
|
||||
switch (editMode) {
|
||||
@@ -250,10 +199,12 @@ void EditDialog::loadData(const QByteArray& data)
|
||||
ui->editorText->setEnabled(false);
|
||||
break;
|
||||
|
||||
case XmlEditor:
|
||||
case JsonEditor:
|
||||
// Disable text editing, and use a warning message as the contents
|
||||
jsonEdit->setText(tr("Image data can't be viewed with the JSON editor"));
|
||||
jsonEdit->setEnabled(false);
|
||||
sciEdit->setText(tr("Image data can't be viewed with this editor"));
|
||||
sciEdit->setEnabled(false);
|
||||
|
||||
break;
|
||||
|
||||
case ImageViewer:
|
||||
@@ -264,16 +215,44 @@ void EditDialog::loadData(const QByteArray& data)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SVG:
|
||||
// Set the XML data in any buffer or update image in image viewer mode
|
||||
switch (editMode) {
|
||||
case TextEditor:
|
||||
setDataInBuffer(data, TextBuffer);
|
||||
break;
|
||||
|
||||
case JsonEditor:
|
||||
case XmlEditor:
|
||||
|
||||
setDataInBuffer(data, SciBuffer);
|
||||
break;
|
||||
|
||||
case HexEditor:
|
||||
|
||||
setDataInBuffer(data, HexBuffer);
|
||||
break;
|
||||
|
||||
case ImageViewer:
|
||||
// Set data in the XML (Sci) Buffer and load the SVG Image
|
||||
setDataInBuffer(data, SciBuffer);
|
||||
sciEdit->setLanguage(DockTextEdit::XML);
|
||||
|
||||
// Load the image into the image viewing widget
|
||||
if (img.loadFromData(data)) {
|
||||
ui->editorImage->setPixmap(QPixmap::fromImage(img));
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// The hex widget buffer is now the main data source
|
||||
dataSource = HexBuffer;
|
||||
|
||||
// The data seems to be general binary data, which is always loaded
|
||||
// into the hex widget (the only safe place for it)
|
||||
|
||||
// Load the data into the hex editor
|
||||
hexEdit->setData(data);
|
||||
// Load the data into the hex buffer
|
||||
setDataInBuffer(data, HexBuffer);
|
||||
|
||||
switch (editMode) {
|
||||
case TextEditor:
|
||||
@@ -285,9 +264,10 @@ void EditDialog::loadData(const QByteArray& data)
|
||||
break;
|
||||
|
||||
case JsonEditor:
|
||||
case XmlEditor:
|
||||
// Disable text editing, and use a warning message as the contents
|
||||
jsonEdit->setText(QString(tr("Binary data can't be viewed with the JSON editor")));
|
||||
jsonEdit->setEnabled(false);
|
||||
sciEdit->setText(QString(tr("Binary data can't be viewed with this editor")));
|
||||
sciEdit->setEnabled(false);
|
||||
break;
|
||||
|
||||
case ImageViewer:
|
||||
@@ -310,7 +290,7 @@ void EditDialog::importData()
|
||||
this,
|
||||
tr("Choose a file to import")
|
||||
#ifndef Q_OS_MAC // Filters on OS X are buggy
|
||||
, tr("Text files(*.txt);;Image files(%1);;JSON files(*.json);;All files(*)").arg(image_formats)
|
||||
, tr("Text files (*.txt);;Image files (%1);;JSON files (*.json);;XML files (*.xml);;All files (*)").arg(image_formats)
|
||||
#endif
|
||||
);
|
||||
if(QFile::exists(fileName))
|
||||
@@ -361,11 +341,10 @@ void EditDialog::exportData()
|
||||
// Data source is the text buffer
|
||||
file.write(ui->editorText->toPlainText().toUtf8());
|
||||
break;
|
||||
case JsonBuffer:
|
||||
case SciBuffer:
|
||||
// Data source is the JSON buffer
|
||||
file.write(jsonEdit->text().toUtf8());
|
||||
file.write(sciEdit->text().toUtf8());
|
||||
break;
|
||||
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
@@ -377,25 +356,17 @@ void EditDialog::setNull()
|
||||
ui->editorText->clear();
|
||||
ui->editorImage->clear();
|
||||
hexEdit->setData(QByteArray());
|
||||
jsonEdit->clear();
|
||||
sciEdit->clear();
|
||||
dataType = Null;
|
||||
removedBom.clear();
|
||||
|
||||
// Check if in text editor mode
|
||||
int editMode = ui->editorStack->currentIndex();
|
||||
if (editMode == TextEditor || editMode == JsonEditor) {
|
||||
// Setting NULL in the text editor switches the data source to it
|
||||
dataSource = TextBuffer;
|
||||
// The text editors don't know the difference between an empty string
|
||||
// and a NULL, so we need to record NULL outside of that
|
||||
dataType = Null;
|
||||
|
||||
// Ensure the text editor is enabled
|
||||
ui->editorText->setEnabled(true);
|
||||
// Ensure the JSON editor is enabled
|
||||
jsonEdit->setEnabled(true);
|
||||
|
||||
// The text editor doesn't know the difference between an empty string
|
||||
// and a NULL, so we need to record NULL outside of that
|
||||
textNullSet = true;
|
||||
}
|
||||
// Ensure the text (plain and Scintilla) editors are enabled
|
||||
ui->editorText->setEnabled(true);
|
||||
sciEdit->setEnabled(true);
|
||||
|
||||
// Update the cell data info in the bottom left of the Edit Cell
|
||||
updateCellInfo(hexEdit->data());
|
||||
@@ -424,47 +395,46 @@ void EditDialog::accept()
|
||||
if(!currentIndex.isValid())
|
||||
return;
|
||||
|
||||
if (dataType == Null) {
|
||||
emit recordTextUpdated(currentIndex, hexEdit->data(), true);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (dataSource) {
|
||||
case TextBuffer:
|
||||
// Check if a NULL is set in the text editor
|
||||
if (textNullSet) {
|
||||
emit recordTextUpdated(currentIndex, hexEdit->data(), true);
|
||||
} else {
|
||||
// It's not NULL, so proceed with normal text string checking
|
||||
QString oldData = currentIndex.data(Qt::EditRole).toString();
|
||||
QString newData = removedBom + ui->editorText->toPlainText();
|
||||
if (oldData != newData)
|
||||
// The data is different, so commit it back to the database
|
||||
emit recordTextUpdated(currentIndex, removedBom + newData.toUtf8(), false);
|
||||
}
|
||||
{
|
||||
QString oldData = currentIndex.data(Qt::EditRole).toString();
|
||||
QString newData = removedBom + ui->editorText->toPlainText();
|
||||
if (oldData != newData)
|
||||
// The data is different, so commit it back to the database
|
||||
emit recordTextUpdated(currentIndex, removedBom + newData.toUtf8(), false);
|
||||
break;
|
||||
case JsonBuffer:
|
||||
// Check if a NULL is set in the text editor
|
||||
if (textNullSet) {
|
||||
emit recordTextUpdated(currentIndex, hexEdit->data(), true);
|
||||
} else {
|
||||
// It's not NULL, so proceed with normal text string checking
|
||||
}
|
||||
case SciBuffer:
|
||||
switch (sciEdit->language()) {
|
||||
case DockTextEdit::JSON:
|
||||
{
|
||||
QString oldData = currentIndex.data(Qt::EditRole).toString();
|
||||
|
||||
QString newData;
|
||||
QJsonParseError parseError;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonEdit->text().toUtf8(), &parseError);
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(sciEdit->text().toUtf8(), &parseError);
|
||||
bool proceed;
|
||||
|
||||
jsonEdit->clearErrorIndicators();
|
||||
sciEdit->clearErrorIndicators();
|
||||
if (parseError.error != QJsonParseError::NoError)
|
||||
jsonEdit->setErrorIndicator(parseError.offset-1);
|
||||
sciEdit->setErrorIndicator(parseError.offset-1);
|
||||
|
||||
if (!jsonDoc.isNull()) {
|
||||
if (mustIndentAndCompact)
|
||||
// Compact the JSON data before storing
|
||||
newData = QString(jsonDoc.toJson(QJsonDocument::Compact));
|
||||
else
|
||||
newData = jsonEdit->text();
|
||||
newData = sciEdit->text();
|
||||
proceed = (oldData != newData);
|
||||
|
||||
} else {
|
||||
newData = jsonEdit->text();
|
||||
newData = sciEdit->text();
|
||||
proceed = (oldData != newData && promptInvalidData("JSON", parseError.errorString()));
|
||||
}
|
||||
if (proceed)
|
||||
@@ -472,7 +442,38 @@ void EditDialog::accept()
|
||||
emit recordTextUpdated(currentIndex, newData.toUtf8(), false);
|
||||
}
|
||||
break;
|
||||
case DockTextEdit::XML:
|
||||
{
|
||||
QString oldData = currentIndex.data(Qt::EditRole).toString();
|
||||
|
||||
QString newData;
|
||||
QDomDocument xmlDoc;
|
||||
QString errorMsg;
|
||||
int errorLine, errorColumn;
|
||||
|
||||
bool isValid = xmlDoc.setContent(sciEdit->text().toUtf8(), true, &errorMsg, &errorLine, &errorColumn);
|
||||
bool proceed;
|
||||
|
||||
sciEdit->clearErrorIndicators();
|
||||
if (!isValid) {
|
||||
sciEdit->setErrorIndicator(errorLine-1, errorColumn-1, errorLine, 0);
|
||||
newData = sciEdit->text();
|
||||
proceed = (oldData != newData && promptInvalidData("XML", errorMsg));
|
||||
} else {
|
||||
if (mustIndentAndCompact)
|
||||
// Compact the XML data before storing. If indent is -1, no whitespace at all is added.
|
||||
newData = xmlDoc.toString(-1);
|
||||
else
|
||||
newData = sciEdit->text();
|
||||
proceed = (oldData != newData);
|
||||
}
|
||||
if (proceed)
|
||||
// The data is different, so commit it back to the database
|
||||
emit recordTextUpdated(currentIndex, newData.toUtf8(), false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case HexBuffer:
|
||||
// The data source is the hex widget buffer, thus binary data
|
||||
QByteArray oldData = currentIndex.data(Qt::EditRole).toByteArray();
|
||||
@@ -483,10 +484,94 @@ void EditDialog::accept()
|
||||
}
|
||||
}
|
||||
|
||||
void EditDialog::setDataInBuffer(const QByteArray& data, DataSources source)
|
||||
{
|
||||
dataSource = source;
|
||||
QString textData;
|
||||
|
||||
// 1) Perform validation and text formatting (if applicable).
|
||||
// 2) Set the text in the corresponding editor widget (the text widget for the Image case).
|
||||
// 3) Enable the widget.
|
||||
switch (dataSource) {
|
||||
case TextBuffer:
|
||||
{
|
||||
// Load the text into the text editor, remove BOM first if there is one
|
||||
QByteArray dataWithoutBom = data;
|
||||
removedBom = removeBom(dataWithoutBom);
|
||||
|
||||
textData = QString::fromUtf8(dataWithoutBom.constData(), dataWithoutBom.size());
|
||||
ui->editorText->setPlainText(textData);
|
||||
|
||||
// Select all of the text by default (this is useful for simple text data that we usually edit as a whole)
|
||||
ui->editorText->selectAll();
|
||||
ui->editorText->setEnabled(true);
|
||||
break;
|
||||
}
|
||||
case SciBuffer:
|
||||
switch (sciEdit->language()) {
|
||||
case DockTextEdit::JSON:
|
||||
{
|
||||
QJsonParseError parseError;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(QByteArray(data.constData(), data.size()), &parseError);
|
||||
|
||||
if (mustIndentAndCompact && !jsonDoc.isNull()) {
|
||||
// Load indented JSON into the JSON editor
|
||||
textData = QString(jsonDoc.toJson(QJsonDocument::Indented));
|
||||
} else {
|
||||
// Fallback case. The data is not yet valid JSON or no auto-formatting applied.
|
||||
textData = QString::fromUtf8(data.constData(), data.size());
|
||||
}
|
||||
sciEdit->setText(textData);
|
||||
|
||||
sciEdit->clearErrorIndicators();
|
||||
if (parseError.error != QJsonParseError::NoError)
|
||||
sciEdit->setErrorIndicator(parseError.offset-1);
|
||||
sciEdit->setEnabled(true);
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case DockTextEdit::XML:
|
||||
{
|
||||
QString errorMsg;
|
||||
int errorLine, errorColumn;
|
||||
QDomDocument xmlDoc;
|
||||
bool isValid = xmlDoc.setContent(data, true, &errorMsg, &errorLine, &errorColumn);
|
||||
|
||||
if (mustIndentAndCompact && isValid) {
|
||||
// Load indented XML into the XML editor
|
||||
textData = xmlDoc.toString(Settings::getValue("editor", "tabsize").toInt());
|
||||
} else {
|
||||
// Fallback case. The data is not yet valid JSON or no auto-formatting applied.
|
||||
textData = QString::fromUtf8(data.constData(), data.size());
|
||||
}
|
||||
sciEdit->setText(textData);
|
||||
|
||||
sciEdit->clearErrorIndicators();
|
||||
if (!isValid)
|
||||
// Adjust line and column by one (Scintilla starts at 1 and QDomDocument at 0)
|
||||
sciEdit->setErrorIndicator(errorLine-1, errorColumn-1, errorLine, 0);
|
||||
sciEdit->setEnabled(true);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case HexBuffer:
|
||||
hexEdit->setData(data);
|
||||
hexEdit->setEnabled(true);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Called when the user manually changes the "Mode" drop down combobox
|
||||
void EditDialog::editModeChanged(int newMode)
|
||||
{
|
||||
ui->buttonIndent->setEnabled(newMode == JsonEditor);
|
||||
ui->buttonIndent->setEnabled(newMode == JsonEditor || newMode == XmlEditor);
|
||||
setStackCurrentIndex(newMode);
|
||||
|
||||
// * If the dataSource is the text buffer, the data is always text *
|
||||
switch (dataSource) {
|
||||
@@ -496,30 +581,16 @@ void EditDialog::editModeChanged(int newMode)
|
||||
// Nothing to do, as the text is already in the text buffer
|
||||
break;
|
||||
|
||||
case JsonEditor: // Switching to the JSON editor
|
||||
case JsonEditor: // Switching to one of the Scintilla editor modes
|
||||
case XmlEditor:
|
||||
|
||||
// Convert the text widget buffer for the JSON widget
|
||||
// * If the dataSource is the TextBuffer, the contents could
|
||||
// be still compacted so we just pass it to our loadData()
|
||||
// function to handle, for indenting if necessary *
|
||||
// Switch to the selected editor first, as loadData() relies
|
||||
// on it being current
|
||||
ui->editorStack->setCurrentIndex(newMode);
|
||||
|
||||
// Load the data into the appropriate widget, as done by loadData()
|
||||
loadData(ui->editorText->toPlainText().toUtf8());
|
||||
// jsonEdit->setText(ui->editorText->toPlainText().toUtf8());
|
||||
|
||||
// The JSON widget buffer is now the main data source
|
||||
dataSource = JsonBuffer;
|
||||
setDataInBuffer(ui->editorText->toPlainText().toUtf8(), SciBuffer);
|
||||
break;
|
||||
|
||||
case HexEditor: // Switching to the hex editor
|
||||
// Convert the text widget buffer for the hex widget
|
||||
hexEdit->setData(removedBom + ui->editorText->toPlainText().toUtf8());
|
||||
|
||||
// The hex widget buffer is now the main data source
|
||||
dataSource = HexBuffer;
|
||||
setDataInBuffer(removedBom + ui->editorText->toPlainText().toUtf8(), HexBuffer);
|
||||
break;
|
||||
|
||||
case ImageViewer:
|
||||
@@ -527,72 +598,76 @@ void EditDialog::editModeChanged(int newMode)
|
||||
ui->editorImage->setPixmap(QPixmap(0,0));
|
||||
break;
|
||||
}
|
||||
|
||||
// Switch to the selected editor
|
||||
ui->editorStack->setCurrentIndex(newMode);
|
||||
return;
|
||||
break;
|
||||
case HexBuffer:
|
||||
|
||||
// * If the dataSource is the hex buffer, the contents could be anything
|
||||
// so we just pass it to our loadData() function to handle *
|
||||
// Switch to the selected editor first, as loadData() relies on it
|
||||
// Note that we have already set the editor, as loadData() relies on it
|
||||
// being current
|
||||
ui->editorStack->setCurrentIndex(newMode);
|
||||
|
||||
// Load the data into the appropriate widget, as done by loadData()
|
||||
loadData(hexEdit->data());
|
||||
break;
|
||||
case JsonBuffer:
|
||||
case SciBuffer:
|
||||
switch (newMode) {
|
||||
case TextEditor: // Switching to the text editor
|
||||
// Convert the text widget buffer for the JSON widget
|
||||
ui->editorText->setText(jsonEdit->text());
|
||||
|
||||
// The Text widget buffer is now the main data source
|
||||
dataSource = TextBuffer;
|
||||
setDataInBuffer(sciEdit->text().toUtf8(), TextBuffer);
|
||||
break;
|
||||
|
||||
case JsonEditor: // Switching to the JSON editor
|
||||
// Nothing to do, as the text is already in the JSON buffer
|
||||
break;
|
||||
|
||||
|
||||
case HexEditor: // Switching to the hex editor
|
||||
// Convert the text widget buffer for the hex widget
|
||||
hexEdit->setData(jsonEdit->text().toUtf8());
|
||||
|
||||
// The hex widget buffer is now the main data source
|
||||
dataSource = HexBuffer;
|
||||
setDataInBuffer(sciEdit->text().toUtf8(), HexBuffer);
|
||||
break;
|
||||
|
||||
case ImageViewer:
|
||||
// Clear any image from the image viewing widget
|
||||
ui->editorImage->setPixmap(QPixmap(0,0));
|
||||
{
|
||||
// When SVG format, load the image, else clear it.
|
||||
QByteArray data = sciEdit->text().toUtf8();
|
||||
dataType = checkDataType(data);
|
||||
if (dataType == SVG) {
|
||||
QImage img;
|
||||
|
||||
if (img.loadFromData(data))
|
||||
ui->editorImage->setPixmap(QPixmap::fromImage(img));
|
||||
else
|
||||
// Clear any image from the image viewing widget
|
||||
ui->editorImage->setPixmap(QPixmap(0,0));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case JsonEditor: // Switching to the JSON editor
|
||||
case XmlEditor: // Switching to the XML editor
|
||||
// The text is already in the Sci buffer but we need to perform the necessary formatting.
|
||||
setDataInBuffer(sciEdit->text().toUtf8(), SciBuffer);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Switch to the selected editor
|
||||
ui->editorStack->setCurrentIndex(newMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Called for every keystroke in the text editor (only)
|
||||
void EditDialog::editTextChanged()
|
||||
{
|
||||
if (dataSource == TextBuffer || dataSource == JsonBuffer) {
|
||||
if (dataSource == TextBuffer || dataSource == SciBuffer) {
|
||||
// Data has been changed in the text editor, so it can't be a NULL
|
||||
// any more
|
||||
textNullSet = false;
|
||||
|
||||
// any more. It hasn't been validated yet, so it cannot be JSON nor XML.
|
||||
if (dataType == Null) {
|
||||
dataType = Text;
|
||||
ui->labelType->setText(tr("Type of data currently in cell: Text / Numeric"));
|
||||
}
|
||||
// Update the cell info in the bottom left manually. This is because
|
||||
// updateCellInfo() only works with QByteArray's (for now)
|
||||
int dataLength;
|
||||
if (dataSource == TextBuffer)
|
||||
switch (dataSource) {
|
||||
case TextBuffer:
|
||||
dataLength = ui->editorText->toPlainText().length();
|
||||
else
|
||||
dataLength = jsonEdit->text().length();
|
||||
ui->labelType->setText(tr("Type of data currently in cell: Text / Numeric"));
|
||||
break;
|
||||
case SciBuffer:
|
||||
dataLength = sciEdit->text().length();
|
||||
break;
|
||||
}
|
||||
ui->labelSize->setText(tr("%n char(s)", "", dataLength));
|
||||
}
|
||||
}
|
||||
@@ -601,12 +676,11 @@ void EditDialog::setMustIndentAndCompact(bool enable)
|
||||
{
|
||||
mustIndentAndCompact = enable;
|
||||
|
||||
// Indent or compact if necessary. If data has changed, reload from the widget, else from the table.
|
||||
if (ui->buttonApply->isEnabled())
|
||||
loadData(jsonEdit->text().toUtf8());
|
||||
else
|
||||
// Indent or compact if necessary. If data has changed (button Apply indicates so), reload from the widget, else from the table.
|
||||
if (ui->buttonApply->isEnabled()) {
|
||||
setDataInBuffer(sciEdit->text().toUtf8(), SciBuffer);
|
||||
} else
|
||||
setCurrentIndex(currentIndex);
|
||||
|
||||
}
|
||||
|
||||
// Determine the type of data in the cell
|
||||
@@ -623,13 +697,14 @@ int EditDialog::checkDataType(const QByteArray& data)
|
||||
// that returned true, do a more sophisticated test of the data. This way we get both, good performance and proper data checking.
|
||||
QBuffer imageBuffer(&cellData);
|
||||
QImageReader readerBuffer(&imageBuffer);
|
||||
QString imageFormat = readerBuffer.format();
|
||||
if(readerBuffer.canRead() && !readerBuffer.read().isNull())
|
||||
return Image;
|
||||
return imageFormat == "svg" ? SVG : Image;
|
||||
|
||||
// Check if it's text only
|
||||
if(isTextOnly(cellData))
|
||||
{
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(QString(cellData).toUtf8());
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(cellData);
|
||||
if (!jsonDoc.isNull())
|
||||
return JSON;
|
||||
else
|
||||
@@ -647,7 +722,7 @@ void EditDialog::toggleOverwriteMode()
|
||||
|
||||
hexEdit->setOverwriteMode(currentMode);
|
||||
ui->editorText->setOverwriteMode(currentMode);
|
||||
jsonEdit->setOverwriteMode(currentMode);
|
||||
sciEdit->setOverwriteMode(currentMode);
|
||||
}
|
||||
|
||||
void EditDialog::setFocus()
|
||||
@@ -658,9 +733,25 @@ void EditDialog::setFocus()
|
||||
// to the dock itself doesn't make much sense as it's just a frame; you'd
|
||||
// have to tab to the editor which is what you most likely want to use. So
|
||||
// in order to save the user from doing this we explicitly set the focus
|
||||
// to the editor.
|
||||
ui->editorText->setFocus();
|
||||
ui->editorText->selectAll();
|
||||
// to the current editor.
|
||||
int editMode = ui->editorStack->currentIndex();
|
||||
|
||||
switch (editMode) {
|
||||
case TextEditor:
|
||||
ui->editorText->setFocus();
|
||||
ui->editorText->selectAll();
|
||||
break;
|
||||
case HexEditor:
|
||||
hexEdit->setFocus();
|
||||
break;
|
||||
case SciEditor:
|
||||
sciEdit->setFocus();
|
||||
break;
|
||||
case ImageViewer:
|
||||
// Nothing to do
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Enables or disables the Apply, Null, & Import buttons in the Edit Cell dock
|
||||
@@ -677,7 +768,7 @@ void EditDialog::setReadOnly(bool ro)
|
||||
ui->editorText->setTextInteractionFlags(textFlags);
|
||||
|
||||
ui->editorBinary->setEnabled(!ro); // We disable the entire hex editor here instead of setting it to read only because it doesn't have a setReadOnly() method
|
||||
jsonEdit->setReadOnly(ro);
|
||||
sciEdit->setReadOnly(ro);
|
||||
}
|
||||
|
||||
// Update the information labels in the bottom left corner of the dialog
|
||||
@@ -686,7 +777,7 @@ void EditDialog::updateCellInfo(const QByteArray& data)
|
||||
QByteArray cellData = data;
|
||||
|
||||
// Image data needs special treatment
|
||||
if (dataType == Image) {
|
||||
if (dataType == Image || dataType == SVG) {
|
||||
QBuffer imageBuffer(&cellData);
|
||||
QImageReader imageReader(&imageBuffer);
|
||||
|
||||
@@ -776,6 +867,27 @@ void EditDialog::reloadSettings()
|
||||
hexFont.setPointSize(Settings::getValue("databrowser", "fontsize").toInt());
|
||||
hexEdit->setFont(hexFont);
|
||||
|
||||
jsonEdit->reloadSettings();
|
||||
|
||||
sciEdit->reloadSettings();
|
||||
}
|
||||
|
||||
void EditDialog::setStackCurrentIndex(int editMode)
|
||||
{
|
||||
switch (editMode) {
|
||||
case TextEditor:
|
||||
case HexEditor:
|
||||
case ImageViewer:
|
||||
// General case: switch to the selected editor
|
||||
ui->editorStack->setCurrentIndex(editMode);
|
||||
break;
|
||||
case JsonEditor:
|
||||
// Scintilla case: switch to the single Scintilla editor and set language
|
||||
ui->editorStack->setCurrentIndex(SciEditor);
|
||||
sciEdit->setLanguage(DockTextEdit::JSON);
|
||||
break;
|
||||
case XmlEditor:
|
||||
// Scintilla case: switch to the single Scintilla editor and set language
|
||||
ui->editorStack->setCurrentIndex(SciEditor);
|
||||
sciEdit->setLanguage(DockTextEdit::XML);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,8 @@
|
||||
#include <QDialog>
|
||||
#include <QPersistentModelIndex>
|
||||
|
||||
#include "jsontextedit.h"
|
||||
|
||||
class QHexEdit;
|
||||
class DockTextEdit;
|
||||
|
||||
namespace Ui {
|
||||
class EditDialog;
|
||||
@@ -50,11 +49,10 @@ signals:
|
||||
private:
|
||||
Ui::EditDialog* ui;
|
||||
QHexEdit* hexEdit;
|
||||
JsonTextEdit* jsonEdit;
|
||||
DockTextEdit* sciEdit;
|
||||
QPersistentModelIndex currentIndex;
|
||||
int dataSource;
|
||||
int dataType;
|
||||
bool textNullSet;
|
||||
bool isReadOnly;
|
||||
bool mustIndentAndCompact;
|
||||
QByteArray removedBom;
|
||||
@@ -62,27 +60,34 @@ private:
|
||||
enum DataSources {
|
||||
TextBuffer,
|
||||
HexBuffer,
|
||||
JsonBuffer
|
||||
SciBuffer
|
||||
};
|
||||
|
||||
// SVG is both an Image and an XML document so it is treated separately
|
||||
enum DataTypes {
|
||||
Binary,
|
||||
Image,
|
||||
Null,
|
||||
Text,
|
||||
JSON
|
||||
JSON,
|
||||
SVG
|
||||
};
|
||||
|
||||
// Edit modes and editor stack (this must be aligned with the UI)
|
||||
// Note that JSON and XML share the Scintilla widget.
|
||||
enum EditModes {
|
||||
TextEditor = 0,
|
||||
HexEditor = 1,
|
||||
JsonEditor = 2,
|
||||
ImageViewer = 3
|
||||
ImageViewer = 2,
|
||||
JsonEditor, SciEditor = 3,
|
||||
XmlEditor = 4
|
||||
};
|
||||
|
||||
int checkDataType(const QByteArray& data);
|
||||
QString humanReadableSize(double byteCount) const;
|
||||
bool promptInvalidData(const QString& dataType, const QString& errorString);
|
||||
void setDataInBuffer(const QByteArray& data, DataSources source);
|
||||
void setStackCurrentIndex(int editMode);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -47,6 +47,11 @@
|
||||
<string>Binary</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Image</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>JSON</string>
|
||||
@@ -54,7 +59,7 @@
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Image</string>
|
||||
<string>XML</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
@@ -182,13 +187,6 @@
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="editorBinary"/>
|
||||
<widget class="QWidget" name="editorJSON">
|
||||
<property name="whatsThis">
|
||||
<string>This editor mode lets you edit JSON data with syntax highlighting, automatic formatting and validation before saving.
|
||||
|
||||
Errors are indicated with a red squiggle underline.</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QScrollArea" name="editorImageScrollArea">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
@@ -213,6 +211,13 @@ Errors are indicated with a red squiggle underline.</string>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="editorSci">
|
||||
<property name="whatsThis">
|
||||
<string>This editor mode lets you edit JSON or XML data with syntax highlighting, automatic formatting and validation before saving.
|
||||
|
||||
Errors are indicated with a red squiggle underline.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -305,22 +310,6 @@ Errors are indicated with a red squiggle underline.</string>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>editorStack</sender>
|
||||
<signal>currentChanged(int)</signal>
|
||||
<receiver>comboMode</receiver>
|
||||
<slot>setCurrentIndex(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>185</x>
|
||||
<y>169</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>149</x>
|
||||
<y>39</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonApply</sender>
|
||||
<signal>clicked()</signal>
|
||||
|
||||
@@ -87,16 +87,16 @@ void ExtendedScintilla::dropEvent(QDropEvent* e)
|
||||
f.close();
|
||||
}
|
||||
|
||||
void ExtendedScintilla::setupSyntaxHighlightingFormat(const QString& settings_name, int style)
|
||||
void ExtendedScintilla::setupSyntaxHighlightingFormat(QsciLexer *lexer, const QString& settings_name, int style)
|
||||
{
|
||||
lexer()->setColor(QColor(Settings::getValue("syntaxhighlighter", settings_name + "_colour").toString()), 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);
|
||||
lexer->setFont(font, style);
|
||||
}
|
||||
|
||||
void ExtendedScintilla::reloadKeywords()
|
||||
@@ -107,23 +107,16 @@ void ExtendedScintilla::reloadKeywords()
|
||||
|
||||
void ExtendedScintilla::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);
|
||||
}
|
||||
|
||||
reloadLexerSettings(lexer());
|
||||
}
|
||||
void ExtendedScintilla::reloadLexerSettings(QsciLexer *lexer)
|
||||
{
|
||||
// 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);
|
||||
lexer->setDefaultColor(Qt::black);
|
||||
lexer->setFont(defaultfont);
|
||||
|
||||
// Set font
|
||||
QFont font(Settings::getValue("editor", "font").toString());
|
||||
@@ -145,7 +138,7 @@ void ExtendedScintilla::reloadSettings()
|
||||
|
||||
// Set tab width
|
||||
setTabWidth(Settings::getValue("editor", "tabsize").toInt());
|
||||
lexer()->refreshProperties();
|
||||
lexer->refreshProperties();
|
||||
|
||||
// Check if error indicators are enabled and clear them if they just got disabled
|
||||
showErrorIndicators = Settings::getValue("editor", "error_indicators").toBool();
|
||||
|
||||
@@ -32,7 +32,8 @@ public slots:
|
||||
protected:
|
||||
void dropEvent(QDropEvent* e);
|
||||
|
||||
void setupSyntaxHighlightingFormat(const QString& settings_name, int style);
|
||||
void setupSyntaxHighlightingFormat(QsciLexer *lexer, const QString& settings_name, int style);
|
||||
void reloadLexerSettings(QsciLexer *lexer);
|
||||
|
||||
int errorIndicatorNumber;
|
||||
bool showErrorIndicators;
|
||||
|
||||
@@ -175,7 +175,7 @@ QVariant Settings::getDefaultValue(const QString& group, const QString& name)
|
||||
return 10;
|
||||
if(name == "symbol_limit")
|
||||
return 5000;
|
||||
if(name == "compact_indent")
|
||||
if(name == "indent_compact")
|
||||
return false;
|
||||
if(name == "null_text")
|
||||
return "NULL";
|
||||
|
||||
79
src/docktextedit.cpp
Normal file
79
src/docktextedit.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
#include "docktextedit.h"
|
||||
#include "Settings.h"
|
||||
|
||||
QsciLexerJSON* DockTextEdit::jsonLexer = nullptr;
|
||||
QsciLexerXML* DockTextEdit::xmlLexer = nullptr;
|
||||
|
||||
DockTextEdit::DockTextEdit(QWidget* parent) :
|
||||
ExtendedScintilla(parent)
|
||||
{
|
||||
// Create lexer objects if not done yet
|
||||
if(jsonLexer == nullptr)
|
||||
jsonLexer = new QsciLexerJSON(this);
|
||||
if(xmlLexer == nullptr)
|
||||
xmlLexer = new QsciLexerXML(this);
|
||||
|
||||
// Set the JSON lexer as default
|
||||
setLexer(jsonLexer);
|
||||
|
||||
jsonLexer->setFoldCompact(false);
|
||||
jsonLexer->setHighlightComments(true);
|
||||
|
||||
// Do rest of initialisation
|
||||
reloadSettings();
|
||||
}
|
||||
|
||||
DockTextEdit::~DockTextEdit()
|
||||
{
|
||||
}
|
||||
|
||||
void DockTextEdit::reloadSettings()
|
||||
{
|
||||
// Set the parent settings for both lexers
|
||||
reloadLexerSettings(jsonLexer);
|
||||
reloadLexerSettings(xmlLexer);
|
||||
|
||||
setupSyntaxHighlightingFormat(jsonLexer, "comment", QsciLexerJSON::CommentLine);
|
||||
setupSyntaxHighlightingFormat(jsonLexer, "comment", QsciLexerJSON::CommentBlock);
|
||||
setupSyntaxHighlightingFormat(jsonLexer, "keyword", QsciLexerJSON::Keyword);
|
||||
setupSyntaxHighlightingFormat(jsonLexer, "keyword", QsciLexerJSON::KeywordLD);
|
||||
setupSyntaxHighlightingFormat(jsonLexer, "string", QsciLexerJSON::String);
|
||||
setupSyntaxHighlightingFormat(jsonLexer, "table", QsciLexerJSON::Number);
|
||||
setupSyntaxHighlightingFormat(jsonLexer, "identifier", QsciLexerJSON::Property);
|
||||
|
||||
// The default style for invalid JSON or unclosed strings uses red
|
||||
// background and white foreground, but the current line has
|
||||
// precedence, so it is by default white over gray. We change the
|
||||
// default to something more readable for the current line at
|
||||
// invalid JSON.
|
||||
QColor stringColor = QColor(Settings::getValue("syntaxhighlighter", "string_colour").toString());
|
||||
jsonLexer->setColor(stringColor, QsciLexerJSON::Error);
|
||||
jsonLexer->setColor(stringColor, QsciLexerJSON::UnclosedString);
|
||||
QFont errorFont(Settings::getValue("editor", "font").toString());
|
||||
errorFont.setPointSize(Settings::getValue("editor", "fontsize").toInt());
|
||||
errorFont.setItalic(true);
|
||||
jsonLexer->setFont(errorFont, QsciLexerJSON::Error);
|
||||
jsonLexer->setFont(errorFont, QsciLexerJSON::UnclosedString);
|
||||
jsonLexer->setPaper(jsonLexer->defaultPaper(QsciLexerJSON::String), QsciLexerJSON::Error);
|
||||
jsonLexer->setPaper(jsonLexer->defaultPaper(QsciLexerJSON::String), QsciLexerJSON::UnclosedString);
|
||||
|
||||
setupSyntaxHighlightingFormat(xmlLexer, "comment", QsciLexerHTML::HTMLComment);
|
||||
setupSyntaxHighlightingFormat(xmlLexer, "keyword", QsciLexerHTML::Tag);
|
||||
setupSyntaxHighlightingFormat(xmlLexer, "string", QsciLexerHTML::HTMLDoubleQuotedString);
|
||||
setupSyntaxHighlightingFormat(xmlLexer, "string", QsciLexerHTML::HTMLSingleQuotedString);
|
||||
setupSyntaxHighlightingFormat(xmlLexer, "table", QsciLexerHTML::HTMLNumber);
|
||||
setupSyntaxHighlightingFormat(xmlLexer, "identifier", QsciLexerHTML::Attribute);
|
||||
}
|
||||
|
||||
void DockTextEdit::setLanguage(Language lang)
|
||||
{
|
||||
m_language = lang;
|
||||
switch (lang) {
|
||||
case JSON:
|
||||
setLexer(jsonLexer);
|
||||
break;
|
||||
case XML:
|
||||
setLexer(xmlLexer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
40
src/docktextedit.h
Normal file
40
src/docktextedit.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef DOCKTEXTEDIT_H
|
||||
#define DOCKTEXTEDIT_H
|
||||
|
||||
#include "ExtendedScintilla.h"
|
||||
#include <Qsci/qscilexerjson.h>
|
||||
#include <Qsci/qscilexerxml.h>
|
||||
|
||||
/**
|
||||
* @brief The DockTextEdit class
|
||||
* This class is based on our Extended QScintilla widget
|
||||
*/
|
||||
class DockTextEdit : public ExtendedScintilla
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DockTextEdit(QWidget *parent = nullptr);
|
||||
virtual ~DockTextEdit();
|
||||
|
||||
// Enumeration of supported languages
|
||||
enum Language
|
||||
{
|
||||
JSON,
|
||||
XML
|
||||
};
|
||||
|
||||
void setLanguage(Language lang);
|
||||
Language language() { return m_language; };
|
||||
|
||||
public slots:
|
||||
void reloadSettings();
|
||||
|
||||
protected:
|
||||
static QsciLexerJSON* jsonLexer;
|
||||
static QsciLexerXML* xmlLexer;
|
||||
private:
|
||||
Language m_language;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,54 +0,0 @@
|
||||
#include "jsontextedit.h"
|
||||
#include "Settings.h"
|
||||
|
||||
QsciLexerJSON* JsonTextEdit::jsonLexer = nullptr;
|
||||
|
||||
JsonTextEdit::JsonTextEdit(QWidget* parent) :
|
||||
ExtendedScintilla(parent)
|
||||
{
|
||||
// Create lexer object if not done yet
|
||||
if(jsonLexer == nullptr)
|
||||
jsonLexer = new QsciLexerJSON(this);
|
||||
|
||||
// Set the JSON lexer
|
||||
setLexer(jsonLexer);
|
||||
|
||||
jsonLexer->setFoldCompact(false);
|
||||
|
||||
// Do rest of initialisation
|
||||
reloadSettings();
|
||||
}
|
||||
|
||||
JsonTextEdit::~JsonTextEdit()
|
||||
{
|
||||
}
|
||||
|
||||
void JsonTextEdit::reloadSettings()
|
||||
{
|
||||
ExtendedScintilla::reloadSettings();
|
||||
|
||||
setupSyntaxHighlightingFormat("comment", QsciLexerJSON::CommentLine);
|
||||
setupSyntaxHighlightingFormat("comment", QsciLexerJSON::CommentBlock);
|
||||
setupSyntaxHighlightingFormat("keyword", QsciLexerJSON::Keyword);
|
||||
setupSyntaxHighlightingFormat("keyword", QsciLexerJSON::KeywordLD);
|
||||
setupSyntaxHighlightingFormat("string", QsciLexerJSON::String);
|
||||
setupSyntaxHighlightingFormat("table", QsciLexerJSON::Number);
|
||||
setupSyntaxHighlightingFormat("identifier", QsciLexerJSON::Property);
|
||||
jsonLexer->setHighlightComments(true);
|
||||
|
||||
// The default style for invalid JSON or unclosed strings uses red
|
||||
// background and white foreground, but the current line has
|
||||
// precedence, so it is by default white over gray. We change the
|
||||
// default to something more readable for the current line at
|
||||
// invalid JSON.
|
||||
QColor stringColor = QColor(Settings::getValue("syntaxhighlighter", "string_colour").toString());
|
||||
jsonLexer->setColor(stringColor, QsciLexerJSON::Error);
|
||||
jsonLexer->setColor(stringColor, QsciLexerJSON::UnclosedString);
|
||||
QFont errorFont(Settings::getValue("editor", "font").toString());
|
||||
errorFont.setPointSize(Settings::getValue("editor", "fontsize").toInt());
|
||||
errorFont.setItalic(true);
|
||||
jsonLexer->setFont(errorFont, QsciLexerJSON::Error);
|
||||
jsonLexer->setFont(errorFont, QsciLexerJSON::UnclosedString);
|
||||
jsonLexer->setPaper(jsonLexer->defaultPaper(QsciLexerJSON::String), QsciLexerJSON::Error);
|
||||
jsonLexer->setPaper(jsonLexer->defaultPaper(QsciLexerJSON::String), QsciLexerJSON::UnclosedString);
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
#ifndef JSONTEXTEDIT_H
|
||||
#define JSONTEXTEDIT_H
|
||||
|
||||
#include "ExtendedScintilla.h"
|
||||
#include <Qsci/qscilexerjson.h>
|
||||
|
||||
/**
|
||||
* @brief The JsonTextEdit class
|
||||
* This class is based on our Extended QScintilla widget
|
||||
*/
|
||||
class JsonTextEdit : public ExtendedScintilla
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit JsonTextEdit(QWidget *parent = nullptr);
|
||||
virtual ~JsonTextEdit();
|
||||
|
||||
static QsciLexerJSON* jsonLexer;
|
||||
|
||||
public slots:
|
||||
void reloadSettings();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -30,16 +30,27 @@ 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("comment", QsciLexerSQL::Comment);
|
||||
setupSyntaxHighlightingFormat("comment", QsciLexerSQL::CommentLine);
|
||||
setupSyntaxHighlightingFormat("comment", QsciLexerSQL::CommentDoc);
|
||||
setupSyntaxHighlightingFormat("keyword", QsciLexerSQL::Keyword);
|
||||
setupSyntaxHighlightingFormat("table", QsciLexerSQL::KeywordSet6);
|
||||
setupSyntaxHighlightingFormat("function", QsciLexerSQL::KeywordSet7);
|
||||
setupSyntaxHighlightingFormat("string", QsciLexerSQL::DoubleQuotedString);
|
||||
setupSyntaxHighlightingFormat("string", QsciLexerSQL::SingleQuotedString);
|
||||
setupSyntaxHighlightingFormat("identifier", QsciLexerSQL::Identifier);
|
||||
setupSyntaxHighlightingFormat("identifier", QsciLexerSQL::QuotedIdentifier);
|
||||
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::DoubleQuotedString);
|
||||
setupSyntaxHighlightingFormat(sqlLexer, "string", QsciLexerSQL::SingleQuotedString);
|
||||
setupSyntaxHighlightingFormat(sqlLexer, "identifier", QsciLexerSQL::Identifier);
|
||||
setupSyntaxHighlightingFormat(sqlLexer, "identifier", QsciLexerSQL::QuotedIdentifier);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
TEMPLATE = app
|
||||
|
||||
QT += core gui network widgets printsupport concurrent
|
||||
QT += core gui network widgets printsupport concurrent xml
|
||||
macx: QT += opengl
|
||||
|
||||
TARGET = sqlitebrowser
|
||||
@@ -59,7 +59,7 @@ HEADERS += \
|
||||
RemoteDock.h \
|
||||
RemoteModel.h \
|
||||
RemotePushDialog.h \
|
||||
jsontextedit.h \
|
||||
docktextedit.h \
|
||||
FindReplaceDialog.h \
|
||||
ExtendedScintilla.h \
|
||||
FileExtensionManager.h \
|
||||
@@ -100,7 +100,7 @@ SOURCES += \
|
||||
RemoteDock.cpp \
|
||||
RemoteModel.cpp \
|
||||
RemotePushDialog.cpp \
|
||||
jsontextedit.cpp \
|
||||
docktextedit.cpp \
|
||||
FindReplaceDialog.cpp \
|
||||
ExtendedScintilla.cpp \
|
||||
FileExtensionManager.cpp \
|
||||
|
||||
Reference in New Issue
Block a user