mirror of
https://github.com/sqlitebrowser/sqlitebrowser.git
synced 2026-01-20 11:00:44 -06:00
Merge branch 'sqlitebrowser-master'
Signed-off-by: Navdeep Singh Sidhu <deepsidhu1313@users.noreply.github.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
project(sqlitebrowser)
|
||||
cmake_minimum_required(VERSION 3.1.0)
|
||||
cmake_minimum_required(VERSION 2.8.12.2)
|
||||
|
||||
# BUILD_VERSION is the current date in YYYYMMDD format. It is only
|
||||
# used by the nightly version to add the date of the build.
|
||||
@@ -22,6 +22,7 @@ if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
endif()
|
||||
|
||||
add_definitions(-std=c++11)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.1.0)
|
||||
cmake_minimum_required(VERSION 2.8.12.2)
|
||||
|
||||
set(ANTLR_SRC
|
||||
src/ANTLRUtil.cpp
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.1.0)
|
||||
cmake_minimum_required(VERSION 2.8.12.2)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.1.0)
|
||||
cmake_minimum_required(VERSION 2.8.12.2)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.1.0)
|
||||
cmake_minimum_required(VERSION 2.8.12.2)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "AboutDialog.h"
|
||||
#include "ui_AboutDialog.h"
|
||||
#include "sqlite.h"
|
||||
#include "sqlitedb.h"
|
||||
#include "Application.h"
|
||||
|
||||
AboutDialog::AboutDialog(QWidget *parent) :
|
||||
@@ -11,13 +11,16 @@ AboutDialog::AboutDialog(QWidget *parent) :
|
||||
this->setFixedSize(this->width(), this->height());
|
||||
this->setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
||||
QString sqlite_version, sqlcipher_version;
|
||||
DBBrowserDB::getSqliteVersion(sqlite_version, sqlcipher_version);
|
||||
if(sqlcipher_version.isNull())
|
||||
sqlite_version = tr("SQLite Version ") + sqlite_version;
|
||||
else
|
||||
sqlite_version = tr("SQLCipher Version ") + sqlcipher_version + tr(" (based on SQLite %1)").arg(sqlite_version);
|
||||
|
||||
ui->label_version->setText(tr("Version ") + Application::versionString() + "\n\n" +
|
||||
tr("Qt Version ") + QT_VERSION_STR + "\n\n" +
|
||||
#ifdef ENABLE_SQLCIPHER
|
||||
tr("SQLCipher Version ") + SQLITE_VERSION
|
||||
#else
|
||||
tr("SQLite Version ") + SQLITE_VERSION
|
||||
#endif
|
||||
sqlite_version
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -601,33 +601,7 @@ void MainWindow::populateTable()
|
||||
m_browseTableModel->setTable(tablename, storedData.sortOrderIndex, storedData.sortOrderMode, v);
|
||||
|
||||
// There is information stored for this table, so extract it and apply it
|
||||
|
||||
// Show rowid column. Needs to be done before the column widths setting because of the workaround in there and before the filter setting
|
||||
// because of the filter row generation.
|
||||
showRowidColumn(storedData.showRowid);
|
||||
|
||||
// Enable editing in general and (un)lock view editing depending on the settings
|
||||
unlockViewEditing(!storedData.unlockViewPk.isEmpty(), storedData.unlockViewPk);
|
||||
|
||||
// Column hidden status
|
||||
on_actionShowAllColumns_triggered();
|
||||
for(auto hiddenIt=storedData.hiddenColumns.constBegin();hiddenIt!=storedData.hiddenColumns.constEnd();++hiddenIt)
|
||||
hideColumns(hiddenIt.key(), hiddenIt.value());
|
||||
|
||||
// Column widths
|
||||
for(auto widthIt=storedData.columnWidths.constBegin();widthIt!=storedData.columnWidths.constEnd();++widthIt)
|
||||
ui->dataTable->setColumnWidth(widthIt.key(), widthIt.value());
|
||||
|
||||
// Sorting
|
||||
ui->dataTable->filterHeader()->setSortIndicator(storedData.sortOrderIndex, storedData.sortOrderMode);
|
||||
|
||||
// Filters
|
||||
FilterTableHeader* filterHeader = qobject_cast<FilterTableHeader*>(ui->dataTable->horizontalHeader());
|
||||
for(auto filterIt=storedData.filterValues.constBegin();filterIt!=storedData.filterValues.constEnd();++filterIt)
|
||||
filterHeader->setFilter(filterIt.key(), filterIt.value());
|
||||
|
||||
// Encoding
|
||||
m_browseTableModel->setEncoding(storedData.encoding);
|
||||
applyBrowseTableSettings(storedData);
|
||||
|
||||
setRecordsetLabel();
|
||||
|
||||
@@ -653,6 +627,39 @@ void MainWindow::populateTable()
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
|
||||
void MainWindow::applyBrowseTableSettings(const BrowseDataTableSettings& storedData, bool skipFilters)
|
||||
{
|
||||
// Show rowid column. Needs to be done before the column widths setting because of the workaround in there and before the filter setting
|
||||
// because of the filter row generation.
|
||||
showRowidColumn(storedData.showRowid, skipFilters);
|
||||
|
||||
// Enable editing in general and (un)lock view editing depending on the settings
|
||||
unlockViewEditing(!storedData.unlockViewPk.isEmpty(), storedData.unlockViewPk);
|
||||
|
||||
// Column hidden status
|
||||
on_actionShowAllColumns_triggered();
|
||||
for(auto hiddenIt=storedData.hiddenColumns.constBegin();hiddenIt!=storedData.hiddenColumns.constEnd();++hiddenIt)
|
||||
hideColumns(hiddenIt.key(), hiddenIt.value());
|
||||
|
||||
// Column widths
|
||||
for(auto widthIt=storedData.columnWidths.constBegin();widthIt!=storedData.columnWidths.constEnd();++widthIt)
|
||||
ui->dataTable->setColumnWidth(widthIt.key(), widthIt.value());
|
||||
|
||||
// Sorting
|
||||
ui->dataTable->filterHeader()->setSortIndicator(storedData.sortOrderIndex, storedData.sortOrderMode);
|
||||
|
||||
// Filters
|
||||
if(!skipFilters)
|
||||
{
|
||||
FilterTableHeader* filterHeader = qobject_cast<FilterTableHeader*>(ui->dataTable->horizontalHeader());
|
||||
for(auto filterIt=storedData.filterValues.constBegin();filterIt!=storedData.filterValues.constEnd();++filterIt)
|
||||
filterHeader->setFilter(filterIt.key(), filterIt.value());
|
||||
}
|
||||
|
||||
// Encoding
|
||||
m_browseTableModel->setEncoding(storedData.encoding);
|
||||
}
|
||||
|
||||
bool MainWindow::fileClose()
|
||||
{
|
||||
// Close the database but stop the closing process here if the user pressed the cancel button in there
|
||||
@@ -1824,9 +1831,8 @@ void MainWindow::browseTableHeaderClicked(int logicalindex)
|
||||
|
||||
attachPlot(ui->dataTable, m_browseTableModel, &browseTableSettings[currentlyBrowsedTableName()]);
|
||||
|
||||
// This seems to be necessary as a workaround for newer Qt versions. Otherwise the rowid column is always shown after changing the data view.
|
||||
bool showRowid = browseTableSettings[currentlyBrowsedTableName()].showRowid;
|
||||
ui->dataTable->setColumnHidden(0, !showRowid);
|
||||
// Reapply the view settings. This seems to be necessary as a workaround for newer Qt versions.
|
||||
applyBrowseTableSettings(settings);
|
||||
}
|
||||
|
||||
void MainWindow::resizeEvent(QResizeEvent*)
|
||||
@@ -2218,7 +2224,16 @@ void MainWindow::on_actionBug_report_triggered()
|
||||
const QString kernelType = QSysInfo::kernelType();
|
||||
const QString kernelVersion = QSysInfo::kernelVersion();
|
||||
const QString arch = QSysInfo::currentCpuArchitecture();
|
||||
const QString body = QString("\n\n\n\n\n\n\n\n> DB4S v%1 on %2 (%3/%4) [%5]").arg(version, os, kernelType, kernelVersion, arch);
|
||||
|
||||
QString sqlite_version, sqlcipher_version;
|
||||
DBBrowserDB::getSqliteVersion(sqlite_version, sqlcipher_version);
|
||||
if(sqlcipher_version.isNull())
|
||||
sqlite_version = QString("SQLite Version ") + sqlite_version;
|
||||
else
|
||||
sqlite_version = QString("SQLCipher Version ") + sqlcipher_version + QString(" (based on SQLite %1)").arg(sqlite_version);
|
||||
|
||||
const QString body = QString("\n\n\n\n\n\n\n\n> DB4S v%1 on %2 (%3/%4) [%5]\n> using %6\n> and Qt %7")
|
||||
.arg(version, os, kernelType, kernelVersion, arch, sqlite_version, QT_VERSION_STR);
|
||||
|
||||
QUrlQuery query;
|
||||
query.addQueryItem("labels", "bug");
|
||||
@@ -2666,12 +2681,12 @@ void MainWindow::fileAttach()
|
||||
void MainWindow::updateFilter(int column, const QString& value)
|
||||
{
|
||||
m_browseTableModel->updateFilter(column, value);
|
||||
browseTableSettings[currentlyBrowsedTableName()].filterValues[column] = value;
|
||||
BrowseDataTableSettings& settings = browseTableSettings[currentlyBrowsedTableName()];
|
||||
settings.filterValues[column] = value;
|
||||
setRecordsetLabel();
|
||||
|
||||
// This seems to be necessary as a workaround for newer Qt versions. Otherwise the rowid column is always shown after changing the data view.
|
||||
bool showRowid = browseTableSettings[currentlyBrowsedTableName()].showRowid;
|
||||
ui->dataTable->setColumnHidden(0, !showRowid);
|
||||
// Reapply the view settings. This seems to be necessary as a workaround for newer Qt versions.
|
||||
applyBrowseTableSettings(settings, true);
|
||||
}
|
||||
|
||||
void MainWindow::editEncryption()
|
||||
@@ -2890,7 +2905,7 @@ void MainWindow::editDataColumnDisplayFormat()
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::showRowidColumn(bool show)
|
||||
void MainWindow::showRowidColumn(bool show, bool skipFilters)
|
||||
{
|
||||
// Block all signals from the horizontal header. Otherwise the QHeaderView::sectionResized signal causes us trouble
|
||||
ui->dataTable->horizontalHeader()->blockSignals(true);
|
||||
@@ -2915,7 +2930,8 @@ void MainWindow::showRowidColumn(bool show)
|
||||
browseTableSettings[current_table].showRowid = show;
|
||||
|
||||
// Update the filter row
|
||||
qobject_cast<FilterTableHeader*>(ui->dataTable->horizontalHeader())->generateFilters(m_browseTableModel->columnCount(), show);
|
||||
if(!skipFilters)
|
||||
qobject_cast<FilterTableHeader*>(ui->dataTable->horizontalHeader())->generateFilters(m_browseTableModel->columnCount(), show);
|
||||
|
||||
// Re-enable signals
|
||||
ui->dataTable->horizontalHeader()->blockSignals(false);
|
||||
@@ -3040,11 +3056,11 @@ void MainWindow::unlockViewEditing(bool unlock, QString pk)
|
||||
ui->actionUnlockViewEditing->blockSignals(false);
|
||||
|
||||
// Save settings for this table
|
||||
browseTableSettings[currentTable].unlockViewPk = pk;
|
||||
BrowseDataTableSettings& settings = browseTableSettings[currentTable];
|
||||
settings.unlockViewPk = pk;
|
||||
|
||||
// This seems to be necessary as a workaround for newer Qt versions. Otherwise the rowid column is always shown after changing the data view.
|
||||
bool showRowid = browseTableSettings[currentlyBrowsedTableName()].showRowid;
|
||||
ui->dataTable->setColumnHidden(0, !showRowid);
|
||||
// Reapply the view settings. This seems to be necessary as a workaround for newer Qt versions.
|
||||
applyBrowseTableSettings(settings);
|
||||
}
|
||||
|
||||
sqlb::ObjectIdentifier MainWindow::currentlyBrowsedTableName() const
|
||||
|
||||
@@ -193,6 +193,8 @@ private:
|
||||
|
||||
StatementType getQueryType(const QString& query) const;
|
||||
|
||||
void applyBrowseTableSettings(const BrowseDataTableSettings& storedData, bool skipFilters = false);
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *);
|
||||
void dragEnterEvent(QDragEnterEvent *event);
|
||||
@@ -277,7 +279,7 @@ private slots:
|
||||
void showDataColumnPopupMenu(const QPoint& pos);
|
||||
void showRecordPopupMenu(const QPoint& pos);
|
||||
void editDataColumnDisplayFormat();
|
||||
void showRowidColumn(bool show);
|
||||
void showRowidColumn(bool show, bool skipFilters = false);
|
||||
void browseDataSetTableEncoding(bool forAllTables = false);
|
||||
void browseDataSetDefaultTableEncoding();
|
||||
void fileOpenReadOnly();
|
||||
|
||||
@@ -375,6 +375,32 @@ bool DBBrowserDB::tryEncryptionSettings(const QString& filePath, bool* encrypted
|
||||
}
|
||||
}
|
||||
|
||||
void DBBrowserDB::getSqliteVersion(QString& sqlite, QString& sqlcipher)
|
||||
{
|
||||
sqlite = QString(SQLITE_VERSION);
|
||||
|
||||
// The SQLCipher version must be queried via a pragma and for a pragma we need a database connection.
|
||||
// Because we want to be able to query the SQLCipher version without opening a database file first, we
|
||||
// open a separate connection to an in-memory database here.
|
||||
sqlcipher = QString();
|
||||
#ifdef ENABLE_SQLCIPHER
|
||||
sqlite3* dummy;
|
||||
if(sqlite3_open(":memory:", &dummy) == SQLITE_OK)
|
||||
{
|
||||
sqlite3_stmt* stmt;
|
||||
if(sqlite3_prepare_v2(dummy, "PRAGMA cipher_version", -1, &stmt, nullptr) == SQLITE_OK)
|
||||
{
|
||||
if(sqlite3_step(stmt) == SQLITE_ROW)
|
||||
sqlcipher = QByteArray(static_cast<const char*>(sqlite3_column_blob(stmt, 0)), sqlite3_column_bytes(stmt, 0));
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
}
|
||||
|
||||
sqlite3_close(dummy);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool DBBrowserDB::setSavepoint(const QString& pointname)
|
||||
{
|
||||
if(!isOpen())
|
||||
@@ -639,11 +665,8 @@ bool DBBrowserDB::dump(const QString& filePath,
|
||||
it.remove();
|
||||
} else {
|
||||
// Otherwise get the number of records in this table
|
||||
SqliteTableModel m(*this);
|
||||
m.setQuery(QString("SELECT COUNT(*) FROM %1;")
|
||||
.arg(sqlb::ObjectIdentifier("main", it.value()->name()).toString()));
|
||||
if(m.completeCache())
|
||||
numRecordsTotal += m.data(m.index(0, 0)).toUInt();
|
||||
numRecordsTotal += querySingeValueFromDb(QString("SELECT COUNT(*) FROM %1;")
|
||||
.arg(sqlb::ObjectIdentifier("main", it.value()->name()).toString())).toUInt();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -955,6 +978,37 @@ bool DBBrowserDB::executeMultiSQL(const QString& statement, bool dirty, bool log
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariant DBBrowserDB::querySingeValueFromDb(const QString& statement, bool log)
|
||||
{
|
||||
waitForDbRelease();
|
||||
if(!_db)
|
||||
return QVariant();
|
||||
|
||||
if(log)
|
||||
logSQL(statement, kLogMsg_App);
|
||||
|
||||
QByteArray utf8Query = statement.toUtf8();
|
||||
sqlite3_stmt* stmt;
|
||||
if(sqlite3_prepare_v2(_db, utf8Query, utf8Query.size(), &stmt, nullptr) == SQLITE_OK)
|
||||
{
|
||||
if(sqlite3_step(stmt) == SQLITE_ROW)
|
||||
{
|
||||
if(sqlite3_column_count(stmt) > 0 && sqlite3_column_type(stmt, 0) != SQLITE_NULL)
|
||||
{
|
||||
int bytes = sqlite3_column_bytes(stmt, 0);
|
||||
if(bytes)
|
||||
return QByteArray(static_cast<const char*>(sqlite3_column_blob(stmt, 0)), bytes);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool DBBrowserDB::getRow(const sqlb::ObjectIdentifier& table, const QString& rowid, QVector<QByteArray>& rowdata)
|
||||
{
|
||||
waitForDbRelease();
|
||||
|
||||
@@ -61,6 +61,9 @@ public:
|
||||
bool create ( const QString & db);
|
||||
bool close();
|
||||
|
||||
// This returns the SQLite version as well as the SQLCipher if DB4S is compiled with encryption support
|
||||
static void getSqliteVersion(QString& sqlite, QString& sqlcipher);
|
||||
|
||||
typedef std::unique_ptr<sqlite3, DatabaseReleaser> db_pointer_type;
|
||||
|
||||
/**
|
||||
@@ -88,9 +91,13 @@ public:
|
||||
bool revertToSavepoint(const QString& 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 executeSQL(QString statement, bool dirtyDB = true, bool logsql = true);
|
||||
bool executeMultiSQL(const QString& statement, bool dirty = true, bool log = false);
|
||||
QVariant querySingeValueFromDb(const QString& statement, bool log = true);
|
||||
|
||||
const QString& lastError() const { return lastErrorMessage; }
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user