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:
Martin Kleusberg
2019-10-17 14:34:51 +02:00
parent b3b1ac6946
commit ba1270cedb
66 changed files with 673 additions and 833 deletions

View File

@@ -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());
}
}

View File

@@ -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);

View File

@@ -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; }

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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

View File

@@ -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)

View File

@@ -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();
}
}

View File

@@ -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; }

View File

@@ -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;

View File

@@ -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,

View File

@@ -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";
}

View File

@@ -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

View File

@@ -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()

View File

@@ -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()

View File

@@ -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);

View File

@@ -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()));

View File

@@ -39,7 +39,7 @@ private:
sqlb::Index index;
bool newIndex;
Ui::EditIndexDialog* ui;
QString m_sRestorePointName;
std::string m_sRestorePointName;
void updateColumnLists();
void updateSqlText();

View File

@@ -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);
}
}

View File

@@ -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;
};

View File

@@ -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));
}
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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:

View File

@@ -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()

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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();
}
}

View File

@@ -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;
}

View File

@@ -15,7 +15,7 @@ public:
explicit FileExtensionManager(QStringList init, QWidget *parent = nullptr);
~FileExtensionManager() override;
QStringList getDBFileExtensions();
QStringList getDBFileExtensions() const;
private:
Ui::FileExtensionManager *ui;

View File

@@ -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()

View File

@@ -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;

View File

@@ -12,7 +12,6 @@ FindReplaceDialog::FindReplaceDialog(QWidget* parent)
{
// Create UI
ui->setupUi(this);
}
FindReplaceDialog::~FindReplaceDialog()

View File

@@ -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();
}

View File

@@ -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 {};
}
}

View File

@@ -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;
};

View File

@@ -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);
}
}

View File

@@ -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();

View File

@@ -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) {

View File

@@ -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:

View File

@@ -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;

View File

@@ -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

View File

@@ -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.

View File

@@ -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

View File

@@ -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;

View File

@@ -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));
}

View File

@@ -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 &);

View File

@@ -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")

View File

@@ -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);

View File

@@ -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

View 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)}");

View File

@@ -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:

View File

@@ -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>

View File

@@ -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();

View File

@@ -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;

View File

@@ -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();
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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)

File diff suppressed because it is too large Load Diff

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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:
/**

View File

@@ -45,10 +45,6 @@ SqlTextEdit::SqlTextEdit(QWidget* parent) :
reloadSettings();
}
SqlTextEdit::~SqlTextEdit()
{
}
void SqlTextEdit::reloadSettings()
{
// Enable auto completion if it hasn't been disabled

View File

@@ -15,7 +15,6 @@ class SqlTextEdit : public ExtendedScintilla
public:
explicit SqlTextEdit(QWidget *parent = nullptr);
~SqlTextEdit() override;
static SqlUiLexer* sqlLexer;