mirror of
https://github.com/sqlitebrowser/sqlitebrowser.git
synced 2026-01-21 03:21:43 -06:00
Clean up the code and make some more minor optimisations
This also includes replacing some more Qt containers by their STL counterparts.
This commit is contained in:
@@ -228,7 +228,6 @@ void AddRecordDialog::populateFields()
|
||||
else
|
||||
tbitem->setIcon(kName, QIcon(":/icons/field"));
|
||||
|
||||
QString defaultValue = QString::fromStdString(f.defaultValue());
|
||||
QString toolTip;
|
||||
|
||||
if (auto_increment && contains(pk, f.name()))
|
||||
@@ -248,9 +247,10 @@ void AddRecordDialog::populateFields()
|
||||
|
||||
// Display Role is used for displaying the default values.
|
||||
// Only when they are changed, the User Role is updated and then used in the INSERT query.
|
||||
if (!defaultValue.isEmpty()) {
|
||||
tbitem->setData(kValue, Qt::DisplayRole, QString::fromStdString(f.defaultValue()));
|
||||
toolTip.append(tr("Default value:\t %1\n").arg (defaultValue));
|
||||
if (!f.defaultValue().empty()) {
|
||||
QString defaultValue = QString::fromStdString(f.defaultValue());
|
||||
tbitem->setData(kValue, Qt::DisplayRole, defaultValue);
|
||||
toolTip.append(tr("Default value:\t %1\n").arg(defaultValue));
|
||||
} else
|
||||
tbitem->setData(kValue, Qt::DisplayRole, Settings::getValue("databrowser", "null_text"));
|
||||
|
||||
@@ -271,7 +271,7 @@ void AddRecordDialog::populateFields()
|
||||
|
||||
void AddRecordDialog::accept()
|
||||
{
|
||||
if(!pdb.executeSQL(ui->sqlTextEdit->text()))
|
||||
if(!pdb.executeSQL(ui->sqlTextEdit->text().toStdString()))
|
||||
{
|
||||
QMessageBox::warning(
|
||||
this,
|
||||
@@ -306,7 +306,7 @@ void AddRecordDialog::updateSqlText()
|
||||
if (isNumeric && item->data(kType, Qt::UserRole).toInt() != sqlb::Field::TextAffinity)
|
||||
vals << value.toString();
|
||||
else
|
||||
vals << QString("'%1'").arg(value.toString().replace("'", "''"));
|
||||
vals << sqlb::escapeString(value.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -204,7 +204,7 @@ QString Application::versionString()
|
||||
// date in order to avoid confusion about what is more important, version number or build date, and about different
|
||||
// build dates for the same version. This also should help making release builds reproducible out of the box.
|
||||
#if PATCH_VERSION >= 99
|
||||
return QString("%1 (%2)").arg(APP_VERSION).arg(__DATE__);
|
||||
return QString("%1 (%2)").arg(APP_VERSION, __DATE__);
|
||||
#else
|
||||
return QString("%1").arg(APP_VERSION);
|
||||
#endif
|
||||
@@ -213,12 +213,12 @@ QString Application::versionString()
|
||||
// Functions for documenting the shortcuts in the user interface using native names
|
||||
static QString shortcutsTip(const QList<QKeySequence>& keys)
|
||||
{
|
||||
QString tip("");
|
||||
QString tip;
|
||||
|
||||
if (!keys.isEmpty()) {
|
||||
tip = " [";
|
||||
|
||||
for (auto shortcut : keys)
|
||||
for (const auto& shortcut : keys)
|
||||
tip.append(shortcut.toString(QKeySequence::NativeText) + ", ");
|
||||
tip.chop(2);
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ public:
|
||||
explicit Application(int& argc, char** argv);
|
||||
~Application() override;
|
||||
|
||||
bool dontShowMainWindow() { return m_dontShowMainWindow; }
|
||||
bool dontShowMainWindow() const { return m_dontShowMainWindow; }
|
||||
|
||||
MainWindow* mainWindow() { return m_mainWindow; }
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ CipherDialog::~CipherDialog()
|
||||
CipherSettings CipherDialog::getCipherSettings() const
|
||||
{
|
||||
CipherSettings::KeyFormats keyFormat = CipherSettings::getKeyFormat(ui->comboKeyFormat->currentIndex());
|
||||
QString password = ui->editPassword->text();
|
||||
std::string password = ui->editPassword->text().toStdString();
|
||||
int pageSize = ui->comboPageSize->itemData(ui->comboPageSize->currentIndex()).toInt();
|
||||
|
||||
CipherSettings cipherSettings;
|
||||
@@ -70,8 +70,8 @@ CipherSettings CipherDialog::getCipherSettings() const
|
||||
cipherSettings.setPassword(password);
|
||||
cipherSettings.setPageSize(pageSize);
|
||||
cipherSettings.setKdfIterations(ui->spinKdfIterations->value());
|
||||
cipherSettings.setHmacAlgorithm(QString("HMAC_") + ui->comboHmacAlgorithm->currentText());
|
||||
cipherSettings.setKdfAlgorithm(QString("PBKDF2_HMAC_") + ui->comboKdfAlgorithm->currentText());
|
||||
cipherSettings.setHmacAlgorithm("HMAC_" + ui->comboHmacAlgorithm->currentText().toStdString());
|
||||
cipherSettings.setKdfAlgorithm("PBKDF2_HMAC_" + ui->comboKdfAlgorithm->currentText().toStdString());
|
||||
|
||||
return cipherSettings;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "CipherSettings.h"
|
||||
#include "sqlitedb.h"
|
||||
|
||||
CipherSettings::CipherSettings()
|
||||
: keyFormat(Passphrase),
|
||||
@@ -7,46 +8,17 @@ CipherSettings::CipherSettings()
|
||||
{
|
||||
}
|
||||
|
||||
CipherSettings::KeyFormats CipherSettings::getKeyFormat() const
|
||||
{
|
||||
return keyFormat;
|
||||
}
|
||||
|
||||
void CipherSettings::setKeyFormat(const KeyFormats &value)
|
||||
{
|
||||
keyFormat = value;
|
||||
}
|
||||
|
||||
QString CipherSettings::getPassword() const
|
||||
std::string CipherSettings::getPassword() const
|
||||
{
|
||||
if(keyFormat == Passphrase)
|
||||
{
|
||||
QString tempPassword = password;
|
||||
|
||||
tempPassword.replace("'", "''");
|
||||
|
||||
return QString("'%1'").arg(tempPassword);
|
||||
return sqlb::escapeString(password);
|
||||
} else {
|
||||
// Remove the '0x' part at the beginning
|
||||
return QString("\"x'%1'\"").arg(password.mid(2));
|
||||
return "\"x'" + password.substr(2) + "'\"";
|
||||
}
|
||||
}
|
||||
|
||||
void CipherSettings::setPassword(const QString &value)
|
||||
{
|
||||
password = value;
|
||||
}
|
||||
|
||||
int CipherSettings::getPageSize() const
|
||||
{
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
void CipherSettings::setPageSize(int value)
|
||||
{
|
||||
pageSize = value;
|
||||
}
|
||||
|
||||
CipherSettings::KeyFormats CipherSettings::getKeyFormat(int rawKeyFormat)
|
||||
{
|
||||
return static_cast<CipherSettings::KeyFormats>(rawKeyFormat);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef CIPHERSETTINGS_H
|
||||
#define CIPHERSETTINGS_H
|
||||
|
||||
#include <QString>
|
||||
#include <string>
|
||||
|
||||
class CipherSettings
|
||||
{
|
||||
@@ -14,33 +14,33 @@ public:
|
||||
RawKey
|
||||
};
|
||||
|
||||
KeyFormats getKeyFormat() const;
|
||||
void setKeyFormat(const KeyFormats &value);
|
||||
KeyFormats getKeyFormat() const { return keyFormat; }
|
||||
void setKeyFormat(const KeyFormats &value) { keyFormat = value; }
|
||||
|
||||
QString getPassword() const;
|
||||
void setPassword(const QString &value);
|
||||
std::string getPassword() const;
|
||||
void setPassword(const std::string& value) { password = value; }
|
||||
|
||||
int getPageSize() const;
|
||||
void setPageSize(int value);
|
||||
int getPageSize() const { return pageSize; }
|
||||
void setPageSize(int value) { pageSize = value; }
|
||||
|
||||
int getKdfIterations() const { return kdfIterations; }
|
||||
void setKdfIterations(int value) { kdfIterations = value; }
|
||||
|
||||
QString getHmacAlgorithm() const { return hmacAlgorithm; }
|
||||
void setHmacAlgorithm(const QString &value) { hmacAlgorithm = value; }
|
||||
std::string getHmacAlgorithm() const { return hmacAlgorithm; }
|
||||
void setHmacAlgorithm(const std::string& value) { hmacAlgorithm = value; }
|
||||
|
||||
QString getKdfAlgorithm() const { return kdfAlgorithm; }
|
||||
void setKdfAlgorithm(const QString &value) { kdfAlgorithm = value; }
|
||||
std::string getKdfAlgorithm() const { return kdfAlgorithm; }
|
||||
void setKdfAlgorithm(const std::string& value) { kdfAlgorithm = value; }
|
||||
|
||||
static KeyFormats getKeyFormat(int rawKeyFormat);
|
||||
|
||||
private:
|
||||
KeyFormats keyFormat;
|
||||
QString password;
|
||||
std::string password;
|
||||
int pageSize;
|
||||
int kdfIterations;
|
||||
QString hmacAlgorithm;
|
||||
QString kdfAlgorithm;
|
||||
std::string hmacAlgorithm;
|
||||
std::string kdfAlgorithm;
|
||||
};
|
||||
|
||||
#endif // CIPHERSETTINGS_H
|
||||
|
||||
@@ -111,12 +111,12 @@ void ColumnDisplayFormatDialog::accept()
|
||||
// Execute a query using the display format and check that it only returns one column.
|
||||
int customNumberColumns = 0;
|
||||
|
||||
DBBrowserDB::execCallback callback = [&customNumberColumns](int numberColumns, QStringList, QStringList) -> bool {
|
||||
DBBrowserDB::execCallback callback = [&customNumberColumns](int numberColumns, std::vector<QByteArray>, std::vector<QByteArray>) -> bool {
|
||||
customNumberColumns = numberColumns;
|
||||
// Return false so the query is not aborted and no error is reported.
|
||||
return false;
|
||||
};
|
||||
if(!pdb.executeSQL(QString("SELECT %1 FROM %2 LIMIT 1").arg(ui->editDisplayFormat->text(), QString::fromStdString(curTable.toString())),
|
||||
if(!pdb.executeSQL("SELECT " + ui->editDisplayFormat->text().toStdString() + " FROM " + curTable.toString() + " LIMIT 1",
|
||||
false, true, callback))
|
||||
errorMessage = tr("Error in custom display format. Message from database engine:\n\n%1").arg(pdb.lastError());
|
||||
else if(customNumberColumns != 1)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "CondFormat.h"
|
||||
#include "Settings.h"
|
||||
#include "Data.h"
|
||||
#include "sqlitedb.h"
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
@@ -48,8 +49,11 @@ CondFormat::CondFormat(const QString& filter,
|
||||
m_font.fromString(model->data(index, Qt::FontRole).toString());
|
||||
}
|
||||
|
||||
QString CondFormat::filterToSqlCondition(const QString& value, const QString& encoding)
|
||||
std::string CondFormat::filterToSqlCondition(const QString& value, const QString& encoding)
|
||||
{
|
||||
if(value.isEmpty())
|
||||
return {};
|
||||
|
||||
// Check for any special comparison operators at the beginning of the value string. If there are none default to LIKE.
|
||||
QString op = "LIKE";
|
||||
QString val, val2;
|
||||
@@ -89,15 +93,15 @@ QString CondFormat::filterToSqlCondition(const QString& value, const QString& en
|
||||
numeric = true;
|
||||
val = "''";
|
||||
} else {
|
||||
value.mid(2).toFloat(&numeric);
|
||||
value.midRef(2).toFloat(&numeric);
|
||||
op = value.left(2);
|
||||
val = value.mid(2);
|
||||
}
|
||||
} else if(value.left(1) == ">" || value.left(1) == "<") {
|
||||
value.mid(1).toFloat(&numeric);
|
||||
op = value.left(1);
|
||||
} else if(value.front() == ">" || value.front() == "<") {
|
||||
value.midRef(1).toFloat(&numeric);
|
||||
op = value.front();
|
||||
val = value.mid(1);
|
||||
} else if(value.left(1) == "=") {
|
||||
} else if(value.front() == "=") {
|
||||
val = value.mid(1);
|
||||
|
||||
// Check if value to compare with is 'NULL'
|
||||
@@ -111,7 +115,7 @@ QString CondFormat::filterToSqlCondition(const QString& value, const QString& en
|
||||
op = "IS";
|
||||
numeric = true;
|
||||
}
|
||||
} else if(value.left(1) == "/" && value.right(1) == "/" && value.length() > 2) {
|
||||
} else if(value.front() == "/" && value.back() == "/" && value.size() > 2) {
|
||||
val = value.mid(1, value.length() - 2);
|
||||
op = "REGEXP";
|
||||
numeric = false;
|
||||
@@ -138,18 +142,18 @@ QString CondFormat::filterToSqlCondition(const QString& value, const QString& en
|
||||
if(val.isEmpty())
|
||||
val = value;
|
||||
|
||||
if(val == "" || val == "%" || val == "%%")
|
||||
return QString();
|
||||
if(val.isEmpty() || val == "%" || val == "%%")
|
||||
return {};
|
||||
else {
|
||||
// Quote and escape value, but only if it's not numeric and not the empty string sequence
|
||||
if(!numeric && val != "''")
|
||||
val = QString("'%1'").arg(val.replace("'", "''"));
|
||||
val = sqlb::escapeString(val);
|
||||
|
||||
QString whereClause(op + " " + QString(encodeString(val.toUtf8(), encoding)));
|
||||
if (!val2.isEmpty())
|
||||
whereClause += " AND " + QString(encodeString(val2.toUtf8(), encoding));
|
||||
whereClause += " " + escape;
|
||||
return whereClause;
|
||||
return whereClause.toStdString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,10 +43,10 @@ public:
|
||||
const QModelIndex index,
|
||||
const QString& encoding = QString());
|
||||
|
||||
static QString filterToSqlCondition(const QString& value, const QString& encoding = QString());
|
||||
static std::string filterToSqlCondition(const QString& value, const QString& encoding = QString());
|
||||
|
||||
private:
|
||||
QString m_sqlCondition;
|
||||
std::string m_sqlCondition;
|
||||
QString m_filter;
|
||||
QColor m_bgColor;
|
||||
QColor m_fgColor;
|
||||
@@ -54,7 +54,7 @@ private:
|
||||
Alignment m_align;
|
||||
|
||||
public:
|
||||
QString sqlCondition() const { return m_sqlCondition; }
|
||||
std::string sqlCondition() const { return m_sqlCondition; }
|
||||
QString filter() const { return m_filter; }
|
||||
|
||||
QColor backgroundColor() const { return m_bgColor; }
|
||||
|
||||
@@ -56,11 +56,11 @@ CondFormatManager::CondFormatManager(const std::vector<CondFormat>& condFormats,
|
||||
ui->tableCondFormats->resizeColumnToContents(col);
|
||||
}
|
||||
|
||||
connect(ui->buttonAdd, SIGNAL(clicked(bool)), this, SLOT(addNewItem()));
|
||||
connect(ui->buttonRemove, SIGNAL(clicked(bool)), this, SLOT(removeItem()));
|
||||
connect(ui->buttonAdd, &QToolButton::clicked, this, &CondFormatManager::addNewItem);
|
||||
connect(ui->buttonRemove, &QToolButton::clicked, this, &CondFormatManager::removeItem);
|
||||
|
||||
connect(ui->buttonDown, SIGNAL(clicked(bool)), this, SLOT(downItem()));
|
||||
connect(ui->buttonUp, SIGNAL(clicked(bool)), this, SLOT(upItem()));
|
||||
connect(ui->buttonDown, &QToolButton::clicked, this, &CondFormatManager::downItem);
|
||||
connect(ui->buttonUp, &QToolButton::clicked, this, &CondFormatManager::upItem);
|
||||
|
||||
connect(ui->tableCondFormats, &QTreeWidget::itemClicked, this, &CondFormatManager::itemClicked);
|
||||
}
|
||||
@@ -181,7 +181,7 @@ void CondFormatManager::downItem()
|
||||
moveItem(+1);
|
||||
}
|
||||
|
||||
std::vector<CondFormat> CondFormatManager::getCondFormats()
|
||||
std::vector<CondFormat> CondFormatManager::getCondFormats() const
|
||||
{
|
||||
std::vector<CondFormat> result;
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ public:
|
||||
explicit CondFormatManager(const std::vector<CondFormat>& condFormats, const QString& encoding, QWidget *parent = nullptr);
|
||||
~CondFormatManager() override;
|
||||
|
||||
std::vector<CondFormat> getCondFormats();
|
||||
std::vector<CondFormat> getCondFormats() const;
|
||||
private:
|
||||
enum Columns {
|
||||
ColumnForeground = 0,
|
||||
|
||||
18
src/Data.cpp
18
src/Data.cpp
@@ -36,7 +36,7 @@ bool isTextOnly(QByteArray data, const QString& encoding, bool quickTest)
|
||||
|
||||
QTextCodec::ConverterState state;
|
||||
QTextCodec *codec = encoding.isEmpty()? QTextCodec::codecForName("UTF-8") : QTextCodec::codecForName(encoding.toUtf8());
|
||||
const QString text = codec->toUnicode(data.constData(), testSize, &state);
|
||||
codec->toUnicode(data.constData(), testSize, &state);
|
||||
return state.invalidChars == 0;
|
||||
} else {
|
||||
// Convert to Unicode if necessary
|
||||
@@ -127,3 +127,19 @@ QByteArray decodeString(const QByteArray& str, const QString& encoding)
|
||||
else
|
||||
return QTextCodec::codecForName(encoding.toUtf8())->toUnicode(str).toUtf8();
|
||||
}
|
||||
|
||||
QString humanReadableSize(unsigned long byteCount)
|
||||
{
|
||||
static const std::vector<QString> units = {"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB"};
|
||||
|
||||
double size = static_cast<double>(byteCount);
|
||||
for(const QString& unit : units)
|
||||
{
|
||||
if(size < 1024.0)
|
||||
return QString::number(size, 'f', 2) + " " + unit;
|
||||
|
||||
size /= 1024.0;
|
||||
}
|
||||
|
||||
return QString::number(size, 'f', 2) + " YiB";
|
||||
}
|
||||
|
||||
@@ -30,4 +30,6 @@ QByteArray encodeString(const QByteArray& str, const QString& encoding);
|
||||
|
||||
QByteArray decodeString(const QByteArray& str, const QString& encoding);
|
||||
|
||||
QString humanReadableSize(unsigned long byteCount);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "DbStructureModel.h"
|
||||
#include <IconCache.h>
|
||||
#include "IconCache.h"
|
||||
#include "sqlitedb.h"
|
||||
#include "sqlitetablemodel.h"
|
||||
#include "Settings.h"
|
||||
@@ -14,6 +14,7 @@
|
||||
DbStructureModel::DbStructureModel(DBBrowserDB& db, QObject* parent)
|
||||
: QAbstractItemModel(parent),
|
||||
m_db(db),
|
||||
browsablesRootItem(nullptr),
|
||||
m_dropQualifiedNames(false),
|
||||
m_dropEnquotedNames(false)
|
||||
{
|
||||
@@ -21,7 +22,6 @@ DbStructureModel::DbStructureModel(DBBrowserDB& db, QObject* parent)
|
||||
QStringList header;
|
||||
header << tr("Name") << tr("Object") << tr("Type") << tr("Schema") << tr("Database");
|
||||
rootItem = new QTreeWidgetItem(header);
|
||||
browsablesRootItem = nullptr;
|
||||
}
|
||||
|
||||
DbStructureModel::~DbStructureModel()
|
||||
|
||||
@@ -49,12 +49,12 @@ EditDialog::EditDialog(QWidget* parent)
|
||||
sciLayout->addWidget(sciEdit);
|
||||
|
||||
QShortcut* ins = new QShortcut(QKeySequence(Qt::Key_Insert), this);
|
||||
connect(ins, SIGNAL(activated()), this, SLOT(toggleOverwriteMode()));
|
||||
connect(ins, &QShortcut::activated, this, &EditDialog::toggleOverwriteMode);
|
||||
|
||||
connect(sciEdit, SIGNAL(textChanged()), this, SLOT(updateApplyButton()));
|
||||
connect(sciEdit, SIGNAL(textChanged()), this, SLOT(editTextChanged()));
|
||||
connect(ui->qtEdit, SIGNAL(textChanged()), this, SLOT(updateApplyButton()));
|
||||
connect(hexEdit, SIGNAL(dataChanged()), this, SLOT(updateApplyButton()));
|
||||
connect(sciEdit, &DockTextEdit::textChanged, this, &EditDialog::updateApplyButton);
|
||||
connect(sciEdit, &DockTextEdit::textChanged, this, &EditDialog::editTextChanged);
|
||||
connect(ui->qtEdit, &QTextEdit::textChanged, this, &EditDialog::updateApplyButton);
|
||||
connect(hexEdit, &QHexEdit::dataChanged, this, &EditDialog::updateApplyButton);
|
||||
|
||||
// Create shortcuts for the widgets that doesn't have its own print action or printing mechanism.
|
||||
QShortcut* shortcutPrint = new QShortcut(QKeySequence::Print, this, nullptr, nullptr, Qt::WidgetShortcut);
|
||||
@@ -116,7 +116,6 @@ void EditDialog::reject()
|
||||
void EditDialog::loadData(const QByteArray& bArrdata)
|
||||
{
|
||||
QImage img;
|
||||
QString textData;
|
||||
|
||||
// Clear previously removed BOM
|
||||
removedBom.clear();
|
||||
@@ -846,7 +845,7 @@ void EditDialog::setMustIndentAndCompact(bool enable)
|
||||
}
|
||||
|
||||
// Determine the type of data in the cell
|
||||
int EditDialog::checkDataType(const QByteArray& bArrdata)
|
||||
int EditDialog::checkDataType(const QByteArray& bArrdata) const
|
||||
{
|
||||
QByteArray cellData = bArrdata;
|
||||
|
||||
@@ -991,7 +990,7 @@ void EditDialog::updateCellInfoAndMode(const QByteArray& bArrdata)
|
||||
|
||||
// Display the image dimensions and size
|
||||
QSize imageDimensions = imageReader.size();
|
||||
int imageSize = cellData.size();
|
||||
unsigned int imageSize = static_cast<unsigned int>(cellData.size());
|
||||
|
||||
QString labelSizeText = tr("%1x%2 pixel(s)").arg(imageDimensions.width()).arg(imageDimensions.height()) + ", " + humanReadableSize(imageSize);
|
||||
|
||||
@@ -1040,28 +1039,6 @@ void EditDialog::updateCellInfoAndMode(const QByteArray& bArrdata)
|
||||
}
|
||||
}
|
||||
|
||||
QString EditDialog::humanReadableSize(double byteCount) const
|
||||
{
|
||||
QStringList units;
|
||||
units << "" << "Ki" << "Mi" << "Gi" << "Ti" << "Pi" << "Ei" << "Zi";
|
||||
|
||||
for(const QString& unit : units)
|
||||
{
|
||||
if(fabs(byteCount) < 1024.0)
|
||||
{
|
||||
QString size = QString::number(byteCount, 'f', 2);
|
||||
return size + " " + unit + "B";
|
||||
}
|
||||
|
||||
byteCount /= 1024.0;
|
||||
}
|
||||
|
||||
QString yiUnit = "Yi";
|
||||
QString size = QString::number(byteCount, 'f', 2);
|
||||
|
||||
return size + " " + yiUnit + "B";
|
||||
}
|
||||
|
||||
void EditDialog::reloadSettings()
|
||||
{
|
||||
// Set the (SQL) editor font for hex editor, since it needs a
|
||||
@@ -1115,29 +1092,28 @@ void EditDialog::openPrintDialog()
|
||||
QPrinter printer;
|
||||
QPrintPreviewDialog *dialog = new QPrintPreviewDialog(&printer);
|
||||
|
||||
QTextDocument *document = new QTextDocument();
|
||||
switch (dataSource) {
|
||||
case SciBuffer:
|
||||
// This case isn't really expected because the Scintilla widget has it's own printing slot
|
||||
document->setPlainText(sciEdit->text());
|
||||
break;
|
||||
case HexBuffer:
|
||||
document->setPlainText(hexEdit->toReadableString());
|
||||
document->setDefaultFont(hexEdit->font());
|
||||
break;
|
||||
case QtBuffer:
|
||||
document->setPlainText(ui->qtEdit->toPlainText());
|
||||
break;
|
||||
}
|
||||
connect(dialog, &QPrintPreviewDialog::paintRequested, [this](QPrinter *previewPrinter) {
|
||||
QTextDocument document;
|
||||
switch (dataSource) {
|
||||
case SciBuffer:
|
||||
// This case isn't really expected because the Scintilla widget has it's own printing slot
|
||||
document.setPlainText(sciEdit->text());
|
||||
break;
|
||||
case HexBuffer:
|
||||
document.setPlainText(hexEdit->toReadableString());
|
||||
document.setDefaultFont(hexEdit->font());
|
||||
break;
|
||||
case QtBuffer:
|
||||
document.setPlainText(ui->qtEdit->toPlainText());
|
||||
break;
|
||||
}
|
||||
|
||||
connect(dialog, &QPrintPreviewDialog::paintRequested, [&](QPrinter *previewPrinter) {
|
||||
document->print(previewPrinter);
|
||||
document.print(previewPrinter);
|
||||
});
|
||||
|
||||
dialog->exec();
|
||||
|
||||
delete dialog;
|
||||
delete document;
|
||||
|
||||
}
|
||||
|
||||
void EditDialog::openPrintImageDialog()
|
||||
|
||||
@@ -94,8 +94,7 @@ private:
|
||||
XmlEditor = 5
|
||||
};
|
||||
|
||||
int checkDataType(const QByteArray& bArrdata);
|
||||
QString humanReadableSize(double byteCount) const;
|
||||
int checkDataType(const QByteArray& bArrdata) const;
|
||||
bool promptInvalidData(const QString& data_type, const QString& errorString);
|
||||
void setDataInBuffer(const QByteArray& bArrdata, DataSources source);
|
||||
void setStackCurrentIndex(int editMode);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "EditIndexDialog.h"
|
||||
#include "ui_EditIndexDialog.h"
|
||||
#include "sqlitedb.h"
|
||||
#include "IconCache.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
@@ -43,7 +44,7 @@ EditIndexDialog::EditIndexDialog(DBBrowserDB& db, const sqlb::ObjectIdentifier&
|
||||
}
|
||||
ui->comboTableName->blockSignals(true);
|
||||
for(auto it=dbobjs.cbegin();it!=dbobjs.cend();++it)
|
||||
ui->comboTableName->addItem(QIcon(QString(":icons/table")), QString::fromStdString(it->first), QString::fromStdString(it->second.toSerialised()));
|
||||
ui->comboTableName->addItem(IconCache::get("table"), QString::fromStdString(it->first), QString::fromStdString(it->second.toSerialised()));
|
||||
ui->comboTableName->blockSignals(false);
|
||||
|
||||
QHeaderView *tableHeaderView = ui->tableIndexColumns->horizontalHeader();
|
||||
@@ -263,7 +264,7 @@ void EditIndexDialog::accept()
|
||||
// When editing an index, delete the old one first
|
||||
if(!newIndex)
|
||||
{
|
||||
if(!pdb.executeSQL(QString("DROP INDEX IF EXISTS %1;").arg(QString::fromStdString(curIndex.toString()))))
|
||||
if(!pdb.executeSQL("DROP INDEX IF EXISTS " + curIndex.toString()))
|
||||
{
|
||||
QMessageBox::warning(this, qApp->applicationName(), tr("Deleting the old index failed:\n%1").arg(pdb.lastError()));
|
||||
return;
|
||||
@@ -271,7 +272,7 @@ void EditIndexDialog::accept()
|
||||
}
|
||||
|
||||
// Create the new index in the schema of the selected table
|
||||
if(pdb.executeSQL(QString::fromStdString(index.sql(sqlb::ObjectIdentifier(ui->comboTableName->currentData().toString().toStdString()).schema()))))
|
||||
if(pdb.executeSQL(index.sql(sqlb::ObjectIdentifier(ui->comboTableName->currentData().toString().toStdString()).schema())))
|
||||
QDialog::accept();
|
||||
else
|
||||
QMessageBox::warning(this, QApplication::applicationName(), tr("Creating the index failed:\n%1").arg(pdb.lastError()));
|
||||
|
||||
@@ -39,7 +39,7 @@ private:
|
||||
sqlb::Index index;
|
||||
bool newIndex;
|
||||
Ui::EditIndexDialog* ui;
|
||||
QString m_sRestorePointName;
|
||||
std::string m_sRestorePointName;
|
||||
|
||||
void updateColumnLists();
|
||||
void updateSqlText();
|
||||
|
||||
@@ -49,7 +49,7 @@ EditTableDialog::EditTableDialog(DBBrowserDB& db, const sqlb::ObjectIdentifier&
|
||||
ui->buttonAddConstraint->setMenu(constraint_menu);
|
||||
|
||||
// Get list of all collations
|
||||
db.executeSQL("PRAGMA collation_list;", false, true, [this](int column_count, QStringList columns, QStringList) -> bool {
|
||||
db.executeSQL("PRAGMA collation_list;", false, true, [this](int column_count, std::vector<QByteArray> columns, std::vector<QByteArray>) -> bool {
|
||||
if(column_count >= 2)
|
||||
m_collationList.push_back(columns.at(1));
|
||||
return false;
|
||||
@@ -328,7 +328,7 @@ void EditTableDialog::accept()
|
||||
if(m_bNewTable)
|
||||
{
|
||||
// Creation of new table
|
||||
if(!pdb.executeSQL(QString::fromStdString(m_table.sql(ui->comboSchema->currentText().toStdString()))))
|
||||
if(!pdb.executeSQL(m_table.sql(ui->comboSchema->currentText().toStdString())))
|
||||
{
|
||||
QMessageBox::warning(
|
||||
this,
|
||||
@@ -571,10 +571,10 @@ void EditTableDialog::fieldItemChanged(QTreeWidgetItem *item, int column)
|
||||
// we need to check for this case and cancel here. Maybe we can think of some way to modify the INSERT INTO ... SELECT statement
|
||||
// to at least replace all troublesome NULL values by the default value
|
||||
SqliteTableModel m(pdb, this);
|
||||
m.setQuery(QString("SELECT COUNT(%1) FROM %2 WHERE coalesce(NULL,%3) IS NULL;")
|
||||
.arg(QString::fromStdString(sqlb::joinStringVector(sqlb::escapeIdentifier(pdb.getObjectByName<sqlb::Table>(curTable)->rowidColumns()), ",")))
|
||||
.arg(QString::fromStdString(curTable.toString()))
|
||||
.arg(QString::fromStdString(sqlb::escapeIdentifier(field.name()))));
|
||||
m.setQuery(QString("SELECT COUNT(%1) FROM %2 WHERE coalesce(NULL,%3) IS NULL;").arg(
|
||||
QString::fromStdString(sqlb::joinStringVector(sqlb::escapeIdentifier(pdb.getObjectByName<sqlb::Table>(curTable)->rowidColumns()), ",")),
|
||||
QString::fromStdString(curTable.toString()),
|
||||
QString::fromStdString(sqlb::escapeIdentifier(field.name()))));
|
||||
if(!m.completeCache())
|
||||
{
|
||||
// If we couldn't load all data because the cancel button was clicked, just unset the checkbox again and stop.
|
||||
@@ -602,10 +602,10 @@ void EditTableDialog::fieldItemChanged(QTreeWidgetItem *item, int column)
|
||||
if(!m_bNewTable)
|
||||
{
|
||||
SqliteTableModel m(pdb, this);
|
||||
m.setQuery(QString("SELECT COUNT(*) FROM %1 WHERE %2 <> CAST(%3 AS INTEGER);")
|
||||
.arg(QString::fromStdString(curTable.toString()))
|
||||
.arg(QString::fromStdString(sqlb::escapeIdentifier(field.name())))
|
||||
.arg(QString::fromStdString(sqlb::escapeIdentifier(field.name()))));
|
||||
m.setQuery(QString("SELECT COUNT(*) FROM %1 WHERE %2 <> CAST(%3 AS INTEGER);").arg(
|
||||
QString::fromStdString(curTable.toString()),
|
||||
QString::fromStdString(sqlb::escapeIdentifier(field.name())),
|
||||
QString::fromStdString(sqlb::escapeIdentifier(field.name()))));
|
||||
if(!m.completeCache())
|
||||
{
|
||||
// If we couldn't load all data because the cancel button was clicked, just unset the checkbox again and stop.
|
||||
@@ -650,7 +650,9 @@ void EditTableDialog::fieldItemChanged(QTreeWidgetItem *item, int column)
|
||||
{
|
||||
// Because our renameColumn() function fails when setting a column to unique when it already contains the same values
|
||||
SqliteTableModel m(pdb, this);
|
||||
m.setQuery(QString("SELECT COUNT(%2) FROM %1;").arg(QString::fromStdString(curTable.toString())).arg(QString::fromStdString(sqlb::escapeIdentifier(field.name()))));
|
||||
m.setQuery(QString("SELECT COUNT(%2) FROM %1;").arg(
|
||||
QString::fromStdString(curTable.toString()),
|
||||
QString::fromStdString(sqlb::escapeIdentifier(field.name()))));
|
||||
if(!m.completeCache())
|
||||
{
|
||||
// If we couldn't load all data because the cancel button was clicked, just unset the checkbox again and stop.
|
||||
@@ -658,7 +660,9 @@ void EditTableDialog::fieldItemChanged(QTreeWidgetItem *item, int column)
|
||||
return;
|
||||
}
|
||||
int rowcount = m.data(m.index(0, 0)).toInt();
|
||||
m.setQuery(QString("SELECT COUNT(DISTINCT %2) FROM %1;").arg(QString::fromStdString(curTable.toString())).arg(QString::fromStdString(sqlb::escapeIdentifier(field.name()))));
|
||||
m.setQuery(QString("SELECT COUNT(DISTINCT %2) FROM %1;").arg(
|
||||
QString::fromStdString(curTable.toString()),
|
||||
QString::fromStdString(sqlb::escapeIdentifier(field.name()))));
|
||||
if(!m.completeCache())
|
||||
{
|
||||
// If we couldn't load all data because the cancel button was clicked, just unset the checkbox again and stop.
|
||||
@@ -699,7 +703,7 @@ void EditTableDialog::fieldItemChanged(QTreeWidgetItem *item, int column)
|
||||
{
|
||||
new_value = new_value.trimmed().mid(1); // Leave the brackets as they are needed for a valid SQL expression
|
||||
} else {
|
||||
new_value = QString("'%1'").arg(new_value.replace("'", "''"));
|
||||
new_value = sqlb::escapeString(new_value);
|
||||
item->setText(column, new_value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ private:
|
||||
std::map<QString, QString> trackColumns;
|
||||
sqlb::Table m_table;
|
||||
bool m_bNewTable;
|
||||
QString m_sRestorePointName;
|
||||
std::string m_sRestorePointName;
|
||||
QStringList m_collationList;
|
||||
};
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "Settings.h"
|
||||
#include "sqlite.h"
|
||||
#include "FileDialog.h"
|
||||
#include "IconCache.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
@@ -13,7 +14,7 @@
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
ExportDataDialog::ExportDataDialog(DBBrowserDB& db, ExportFormats format, QWidget* parent, const QString& query, const sqlb::ObjectIdentifier& selection)
|
||||
ExportDataDialog::ExportDataDialog(DBBrowserDB& db, ExportFormats format, QWidget* parent, const std::string& query, const sqlb::ObjectIdentifier& selection)
|
||||
: QDialog(parent),
|
||||
ui(new Ui::ExportDataDialog),
|
||||
pdb(db),
|
||||
@@ -40,7 +41,7 @@ ExportDataDialog::ExportDataDialog(DBBrowserDB& db, ExportFormats format, QWidge
|
||||
showCustomCharEdits();
|
||||
|
||||
// If a SQL query was specified hide the table combo box. If not fill it with tables to export
|
||||
if(query.isEmpty())
|
||||
if(query.empty())
|
||||
{
|
||||
// Get list of tables to export
|
||||
for(const auto& it : pdb.schemata)
|
||||
@@ -56,7 +57,7 @@ ExportDataDialog::ExportDataDialog(DBBrowserDB& db, ExportFormats format, QWidge
|
||||
for(const auto& jt : objects)
|
||||
{
|
||||
sqlb::ObjectIdentifier obj(it.first, jt.second->name());
|
||||
QListWidgetItem* item = new QListWidgetItem(QIcon(QString(":icons/%1").arg(QString::fromStdString(sqlb::Object::typeToString(jt.second->type())))), QString::fromStdString(obj.toDisplayString()));
|
||||
QListWidgetItem* item = new QListWidgetItem(IconCache::get(sqlb::Object::typeToString(jt.second->type())), QString::fromStdString(obj.toDisplayString()));
|
||||
item->setData(Qt::UserRole, QString::fromStdString(obj.toSerialised()));
|
||||
ui->listTables->addItem(item);
|
||||
}
|
||||
@@ -90,7 +91,7 @@ ExportDataDialog::~ExportDataDialog()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool ExportDataDialog::exportQuery(const QString& sQuery, const QString& sFilename)
|
||||
bool ExportDataDialog::exportQuery(const std::string& sQuery, const QString& sFilename)
|
||||
{
|
||||
switch(m_format)
|
||||
{
|
||||
@@ -103,7 +104,7 @@ bool ExportDataDialog::exportQuery(const QString& sQuery, const QString& sFilena
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ExportDataDialog::exportQueryCsv(const QString& sQuery, const QString& sFilename)
|
||||
bool ExportDataDialog::exportQueryCsv(const std::string& sQuery, const QString& sFilename)
|
||||
{
|
||||
// Prepare the quote and separating characters
|
||||
QChar quoteChar = currentQuoteChar();
|
||||
@@ -121,11 +122,10 @@ bool ExportDataDialog::exportQueryCsv(const QString& sQuery, const QString& sFil
|
||||
// Open text stream to the file
|
||||
QTextStream stream(&file);
|
||||
|
||||
QByteArray utf8Query = sQuery.toUtf8();
|
||||
sqlite3_stmt *stmt;
|
||||
|
||||
auto pDb = pdb.get(tr("exporting CSV"));
|
||||
int status = sqlite3_prepare_v2(pDb.get(), utf8Query.data(), utf8Query.size(), &stmt, nullptr);
|
||||
|
||||
sqlite3_stmt* stmt;
|
||||
int status = sqlite3_prepare_v2(pDb.get(), sQuery.c_str(), static_cast<int>(sQuery.size()), &stmt, nullptr);
|
||||
if(SQLITE_OK == status)
|
||||
{
|
||||
if(ui->checkHeader->isChecked())
|
||||
@@ -199,17 +199,16 @@ bool ExportDataDialog::exportQueryCsv(const QString& sQuery, const QString& sFil
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExportDataDialog::exportQueryJson(const QString& sQuery, const QString& sFilename)
|
||||
bool ExportDataDialog::exportQueryJson(const std::string& sQuery, const QString& sFilename)
|
||||
{
|
||||
// Open file
|
||||
QFile file(sFilename);
|
||||
if(file.open(QIODevice::WriteOnly))
|
||||
{
|
||||
QByteArray utf8Query = sQuery.toUtf8();
|
||||
sqlite3_stmt *stmt;
|
||||
|
||||
auto pDb = pdb.get(tr("exporting JSON"));
|
||||
int status = sqlite3_prepare_v2(pDb.get(), utf8Query.data(), utf8Query.size(), &stmt, nullptr);
|
||||
|
||||
sqlite3_stmt* stmt;
|
||||
int status = sqlite3_prepare_v2(pDb.get(), sQuery.c_str(), static_cast<int>(sQuery.size()), &stmt, nullptr);
|
||||
|
||||
json json_table;
|
||||
|
||||
@@ -316,7 +315,7 @@ void ExportDataDialog::accept()
|
||||
break;
|
||||
}
|
||||
|
||||
if(!m_sQuery.isEmpty())
|
||||
if(!m_sQuery.empty())
|
||||
{
|
||||
// called from sqlexecute query tab
|
||||
QString sFilename = FileDialog::getSaveFileName(
|
||||
@@ -382,7 +381,7 @@ void ExportDataDialog::accept()
|
||||
{
|
||||
// if we are called from execute sql tab, query is already set
|
||||
// and we only export 1 select
|
||||
QString sQuery = QString("SELECT * FROM %1;").arg(QString::fromStdString(sqlb::ObjectIdentifier(selectedItems.at(i)->data(Qt::UserRole).toString().toStdString()).toString()));
|
||||
std::string sQuery = "SELECT * FROM " + sqlb::ObjectIdentifier(selectedItems.at(i)->data(Qt::UserRole).toString().toStdString()).toString() + ";";
|
||||
exportQuery(sQuery, filenames.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ public:
|
||||
};
|
||||
|
||||
explicit ExportDataDialog(DBBrowserDB& db, ExportFormats format, QWidget* parent = nullptr,
|
||||
const QString& query = "", const sqlb::ObjectIdentifier& selection = sqlb::ObjectIdentifier());
|
||||
const std::string& query = {}, const sqlb::ObjectIdentifier& selection = sqlb::ObjectIdentifier());
|
||||
~ExportDataDialog() override;
|
||||
|
||||
private slots:
|
||||
@@ -40,9 +40,9 @@ private:
|
||||
void setNewLineString(const QString& s);
|
||||
QString currentNewLineString() const;
|
||||
|
||||
bool exportQuery(const QString& sQuery, const QString& sFilename);
|
||||
bool exportQueryCsv(const QString& sQuery, const QString& sFilename);
|
||||
bool exportQueryJson(const QString& sQuery, const QString& sFilename);
|
||||
bool exportQuery(const std::string& sQuery, const QString& sFilename);
|
||||
bool exportQueryCsv(const std::string& sQuery, const QString& sFilename);
|
||||
bool exportQueryJson(const std::string& sQuery, const QString& sFilename);
|
||||
|
||||
private:
|
||||
Ui::ExportDataDialog* ui;
|
||||
@@ -50,7 +50,7 @@ private:
|
||||
|
||||
ExportFormats m_format;
|
||||
|
||||
QString m_sQuery;
|
||||
std::string m_sQuery;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "sqlitedb.h"
|
||||
#include "FileDialog.h"
|
||||
#include "Settings.h"
|
||||
#include "IconCache.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QMessageBox>
|
||||
@@ -30,7 +31,7 @@ ExportSqlDialog::ExportSqlDialog(DBBrowserDB* db, QWidget* parent, const QString
|
||||
// Get list of tables to export
|
||||
const auto objects = pdb->schemata["main"].equal_range("table");
|
||||
for(auto it=objects.first;it!=objects.second;++it)
|
||||
ui->listTables->addItem(new QListWidgetItem(QIcon(QString(":icons/%1").arg(QString::fromStdString(sqlb::Object::typeToString(it->second->type())))), QString::fromStdString(it->second->name())));
|
||||
ui->listTables->addItem(new QListWidgetItem(IconCache::get(sqlb::Object::typeToString(it->second->type())), QString::fromStdString(it->second->name())));
|
||||
|
||||
// Sort list of tables and select the table specified in the
|
||||
// selection parameter or all tables if table not specified
|
||||
@@ -96,9 +97,9 @@ void ExportSqlDialog::accept()
|
||||
Settings::setValue("exportsql", "insertmultiple", ui->checkMultiple->isChecked());
|
||||
Settings::setValue("exportsql", "oldschema", ui->comboOldSchema->currentIndex());
|
||||
|
||||
QStringList tables;
|
||||
std::vector<std::string> tables;
|
||||
for(const QListWidgetItem* item : ui->listTables->selectedItems())
|
||||
tables.push_back(item->text());
|
||||
tables.push_back(item->text().toStdString());
|
||||
|
||||
// Check what to export. The indices here depend on the order of the items in the combobox in the ui file
|
||||
bool exportSchema = ui->comboWhat->currentIndex() == ExportEverything || ui->comboWhat->currentIndex() == ExportSchemaOnly;
|
||||
|
||||
@@ -14,7 +14,7 @@ class ExportSqlDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ExportSqlDialog(DBBrowserDB* db, QWidget* parent = nullptr, const QString& selection = "");
|
||||
explicit ExportSqlDialog(DBBrowserDB* db, QWidget* parent = nullptr, const QString& selection = QString());
|
||||
~ExportSqlDialog() override;
|
||||
|
||||
private slots:
|
||||
|
||||
@@ -30,7 +30,6 @@ ExtendedScintilla::ExtendedScintilla(QWidget* parent) :
|
||||
// Enable UTF8
|
||||
setUtf8(true);
|
||||
|
||||
|
||||
// Enable brace matching
|
||||
setBraceMatching(QsciScintilla::SloppyBraceMatch);
|
||||
|
||||
@@ -57,13 +56,13 @@ ExtendedScintilla::ExtendedScintilla(QWidget* parent) :
|
||||
setWrapVisualFlags(QsciScintilla::WrapFlagByBorder);
|
||||
|
||||
// Connect signals
|
||||
connect(this, SIGNAL(linesChanged()), this, SLOT(updateLineNumberAreaWidth()));
|
||||
connect(this, &ExtendedScintilla::linesChanged, this, &ExtendedScintilla::updateLineNumberAreaWidth);
|
||||
|
||||
// The shortcuts are constrained to the Widget context so they do 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()));
|
||||
connect(shortcutFindReplace, &QShortcut::activated, this, &ExtendedScintilla::openFindReplaceDialog);
|
||||
shortcutFind = new QShortcut(QKeySequence(tr("Ctrl+F")), this, nullptr, nullptr, Qt::WidgetShortcut);
|
||||
connect(shortcutFind, SIGNAL(activated()), this, SLOT(openFindDialog()));
|
||||
connect(shortcutFind, &QShortcut::activated, this, &ExtendedScintilla::openFindDialog);
|
||||
|
||||
#ifdef Q_OS_MACX
|
||||
// Alt+Backspace on Mac is expected to delete one word to the left,
|
||||
@@ -80,11 +79,7 @@ ExtendedScintilla::ExtendedScintilla(QWidget* parent) :
|
||||
|
||||
// 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()
|
||||
{
|
||||
connect(this, &ExtendedScintilla::customContextMenuRequested, this, &ExtendedScintilla::showContextMenu);
|
||||
}
|
||||
|
||||
void ExtendedScintilla::updateLineNumberAreaWidth()
|
||||
|
||||
@@ -16,7 +16,6 @@ class ExtendedScintilla : public QsciScintilla
|
||||
|
||||
public:
|
||||
explicit ExtendedScintilla(QWidget *parent = nullptr);
|
||||
~ExtendedScintilla() override;
|
||||
|
||||
bool findText(QString text, bool regexp, bool caseSensitive, bool words, bool wrap, bool forward);
|
||||
void setEnabledFindDialog(bool value);
|
||||
|
||||
@@ -144,7 +144,7 @@ QWidget* ExtendedTableWidgetEditorDelegate::createEditor(QWidget* parent, const
|
||||
column = fk.columns().at(0);
|
||||
|
||||
sqlb::TablePtr currentTable = m->db().getObjectByName<sqlb::Table>(m->currentTableName());
|
||||
QString query = QString("SELECT %1 FROM %2").arg(QString::fromStdString(sqlb::escapeIdentifier(column))).arg(QString::fromStdString(foreignTable.toString()));
|
||||
QString query = QString("SELECT %1 FROM %2").arg(QString::fromStdString(sqlb::escapeIdentifier(column)), QString::fromStdString(foreignTable.toString()));
|
||||
|
||||
// if the current column of the current table does NOT have not-null constraint,
|
||||
// the NULL is united to the query to get the possible values in the combo-box.
|
||||
@@ -520,9 +520,15 @@ void ExtendedTableWidget::copyMimeData(const QModelIndexList& fromIndices, QMime
|
||||
const Qt::Alignment align(index.data(Qt::TextAlignmentRole).toInt());
|
||||
const QString textAlign(CondFormat::alignmentTexts().at(CondFormat::fromCombinedAlignment(align)).toLower());
|
||||
const QString style = QString("font-family: '%1'; font-size: %2pt; font-style: %3; font-weight: %4;%5 "
|
||||
"background-color: %6; color: %7; text-align: %8").
|
||||
arg(font.family().toHtmlEscaped()).arg(font.pointSize()).arg(fontStyle).arg(fontWeigth).arg(fontDecoration).
|
||||
arg(bgColor.name()).arg(fgColor.name()).arg(textAlign);
|
||||
"background-color: %6; color: %7; text-align: %8").arg(
|
||||
font.family().toHtmlEscaped(),
|
||||
QString::number(font.pointSize()),
|
||||
fontStyle,
|
||||
fontWeigth,
|
||||
fontDecoration,
|
||||
bgColor.name(),
|
||||
fgColor.name(),
|
||||
textAlign);
|
||||
|
||||
// Separators. For first cell, only opening table row tags must be added for the HTML and nothing for the text version.
|
||||
if (indices.first() == index) {
|
||||
@@ -568,7 +574,7 @@ void ExtendedTableWidget::copyMimeData(const QModelIndexList& fromIndices, QMime
|
||||
htmlResult.append(QString(text).toHtmlEscaped());
|
||||
|
||||
result.append(text);
|
||||
sqlResult.append("'" + text.replace("'", "''") + "'");
|
||||
sqlResult.append(sqlb::escapeString(text));
|
||||
} else
|
||||
// Table cell data: binary. Save as BLOB literal in SQL
|
||||
sqlResult.append( "X'" + bArrdata.toByteArray().toHex() + "'" );
|
||||
@@ -891,7 +897,7 @@ void ExtendedTableWidget::cellClicked(const QModelIndex& index)
|
||||
|
||||
if(fk.isSet())
|
||||
emit foreignKeyClicked(sqlb::ObjectIdentifier(m->currentTableName().schema(), fk.table()),
|
||||
fk.columns().size() ? QString::fromStdString(fk.columns().at(0)) : "",
|
||||
fk.columns().size() ? fk.columns().at(0) : "",
|
||||
m->data(index, Qt::EditRole).toByteArray());
|
||||
}
|
||||
}
|
||||
@@ -999,20 +1005,18 @@ void ExtendedTableWidget::openPrintDialog()
|
||||
// the table with headers. We can then print it using an HTML text document.
|
||||
copyMimeData(indices, mimeData, true, false);
|
||||
|
||||
QTextDocument *document = new QTextDocument();
|
||||
document->setHtml(mimeData->html());
|
||||
|
||||
QPrinter printer;
|
||||
QPrintPreviewDialog *dialog = new QPrintPreviewDialog(&printer);
|
||||
|
||||
connect(dialog, &QPrintPreviewDialog::paintRequested, [&](QPrinter *previewPrinter) {
|
||||
document->print(previewPrinter);
|
||||
connect(dialog, &QPrintPreviewDialog::paintRequested, [mimeData](QPrinter *previewPrinter) {
|
||||
QTextDocument document;
|
||||
document.setHtml(mimeData->html());
|
||||
document.print(previewPrinter);
|
||||
});
|
||||
|
||||
dialog->exec();
|
||||
|
||||
delete dialog;
|
||||
delete document;
|
||||
delete mimeData;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ public slots:
|
||||
void openPrintDialog();
|
||||
|
||||
signals:
|
||||
void foreignKeyClicked(const sqlb::ObjectIdentifier& table, const QString& column, const QByteArray& value);
|
||||
void foreignKeyClicked(const sqlb::ObjectIdentifier& table, const std::string& column, const QByteArray& value);
|
||||
void switchTable(bool next); // 'next' parameter is set to true if next table should be selected and to false if previous table should be selected
|
||||
void openFileFromDropEvent(QString);
|
||||
void selectedRowsToBeDeleted();
|
||||
@@ -81,7 +81,7 @@ private:
|
||||
void copy(const bool withHeaders, const bool inSQL);
|
||||
void paste();
|
||||
|
||||
void useAsFilter(const QString& filterOperator, bool binary = false, const QString& operatorSuffix = "");
|
||||
void useAsFilter(const QString& filterOperator, bool binary = false, const QString& operatorSuffix = QString());
|
||||
void duplicateUpperCell();
|
||||
|
||||
static std::vector<std::vector<QByteArray>> m_buffer;
|
||||
|
||||
@@ -53,7 +53,7 @@ QString FileDialog::getFileDialogPath(const FileDialogTypes dialogType)
|
||||
case 1: // Always use this locations
|
||||
return Settings::getValue("db", "defaultlocation").toString();
|
||||
default:
|
||||
return "";
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -92,12 +92,12 @@ void FileExtensionManager::downItem()
|
||||
ui->tableExtensions->selectRow(selectedRow+1);
|
||||
}
|
||||
|
||||
QStringList FileExtensionManager::getDBFileExtensions()
|
||||
QStringList FileExtensionManager::getDBFileExtensions() const
|
||||
{
|
||||
QStringList result;
|
||||
for (int i = 0; i < ui->tableExtensions->rowCount(); ++i)
|
||||
{
|
||||
result.append(QString("%1 (%2)").arg(ui->tableExtensions->item(i, 0)->text()).arg(ui->tableExtensions->item(i, 1)->text()));
|
||||
result.append(QString("%1 (%2)").arg(ui->tableExtensions->item(i, 0)->text(), ui->tableExtensions->item(i, 1)->text()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ public:
|
||||
explicit FileExtensionManager(QStringList init, QWidget *parent = nullptr);
|
||||
~FileExtensionManager() override;
|
||||
|
||||
QStringList getDBFileExtensions();
|
||||
QStringList getDBFileExtensions() const;
|
||||
|
||||
private:
|
||||
Ui::FileExtensionManager *ui;
|
||||
|
||||
@@ -19,8 +19,8 @@ FilterLineEdit::FilterLineEdit(QWidget* parent, std::vector<FilterLineEdit*>* fi
|
||||
// delayedSignalTimerTriggered() method which then stops the timer and emits the delayed signal.
|
||||
delaySignalTimer = new QTimer(this);
|
||||
delaySignalTimer->setInterval(Settings::getValue("databrowser", "filter_delay").toInt()); // This is the milliseconds of not-typing we want to wait before triggering
|
||||
connect(this, SIGNAL(textChanged(QString)), delaySignalTimer, SLOT(start()));
|
||||
connect(delaySignalTimer, SIGNAL(timeout()), this, SLOT(delayedSignalTimerTriggered()));
|
||||
connect(this, &FilterLineEdit::textChanged, delaySignalTimer, static_cast<void (QTimer::*)()>(&QTimer::start));
|
||||
connect(delaySignalTimer, &QTimer::timeout, this, &FilterLineEdit::delayedSignalTimerTriggered);
|
||||
|
||||
setWhatsThis(tr("These input fields allow you to perform quick filters in the currently selected table.\n"
|
||||
"By default, the rows containing the input text are filtered out.\n"
|
||||
@@ -37,11 +37,11 @@ FilterLineEdit::FilterLineEdit(QWidget* parent, std::vector<FilterLineEdit*>* fi
|
||||
|
||||
// Immediately emit the delayed filter value changed signal if the user presses the enter or the return key or
|
||||
// the line edit widget loses focus
|
||||
connect(this, SIGNAL(editingFinished()), this, SLOT(delayedSignalTimerTriggered()));
|
||||
connect(this, &FilterLineEdit::editingFinished, this, &FilterLineEdit::delayedSignalTimerTriggered);
|
||||
|
||||
// Prepare for adding the What's This information and filter helper actions to the context menu
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showContextMenu(const QPoint &)));
|
||||
connect(this, &FilterLineEdit::customContextMenuRequested, this, &FilterLineEdit::showContextMenu);
|
||||
}
|
||||
|
||||
void FilterLineEdit::delayedSignalTimerTriggered()
|
||||
|
||||
@@ -31,7 +31,7 @@ signals:
|
||||
|
||||
protected:
|
||||
void keyReleaseEvent(QKeyEvent* event) override;
|
||||
void setFilterHelper(const QString& filterOperator, const QString& operatorSuffix = "");
|
||||
void setFilterHelper(const QString& filterOperator, const QString& operatorSuffix = QString());
|
||||
|
||||
private:
|
||||
std::vector<FilterLineEdit*>* filterList;
|
||||
|
||||
@@ -12,7 +12,6 @@ FindReplaceDialog::FindReplaceDialog(QWidget* parent)
|
||||
{
|
||||
// Create UI
|
||||
ui->setupUi(this);
|
||||
|
||||
}
|
||||
|
||||
FindReplaceDialog::~FindReplaceDialog()
|
||||
|
||||
@@ -61,10 +61,10 @@ public:
|
||||
if (!id.isEmpty())
|
||||
id = QString("(%1)").arg(sqlb::escapeIdentifier(id));
|
||||
|
||||
return QString("%1%2 %3")
|
||||
.arg(table)
|
||||
.arg(id)
|
||||
.arg(clauses)
|
||||
return QString("%1%2 %3").arg(
|
||||
table,
|
||||
id,
|
||||
clauses)
|
||||
.trimmed();
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include <QElapsedTimer>
|
||||
#endif
|
||||
|
||||
ImportCsvDialog::ImportCsvDialog(const QStringList &filenames, DBBrowserDB* db, QWidget* parent)
|
||||
ImportCsvDialog::ImportCsvDialog(const std::vector<QString>& filenames, DBBrowserDB* db, QWidget* parent)
|
||||
: QDialog(parent),
|
||||
ui(new Ui::ImportCsvDialog),
|
||||
csvFilenames(filenames),
|
||||
@@ -39,7 +39,7 @@ ImportCsvDialog::ImportCsvDialog(const QStringList &filenames, DBBrowserDB* db,
|
||||
|
||||
// Get the actual file name out of the provided path and use it as the default table name for import
|
||||
// For importing several files at once, the fields have to be the same so we can safely use the first
|
||||
QFileInfo file(filenames.first());
|
||||
QFileInfo file(filenames.front());
|
||||
ui->editName->setText(file.baseName());
|
||||
|
||||
// Create a list of all available encodings and create an auto completion list from them
|
||||
@@ -70,21 +70,21 @@ ImportCsvDialog::ImportCsvDialog(const QStringList &filenames, DBBrowserDB* db,
|
||||
ui->comboEncoding->blockSignals(false);
|
||||
|
||||
// Prepare and show interface depending on how many files are selected
|
||||
if (csvFilenames.length() > 1)
|
||||
if (csvFilenames.size() > 1)
|
||||
{
|
||||
ui->separateTables->setVisible(true);
|
||||
ui->checkBoxSeparateTables->setVisible(true);
|
||||
ui->filePickerBlock->setVisible(true);
|
||||
selectFiles();
|
||||
}
|
||||
else if (csvFilenames.length() == 1)
|
||||
else if (csvFilenames.size() == 1)
|
||||
{
|
||||
ui->separateTables->setVisible(false);
|
||||
ui->checkBoxSeparateTables->setVisible(false);
|
||||
ui->filePickerBlock->setVisible(false);
|
||||
}
|
||||
|
||||
selectedFile = csvFilenames.first();
|
||||
selectedFile = csvFilenames.front();
|
||||
updatePreview();
|
||||
checkInput();
|
||||
}
|
||||
@@ -99,7 +99,7 @@ void rollback(
|
||||
ImportCsvDialog* dialog,
|
||||
DBBrowserDB* pdb,
|
||||
DBBrowserDB::db_pointer_type* db_ptr,
|
||||
const QString& savepointName,
|
||||
const std::string& savepointName,
|
||||
size_t nRecord,
|
||||
const QString& message)
|
||||
{
|
||||
@@ -124,24 +124,19 @@ class CSVImportProgress : public CSVProgress
|
||||
{
|
||||
public:
|
||||
explicit CSVImportProgress(int64_t filesize)
|
||||
: totalFileSize(filesize)
|
||||
: m_pProgressDlg(new QProgressDialog(
|
||||
QObject::tr("Importing CSV file..."),
|
||||
QObject::tr("Cancel"),
|
||||
0,
|
||||
10000)),
|
||||
totalFileSize(filesize)
|
||||
{
|
||||
m_pProgressDlg = new QProgressDialog(
|
||||
QObject::tr("Importing CSV file..."),
|
||||
QObject::tr("Cancel"),
|
||||
0,
|
||||
10000);
|
||||
m_pProgressDlg->setWindowModality(Qt::ApplicationModal);
|
||||
}
|
||||
|
||||
CSVImportProgress(const CSVImportProgress&) = delete;
|
||||
bool operator=(const CSVImportProgress&) = delete;
|
||||
|
||||
~CSVImportProgress() override
|
||||
{
|
||||
delete m_pProgressDlg;
|
||||
}
|
||||
|
||||
void start() override
|
||||
{
|
||||
m_pProgressDlg->show();
|
||||
@@ -161,7 +156,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
QProgressDialog* m_pProgressDlg;
|
||||
std::unique_ptr<QProgressDialog> m_pProgressDlg;
|
||||
|
||||
int64_t totalFileSize;
|
||||
};
|
||||
@@ -212,7 +207,7 @@ void ImportCsvDialog::accept()
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
importCsv(csvFilenames.first());
|
||||
importCsv(csvFilenames.front());
|
||||
}
|
||||
|
||||
QApplication::restoreOverrideCursor(); // restore original cursor
|
||||
@@ -305,7 +300,7 @@ void ImportCsvDialog::checkInput()
|
||||
|
||||
void ImportCsvDialog::selectFiles()
|
||||
{
|
||||
for (auto fileName : csvFilenames) {
|
||||
for (const auto& fileName : csvFilenames) {
|
||||
auto fInfo = QFileInfo(fileName);
|
||||
auto item = new QListWidgetItem();
|
||||
item->setText(fileName);
|
||||
@@ -368,7 +363,7 @@ void ImportCsvDialog::matchSimilar()
|
||||
checkInput();
|
||||
}
|
||||
|
||||
CSVParser::ParserResult ImportCsvDialog::parseCSV(const QString &fileName, std::function<bool(size_t, CSVRow)> rowFunction, size_t count)
|
||||
CSVParser::ParserResult ImportCsvDialog::parseCSV(const QString &fileName, std::function<bool(size_t, CSVRow)> rowFunction, size_t count) const
|
||||
{
|
||||
// Parse all csv data
|
||||
QFile file(fileName);
|
||||
@@ -386,7 +381,7 @@ CSVParser::ParserResult ImportCsvDialog::parseCSV(const QString &fileName, std::
|
||||
return csv.parse(rowFunction, tstream, count);
|
||||
}
|
||||
|
||||
sqlb::FieldVector ImportCsvDialog::generateFieldList(const QString& filename)
|
||||
sqlb::FieldVector ImportCsvDialog::generateFieldList(const QString& filename) const
|
||||
{
|
||||
sqlb::FieldVector fieldList; // List of fields in the file
|
||||
|
||||
@@ -395,28 +390,28 @@ sqlb::FieldVector ImportCsvDialog::generateFieldList(const QString& filename)
|
||||
// Has this row more columns than the previous one? Then add more fields to the field list as necessary.
|
||||
for(size_t i=fieldList.size();i<rowData.num_fields;i++)
|
||||
{
|
||||
QString fieldname;
|
||||
std::string fieldname;
|
||||
|
||||
// If the user wants to use the first row as table header and if this is the first row, extract a field name
|
||||
if(rowNum == 0 && ui->checkboxHeader->isChecked())
|
||||
{
|
||||
// Take field name from CSV and remove invalid characters
|
||||
fieldname = QString::fromUtf8(rowData.fields[i].data, static_cast<int>(rowData.fields[i].data_length));
|
||||
fieldname.replace("`", "");
|
||||
fieldname.replace(" ", "");
|
||||
fieldname.replace('"', "");
|
||||
fieldname.replace("'","");
|
||||
fieldname.replace(",","");
|
||||
fieldname.replace(";","");
|
||||
fieldname = std::string(rowData.fields[i].data, rowData.fields[i].data_length);
|
||||
fieldname.erase(std::remove(fieldname.begin(), fieldname.end(), '`'));
|
||||
fieldname.erase(std::remove(fieldname.begin(), fieldname.end(), ' '));
|
||||
fieldname.erase(std::remove(fieldname.begin(), fieldname.end(), '"'));
|
||||
fieldname.erase(std::remove(fieldname.begin(), fieldname.end(), '\''));
|
||||
fieldname.erase(std::remove(fieldname.begin(), fieldname.end(), ','));
|
||||
fieldname.erase(std::remove(fieldname.begin(), fieldname.end(), ';'));
|
||||
}
|
||||
|
||||
// If we don't have a field name by now, generate one
|
||||
if(fieldname.isEmpty())
|
||||
fieldname = QString("field%1").arg(i+1);
|
||||
if(fieldname.empty())
|
||||
fieldname = "field" + std::to_string(i + 1);
|
||||
|
||||
// Add field to the column list. For now we set the data type to nothing but this might be overwritten later in the automatic
|
||||
// type detection code.
|
||||
fieldList.emplace_back(fieldname.toStdString(), "");
|
||||
fieldList.emplace_back(fieldname, "");
|
||||
}
|
||||
|
||||
// Try to find out a data type for each column. Skip the header row if there is one.
|
||||
@@ -440,9 +435,9 @@ sqlb::FieldVector ImportCsvDialog::generateFieldList(const QString& filename)
|
||||
std::string new_type = "TEXT";
|
||||
if(old_type == "INTEGER" && !convert_to_int && convert_to_float) // So far it's integer, but now it's only convertible to float
|
||||
new_type = "REAL";
|
||||
else if(old_type == "" && convert_to_int) // No type yet, but this bit is convertible to integer
|
||||
else if(old_type.empty() && convert_to_int) // No type yet, but this bit is convertible to integer
|
||||
new_type = "INTEGER";
|
||||
else if(old_type == "" && convert_to_float) // No type yet and only convertible to float (less 'difficult' than integer)
|
||||
else if(old_type.empty() && convert_to_float) // No type yet and only convertible to float (less 'difficult' than integer)
|
||||
new_type = "REAL";
|
||||
else if(old_type == "REAL" && convert_to_float) // It was float so far and still is
|
||||
new_type = "INTEGER";
|
||||
@@ -534,7 +529,7 @@ bool ImportCsvDialog::importCsv(const QString& fileName, const QString& name)
|
||||
|
||||
// Create a savepoint, so we can rollback in case of any errors during importing
|
||||
// db needs to be saved or an error will occur
|
||||
QString restorepointName = pdb->generateSavepointName("csvimport");
|
||||
std::string restorepointName = pdb->generateSavepointName("csvimport");
|
||||
if(!pdb->setSavepoint(restorepointName))
|
||||
{
|
||||
rollback(this, pdb, nullptr, restorepointName, 0, tr("Creating restore point failed: %1").arg(pdb->lastError()));
|
||||
@@ -605,14 +600,14 @@ bool ImportCsvDialog::importCsv(const QString& fileName, const QString& name)
|
||||
}
|
||||
|
||||
// Prepare the INSERT statement. The prepared statement can then be reused for each row to insert
|
||||
QString sQuery = QString("INSERT %1 INTO %2 VALUES(").arg(currentOnConflictStrategy()).arg(sqlb::escapeIdentifier(tableName));
|
||||
std::string sQuery = "INSERT " + currentOnConflictStrategy() + " INTO " + sqlb::escapeIdentifier(tableName.toStdString()) + " VALUES(";
|
||||
for(size_t i=1;i<=fieldList.size();i++)
|
||||
sQuery.append(QString("?%1,").arg(i));
|
||||
sQuery.chop(1); // Remove last comma
|
||||
sQuery += "?" + std::to_string(i) + ",";
|
||||
sQuery.pop_back(); // Remove last comma
|
||||
sQuery.append(")");
|
||||
sqlite3_stmt* stmt;
|
||||
auto pDb = pdb->get(tr("importing CSV"));
|
||||
sqlite3_prepare_v2(pDb.get(), sQuery.toUtf8(), sQuery.toUtf8().length(), &stmt, nullptr);
|
||||
sqlite3_prepare_v2(pDb.get(), sQuery.c_str(), static_cast<int>(sQuery.size()), &stmt, nullptr);
|
||||
|
||||
// Parse entire file
|
||||
size_t lastRowNum = 0;
|
||||
@@ -784,7 +779,7 @@ QString ImportCsvDialog::currentEncoding() const
|
||||
return ui->comboEncoding->currentText();
|
||||
}
|
||||
|
||||
QString ImportCsvDialog::currentOnConflictStrategy() const
|
||||
std::string ImportCsvDialog::currentOnConflictStrategy() const
|
||||
{
|
||||
switch(ui->comboOnConflictStrategy->currentIndex())
|
||||
{
|
||||
@@ -793,7 +788,7 @@ QString ImportCsvDialog::currentOnConflictStrategy() const
|
||||
case 2:
|
||||
return "OR REPLACE";
|
||||
default:
|
||||
return QString();
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ class ImportCsvDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ImportCsvDialog(const QStringList& filenames, DBBrowserDB* db, QWidget* parent = nullptr);
|
||||
explicit ImportCsvDialog(const std::vector<QString>& filenames, DBBrowserDB* db, QWidget* parent = nullptr);
|
||||
~ImportCsvDialog() override;
|
||||
|
||||
private slots:
|
||||
@@ -34,14 +34,14 @@ private slots:
|
||||
|
||||
private:
|
||||
Ui::ImportCsvDialog* ui;
|
||||
QStringList csvFilenames;
|
||||
std::vector<QString> csvFilenames;
|
||||
QString selectedFile;
|
||||
DBBrowserDB* pdb;
|
||||
QCompleter* encodingCompleter;
|
||||
QStringList dontAskForExistingTableAgain;
|
||||
|
||||
CSVParser::ParserResult parseCSV(const QString& fileName, std::function<bool(size_t, CSVRow)> rowFunction, size_t count = 0);
|
||||
sqlb::FieldVector generateFieldList(const QString& filename);
|
||||
CSVParser::ParserResult parseCSV(const QString& fileName, std::function<bool(size_t, CSVRow)> rowFunction, size_t count = 0) const;
|
||||
sqlb::FieldVector generateFieldList(const QString& filename) const;
|
||||
|
||||
bool importCsv(const QString& f, const QString& n = QString());
|
||||
|
||||
@@ -54,7 +54,7 @@ private:
|
||||
void setEncoding(const QString& sEnc);
|
||||
QString currentEncoding() const;
|
||||
|
||||
QString currentOnConflictStrategy() const;
|
||||
std::string currentOnConflictStrategy() const;
|
||||
|
||||
char32_t toUtf8(const QString& s) const;
|
||||
};
|
||||
|
||||
@@ -586,15 +586,19 @@ void MainWindow::populateStructure(const QString& old_table)
|
||||
for(const auto& it : db.schemata)
|
||||
{
|
||||
SqlUiLexer::TablesAndColumnsMap tablesToColumnsMap;
|
||||
objectMap tab = db.getBrowsableObjects(it.first);
|
||||
for(const auto& jt : tab)
|
||||
{
|
||||
QString objectname = QString::fromStdString(jt.second->name());
|
||||
|
||||
sqlb::FieldInfoList fi = jt.second->fieldInformation();
|
||||
for(const sqlb::FieldInfo& f : fi)
|
||||
tablesToColumnsMap[objectname].push_back(QString::fromStdString(f.name));
|
||||
for(const auto& jt : it.second)
|
||||
{
|
||||
if(jt.second->type() == sqlb::Object::Types::Table || jt.second->type() == sqlb::Object::Types::View)
|
||||
{
|
||||
QString objectname = QString::fromStdString(jt.second->name());
|
||||
|
||||
sqlb::FieldInfoList fi = jt.second->fieldInformation();
|
||||
for(const sqlb::FieldInfo& f : fi)
|
||||
tablesToColumnsMap[objectname].push_back(QString::fromStdString(f.name));
|
||||
}
|
||||
}
|
||||
|
||||
qualifiedTablesMap[QString::fromStdString(it.first)] = tablesToColumnsMap;
|
||||
}
|
||||
SqlTextEdit::sqlLexer->setTableNames(qualifiedTablesMap);
|
||||
@@ -801,8 +805,8 @@ void MainWindow::deleteObject()
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes)
|
||||
{
|
||||
// Delete the table
|
||||
QString statement = QString("DROP %1 %2;").arg(type.toUpper()).arg(QString::fromStdString(name.toString()));
|
||||
if(!db.executeSQL(statement))
|
||||
QString statement = QString("DROP %1 %2;").arg(type.toUpper(), QString::fromStdString(name.toString()));
|
||||
if(!db.executeSQL(statement.toStdString()))
|
||||
{
|
||||
if (type == "table")
|
||||
message = tr("Error: could not delete the table.");
|
||||
@@ -856,7 +860,7 @@ void MainWindow::editObject()
|
||||
|
||||
// If foreign_keys were enabled, we must commit or rollback the transaction so the foreign_keys pragma can be restored.
|
||||
if (foreign_keys == "1") {
|
||||
if (!db.querySingleValueFromDb(QString("PRAGMA %1.foreign_key_check").arg(QString::fromStdString(sqlb::escapeIdentifier(name.schema())))).isNull()) {
|
||||
if (!db.querySingleValueFromDb("PRAGMA " + sqlb::escapeIdentifier(name.schema()) + ".foreign_key_check").isNull()) {
|
||||
// Raise warning for accepted modification. When rejected, warn user also since we know now that the table has problems,
|
||||
// but it wasn't our fault.
|
||||
if (ok)
|
||||
@@ -1221,13 +1225,13 @@ void MainWindow::importTableFromCSV()
|
||||
tr("Choose text files"),
|
||||
file_filter.join(";;"));
|
||||
|
||||
QStringList validFiles;
|
||||
std::vector<QString> validFiles;
|
||||
for(const auto& file : wFiles) {
|
||||
if (QFile::exists(file))
|
||||
validFiles.append(file);
|
||||
validFiles.push_back(file);
|
||||
}
|
||||
|
||||
if (!validFiles.isEmpty())
|
||||
if (!validFiles.empty())
|
||||
{
|
||||
ImportCsvDialog dialog(validFiles, &db, this);
|
||||
if (dialog.exec())
|
||||
@@ -1381,7 +1385,7 @@ void MainWindow::importDatabaseFromSQL()
|
||||
QApplication::restoreOverrideCursor();
|
||||
if(!ok)
|
||||
QMessageBox::warning(this, QApplication::applicationName(), tr("Error importing data: %1").arg(db.lastError()));
|
||||
else if(db.getPragma("foreign_keys") == "1" && !db.querySingleValueFromDb(QString("PRAGMA foreign_key_check")).isNull())
|
||||
else if(db.getPragma("foreign_keys") == "1" && !db.querySingleValueFromDb("PRAGMA foreign_key_check").isNull())
|
||||
QMessageBox::warning(this, QApplication::applicationName(), tr("Import completed. Some foreign key constraints are violated. Please fix them before saving."));
|
||||
else
|
||||
QMessageBox::information(this, QApplication::applicationName(), tr("Import completed."));
|
||||
@@ -1539,7 +1543,7 @@ void MainWindow::updateRecentFileActions()
|
||||
read_only = true;
|
||||
}
|
||||
|
||||
QString text = tr("&%1 %2%3").arg(i + 1).arg(QDir::toNativeSeparators(file)).arg(read_only ? tr(" (read only)") : "");
|
||||
QString text = tr("&%1 %2%3").arg(i + 1).arg(QDir::toNativeSeparators(file), read_only ? tr(" (read only)") : "");
|
||||
recentFileActs[i]->setText(text);
|
||||
recentFileActs[i]->setData(files[i]);
|
||||
recentFileActs[i]->setVisible(true);
|
||||
@@ -1638,10 +1642,10 @@ void MainWindow::dropEvent(QDropEvent *event)
|
||||
fileAttach(fileName);
|
||||
} else if (action == import) {
|
||||
|
||||
QStringList validFiles;
|
||||
std::vector<QString> validFiles;
|
||||
for(const auto& url : urls) {
|
||||
if (QFile::exists(url.toLocalFile()))
|
||||
validFiles.append(url.toLocalFile());
|
||||
validFiles.push_back(url.toLocalFile());
|
||||
}
|
||||
ImportCsvDialog dialog(validFiles, &db, this);
|
||||
if (dialog.exec())
|
||||
@@ -2144,13 +2148,13 @@ void MainWindow::checkNewVersion(const QString& versionstring, const QString& ur
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionWiki_triggered()
|
||||
void MainWindow::on_actionWiki_triggered() const
|
||||
{
|
||||
QDesktopServices::openUrl(QUrl("https://github.com/sqlitebrowser/sqlitebrowser/wiki"));
|
||||
}
|
||||
|
||||
// 'Help | Bug Report...' link will set an appropiate body, add the system information and set the label 'bug' automatically to the issue
|
||||
void MainWindow::on_actionBug_report_triggered()
|
||||
void MainWindow::on_actionBug_report_triggered() const
|
||||
{
|
||||
const QString version = Application::versionString();
|
||||
const QString os = QSysInfo::prettyProductName();
|
||||
@@ -2189,7 +2193,7 @@ void MainWindow::on_actionBug_report_triggered()
|
||||
}
|
||||
|
||||
// 'Help | Feature Request...' link will set an appropiate body and add the label 'enhancement' automatically to the issue
|
||||
void MainWindow::on_actionFeature_Request_triggered()
|
||||
void MainWindow::on_actionFeature_Request_triggered() const
|
||||
{
|
||||
QUrlQuery query;
|
||||
|
||||
@@ -2203,17 +2207,17 @@ void MainWindow::on_actionFeature_Request_triggered()
|
||||
QDesktopServices::openUrl(url);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionSqlCipherFaq_triggered()
|
||||
void MainWindow::on_actionSqlCipherFaq_triggered() const
|
||||
{
|
||||
QDesktopServices::openUrl(QUrl("https://discuss.zetetic.net/c/sqlcipher/sqlcipher-faq"));
|
||||
}
|
||||
|
||||
void MainWindow::on_actionWebsite_triggered()
|
||||
void MainWindow::on_actionWebsite_triggered() const
|
||||
{
|
||||
QDesktopServices::openUrl(QUrl("https://sqlitebrowser.org"));
|
||||
}
|
||||
|
||||
void MainWindow::on_actionDonatePatreon_triggered()
|
||||
void MainWindow::on_actionDonatePatreon_triggered() const
|
||||
{
|
||||
QDesktopServices::openUrl(QUrl("https://www.patreon.com/bePatron?u=11578749"));
|
||||
}
|
||||
@@ -2732,25 +2736,18 @@ void MainWindow::saveProject(const QString& currentFilename)
|
||||
|
||||
// Attached databases
|
||||
xml.writeStartElement("attached");
|
||||
QString sql("PRAGMA database_list;");
|
||||
db.logSQL(sql, kLogMsg_App);
|
||||
sqlite3_stmt* db_vm;
|
||||
if(sqlite3_prepare_v2(db.get("project").get(), sql.toUtf8(), sql.toUtf8().length(), &db_vm, nullptr) == SQLITE_OK)
|
||||
{
|
||||
while(sqlite3_step(db_vm) == SQLITE_ROW)
|
||||
db.executeSQL("PRAGMA database_list;", false, true, [&xml](int, std::vector<QByteArray> values, std::vector<QByteArray>) -> bool {
|
||||
auto schema = values.at(1);
|
||||
if(schema != "main" && schema != "temp")
|
||||
{
|
||||
QString schema(QString::fromUtf8(reinterpret_cast<const char*>(sqlite3_column_text(db_vm, 1))));
|
||||
if(schema != "main" && schema != "temp")
|
||||
{
|
||||
QString path(QString::fromUtf8(reinterpret_cast<const char*>(sqlite3_column_text(db_vm, 2))));
|
||||
xml.writeStartElement("db");
|
||||
xml.writeAttribute("schema", schema);
|
||||
xml.writeAttribute("path", path);
|
||||
xml.writeEndElement();
|
||||
}
|
||||
auto path = values.at(2);
|
||||
xml.writeStartElement("db");
|
||||
xml.writeAttribute("schema", schema);
|
||||
xml.writeAttribute("path", path);
|
||||
xml.writeEndElement();
|
||||
}
|
||||
sqlite3_finalize(db_vm);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
xml.writeEndElement();
|
||||
|
||||
// Window settings
|
||||
@@ -2887,17 +2884,17 @@ void MainWindow::editEncryption()
|
||||
// Attach a new database using the new settings
|
||||
qApp->processEvents();
|
||||
if(ok)
|
||||
ok = db.executeSQL(QString("ATTACH DATABASE '%1' AS sqlitebrowser_edit_encryption KEY %2;").arg(db.currentFile() + ".enctemp").arg(cipherSettings.getPassword()),
|
||||
ok = db.executeSQL("ATTACH DATABASE '" + db.currentFile().toStdString() + ".enctemp' AS sqlitebrowser_edit_encryption KEY " + cipherSettings.getPassword() + ";",
|
||||
false, false);
|
||||
qApp->processEvents();
|
||||
if(ok)
|
||||
ok = db.executeSQL(QString("PRAGMA sqlitebrowser_edit_encryption.cipher_page_size = %1").arg(cipherSettings.getPageSize()), false, false);
|
||||
ok = db.executeSQL("PRAGMA sqlitebrowser_edit_encryption.cipher_page_size = " + std::to_string(cipherSettings.getPageSize()), false, false);
|
||||
if(ok)
|
||||
ok = db.executeSQL(QString("PRAGMA sqlitebrowser_edit_encryption.cipher_hmac_algorithm = %1").arg(cipherSettings.getHmacAlgorithm()), false, false);
|
||||
ok = db.executeSQL("PRAGMA sqlitebrowser_edit_encryption.cipher_hmac_algorithm = " + cipherSettings.getHmacAlgorithm(), false, false);
|
||||
if(ok)
|
||||
ok = db.executeSQL(QString("PRAGMA sqlitebrowser_edit_encryption.cipher_kdf_algorithm = %1").arg(cipherSettings.getKdfAlgorithm()), false, false);
|
||||
ok = db.executeSQL("PRAGMA sqlitebrowser_edit_encryption.cipher_kdf_algorithm = " + cipherSettings.getKdfAlgorithm(), false, false);
|
||||
if(ok)
|
||||
ok = db.executeSQL(QString("PRAGMA sqlitebrowser_edit_encryption.kdf_iter = %1").arg(cipherSettings.getKdfIterations()), false, false);
|
||||
ok = db.executeSQL("PRAGMA sqlitebrowser_edit_encryption.kdf_iter = " + std::to_string(cipherSettings.getKdfIterations()), false, false);
|
||||
|
||||
// Export the current database to the new one
|
||||
qApp->processEvents();
|
||||
@@ -2907,7 +2904,7 @@ void MainWindow::editEncryption()
|
||||
// Set user version of the new database
|
||||
qApp->processEvents();
|
||||
if (ok)
|
||||
ok = db.executeSQL(QString("PRAGMA sqlitebrowser_edit_encryption.user_version = %1;").arg(db.getPragma("user_version").toInt()), false, false);
|
||||
ok = db.executeSQL("PRAGMA sqlitebrowser_edit_encryption.user_version = " + std::to_string(db.getPragma("user_version").toInt()) + ";", false, false);
|
||||
|
||||
// We need to detach the database before proceeding
|
||||
qApp->processEvents();
|
||||
@@ -3035,7 +3032,7 @@ void MainWindow::openSqlPrintDialog()
|
||||
sqlWidget->getEditor()->openPrintDialog();
|
||||
}
|
||||
|
||||
void MainWindow::saveAsView(QString query)
|
||||
void MainWindow::saveAsView(const std::string& query)
|
||||
{
|
||||
// Let the user select a name for the new view and make sure it doesn't already exist
|
||||
QString name;
|
||||
@@ -3051,7 +3048,7 @@ void MainWindow::saveAsView(QString query)
|
||||
}
|
||||
|
||||
// Create the view
|
||||
if(db.executeSQL(QString("CREATE VIEW %1 AS %2;").arg(sqlb::escapeIdentifier(name)).arg(query)))
|
||||
if(db.executeSQL("CREATE VIEW " + sqlb::escapeIdentifier(name.toStdString()) + " AS " + query + ";"))
|
||||
QMessageBox::information(this, qApp->applicationName(), tr("View successfully created."));
|
||||
else
|
||||
QMessageBox::warning(this, qApp->applicationName(), tr("Error creating view: %1").arg(db.lastError()));
|
||||
@@ -3156,21 +3153,19 @@ void MainWindow::printDbStructure ()
|
||||
}
|
||||
out << "</body></html>";
|
||||
|
||||
QTextDocument *document = new QTextDocument();
|
||||
document->setHtml(strStream);
|
||||
|
||||
QPrinter printer;
|
||||
printer.setDocName(treeView->windowTitle());
|
||||
|
||||
QPrintPreviewDialog *dialog = new QPrintPreviewDialog(&printer);
|
||||
connect(dialog, &QPrintPreviewDialog::paintRequested, [&](QPrinter *previewPrinter) {
|
||||
document->print(previewPrinter);
|
||||
connect(dialog, &QPrintPreviewDialog::paintRequested, [strStream](QPrinter *previewPrinter) {
|
||||
QTextDocument document;
|
||||
document.setHtml(strStream);
|
||||
document.print(previewPrinter);
|
||||
});
|
||||
|
||||
dialog->exec();
|
||||
|
||||
delete dialog;
|
||||
delete document;
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::updateDatabaseBusyStatus(bool busy, const QString& user)
|
||||
@@ -3206,7 +3201,7 @@ void MainWindow::restoreOpenTabs(QString tabs)
|
||||
// Avoid flickering while clearing and adding tabs.
|
||||
ui->mainTab->setUpdatesEnabled(false);
|
||||
ui->mainTab->clear();
|
||||
for (QString objectName : tabList) {
|
||||
for (const auto& objectName : tabList) {
|
||||
for (QWidget* widget : {ui->structure, ui->browser, ui->pragmas, ui->query})
|
||||
if (widget->objectName() == objectName) {
|
||||
ui->mainTab->addTab(widget, widget->accessibleName());
|
||||
@@ -3216,7 +3211,7 @@ void MainWindow::restoreOpenTabs(QString tabs)
|
||||
ui->mainTab->setUpdatesEnabled(true);
|
||||
// Force the update of the View menu toggable entries
|
||||
// (it doesn't seem to be a better way)
|
||||
ui->mainTab->tabCloseRequested(-1);
|
||||
emit ui->mainTab->tabCloseRequested(-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ private:
|
||||
void setCurrentFile(const QString& fileName);
|
||||
void addToRecentFilesMenu(const QString& filename, bool read_only = false);
|
||||
void activateFields(bool enable = true);
|
||||
void saveAsView(QString query);
|
||||
void saveAsView(const std::string& query);
|
||||
void attachPlot(ExtendedTableWidget* tableWidget, SqliteTableModel* model, BrowseDataTableSettings* settings = nullptr, bool keepOrResetSelection = true);
|
||||
|
||||
void toggleTabVisible(QWidget* tabWidget, bool show);
|
||||
@@ -176,12 +176,12 @@ private slots:
|
||||
void saveSqlResultsAsView();
|
||||
void loadExtension();
|
||||
void checkNewVersion(const QString& versionstring, const QString& url);
|
||||
void on_actionWiki_triggered();
|
||||
void on_actionBug_report_triggered();
|
||||
void on_actionFeature_Request_triggered();
|
||||
void on_actionSqlCipherFaq_triggered();
|
||||
void on_actionWebsite_triggered();
|
||||
void on_actionDonatePatreon_triggered();
|
||||
void on_actionWiki_triggered() const;
|
||||
void on_actionBug_report_triggered() const;
|
||||
void on_actionFeature_Request_triggered() const;
|
||||
void on_actionSqlCipherFaq_triggered() const;
|
||||
void on_actionWebsite_triggered() const;
|
||||
void on_actionDonatePatreon_triggered() const;
|
||||
bool loadProject(QString filename = QString(), bool readOnly = false);
|
||||
void saveProject();
|
||||
void saveProjectAs();
|
||||
|
||||
@@ -689,7 +689,7 @@ void PlotDock::on_comboPointShape_currentIndexChanged(int index)
|
||||
}
|
||||
}
|
||||
|
||||
QVariant::Type PlotDock::guessDataType(SqliteTableModel* model, int column)
|
||||
QVariant::Type PlotDock::guessDataType(SqliteTableModel* model, int column) const
|
||||
{
|
||||
QVariant::Type type = QVariant::Invalid;
|
||||
for(int i = 0; i < std::min(10, model->rowCount()) && type != QVariant::String; ++i)
|
||||
@@ -747,9 +747,9 @@ void PlotDock::fetchAllData()
|
||||
void PlotDock::selectionChanged()
|
||||
{
|
||||
|
||||
for (QCPAbstractPlottable* plottable : ui->plotWidget->selectedPlottables()) {
|
||||
for (const QCPAbstractPlottable* plottable : ui->plotWidget->selectedPlottables()) {
|
||||
|
||||
for (QCPDataRange dataRange : plottable->selection().dataRanges()) {
|
||||
for (const QCPDataRange& dataRange : plottable->selection().dataRanges()) {
|
||||
|
||||
int index = dataRange.begin();
|
||||
if (dataRange.length() != 0) {
|
||||
|
||||
@@ -100,7 +100,7 @@ private:
|
||||
* \param column index of the column to check
|
||||
* \return the guessed datatype
|
||||
*/
|
||||
QVariant::Type guessDataType(SqliteTableModel* model, int column);
|
||||
QVariant::Type guessDataType(SqliteTableModel* model, int column) const;
|
||||
void adjustBars();
|
||||
|
||||
private slots:
|
||||
|
||||
@@ -33,8 +33,8 @@ PreferencesDialog::PreferencesDialog(QWidget* parent, Tabs tab)
|
||||
ui->fr_null_bg->installEventFilter(this);
|
||||
ui->fr_null_fg->installEventFilter(this);
|
||||
|
||||
connect(ui->comboDataBrowserFont, SIGNAL(currentIndexChanged(int)), this, SLOT(updatePreviewFont()));
|
||||
connect(ui->spinDataBrowserFontSize, SIGNAL(valueChanged(int)), this, SLOT(updatePreviewFont()));
|
||||
connect(ui->comboDataBrowserFont, static_cast<void (QFontComboBox::*)(int)>(&QFontComboBox::currentIndexChanged), this, &PreferencesDialog::updatePreviewFont);
|
||||
connect(ui->spinDataBrowserFontSize, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &PreferencesDialog::updatePreviewFont);
|
||||
|
||||
#ifndef CHECKNEWVERSION
|
||||
ui->labelUpdates->setVisible(false);
|
||||
@@ -339,7 +339,7 @@ void PreferencesDialog::saveSettings()
|
||||
|
||||
void PreferencesDialog::showColourDialog(QTreeWidgetItem* item, int column)
|
||||
{
|
||||
if(item->text(column).left(1) != "#")
|
||||
if(item->text(column).front() != "#")
|
||||
return;
|
||||
|
||||
QColor colour = QColorDialog::getColor(QColor(item->text(column)), this);
|
||||
@@ -481,33 +481,26 @@ void PreferencesDialog::loadColorSetting(QFrame *frame, const std::string& setti
|
||||
void PreferencesDialog::setColorSetting(QFrame *frame, const QColor &color)
|
||||
{
|
||||
QPalette::ColorRole role;
|
||||
QString style;
|
||||
QLineEdit *line;
|
||||
|
||||
if (frame == ui->fr_bin_bg) {
|
||||
line = ui->txtBlob;
|
||||
role = line->backgroundRole();
|
||||
style = QString("background-color");
|
||||
} else if (frame == ui->fr_bin_fg) {
|
||||
line = ui->txtBlob;
|
||||
role = line->foregroundRole();
|
||||
style = QString("color");
|
||||
} else if (frame == ui->fr_reg_bg) {
|
||||
line = ui->txtRegular;
|
||||
role = line->backgroundRole();
|
||||
style = QString("background-color");
|
||||
} else if (frame == ui->fr_reg_fg) {
|
||||
line = ui->txtRegular;
|
||||
role = line->foregroundRole();
|
||||
style = QString("color");
|
||||
} else if (frame == ui->fr_null_bg) {
|
||||
line = ui->txtNull;
|
||||
role = line->backgroundRole();
|
||||
style = QString("background-color");
|
||||
} else if (frame == ui->fr_null_fg) {
|
||||
line = ui->txtNull;
|
||||
role = line->foregroundRole();
|
||||
style = QString("color");
|
||||
} else
|
||||
return;
|
||||
|
||||
|
||||
@@ -170,7 +170,7 @@ void RemoteDatabase::gotReply(QNetworkReply* reply)
|
||||
if(reply->error() != QNetworkReply::NoError)
|
||||
{
|
||||
QMessageBox::warning(nullptr, qApp->applicationName(),
|
||||
tr("Error when connecting to %1.\n%2").arg(reply->url().toString()).arg(reply->errorString()));
|
||||
tr("Error when connecting to %1.\n%2").arg(reply->url().toString(), reply->errorString()));
|
||||
reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
@@ -321,7 +321,7 @@ void RemoteDatabase::gotError(QNetworkReply* reply, const QList<QSslError>& erro
|
||||
}
|
||||
|
||||
// Build an error message and short it to the user
|
||||
QString message = tr("Error opening remote file at %1.\n%2").arg(reply->url().toString()).arg(errors.at(0).errorString());
|
||||
QString message = tr("Error opening remote file at %1.\n%2").arg(reply->url().toString(), errors.at(0).errorString());
|
||||
QMessageBox::warning(nullptr, qApp->applicationName(), message);
|
||||
|
||||
// Delete reply later, i.e. after returning from this slot function
|
||||
@@ -473,7 +473,7 @@ void RemoteDatabase::fetch(const QString& url, RequestType type, const QString&
|
||||
// Build network request
|
||||
QNetworkRequest request;
|
||||
request.setUrl(url);
|
||||
request.setRawHeader("User-Agent", QString("%1 %2").arg(qApp->organizationName()).arg(APP_VERSION).toUtf8());
|
||||
request.setRawHeader("User-Agent", QString("%1 %2").arg(qApp->organizationName(), APP_VERSION).toUtf8());
|
||||
|
||||
// Set SSL configuration when trying to access a file via the HTTPS protocol.
|
||||
// Skip this step when no client certificate was specified. In this case the default HTTPS configuration is used.
|
||||
@@ -522,7 +522,7 @@ void RemoteDatabase::push(const QString& filename, const QString& url, const QSt
|
||||
// Build network request
|
||||
QNetworkRequest request;
|
||||
request.setUrl(url);
|
||||
request.setRawHeader("User-Agent", QString("%1 %2").arg(qApp->organizationName()).arg(APP_VERSION).toUtf8());
|
||||
request.setRawHeader("User-Agent", QString("%1 %2").arg(qApp->organizationName(), APP_VERSION).toUtf8());
|
||||
|
||||
// Get the last modified date of the file and prepare it for conversion into the ISO date format
|
||||
QDateTime last_modified = QFileInfo(filename).lastModified();
|
||||
@@ -565,7 +565,7 @@ void RemoteDatabase::push(const QString& filename, const QString& url, const QSt
|
||||
prepareProgressDialog(reply, true, url);
|
||||
}
|
||||
|
||||
void RemoteDatabase::addPart(QHttpMultiPart* multipart, const QString& name, const QString& value)
|
||||
void RemoteDatabase::addPart(QHttpMultiPart* multipart, const QString& name, const QString& value) const
|
||||
{
|
||||
QHttpPart part;
|
||||
part.setHeader(QNetworkRequest::ContentDispositionHeader, QString("form-data; name=\"%1\"").arg(name));
|
||||
@@ -574,10 +574,10 @@ void RemoteDatabase::addPart(QHttpMultiPart* multipart, const QString& name, con
|
||||
multipart->append(part);
|
||||
}
|
||||
|
||||
void RemoteDatabase::addPart(QHttpMultiPart* multipart, const QString& name, QFile* file, const QString& filename)
|
||||
void RemoteDatabase::addPart(QHttpMultiPart* multipart, const QString& name, QFile* file, const QString& filename) const
|
||||
{
|
||||
QHttpPart part;
|
||||
part.setHeader(QNetworkRequest::ContentDispositionHeader, QString("form-data; name=\"%1\"; filename=\"%2\"").arg(name).arg(filename));
|
||||
part.setHeader(QNetworkRequest::ContentDispositionHeader, QString("form-data; name=\"%1\"; filename=\"%2\"").arg(name, filename));
|
||||
part.setBodyDevice(file);
|
||||
file->setParent(multipart); // Close the file and delete the file object as soon as the multi-part object is destroyed
|
||||
|
||||
|
||||
@@ -85,8 +85,8 @@ private:
|
||||
std::string localLastCommitId(QString clientCert, const QUrl& url);
|
||||
|
||||
// Helper functions for building multi-part HTTP requests
|
||||
void addPart(QHttpMultiPart* multipart, const QString& name, const QString& value);
|
||||
void addPart(QHttpMultiPart* multipart, const QString& name, QFile* file, const QString& filename);
|
||||
void addPart(QHttpMultiPart* multipart, const QString& name, const QString& value) const;
|
||||
void addPart(QHttpMultiPart* multipart, const QString& name, QFile* file, const QString& filename) const;
|
||||
|
||||
// Before using a new client certificate we need to clear the access and authentication cache of the network manager
|
||||
// object. Otherwise Qt might reuse the old certificate if the requested URL has been used before.
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
#include <QImage>
|
||||
|
||||
#include "Data.h"
|
||||
#include "RemoteModel.h"
|
||||
#include "RemoteDatabase.h"
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
// The header list is a list of column titles
|
||||
const static std::vector<QString> headerList = {QObject::tr("Name"), QObject::tr("Commit"), QObject::tr("Last modified"), QObject::tr("Size")};
|
||||
|
||||
RemoteModelItem::RemoteModelItem(RemoteModelItem* parent) :
|
||||
m_parent(parent),
|
||||
m_fetchedDirectoryList(false)
|
||||
@@ -102,9 +106,6 @@ RemoteModel::RemoteModel(QObject* parent, RemoteDatabase& remote) :
|
||||
rootItem(new RemoteModelItem()),
|
||||
remoteDatabase(remote)
|
||||
{
|
||||
// Initialise list of column names
|
||||
headerList << tr("Name") << tr("Commit") << tr("Last modified") << tr("Size");
|
||||
|
||||
// Set up signals
|
||||
connect(&remoteDatabase, &RemoteDatabase::gotDirList, this, &RemoteModel::parseDirectoryListing);
|
||||
}
|
||||
@@ -238,17 +239,8 @@ QVariant RemoteModel::data(const QModelIndex& index, int role) const
|
||||
return QVariant();
|
||||
|
||||
// Convert size to human readable format
|
||||
float size = item->value(RemoteModelColumnSize).toFloat();
|
||||
QStringList list;
|
||||
list << "KiB" << "MiB" << "GiB" << "TiB";
|
||||
QStringListIterator it(list);
|
||||
QString unit(tr("bytes"));
|
||||
while(size >= 1024.0f && it.hasNext())
|
||||
{
|
||||
unit = it.next();
|
||||
size /= 1024.0f;
|
||||
}
|
||||
return QString().setNum(size, 'f', 2).remove(".00") + QString(" ") + unit;
|
||||
unsigned int size = item->value(RemoteModelColumnSize).toUInt();
|
||||
return humanReadableSize(size);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -263,7 +255,7 @@ QVariant RemoteModel::headerData(int section, Qt::Orientation orientation, int r
|
||||
return QAbstractItemModel::headerData(section, orientation, role);
|
||||
|
||||
// Return header string depending on column
|
||||
return headerList.at(section);
|
||||
return headerList.at(static_cast<size_t>(section));
|
||||
}
|
||||
|
||||
int RemoteModel::rowCount(const QModelIndex& parent) const
|
||||
@@ -277,7 +269,7 @@ int RemoteModel::rowCount(const QModelIndex& parent) const
|
||||
|
||||
int RemoteModel::columnCount(const QModelIndex& /*parent*/) const
|
||||
{
|
||||
return headerList.size();
|
||||
return static_cast<int>(headerList.size());
|
||||
}
|
||||
|
||||
bool RemoteModel::hasChildren(const QModelIndex& parent) const
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#define REMOTEMODEL_H
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QStringList>
|
||||
|
||||
#include <json.hpp>
|
||||
|
||||
@@ -101,9 +100,6 @@ private:
|
||||
// Pointer to the root item. This contains all the actual item data.
|
||||
RemoteModelItem* rootItem;
|
||||
|
||||
// The header list is a list of column titles. It's a static list that's getting filled in the constructor.
|
||||
QStringList headerList;
|
||||
|
||||
// Reference to the remote database object which is stored somewhere in the main window.
|
||||
RemoteDatabase& remoteDatabase;
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ RowLoader::RowLoader (
|
||||
std::function<std::shared_ptr<sqlite3>(void)> db_getter_,
|
||||
std::function<void(QString)> statement_logger_,
|
||||
std::vector<std::string> & headers_,
|
||||
QMutex & cache_mutex_,
|
||||
std::mutex & cache_mutex_,
|
||||
Cache & cache_data_
|
||||
)
|
||||
: db_getter(db_getter_), statement_logger(statement_logger_), headers(headers_)
|
||||
@@ -76,7 +76,7 @@ std::shared_ptr<sqlite3> RowLoader::getDb () const
|
||||
return pDb;
|
||||
}
|
||||
|
||||
int RowLoader::countRows()
|
||||
int RowLoader::countRows() const
|
||||
{
|
||||
int retval = -1;
|
||||
|
||||
@@ -239,7 +239,7 @@ void RowLoader::process (Task & t)
|
||||
rowdata[i] = "";
|
||||
}
|
||||
}
|
||||
QMutexLocker lk(&cache_mutex);
|
||||
std::lock_guard<std::mutex> lk(cache_mutex);
|
||||
cache_data.set(row++, std::move(rowdata));
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
#include <QThread>
|
||||
#include <QString>
|
||||
#include <QMutex>
|
||||
|
||||
#include "RowCache.h"
|
||||
|
||||
@@ -31,7 +30,7 @@ public:
|
||||
std::function<std::shared_ptr<sqlite3>(void)> db_getter,
|
||||
std::function<void(QString)> statement_logger,
|
||||
std::vector<std::string> & headers,
|
||||
QMutex & cache_mutex,
|
||||
std::mutex & cache_mutex,
|
||||
Cache & cache_data
|
||||
);
|
||||
|
||||
@@ -71,7 +70,7 @@ private:
|
||||
const std::function<std::shared_ptr<sqlite3>()> db_getter;
|
||||
const std::function<void(QString)> statement_logger;
|
||||
std::vector<std::string> & headers;
|
||||
QMutex & cache_mutex;
|
||||
std::mutex & cache_mutex;
|
||||
Cache & cache_data;
|
||||
|
||||
mutable std::mutex m;
|
||||
@@ -111,7 +110,7 @@ private:
|
||||
std::unique_ptr<Task> current_task;
|
||||
std::unique_ptr<Task> next_task;
|
||||
|
||||
int countRows ();
|
||||
int countRows () const;
|
||||
|
||||
void process (Task &);
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ QVariant Settings::getDefaultValue(const std::string& group, const std::string&
|
||||
|
||||
// db/defaultsqltext?
|
||||
if(group == "db" && name == "defaultsqltext")
|
||||
return "";
|
||||
return QString();
|
||||
|
||||
// exportcsv/firstrowheader?
|
||||
if(group == "exportcsv" && name == "firstrowheader")
|
||||
@@ -137,15 +137,15 @@ QVariant Settings::getDefaultValue(const std::string& group, const std::string&
|
||||
|
||||
// MainWindow/geometry?
|
||||
if(group == "MainWindow" && name == "geometry")
|
||||
return "";
|
||||
return QString();
|
||||
|
||||
// MainWindow/windowState?
|
||||
if(group == "MainWindow" && name == "windowState")
|
||||
return "";
|
||||
return QString();
|
||||
|
||||
// MainWindow/openTabs?
|
||||
if(group == "MainWindow" && name == "openTabs")
|
||||
return "";
|
||||
return QString();
|
||||
|
||||
// SQLLogDock/Log?
|
||||
if(group == "SQLLogDock" && name == "Log")
|
||||
|
||||
@@ -19,7 +19,7 @@ public:
|
||||
static void restoreDefaults();
|
||||
|
||||
private:
|
||||
Settings() { } // class is fully static
|
||||
Settings() = delete; // class is fully static
|
||||
|
||||
// This works similar to getValue but returns the default value instead of the value set by the user
|
||||
static QVariant getDefaultValue(const std::string& group, const std::string& name);
|
||||
|
||||
@@ -171,7 +171,7 @@ void SqlExecutionArea::find(QString expr, bool forward)
|
||||
forward);
|
||||
|
||||
// Set reddish background when not found
|
||||
if (found || expr == "")
|
||||
if (found || expr.isEmpty())
|
||||
ui->findLineEdit->setStyleSheet("");
|
||||
else
|
||||
ui->findLineEdit->setStyleSheet("QLineEdit {color: white; background-color: rgb(255, 102, 102)}");
|
||||
@@ -296,7 +296,7 @@ void SqlExecutionArea::fileChanged(const QString& filename)
|
||||
if(QMessageBox::question(
|
||||
this,
|
||||
qApp->applicationName(),
|
||||
tr("The file \"%1\" was modified by another program. Do you want to reload it?%2").arg(filename).arg(changes),
|
||||
tr("The file \"%1\" was modified by another program. Do you want to reload it?%2").arg(filename, changes),
|
||||
QMessageBox::Yes | QMessageBox::Ignore) == QMessageBox::Yes)
|
||||
{
|
||||
// Read in the file
|
||||
|
||||
@@ -475,11 +475,11 @@ void TableBrowser::updateTable()
|
||||
|
||||
// Filters
|
||||
for(auto it=storedData.filterValues.constBegin();it!=storedData.filterValues.constEnd();++it)
|
||||
query.where().insert({it.key(), CondFormat::filterToSqlCondition(it.value(), m_model->encoding()).toStdString()});
|
||||
query.where().insert({it.key(), CondFormat::filterToSqlCondition(it.value(), m_model->encoding())});
|
||||
|
||||
// Global filter
|
||||
for(const auto& f : storedData.globalFilters)
|
||||
query.globalWhere().push_back(CondFormat::filterToSqlCondition(f, m_model->encoding()).toStdString());
|
||||
query.globalWhere().push_back(CondFormat::filterToSqlCondition(f, m_model->encoding()));
|
||||
|
||||
// Display formats
|
||||
bool only_defaults = true;
|
||||
@@ -701,7 +701,7 @@ void TableBrowser::updateRecordsetLabel()
|
||||
// that the row count query will never finish. And because of this the row count will be forever unknown. To avoid always showing
|
||||
// a misleading "determining row count" text in the UI we set the row count status to complete here for empty queries.
|
||||
auto row_count_available = m_model->rowCountAvailable();
|
||||
if(m_model->query().isEmpty())
|
||||
if(m_model->query().empty())
|
||||
row_count_available = SqliteTableModel::RowCount::Complete;
|
||||
|
||||
// Update the label showing the current position
|
||||
@@ -869,7 +869,7 @@ void TableBrowser::unlockViewEditing(bool unlock, QString pk)
|
||||
}
|
||||
|
||||
// Do some basic testing of the input and if the input appears to be good, go on
|
||||
if(db->executeSQL(QString("SELECT %1 FROM %2 LIMIT 1;").arg(sqlb::escapeIdentifier(pk)).arg(QString::fromStdString(currentTable.toString())), false, true))
|
||||
if(db->executeSQL("SELECT " + sqlb::escapeIdentifier(pk.toStdString()) + " FROM " + currentTable.toString() + " LIMIT 1;", false, true))
|
||||
break;
|
||||
}
|
||||
} else if(!unlock) {
|
||||
@@ -1130,17 +1130,16 @@ void TableBrowser::showRecordPopupMenu(const QPoint& pos)
|
||||
action->setShortcut(QKeySequence(tr("Ctrl+\"")));
|
||||
popupRecordMenu.addAction(action);
|
||||
|
||||
connect(action, &QAction::triggered, [&]() {
|
||||
for (QModelIndex index : rowList) {
|
||||
duplicateRecord(index.row());
|
||||
}
|
||||
connect(action, &QAction::triggered, [rowList, this]() {
|
||||
for (const QModelIndex& index : rowList)
|
||||
duplicateRecord(index.row());
|
||||
});
|
||||
|
||||
QAction* deleteRecordAction = new QAction(QIcon(":icons/delete_record"), ui->actionDeleteRecord->text(), &popupRecordMenu);
|
||||
popupRecordMenu.addAction(deleteRecordAction);
|
||||
|
||||
connect(deleteRecordAction, &QAction::triggered, [&]() {
|
||||
deleteRecord();
|
||||
deleteRecord();
|
||||
});
|
||||
|
||||
popupRecordMenu.exec(ui->dataTable->verticalHeader()->mapToGlobal(pos));
|
||||
@@ -1362,7 +1361,7 @@ void TableBrowser::setDefaultTableEncoding()
|
||||
setTableEncoding(true);
|
||||
}
|
||||
|
||||
void TableBrowser::jumpToRow(const sqlb::ObjectIdentifier& table, QString column, const QByteArray& value)
|
||||
void TableBrowser::jumpToRow(const sqlb::ObjectIdentifier& table, std::string column, const QByteArray& value)
|
||||
{
|
||||
// First check if table exists
|
||||
sqlb::TablePtr obj = db->getObjectByName<sqlb::Table>(table);
|
||||
@@ -1371,10 +1370,10 @@ void TableBrowser::jumpToRow(const sqlb::ObjectIdentifier& table, QString column
|
||||
|
||||
// If no column name is set, assume the primary key is meant
|
||||
if(!column.size())
|
||||
column = QString::fromStdString(obj->primaryKey()->columnList().front());
|
||||
column = obj->primaryKey()->columnList().front();
|
||||
|
||||
// If column doesn't exist don't do anything
|
||||
auto column_index = sqlb::findField(obj, column.toStdString());
|
||||
auto column_index = sqlb::findField(obj, column);
|
||||
if(column_index == obj->fields.end())
|
||||
return;
|
||||
|
||||
@@ -1430,7 +1429,7 @@ void TableBrowser::find(const QString& expr, bool forward, bool include_first)
|
||||
ui->dataTable->setCurrentIndex(match);
|
||||
|
||||
// Make the expression control red if no results were found
|
||||
if(match.isValid() || expr == "")
|
||||
if(match.isValid() || expr.isEmpty())
|
||||
ui->editFindExpression->setStyleSheet("");
|
||||
else
|
||||
ui->editFindExpression->setStyleSheet("QLineEdit {color: white; background-color: rgb(255, 102, 102)}");
|
||||
|
||||
@@ -109,7 +109,7 @@ public slots:
|
||||
void reloadSettings();
|
||||
void setCurrentTable(const sqlb::ObjectIdentifier& name);
|
||||
void updateRecordsetLabel();
|
||||
void jumpToRow(const sqlb::ObjectIdentifier& table, QString column, const QByteArray& value);
|
||||
void jumpToRow(const sqlb::ObjectIdentifier& table, std::string column, const QByteArray& value);
|
||||
|
||||
signals:
|
||||
void projectModified();
|
||||
@@ -117,7 +117,7 @@ signals:
|
||||
void selectionChangedByDoubleClick(QModelIndex index);
|
||||
void statusMessageRequested(QString message);
|
||||
void updatePlot(ExtendedTableWidget* tableWidget, SqliteTableModel* model, BrowseDataTableSettings* settings, bool keepOrResetSelection);
|
||||
void createView(QString sql);
|
||||
void createView(std::string sql);
|
||||
void requestFileOpen(QString file);
|
||||
|
||||
private slots:
|
||||
|
||||
@@ -1103,9 +1103,9 @@
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>dataTable</sender>
|
||||
<signal>foreignKeyClicked(sqlb::ObjectIdentifier,QString,QByteArray)</signal>
|
||||
<signal>foreignKeyClicked(sqlb::ObjectIdentifier,std::string,QByteArray)</signal>
|
||||
<receiver>TableBrowser</receiver>
|
||||
<slot>jumpToRow(sqlb::ObjectIdentifier,QString,QByteArray)</slot>
|
||||
<slot>jumpToRow(sqlb::ObjectIdentifier,std::string,QByteArray)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>70</x>
|
||||
@@ -1350,7 +1350,7 @@
|
||||
<slot>navigateBegin()</slot>
|
||||
<slot>navigateEnd()</slot>
|
||||
<slot>navigateGoto()</slot>
|
||||
<slot>jumpToRow(sqlb::ObjectIdentifier,QString,QByteArray)</slot>
|
||||
<slot>jumpToRow(sqlb::ObjectIdentifier,std::string,QByteArray)</slot>
|
||||
<slot>showRowidColumn(bool)</slot>
|
||||
<slot>unlockViewEditing(bool)</slot>
|
||||
<slot>editDisplayFormat()</slot>
|
||||
|
||||
@@ -46,7 +46,7 @@ void VacuumDialog::accept()
|
||||
// Loop through all selected databases and vacuum them individually
|
||||
QList<QTreeWidgetItem*> selection = ui->treeDatabases->selectedItems();
|
||||
for(const QTreeWidgetItem* item : selection)
|
||||
db->executeSQL(QString("VACUUM %1;").arg(sqlb::escapeIdentifier(item->text(0))), false);
|
||||
db->executeSQL("VACUUM " + sqlb::escapeIdentifier(item->text(0).toStdString()), false);
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
QDialog::accept();
|
||||
|
||||
@@ -16,7 +16,7 @@ class QTextStream;
|
||||
class CSVProgress
|
||||
{
|
||||
public:
|
||||
virtual ~CSVProgress() { }
|
||||
virtual ~CSVProgress() = default;
|
||||
|
||||
virtual void start() = 0;
|
||||
virtual bool update(int64_t pos) = 0;
|
||||
|
||||
@@ -27,10 +27,6 @@ DockTextEdit::DockTextEdit(QWidget* parent) :
|
||||
reloadSettings();
|
||||
}
|
||||
|
||||
DockTextEdit::~DockTextEdit()
|
||||
{
|
||||
}
|
||||
|
||||
void DockTextEdit::reloadSettings()
|
||||
{
|
||||
// Set the parent settings for both lexers
|
||||
@@ -115,5 +111,5 @@ void DockTextEdit::clearTextInMargin()
|
||||
clearMarginText();
|
||||
setMarginLineNumbers(0, true);
|
||||
reloadCommonSettings();
|
||||
linesChanged();
|
||||
emit linesChanged();
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ class DockTextEdit : public ExtendedScintilla
|
||||
|
||||
public:
|
||||
explicit DockTextEdit(QWidget *parent = nullptr);
|
||||
~DockTextEdit() override;
|
||||
|
||||
// Enumeration of supported languages
|
||||
enum Language
|
||||
@@ -27,7 +26,7 @@ public:
|
||||
};
|
||||
|
||||
void setLanguage(Language lang);
|
||||
Language language() { return m_language; }
|
||||
Language language() const { return m_language; }
|
||||
|
||||
// Disables the line-number margin and sets this text in the first line.
|
||||
void setTextInMargin(const QString& text);
|
||||
|
||||
@@ -6,16 +6,6 @@
|
||||
#include <iterator>
|
||||
#include <numeric>
|
||||
|
||||
namespace {
|
||||
bool starts_with_ci(const std::string& str, const std::string& with)
|
||||
{
|
||||
if(str.size() < with.size())
|
||||
return false;
|
||||
else
|
||||
return compare_ci(str.substr(0, with.size()), with);
|
||||
}
|
||||
}
|
||||
|
||||
namespace sqlb {
|
||||
|
||||
StringVector escapeIdentifier(StringVector ids)
|
||||
@@ -54,7 +44,7 @@ std::string Object::typeToString(Types type)
|
||||
case Types::View: return "view";
|
||||
case Types::Trigger: return "trigger";
|
||||
}
|
||||
return "";
|
||||
return std::string();
|
||||
}
|
||||
|
||||
ConstraintPtr Constraint::makeConstraint(ConstraintTypes type)
|
||||
@@ -62,13 +52,13 @@ ConstraintPtr Constraint::makeConstraint(ConstraintTypes type)
|
||||
switch(type)
|
||||
{
|
||||
case PrimaryKeyConstraintType:
|
||||
return sqlb::ConstraintPtr(new sqlb::PrimaryKeyConstraint());
|
||||
return std::make_shared<PrimaryKeyConstraint>();
|
||||
case UniqueConstraintType:
|
||||
return sqlb::ConstraintPtr(new sqlb::UniqueConstraint());
|
||||
return std::make_shared<UniqueConstraint>();
|
||||
case ForeignKeyConstraintType:
|
||||
return sqlb::ConstraintPtr(new sqlb::ForeignKeyClause());
|
||||
return std::make_shared<ForeignKeyClause>();
|
||||
case CheckConstraintType:
|
||||
return sqlb::ConstraintPtr(new sqlb::CheckConstraint());
|
||||
return std::make_shared<CheckConstraint>();
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
@@ -92,7 +82,7 @@ bool ForeignKeyClause::isSet() const
|
||||
std::string ForeignKeyClause::toString() const
|
||||
{
|
||||
if(!isSet())
|
||||
return "";
|
||||
return std::string();
|
||||
|
||||
if(m_override.size())
|
||||
return m_override;
|
||||
@@ -427,7 +417,7 @@ TablePtr Table::parseSQL(const std::string& sSQL)
|
||||
return t;
|
||||
} else {
|
||||
std::cerr << "Sqlite parse error: " << sSQL << std::endl;
|
||||
return TablePtr(new Table(""));
|
||||
return std::make_shared<Table>("");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -664,7 +654,7 @@ IndexPtr Index::parseSQL(const std::string& sSQL)
|
||||
return i;
|
||||
} else {
|
||||
std::cerr << "Sqlite parse error: " << sSQL << std::endl;
|
||||
return IndexPtr(new Index(""));
|
||||
return std::make_shared<Index>("");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -674,7 +664,7 @@ ViewPtr View::parseSQL(const std::string& sSQL)
|
||||
{
|
||||
// TODO
|
||||
|
||||
auto v = ViewPtr(new View(""));
|
||||
auto v = std::make_shared<View>("");
|
||||
v->setOriginalSql(sSQL);
|
||||
return v;
|
||||
}
|
||||
@@ -702,7 +692,7 @@ TriggerPtr Trigger::parseSQL(const std::string& sSQL)
|
||||
{
|
||||
// TODO
|
||||
|
||||
auto t = TriggerPtr(new Trigger(""));
|
||||
auto t = std::make_shared<Trigger>("");
|
||||
t->setOriginalSql(sSQL);
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,14 @@ bool compare_ci(const T& a, const char* b)
|
||||
return compare_ci(a, std::string(b));
|
||||
}
|
||||
|
||||
inline bool starts_with_ci(const std::string& str, const std::string& with)
|
||||
{
|
||||
if(str.size() < with.size())
|
||||
return false;
|
||||
else
|
||||
return compare_ci(str.substr(0, with.size()), with);
|
||||
}
|
||||
|
||||
namespace sqlb {
|
||||
|
||||
using StringVector = std::vector<std::string>;
|
||||
@@ -80,7 +88,7 @@ public:
|
||||
};
|
||||
|
||||
explicit Object(const std::string& name): m_name(name), m_fullyParsed(false) {}
|
||||
virtual ~Object() {}
|
||||
virtual ~Object() = default;
|
||||
|
||||
bool operator==(const Object& rhs) const;
|
||||
|
||||
@@ -132,7 +140,7 @@ public:
|
||||
m_name(name)
|
||||
{
|
||||
}
|
||||
virtual ~Constraint() {}
|
||||
virtual ~Constraint() = default;
|
||||
|
||||
static ConstraintPtr makeConstraint(ConstraintTypes type);
|
||||
|
||||
@@ -265,10 +273,10 @@ public:
|
||||
Field(const std::string& name,
|
||||
const std::string& type,
|
||||
bool notnull = false,
|
||||
const std::string& defaultvalue = "",
|
||||
const std::string& check = "",
|
||||
const std::string& defaultvalue = std::string(),
|
||||
const std::string& check = std::string(),
|
||||
bool unique = false,
|
||||
const std::string& collation = "")
|
||||
const std::string& collation = std::string())
|
||||
: m_name(name)
|
||||
, m_type(type)
|
||||
, m_notnull(notnull)
|
||||
|
||||
571
src/sqlitedb.cpp
571
src/sqlitedb.cpp
File diff suppressed because it is too large
Load Diff
@@ -67,10 +67,10 @@ private:
|
||||
public:
|
||||
|
||||
explicit DBBrowserDB();
|
||||
~DBBrowserDB () override {}
|
||||
~DBBrowserDB () override = default;
|
||||
|
||||
bool open(const QString& db, bool readOnly = false);
|
||||
bool attach(const QString& filename, QString attach_as = "");
|
||||
bool attach(const QString& filename, QString attach_as = QString());
|
||||
bool create ( const QString & db);
|
||||
bool close();
|
||||
|
||||
@@ -102,13 +102,13 @@ public:
|
||||
**/
|
||||
db_pointer_type get (const QString& user, bool force_wait = false);
|
||||
|
||||
bool setSavepoint(const QString& pointname = "RESTOREPOINT");
|
||||
bool releaseSavepoint(const QString& pointname = "RESTOREPOINT");
|
||||
bool revertToSavepoint(const QString& pointname = "RESTOREPOINT");
|
||||
bool setSavepoint(const std::string& pointname = "RESTOREPOINT");
|
||||
bool releaseSavepoint(const std::string& pointname = "RESTOREPOINT");
|
||||
bool revertToSavepoint(const std::string& pointname = "RESTOREPOINT");
|
||||
bool releaseAllSavepoints();
|
||||
bool revertAll();
|
||||
|
||||
bool dump(const QString& filename, const QStringList& tablesToDump, bool insertColNames, bool insertNew, bool exportSchema, bool exportData, bool keepOldSchema);
|
||||
bool dump(const QString& filename, const std::vector<std::string>& tablesToDump, bool insertColNames, bool insertNew, bool exportSchema, bool exportData, bool keepOldSchema) const;
|
||||
|
||||
enum ChoiceOnUse
|
||||
{
|
||||
@@ -125,10 +125,10 @@ public:
|
||||
// callback is the text representation of the values, one for each
|
||||
// column. The 3rd argument is a list of strings where each entry
|
||||
// represents the name of corresponding result column.
|
||||
using execCallback = std::function<bool(int, QStringList, QStringList)>;
|
||||
bool executeSQL(QString statement, bool dirtyDB = true, bool logsql = true, execCallback callback = nullptr);
|
||||
using execCallback = std::function<bool(int, std::vector<QByteArray>, std::vector<QByteArray>)>;
|
||||
bool executeSQL(const std::string& statement, bool dirtyDB = true, bool logsql = true, execCallback callback = nullptr);
|
||||
bool executeMultiSQL(QByteArray query, bool dirty = true, bool log = false);
|
||||
QByteArray querySingleValueFromDb(const QString& sql, bool log = true, ChoiceOnUse choice = Ask);
|
||||
QByteArray querySingleValueFromDb(const std::string& sql, bool log = true, ChoiceOnUse choice = Ask) const;
|
||||
|
||||
const QString& lastError() const { return lastErrorMessage; }
|
||||
|
||||
@@ -141,7 +141,7 @@ public:
|
||||
* @param rowdata A list of QByteArray containing the row data.
|
||||
* @return true if statement execution was ok, else false.
|
||||
*/
|
||||
bool getRow(const sqlb::ObjectIdentifier& table, const QString& rowid, std::vector<QByteArray>& rowdata);
|
||||
bool getRow(const sqlb::ObjectIdentifier& table, const QString& rowid, std::vector<QByteArray>& rowdata) const;
|
||||
|
||||
/**
|
||||
* @brief Interrupts the currenty running statement as soon as possible.
|
||||
@@ -169,11 +169,11 @@ private:
|
||||
* @param pk_value This optional parameter can be used to manually set a specific value for the primary key column
|
||||
* @return An sqlite conform INSERT INTO statement with empty values. (NULL,'',0)
|
||||
*/
|
||||
QString emptyInsertStmt(const std::string& schemaName, const sqlb::Table& t, const QString& pk_value = QString()) const;
|
||||
std::string emptyInsertStmt(const std::string& schemaName, const sqlb::Table& t, const QString& pk_value = QString()) const;
|
||||
|
||||
public:
|
||||
QString addRecord(const sqlb::ObjectIdentifier& tablename);
|
||||
bool deleteRecords(const sqlb::ObjectIdentifier& table, const QStringList& rowids, const sqlb::StringVector& pseudo_pk = {});
|
||||
bool deleteRecords(const sqlb::ObjectIdentifier& table, const std::vector<QString>& rowids, const sqlb::StringVector& pseudo_pk = {});
|
||||
bool updateRecord(const sqlb::ObjectIdentifier& table, const std::string& column, const QString& rowid, const QByteArray& value, int force_type = 0, const sqlb::StringVector& pseudo_pk = {});
|
||||
|
||||
bool createTable(const sqlb::ObjectIdentifier& name, const sqlb::FieldVector& structure);
|
||||
@@ -199,9 +199,7 @@ public:
|
||||
* @param newSchema Set this to a non-empty string to move the table to a new schema
|
||||
* @return true if renaming was successful, false if not. In the latter case also lastErrorMessage is set
|
||||
*/
|
||||
bool alterTable(const sqlb::ObjectIdentifier& tablename, const sqlb::Table& new_table, AlterTableTrackColumns track_columns, std::string newSchemaName = "");
|
||||
|
||||
objectMap getBrowsableObjects(const std::string& schema) const;
|
||||
bool alterTable(const sqlb::ObjectIdentifier& tablename, const sqlb::Table& new_table, AlterTableTrackColumns track_columns, std::string newSchemaName = std::string());
|
||||
|
||||
template<typename T = sqlb::Object>
|
||||
const std::shared_ptr<T> getObjectByName(const sqlb::ObjectIdentifier& name) const
|
||||
@@ -221,12 +219,12 @@ public:
|
||||
QString currentFile() const { return curDBFilename; }
|
||||
|
||||
/// log an SQL statement [thread-safe]
|
||||
void logSQL(const QString& statement, LogMessageType msgtype);
|
||||
void logSQL(const QString& statement, LogMessageType msgtype) const;
|
||||
|
||||
QString getPragma(const QString& pragma);
|
||||
bool setPragma(const QString& pragma, const QString& value);
|
||||
bool setPragma(const QString& pragma, const QString& value, QString& originalvalue);
|
||||
bool setPragma(const QString& pragma, int value, int& originalvalue);
|
||||
QString getPragma(const std::string& pragma) const;
|
||||
bool setPragma(const std::string& pragma, const QString& value);
|
||||
bool setPragma(const std::string& pragma, const QString& value, QString& originalvalue);
|
||||
bool setPragma(const std::string& pragma, int value, int& originalvalue);
|
||||
|
||||
bool loadExtension(const QString& filename);
|
||||
void loadExtensionsFromSettings();
|
||||
@@ -234,10 +232,10 @@ public:
|
||||
static QStringList Datatypes;
|
||||
|
||||
private:
|
||||
std::vector<std::pair<std::string, std::string> > queryColumnInformation(const std::string& schema_name, const std::string& object_name);
|
||||
std::vector<std::pair<std::string, std::string> > queryColumnInformation(const std::string& schema_name, const std::string& object_name) const;
|
||||
|
||||
public:
|
||||
QString generateSavepointName(const QString& identifier = QString()) const;
|
||||
std::string generateSavepointName(const std::string& identifier = std::string()) const;
|
||||
|
||||
// This function generates the name for a temporary table. It guarantees that there is no table with this name yet
|
||||
std::string generateTemporaryTableName(const std::string& schema) const;
|
||||
@@ -245,7 +243,7 @@ public:
|
||||
schemaMap schemata;
|
||||
|
||||
signals:
|
||||
void sqlExecuted(QString sql, int msgtype);
|
||||
void sqlExecuted(QString sql, int msgtype) const;
|
||||
void dbChanged(bool dirty);
|
||||
void structureUpdated();
|
||||
void requestCollation(QString name, int eTextRep);
|
||||
@@ -254,19 +252,19 @@ signals:
|
||||
private:
|
||||
/// external code needs to go through get() to obtain access to the database
|
||||
sqlite3 * _db;
|
||||
std::mutex m;
|
||||
std::condition_variable cv;
|
||||
mutable std::mutex m;
|
||||
mutable std::condition_variable cv;
|
||||
bool db_used;
|
||||
QString db_user;
|
||||
|
||||
/// wait for release of the DB locked through a previous get(),
|
||||
/// giving users the option to discard running task through a
|
||||
/// message box.
|
||||
void waitForDbRelease(ChoiceOnUse choice = Ask);
|
||||
void waitForDbRelease(ChoiceOnUse choice = Ask) const;
|
||||
|
||||
QString curDBFilename;
|
||||
QString lastErrorMessage;
|
||||
QStringList savepointList;
|
||||
mutable QString lastErrorMessage;
|
||||
std::vector<std::string> savepointList;
|
||||
bool isEncrypted;
|
||||
bool isReadOnly;
|
||||
|
||||
@@ -276,7 +274,7 @@ private:
|
||||
void collationNeeded(void* pData, sqlite3* db, int eTextRep, const char* sCollationName);
|
||||
void errorLogCallback(void* user_data, int error_code, const char* message);
|
||||
|
||||
bool tryEncryptionSettings(const QString& filename, bool* encrypted, CipherSettings*& cipherSettings);
|
||||
bool tryEncryptionSettings(const QString& filename, bool* encrypted, CipherSettings*& cipherSettings) const;
|
||||
|
||||
bool dontCheckForStructureUpdates;
|
||||
|
||||
|
||||
@@ -147,7 +147,7 @@ void SqliteTableModel::setQuery(const sqlb::Query& query)
|
||||
// information we retrieve it from SQLite using an extra query.
|
||||
// NOTE: It would be nice to eventually get rid of this piece here. As soon as the grammar parser is good enough...
|
||||
|
||||
QString sColumnQuery = QString::fromUtf8("SELECT * FROM %1;").arg(QString::fromStdString(query.table().toString()));
|
||||
std::string sColumnQuery = "SELECT * FROM " + query.table().toString() + ";";
|
||||
if(m_query.rowIdColumns().empty())
|
||||
m_query.setRowIdColumn("_rowid_");
|
||||
m_headers.emplace_back("_rowid_");
|
||||
@@ -181,7 +181,7 @@ void SqliteTableModel::setQuery(const QString& sQuery, const QString& sCountQuer
|
||||
|
||||
if(!dontClearHeaders)
|
||||
{
|
||||
auto columns = getColumns(worker->getDb(), sQuery, m_vDataTypes);
|
||||
auto columns = getColumns(worker->getDb(), sQuery.toStdString(), m_vDataTypes);
|
||||
m_headers.insert(m_headers.end(), columns.begin(), columns.end());
|
||||
}
|
||||
|
||||
@@ -264,15 +264,15 @@ QVariant SqliteTableModel::getMatchingCondFormat(const std::map<size_t, std::vec
|
||||
|
||||
bool isNumber;
|
||||
value.toDouble(&isNumber);
|
||||
QString sql;
|
||||
std::string sql;
|
||||
|
||||
// For each conditional format for this column,
|
||||
// if the condition matches the current data, return the associated format.
|
||||
for (const CondFormat& eachCondFormat : mCondFormats.at(column)) {
|
||||
if (isNumber && !eachCondFormat.sqlCondition().contains("'"))
|
||||
sql = QString("SELECT %1 %2").arg(value, eachCondFormat.sqlCondition());
|
||||
if (isNumber && !contains(eachCondFormat.sqlCondition(), '\''))
|
||||
sql = "SELECT " + value.toStdString() + " " + eachCondFormat.sqlCondition();
|
||||
else
|
||||
sql = QString("SELECT '%1' %2").arg(value, eachCondFormat.sqlCondition());
|
||||
sql = "SELECT '" + value.toStdString() + "' " + eachCondFormat.sqlCondition();
|
||||
|
||||
// Empty filter means: apply format to any row.
|
||||
// Query the DB for the condition, waiting in case there is a loading in progress.
|
||||
@@ -295,12 +295,14 @@ QVariant SqliteTableModel::getMatchingCondFormat(size_t row, size_t column, cons
|
||||
{
|
||||
QVariant format;
|
||||
// Check first for a row-id format and when there is none, for a conditional format.
|
||||
if (m_mRowIdFormats.count(column)) {
|
||||
QMutexLocker lock(&m_mutexDataCache);
|
||||
if (m_mRowIdFormats.count(column))
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutexDataCache);
|
||||
const bool row_available = m_cache.count(row);
|
||||
const QByteArray blank_data("");
|
||||
const QByteArray& row_id_data = row_available ? m_cache.at(row).at(0) : blank_data;
|
||||
lock.unlock();
|
||||
|
||||
format = getMatchingCondFormat(m_mRowIdFormats, column, row_id_data, role);
|
||||
if (format.isValid())
|
||||
return format;
|
||||
@@ -319,7 +321,7 @@ QVariant SqliteTableModel::data(const QModelIndex &index, int role) const
|
||||
if (index.row() >= rowCount())
|
||||
return QVariant();
|
||||
|
||||
QMutexLocker lock(&m_mutexDataCache);
|
||||
std::unique_lock<std::mutex> lock(m_mutexDataCache);
|
||||
|
||||
const size_t row = static_cast<size_t>(index.row());
|
||||
const size_t column = static_cast<size_t>(index.column());
|
||||
@@ -396,10 +398,10 @@ QVariant SqliteTableModel::data(const QModelIndex &index, int role) const
|
||||
} else if(role == Qt::ToolTipRole) {
|
||||
sqlb::ForeignKeyClause fk = getForeignKeyClause(column-1);
|
||||
if(fk.isSet())
|
||||
return tr("References %1(%2)\nHold %3Shift and click to jump there")
|
||||
.arg(QString::fromStdString(fk.table()))
|
||||
.arg(QString::fromStdString(sqlb::joinStringVector(fk.columns(), ",")))
|
||||
.arg(QKeySequence(Qt::CTRL).toString(QKeySequence::NativeText));
|
||||
return tr("References %1(%2)\nHold %3Shift and click to jump there").arg(
|
||||
QString::fromStdString(fk.table()),
|
||||
QString::fromStdString(sqlb::joinStringVector(fk.columns(), ",")),
|
||||
QKeySequence(Qt::CTRL).toString(QKeySequence::NativeText));
|
||||
} else if (role == Qt::TextAlignmentRole) {
|
||||
// Align horizontally according to conditional format or default (left for text and right for numbers)
|
||||
// Align vertically to the center, which displays better.
|
||||
@@ -477,7 +479,7 @@ bool SqliteTableModel::setTypedData(const QModelIndex& index, bool isBlob, const
|
||||
|
||||
if(index.isValid() && role == Qt::EditRole)
|
||||
{
|
||||
QMutexLocker lock(&m_mutexDataCache);
|
||||
std::unique_lock<std::mutex> lock(m_mutexDataCache);
|
||||
|
||||
auto & cached_row = m_cache.at(static_cast<size_t>(index.row()));
|
||||
const size_t column = static_cast<size_t>(index.column());
|
||||
@@ -676,11 +678,11 @@ bool SqliteTableModel::removeRows(int row, int count, const QModelIndex& parent)
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList rowids;
|
||||
std::vector<QString> rowids;
|
||||
for(int i=count-1;i>=0;i--)
|
||||
{
|
||||
if(m_cache.count(static_cast<size_t>(row+i))) {
|
||||
rowids.append(m_cache.at(static_cast<size_t>(row + i)).at(0));
|
||||
rowids.push_back(m_cache.at(static_cast<size_t>(row + i)).at(0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -750,7 +752,7 @@ void SqliteTableModel::removeCommentsFromQuery(QString& query)
|
||||
query = rxSQL.cap(3);
|
||||
} else {
|
||||
result += query;
|
||||
query = "";
|
||||
query.clear();
|
||||
}
|
||||
}
|
||||
query = result;
|
||||
@@ -780,7 +782,7 @@ void SqliteTableModel::removeCommentsFromQuery(QString& query)
|
||||
query = rxSQL.cap(4);
|
||||
} else {
|
||||
result += query;
|
||||
query = "";
|
||||
query.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -796,14 +798,13 @@ void SqliteTableModel::removeCommentsFromQuery(QString& query)
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> SqliteTableModel::getColumns(std::shared_ptr<sqlite3> pDb, const QString& sQuery, std::vector<int>& fieldsTypes)
|
||||
std::vector<std::string> SqliteTableModel::getColumns(std::shared_ptr<sqlite3> pDb, const std::string& sQuery, std::vector<int>& fieldsTypes) const
|
||||
{
|
||||
if(!pDb)
|
||||
pDb = m_db.get(tr("retrieving list of columns"));
|
||||
|
||||
sqlite3_stmt* stmt;
|
||||
QByteArray utf8Query = sQuery.toUtf8();
|
||||
int status = sqlite3_prepare_v2(pDb.get(), utf8Query, utf8Query.size(), &stmt, nullptr);
|
||||
int status = sqlite3_prepare_v2(pDb.get(), sQuery.c_str(), static_cast<int>(sQuery.size()), &stmt, nullptr);
|
||||
std::vector<std::string> listColumns;
|
||||
if(SQLITE_OK == status)
|
||||
{
|
||||
@@ -857,13 +858,13 @@ void SqliteTableModel::setCondFormats(const bool isRowIdFormat, size_t column, c
|
||||
|
||||
void SqliteTableModel::updateFilter(size_t column, const QString& value)
|
||||
{
|
||||
QString whereClause = CondFormat::filterToSqlCondition(value, m_encoding);
|
||||
std::string whereClause = CondFormat::filterToSqlCondition(value, m_encoding);
|
||||
|
||||
// If the value was set to an empty string remove any filter for this column. Otherwise insert a new filter rule or replace the old one if there is already one
|
||||
if(whereClause.isEmpty())
|
||||
if(whereClause.empty())
|
||||
m_query.where().erase(column);
|
||||
else
|
||||
m_query.where()[column] = whereClause.toStdString();
|
||||
m_query.where()[column] = whereClause;
|
||||
|
||||
// Build the new query
|
||||
buildQuery();
|
||||
@@ -873,7 +874,7 @@ void SqliteTableModel::updateGlobalFilter(const std::vector<QString>& values)
|
||||
{
|
||||
std::vector<std::string> filters;
|
||||
for(auto& v : values)
|
||||
filters.push_back(CondFormat::filterToSqlCondition(v, m_encoding).toStdString());
|
||||
filters.push_back(CondFormat::filterToSqlCondition(v, m_encoding));
|
||||
m_query.setGlobalWhere(filters);
|
||||
|
||||
// Build the new query
|
||||
@@ -902,7 +903,7 @@ void SqliteTableModel::clearCache()
|
||||
|
||||
bool SqliteTableModel::isBinary(const QModelIndex& index) const
|
||||
{
|
||||
QMutexLocker lock(&m_mutexDataCache);
|
||||
std::lock_guard<std::mutex> lock(m_mutexDataCache);
|
||||
|
||||
const size_t row = static_cast<size_t>(index.row());
|
||||
if(!m_cache.count(row))
|
||||
@@ -995,7 +996,7 @@ void SqliteTableModel::triggerCacheLoad (int row) const
|
||||
}
|
||||
|
||||
// avoid re-fetching data
|
||||
QMutexLocker lk(&m_mutexDataCache);
|
||||
std::lock_guard<std::mutex> lk(m_mutexDataCache);
|
||||
m_cache.smallestNonAvailableRange(row_begin, row_end);
|
||||
|
||||
if(row_end != row_begin)
|
||||
@@ -1040,7 +1041,7 @@ bool SqliteTableModel::isCacheComplete () const
|
||||
{
|
||||
if(readingData())
|
||||
return false;
|
||||
QMutexLocker lock(&m_mutexDataCache);
|
||||
std::lock_guard<std::mutex> lock(m_mutexDataCache);
|
||||
return m_cache.numSet() == m_currentRowCount;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QColor>
|
||||
#include <QMutex>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include "RowCache.h"
|
||||
#include "sql/Query.h"
|
||||
@@ -81,8 +81,8 @@ public:
|
||||
/// configure for browsing results of specified query
|
||||
void setQuery(const QString& sQuery, const QString& sCountQuery = QString(), bool dontClearHeaders = false);
|
||||
|
||||
QString query() const { return m_sQuery; }
|
||||
QString customQuery(bool withRowid) const { return QString::fromStdString(m_query.buildQuery(withRowid)); }
|
||||
std::string query() const { return m_sQuery.toStdString(); }
|
||||
std::string customQuery(bool withRowid) const { return m_query.buildQuery(withRowid); }
|
||||
|
||||
/// configure for browsing specified table
|
||||
void setQuery(const sqlb::Query& query);
|
||||
@@ -162,7 +162,7 @@ private:
|
||||
void buildQuery();
|
||||
|
||||
/// \param pDb connection to query; if null, obtains it from 'm_db'.
|
||||
std::vector<std::string> getColumns(std::shared_ptr<sqlite3> pDb, const QString& sQuery, std::vector<int>& fieldsTypes);
|
||||
std::vector<std::string> getColumns(std::shared_ptr<sqlite3> pDb, const std::string& sQuery, std::vector<int>& fieldsTypes) const;
|
||||
|
||||
QByteArray encode(const QByteArray& str) const;
|
||||
QByteArray decode(const QByteArray& str) const;
|
||||
@@ -211,7 +211,7 @@ private:
|
||||
/**
|
||||
* These are used for multi-threaded population of the table
|
||||
*/
|
||||
mutable QMutex m_mutexDataCache;
|
||||
mutable std::mutex m_mutexDataCache;
|
||||
|
||||
private:
|
||||
/**
|
||||
|
||||
@@ -45,10 +45,6 @@ SqlTextEdit::SqlTextEdit(QWidget* parent) :
|
||||
reloadSettings();
|
||||
}
|
||||
|
||||
SqlTextEdit::~SqlTextEdit()
|
||||
{
|
||||
}
|
||||
|
||||
void SqlTextEdit::reloadSettings()
|
||||
{
|
||||
// Enable auto completion if it hasn't been disabled
|
||||
|
||||
@@ -15,7 +15,6 @@ class SqlTextEdit : public ExtendedScintilla
|
||||
|
||||
public:
|
||||
explicit SqlTextEdit(QWidget *parent = nullptr);
|
||||
~SqlTextEdit() override;
|
||||
|
||||
static SqlUiLexer* sqlLexer;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user