mirror of
https://github.com/sqlitebrowser/sqlitebrowser.git
synced 2026-01-19 18:40:13 -06:00
Add some basic initial support for SQLCipher. Note that this is more of a POC than a final implementation. This commit adds an option called 'sqlcipher' to the cmake and qmake projects which - when enabled - replaces the default SQLite3 include and library files by their SQLCipher counter-parts. Especially on MacOS X there might be some more work required in finding the correct include paths. The SQLCipher library supports unencrypted databases, too, so even if the option is enabled the program behaves like before. You can see the difference, though, in the About Dialog where the SQLite version string will say 'SQLCipher version xy'. When the sqlcipher option is enabled and you try to open a file which is neither a project file nor a normal SQLite3 database it is assumed now that the file is an encypted database. There is no way to tell between an invalid file and an encypted file, so in both cases a password dialog pops up. When the correct password and page size are entered the file is opened and can be edited like any other database before. Creating encrypted databases isn't supported yet. So for testing you need to fall back to the sqlcipher command line tool. See issue #12.
153 lines
5.7 KiB
C++
153 lines
5.7 KiB
C++
#include "ExportCsvDialog.h"
|
|
#include "ui_ExportCsvDialog.h"
|
|
#include "sqlitedb.h"
|
|
#include "PreferencesDialog.h"
|
|
#include "sqlitetablemodel.h"
|
|
#include "sqlite.h"
|
|
|
|
#include <QFile>
|
|
#include <QTextStream>
|
|
#include <QMessageBox>
|
|
#include <QFileDialog>
|
|
|
|
ExportCsvDialog::ExportCsvDialog(DBBrowserDB* db, QWidget* parent, const QString& query, const QString& selection)
|
|
: QDialog(parent),
|
|
ui(new Ui::ExportCsvDialog),
|
|
pdb(db),
|
|
m_sQuery(query)
|
|
{
|
|
// Create UI
|
|
ui->setupUi(this);
|
|
showCustomCharEdits();
|
|
|
|
// If a SQL query was specified hide the table combo box. If not fill it with tables to export
|
|
if(query.isEmpty())
|
|
{
|
|
// Get list of tables to export
|
|
objectMap objects = pdb->getBrowsableObjects();
|
|
for(objectMap::ConstIterator i=objects.begin();i!=objects.end();++i)
|
|
ui->comboTable->addItem(QIcon(QString(":icons/%1").arg(i.value().gettype())), i.value().getname());
|
|
|
|
// Sort list of tables and select the table specified in the selection parameter or alternatively the first one
|
|
ui->comboTable->model()->sort(0);
|
|
if(selection.isEmpty())
|
|
ui->comboTable->setCurrentIndex(0);
|
|
else
|
|
ui->comboTable->setCurrentIndex(ui->comboTable->findText(selection));
|
|
} else {
|
|
// Hide table combo box
|
|
ui->labelTable->setVisible(false);
|
|
ui->comboTable->setVisible(false);
|
|
}
|
|
}
|
|
|
|
ExportCsvDialog::~ExportCsvDialog()
|
|
{
|
|
delete ui;
|
|
}
|
|
|
|
void ExportCsvDialog::accept()
|
|
{
|
|
// Get filename
|
|
QString fileName = QFileDialog::getSaveFileName(
|
|
this,
|
|
tr("Choose a filename to export data"),
|
|
PreferencesDialog::getSettingsValue("db", "defaultlocation").toString(),
|
|
tr("Text files(*.csv *.txt)"));
|
|
|
|
// Only if the user hasn't clicked the cancel button
|
|
if(fileName.size() > 0)
|
|
{
|
|
if(m_sQuery.isEmpty())
|
|
{
|
|
m_sQuery = QString("SELECT * from `%1`;").arg(ui->comboTable->currentText());
|
|
}
|
|
|
|
// Prepare the quote and separating characters
|
|
QString quoteChar = ui->comboQuoteCharacter->currentIndex() == ui->comboQuoteCharacter->count()-1
|
|
? ui->editCustomQuote->text() : ui->comboQuoteCharacter->currentText();
|
|
QString quotequoteChar = quoteChar + quoteChar;
|
|
QString sepChar;
|
|
if(ui->comboFieldSeparator->currentIndex() == ui->comboFieldSeparator->count()-1)
|
|
{
|
|
sepChar = ui->editCustomSeparator->text();
|
|
} else {
|
|
sepChar = ui->comboFieldSeparator->currentText();
|
|
if(sepChar == tr("Tab")) sepChar = "\t";
|
|
}
|
|
QString newlineChar = "\r\n";
|
|
|
|
// Open file
|
|
QFile file(fileName);
|
|
if(file.open(QIODevice::WriteOnly))
|
|
{
|
|
// Open text stream to the file
|
|
QTextStream stream(&file);
|
|
|
|
QByteArray utf8Query = m_sQuery.toUtf8();
|
|
sqlite3_stmt *stmt;
|
|
|
|
int status = sqlite3_prepare_v2(pdb->_db, utf8Query.data(), utf8Query.size(), &stmt, NULL);
|
|
if(SQLITE_OK == status)
|
|
{
|
|
if(ui->checkHeader->isChecked())
|
|
{
|
|
int columns = sqlite3_column_count(stmt);
|
|
for (int i = 0; i < columns; ++i)
|
|
{
|
|
QString content = QString::fromUtf8(sqlite3_column_name(stmt, i));
|
|
if(content.contains(quoteChar) || content.contains(newlineChar))
|
|
stream << quoteChar << content.replace(quoteChar, quotequoteChar) << quoteChar;
|
|
else
|
|
stream << content;
|
|
if(i != columns - 1)
|
|
stream << sepChar;
|
|
}
|
|
stream << newlineChar;
|
|
}
|
|
|
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
|
int columns = sqlite3_column_count(stmt);
|
|
size_t counter = 0;
|
|
while(sqlite3_step(stmt) == SQLITE_ROW)
|
|
{
|
|
for (int i = 0; i < columns; ++i)
|
|
{
|
|
QString content = QString::fromUtf8(
|
|
(const char*)sqlite3_column_blob(stmt, i),
|
|
sqlite3_column_bytes(stmt, i));
|
|
if(content.contains(quoteChar) || content.contains("\r\n") || content.contains('\n'))
|
|
stream << quoteChar << content.replace(quoteChar, quotequoteChar) << quoteChar;
|
|
else
|
|
stream << content;
|
|
if(i != columns - 1)
|
|
stream << sepChar;
|
|
}
|
|
stream << newlineChar;
|
|
if(counter % 1000 == 0)
|
|
qApp->processEvents();
|
|
counter++;
|
|
}
|
|
}
|
|
sqlite3_finalize(stmt);
|
|
|
|
QApplication::restoreOverrideCursor();
|
|
qApp->processEvents();
|
|
|
|
// Done writing the file
|
|
file.close();
|
|
QMessageBox::information(this, QApplication::applicationName(), tr("Export completed."));
|
|
QDialog::accept();
|
|
} else {
|
|
QMessageBox::warning(this, QApplication::applicationName(), tr("Could not open output file."));
|
|
}
|
|
}
|
|
}
|
|
|
|
void ExportCsvDialog::showCustomCharEdits()
|
|
{
|
|
// Show/hide custom quote/separator input fields
|
|
ui->editCustomQuote->setVisible(ui->comboQuoteCharacter->currentIndex() == ui->comboQuoteCharacter->count()-1);
|
|
ui->editCustomSeparator->setVisible(ui->comboFieldSeparator->currentIndex() == ui->comboFieldSeparator->count()-1);
|
|
}
|