mirror of
https://github.com/sqlitebrowser/sqlitebrowser.git
synced 2026-01-20 02:50:46 -06:00
Add a row of line edits between the table header and the actual content of the table in the browse tab. Show one input widget per table column in this row. Add a live search which hides any table rows which do not fit to the current filter settings. Why add this to the parital-data-fetch branch? Because this is an attempt to get rid of the find dialog which is broken again and not even worth fixing. Also there is not much to break in this branch at the moment ;)
1164 lines
42 KiB
C++
1164 lines
42 KiB
C++
#include "MainWindow.h"
|
|
#include "ui_MainWindow.h"
|
|
#include <QFileDialog>
|
|
#include <QFile>
|
|
#include <QApplication>
|
|
#include <QTextStream>
|
|
#include <QWhatsThis>
|
|
#include <QMessageBox>
|
|
#include <QUrl>
|
|
#include <QStandardItemModel>
|
|
#include <QDragEnterEvent>
|
|
#include <QScrollBar>
|
|
#include <QSortFilterProxyModel>
|
|
|
|
#include "CreateIndexDialog.h"
|
|
#include "AboutDialog.h"
|
|
#include "EditTableDialog.h"
|
|
#include "ImportCsvDialog.h"
|
|
#include "ExportCsvDialog.h"
|
|
#include "PreferencesDialog.h"
|
|
#include "EditDialog.h"
|
|
#include "FindDialog.h"
|
|
#include "SQLiteSyntaxHighlighter.h"
|
|
#include "sqltextedit.h"
|
|
#include "sqlitetablemodel.h"
|
|
#include "FilterTableHeader.h"
|
|
|
|
MainWindow::MainWindow(QWidget* parent)
|
|
: QMainWindow(parent),
|
|
ui(new Ui::MainWindow),
|
|
m_browseTableModel(new SqliteTableModel(this, &db)),
|
|
sqliteHighlighterTabSql(0),
|
|
sqliteHighlighterLogUser(0),
|
|
sqliteHighlighterLogApp(0),
|
|
editWin(new EditDialog(this)),
|
|
findWin(0),
|
|
gotoValidator(new QIntValidator(0, 0, this))
|
|
{
|
|
ui->setupUi(this);
|
|
init();
|
|
|
|
activateFields(false);
|
|
resetBrowser();
|
|
updateRecentFileActions();
|
|
}
|
|
|
|
MainWindow::~MainWindow()
|
|
{
|
|
delete gotoValidator;
|
|
delete ui;
|
|
}
|
|
|
|
void MainWindow::init()
|
|
{
|
|
// Init the SQL log dock
|
|
db.mainWindow = this;
|
|
|
|
// Set up the db tree widget
|
|
ui->dbTreeWidget->setColumnHidden(1, true);
|
|
ui->dbTreeWidget->setColumnWidth(0, 300);
|
|
|
|
// Set the validator for the goto line edit
|
|
ui->editGoto->setValidator(gotoValidator);
|
|
|
|
// Create the SQL sytax highlighters
|
|
createSyntaxHighlighters();
|
|
|
|
// Set up DB models
|
|
ui->dataTable->setModel(m_browseTableModel);
|
|
|
|
queryResultListModel = new QStandardItemModel(this);
|
|
ui->queryResultTableView->setModel(queryResultListModel);
|
|
|
|
FilterTableHeader* tableHeader = new FilterTableHeader(ui->dataTable);
|
|
connect(tableHeader, SIGNAL(filterChanged(int,QString)), m_browseTableModel, SLOT(updateFilter(int,QString)));
|
|
ui->dataTable->setHorizontalHeader(tableHeader);
|
|
|
|
// Create the actions for the recently opened dbs list
|
|
for(int i = 0; i < MaxRecentFiles; ++i) {
|
|
recentFileActs[i] = new QAction(this);
|
|
recentFileActs[i]->setVisible(false);
|
|
connect(recentFileActs[i], SIGNAL(triggered()), this, SLOT(openRecentFile()));
|
|
}
|
|
for(int i = 0; i < MaxRecentFiles; ++i)
|
|
ui->fileMenu->insertAction(ui->fileExitAction, recentFileActs[i]);
|
|
recentSeparatorAct = ui->fileMenu->insertSeparator(ui->fileExitAction);
|
|
|
|
// Create popup menus
|
|
popupTableMenu = new QMenu(this);
|
|
popupTableMenu->addAction(ui->editModifyTableAction);
|
|
popupTableMenu->addSeparator();
|
|
popupTableMenu->addAction(ui->editDeleteObjectAction);
|
|
|
|
// Set state of checkable menu actions
|
|
ui->sqlLogAction->setChecked(!ui->dockLog->isHidden());
|
|
ui->viewDBToolbarAction->setChecked(!ui->toolbarDB->isHidden());
|
|
|
|
// Set statusbar fields
|
|
statusEncodingLabel = new QLabel(ui->statusbar);
|
|
statusEncodingLabel->setEnabled(false);
|
|
statusEncodingLabel->setText("UTF-8");
|
|
statusEncodingLabel->setToolTip(tr("Database encoding"));
|
|
ui->statusbar->addPermanentWidget(statusEncodingLabel);
|
|
|
|
// Connect some more signals and slots
|
|
connect(tableHeader, SIGNAL(sectionClicked(int)), this, SLOT(browseTableHeaderClicked(int)));
|
|
connect(ui->dataTable->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(setRecordsetLabel()));
|
|
connect(editWin, SIGNAL(goingAway()), this, SLOT(editWinAway()));
|
|
connect(editWin, SIGNAL(updateRecordText(int, int, QByteArray)), this, SLOT(updateRecordText(int, int, QByteArray)));
|
|
|
|
// Load window settings
|
|
restoreGeometry(PreferencesDialog::getSettingsValue("MainWindow", "geometry").toByteArray());
|
|
restoreState(PreferencesDialog::getSettingsValue("MainWindow", "windowState").toByteArray());
|
|
ui->comboLogSubmittedBy->setCurrentIndex(ui->comboLogSubmittedBy->findText(PreferencesDialog::getSettingsValue("SQLLogDock", "Log").toString()));
|
|
|
|
// Set other window settings
|
|
setAcceptDrops(true);
|
|
setWindowTitle(QApplication::applicationName());
|
|
|
|
// Fonts for edit fields
|
|
QFont font("Monospace");
|
|
font.setStyleHint(QFont::TypeWriter);
|
|
font.setPointSize(8);
|
|
ui->sqlTextEdit->setFont(font);
|
|
ui->editLogApplication->setFont(font);
|
|
ui->editLogUser->setFont(font);
|
|
}
|
|
|
|
//***********************************************************
|
|
//*** Open File
|
|
void MainWindow::fileOpen(const QString & fileName)
|
|
{
|
|
QString wFile = fileName;
|
|
if (!QFile::exists(wFile))
|
|
{
|
|
wFile = QFileDialog::getOpenFileName(
|
|
this,
|
|
tr("Choose a database file"),
|
|
PreferencesDialog::getSettingsValue("db", "defaultlocation").toString());
|
|
}
|
|
if(QFile::exists(wFile) )
|
|
{
|
|
fileClose();
|
|
if(db.open(wFile))
|
|
{
|
|
statusEncodingLabel->setText(db.getPragma("encoding"));
|
|
setCurrentFile(wFile);
|
|
} else {
|
|
QString err = tr("An error occurred: %1").arg(db.lastErrorMessage);
|
|
QMessageBox::warning(this, QApplication::applicationName(), err);
|
|
}
|
|
populateStructure();
|
|
resetBrowser();
|
|
if(ui->mainTab->currentIndex() == 2)
|
|
loadPragmas();
|
|
}
|
|
}
|
|
|
|
void MainWindow::fileOpen()
|
|
{
|
|
fileOpen(QString());
|
|
}
|
|
|
|
void MainWindow::fileNew()
|
|
{
|
|
QString fileName = QFileDialog::getSaveFileName(this, tr("Choose a filename to save under"), PreferencesDialog::getSettingsValue("db", "defaultlocation").toString());
|
|
if(!fileName.isEmpty())
|
|
{
|
|
if(QFile::exists(fileName))
|
|
QFile::remove(fileName);
|
|
db.create(fileName);
|
|
setCurrentFile(fileName);
|
|
statusEncodingLabel->setText(db.getPragma("encoding"));
|
|
populateStructure();
|
|
resetBrowser();
|
|
createTable();
|
|
}
|
|
}
|
|
|
|
//** Populate DbTree Structure
|
|
void MainWindow::populateStructure()
|
|
{
|
|
ui->dbTreeWidget->model()->removeRows(0, ui->dbTreeWidget->model()->rowCount());
|
|
ui->sqlTextEdit->clearFieldCompleterModelMap();
|
|
ui->sqlTextEdit->setDefaultCompleterModel(new QStandardItemModel());
|
|
if (!db.isOpen()){
|
|
return;
|
|
}
|
|
db.updateSchema();
|
|
QStringList tblnames = db.getBrowsableObjectNames();
|
|
sqliteHighlighterTabSql->setTableNames(tblnames);
|
|
sqliteHighlighterLogUser->setTableNames(tblnames);
|
|
sqliteHighlighterLogApp->setTableNames(tblnames);
|
|
|
|
// setup models for sqltextedit autocomplete
|
|
QStandardItemModel* completerModel = new QStandardItemModel();
|
|
completerModel->setRowCount(tblnames.count());
|
|
completerModel->setColumnCount(1);
|
|
|
|
objectMap tab = db.getBrowsableObjects();
|
|
int row = 0;
|
|
for(objectMap::ConstIterator it=tab.begin(); it!=tab.end(); ++it, ++row)
|
|
{
|
|
QString sName = it.value().getname();
|
|
QStandardItem* item = new QStandardItem(sName);
|
|
item->setIcon(QIcon(QString(":icons/%1").arg(it.value().gettype())));
|
|
completerModel->setItem(row, 0, item);
|
|
|
|
// If it is a table add the field Nodes
|
|
if((*it).gettype() == "table" || (*it).gettype() == "view")
|
|
{
|
|
QStandardItemModel* tablefieldmodel = new QStandardItemModel();
|
|
tablefieldmodel->setRowCount((*it).fldmap.count());
|
|
tablefieldmodel->setColumnCount(1);
|
|
|
|
fieldMap::ConstIterator fit;
|
|
int fldrow = 0;
|
|
for ( fit = (*it).fldmap.begin(); fit != (*it).fldmap.end(); ++fit, ++fldrow ) {
|
|
QString fieldname = fit.value().getname();
|
|
QStandardItem* fldItem = new QStandardItem(fieldname);
|
|
fldItem->setIcon(QIcon(":/icons/field"));
|
|
tablefieldmodel->setItem(fldrow, 0, fldItem);
|
|
}
|
|
ui->sqlTextEdit->addFieldCompleterModel(sName.toLower(), tablefieldmodel);
|
|
}
|
|
|
|
}
|
|
ui->sqlTextEdit->setDefaultCompleterModel(completerModel);
|
|
// end setup models for sqltextedit autocomplete
|
|
|
|
// fill the structure tab
|
|
QMap<QString, QTreeWidgetItem*> typeToParentItem;
|
|
QTreeWidgetItem* itemTables = new QTreeWidgetItem(ui->dbTreeWidget);
|
|
itemTables->setIcon(0, QIcon(QString(":/icons/table")));
|
|
itemTables->setText(0, tr("Tables (%1)").arg(db.objMap.values("table").count()));
|
|
typeToParentItem.insert("table", itemTables);
|
|
QTreeWidgetItem* itemIndices = new QTreeWidgetItem(ui->dbTreeWidget);
|
|
itemIndices->setIcon(0, QIcon(QString(":/icons/index")));
|
|
itemIndices->setText(0, tr("Indices (%1)").arg(db.objMap.values("index").count()));
|
|
typeToParentItem.insert("index", itemIndices);
|
|
QTreeWidgetItem* itemViews = new QTreeWidgetItem(ui->dbTreeWidget);
|
|
itemViews->setIcon(0, QIcon(QString(":/icons/view")));
|
|
itemViews->setText(0, tr("Views (%1)").arg(db.objMap.values("view").count()));
|
|
typeToParentItem.insert("view", itemViews);
|
|
QTreeWidgetItem* itemTriggers = new QTreeWidgetItem(ui->dbTreeWidget);
|
|
itemTriggers->setIcon(0, QIcon(QString(":/icons/trigger")));
|
|
itemTriggers->setText(0, tr("Triggers (%1)").arg(db.objMap.values("trigger").count()));
|
|
typeToParentItem.insert("trigger", itemTriggers);
|
|
ui->dbTreeWidget->setItemExpanded(itemTables, true);
|
|
ui->dbTreeWidget->setItemExpanded(itemIndices, true);
|
|
ui->dbTreeWidget->setItemExpanded(itemViews, true);
|
|
ui->dbTreeWidget->setItemExpanded(itemTriggers, true);
|
|
|
|
for(objectMap::ConstIterator it=db.objMap.begin();it!=db.objMap.end();++it)
|
|
{
|
|
// Object node
|
|
QTreeWidgetItem *tableItem = new QTreeWidgetItem(typeToParentItem.value((*it).gettype()));
|
|
tableItem->setIcon(0, QIcon(QString(":/icons/%1").arg((*it).gettype())));
|
|
tableItem->setText(0, (*it).getname());
|
|
tableItem->setText(1, (*it).gettype());
|
|
tableItem->setText(3, (*it).getsql());
|
|
|
|
// If it is a table add the field Nodes
|
|
if((*it).gettype() == "table" || (*it).gettype() == "view")
|
|
{
|
|
fieldMap::ConstIterator fit;
|
|
for ( fit = (*it).fldmap.begin(); fit != (*it).fldmap.end(); ++fit ) {
|
|
QTreeWidgetItem *fldItem = new QTreeWidgetItem(tableItem);
|
|
fldItem->setText(0, fit.value().getname());
|
|
fldItem->setText(1, "field");
|
|
fldItem->setText(2, fit.value().gettype());
|
|
fldItem->setIcon(0, QIcon(":/icons/field"));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::populateTable( const QString & tablename)
|
|
{
|
|
// Remove the model-view link if the table name is empty in order to remove any data from the view
|
|
if(tablename.isEmpty())
|
|
{
|
|
ui->dataTable->setModel(0);
|
|
return;
|
|
}
|
|
|
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
|
|
|
// Set model
|
|
ui->dataTable->setModel(m_browseTableModel);
|
|
|
|
// Set new table
|
|
m_browseTableModel->setTable(tablename);
|
|
ui->dataTable->setColumnHidden(0, true);
|
|
|
|
// Reset sorting
|
|
curBrowseOrderByIndex = 0;
|
|
curBrowseOrderByMode = Qt::AscendingOrder;
|
|
m_browseTableModel->sort(curBrowseOrderByIndex, curBrowseOrderByMode);
|
|
|
|
// Get table layout
|
|
db.browseTable(tablename);
|
|
|
|
// Update the filter row
|
|
qobject_cast<FilterTableHeader*>(ui->dataTable->horizontalHeader())->generateFilters(m_browseTableModel->columnCount());
|
|
|
|
// Activate the add and delete record buttons and editing only if a table has been selected
|
|
bool is_table = db.getObjectByName(tablename).gettype() == "table";
|
|
ui->buttonNewRecord->setEnabled(is_table);
|
|
ui->buttonDeleteRecord->setEnabled(is_table);
|
|
ui->dataTable->setEditTriggers(is_table ? QAbstractItemView::DoubleClicked | QAbstractItemView::AnyKeyPressed | QAbstractItemView::EditKeyPressed : QAbstractItemView::NoEditTriggers);
|
|
|
|
// Set the recordset label
|
|
setRecordsetLabel();
|
|
|
|
//got to keep findWin in synch
|
|
if(findWin)
|
|
findWin->resetFields();
|
|
if(editWin)
|
|
editWin->reset();
|
|
|
|
QApplication::restoreOverrideCursor();
|
|
}
|
|
|
|
void MainWindow::resetBrowser()
|
|
{
|
|
QString sCurrentTable = ui->comboBrowseTable->currentText();
|
|
ui->comboBrowseTable->clear();
|
|
objectMap tab = db.getBrowsableObjects();
|
|
for(objectMap::ConstIterator i=tab.begin();i!=tab.end();++i)
|
|
{
|
|
ui->comboBrowseTable->addItem(QIcon(QString(":icons/%1").arg(i.value().gettype())), i.value().getname());
|
|
|
|
//ui->comboBrowseTable->addItems(tab);
|
|
}
|
|
setRecordsetLabel();
|
|
int pos = ui->comboBrowseTable->findText(sCurrentTable);
|
|
pos = pos == -1 ? 0 : pos;
|
|
ui->comboBrowseTable->setCurrentIndex(pos);
|
|
curBrowseOrderByIndex = 0;
|
|
curBrowseOrderByMode = Qt::AscendingOrder;
|
|
m_browseTableModel->sort(curBrowseOrderByIndex, curBrowseOrderByMode);
|
|
populateTable(ui->comboBrowseTable->currentText());
|
|
}
|
|
|
|
void MainWindow::fileClose()
|
|
{
|
|
db.close();
|
|
setWindowTitle(QApplication::applicationName());
|
|
resetBrowser();
|
|
populateStructure();
|
|
loadPragmas();
|
|
activateFields(false);
|
|
ui->buttonLogClear->click();
|
|
}
|
|
|
|
void MainWindow::fileExit()
|
|
{
|
|
if (db.isOpen())
|
|
{
|
|
if (db.getDirty())
|
|
{
|
|
QString msg = tr("Do you want to save the changes made to the database file %1?").arg(db.curDBFilename);
|
|
if(QMessageBox::question( this, QApplication::applicationName() ,msg, QMessageBox::Yes, QMessageBox::No)==QMessageBox::Yes)
|
|
db.save();
|
|
else
|
|
db.revert(); //not really necessary, I think... but will not hurt.
|
|
}
|
|
db.close();
|
|
}
|
|
}
|
|
|
|
void MainWindow::closeEvent( QCloseEvent* event )
|
|
{
|
|
PreferencesDialog::setSettingsValue("MainWindow", "geometry", saveGeometry());
|
|
PreferencesDialog::setSettingsValue("MainWindow", "windowState", saveState());
|
|
PreferencesDialog::setSettingsValue("SQLLogDock", "Log", ui->comboLogSubmittedBy->currentText());
|
|
fileExit();
|
|
QMainWindow::closeEvent(event);
|
|
}
|
|
|
|
void MainWindow::addRecord()
|
|
{
|
|
int row = m_browseTableModel->rowCount();
|
|
if(m_browseTableModel->insertRow(row))
|
|
{
|
|
selectTableLine(row);
|
|
} else {
|
|
QMessageBox::warning( this, QApplication::applicationName(), tr("Error adding record:\n") + db.lastErrorMessage);
|
|
}
|
|
}
|
|
|
|
void MainWindow::deleteRecord()
|
|
{
|
|
if(ui->dataTable->currentIndex().isValid())
|
|
{
|
|
int row = ui->dataTable->currentIndex().row();
|
|
if(m_browseTableModel->removeRow(row))
|
|
{
|
|
populateTable(db.curBrowseTableName);
|
|
if(row > m_browseTableModel->totalRowCount())
|
|
row = m_browseTableModel->totalRowCount();
|
|
selectTableLine(row);
|
|
} else {
|
|
QMessageBox::warning( this, QApplication::applicationName(), tr("Error deleting record:\n") + db.lastErrorMessage);
|
|
}
|
|
} else {
|
|
QMessageBox::information( this, QApplication::applicationName(), tr("Please select a record first"));
|
|
}
|
|
}
|
|
|
|
void MainWindow::selectTableLine(int lineToSelect)
|
|
{
|
|
ui->dataTable->clearSelection();
|
|
ui->dataTable->selectRow(lineToSelect);
|
|
ui->dataTable->scrollTo(ui->dataTable->currentIndex());
|
|
}
|
|
|
|
void MainWindow::navigatePrevious()
|
|
{
|
|
int curRow = ui->dataTable->currentIndex().row();
|
|
curRow -= 100;
|
|
if(curRow < 0)
|
|
curRow = 0;
|
|
selectTableLine(curRow);
|
|
}
|
|
|
|
|
|
void MainWindow::navigateNext()
|
|
{
|
|
// TODO: Fetch more data from DB if necessary
|
|
|
|
int curRow = ui->dataTable->currentIndex().row();
|
|
curRow += 100;
|
|
if(curRow >= m_browseTableModel->totalRowCount())
|
|
curRow = m_browseTableModel->totalRowCount() - 1;
|
|
selectTableLine(curRow);
|
|
}
|
|
|
|
|
|
void MainWindow::navigateGoto()
|
|
{
|
|
// TODO: Fetch more data from DB if necessary
|
|
|
|
int row = ui->editGoto->text().toInt();
|
|
if(row <= 0)
|
|
row = 1;
|
|
if(row > m_browseTableModel->totalRowCount())
|
|
row = m_browseTableModel->totalRowCount();
|
|
|
|
selectTableLine(row - 1);
|
|
ui->editGoto->setText(QString::number(row));
|
|
}
|
|
|
|
void MainWindow::setRecordsetLabel()
|
|
{
|
|
// Get all the numbers, i.e. the number of the first row and the last row as well as the total number of rows
|
|
int from = ui->dataTable->verticalHeader()->visualIndexAt(0) + 1;
|
|
int to = ui->dataTable->verticalHeader()->visualIndexAt(ui->dataTable->height()) - 1;
|
|
int total = m_browseTableModel->totalRowCount();
|
|
if(to == -2)
|
|
to = total;
|
|
|
|
// Update the validator of the goto row field
|
|
gotoValidator->setRange(0, total);
|
|
|
|
// Update the label showing the current position
|
|
ui->labelRecordset->setText(tr("%1 - %2 of %3").arg(from).arg(to).arg(total));
|
|
}
|
|
|
|
void MainWindow::browseFind(bool open)
|
|
{
|
|
if(open)
|
|
{
|
|
if(!findWin)
|
|
{
|
|
findWin = new FindDialog(this);
|
|
connect(findWin, SIGNAL(lookfor(const QString&, const QString&, const QString&)), this, SLOT(lookfor(const QString&, const QString&, const QString&)));
|
|
connect(findWin, SIGNAL(showrecord(int)),this, SLOT(selectTableLine(int)));
|
|
connect(findWin, SIGNAL(goingAway()),this, SLOT(browseFindAway()));
|
|
}
|
|
findWin->resetFields(db.getTableFields(db.curBrowseTableName));
|
|
findWin->show();
|
|
} else {
|
|
if(findWin)
|
|
findWin->hide();
|
|
}
|
|
}
|
|
|
|
void MainWindow::browseFindAway()
|
|
{
|
|
ui->buttonFind->toggle();
|
|
}
|
|
|
|
void MainWindow::browseRefresh()
|
|
{
|
|
populateTable(ui->comboBrowseTable->currentText());
|
|
}
|
|
|
|
void MainWindow::lookfor( const QString & wfield, const QString & woperator, const QString & wsearchterm )
|
|
{
|
|
if (!db.isOpen()){
|
|
QMessageBox::information( this, QApplication::applicationName(), tr("There is no database opened. Please open or create a new database file."));
|
|
return;
|
|
}
|
|
|
|
//we may need to modify woperator and wsearchterm, so use copies
|
|
QString finaloperator = woperator;
|
|
QString finalsearchterm = wsearchterm;
|
|
|
|
//special case for CONTAINS operator: use LIKE and surround the search word with % characters
|
|
if(woperator.compare(tr("contains")) == 0)
|
|
{
|
|
finaloperator = QString("LIKE");
|
|
QString newsearchterm = "%";
|
|
newsearchterm.append(wsearchterm);
|
|
newsearchterm.append("%");
|
|
finalsearchterm = QString(newsearchterm);
|
|
}
|
|
QApplication::setOverrideCursor( Qt::WaitCursor );
|
|
QString statement = QString("SELECT rowid, `%1` FROM `%2` WHERE `%3` %4 ").arg(wfield).arg(db.curBrowseTableName).arg(wfield).arg(finaloperator);
|
|
//searchterm needs to be quoted if it is not a number
|
|
bool ok = false;
|
|
finalsearchterm.toDouble(&ok);
|
|
if (!ok) finalsearchterm.toInt(&ok, 10);
|
|
if (!ok) {//not a number, quote it
|
|
char * formSQL = sqlite3_mprintf("%Q",(const char *) finalsearchterm.toUtf8());
|
|
statement.append(formSQL);
|
|
if (formSQL) sqlite3_free(formSQL);
|
|
} else {//append the number, unquoted
|
|
statement.append(finalsearchterm);
|
|
}
|
|
statement.append(" ORDER BY rowid;");
|
|
resultMap res = db.getFindResults(statement);
|
|
findWin->showResults(res);
|
|
QApplication::restoreOverrideCursor();
|
|
}
|
|
|
|
void MainWindow::createTable()
|
|
{
|
|
if (!db.isOpen()){
|
|
QMessageBox::information( this, QApplication::applicationName(), tr("There is no database opened. Please open or create a new database file."));
|
|
return;
|
|
}
|
|
|
|
EditTableDialog dialog(&db, "", this);
|
|
if(dialog.exec())
|
|
{
|
|
populateStructure();
|
|
resetBrowser();
|
|
}
|
|
}
|
|
|
|
void MainWindow::createIndex()
|
|
{
|
|
if (!db.isOpen()){
|
|
QMessageBox::information( this, QApplication::applicationName(), tr("There is no database opened. Please open or create a new database file."));
|
|
return;
|
|
}
|
|
CreateIndexDialog dialog(&db, this);
|
|
if(dialog.exec())
|
|
{
|
|
populateStructure();
|
|
resetBrowser();
|
|
}
|
|
}
|
|
|
|
void MainWindow::compact()
|
|
{
|
|
QApplication::setOverrideCursor( Qt::WaitCursor );
|
|
if (!db.compact()){
|
|
QString error = tr("Error: could not compact the database file. Message from database engine: %1").arg(db.lastErrorMessage);
|
|
QApplication::restoreOverrideCursor( );
|
|
QMessageBox::warning( this, QApplication::applicationName(), error );
|
|
} else {
|
|
QApplication::restoreOverrideCursor( );
|
|
QMessageBox::information(this, QApplication::applicationName(), tr("Database successfully compacted."));
|
|
}
|
|
db.open(db.curDBFilename);
|
|
populateStructure();
|
|
resetBrowser();
|
|
}
|
|
|
|
void MainWindow::deleteObject()
|
|
{
|
|
// Get name of table to delete
|
|
QString table = ui->dbTreeWidget->currentItem()->text(0);
|
|
QString type = ui->dbTreeWidget->currentItem()->text(1);
|
|
|
|
// Ask user if he really wants to delete that table
|
|
if(QMessageBox::warning(this, QApplication::applicationName(), tr("Are you sure you want to delete the %1 '%2'?\nAll data associated with the %1 will be lost.").arg(type).arg(table),
|
|
QMessageBox::Yes, QMessageBox::No | QMessageBox::Default | QMessageBox::Escape) == QMessageBox::Yes)
|
|
{
|
|
// Delete the table
|
|
QString statement = QString("DROP %1 `%2`;").arg(type.toUpper()).arg(table);
|
|
if(!db.executeSQL( statement))
|
|
{
|
|
QString error = tr("Error: could not delete the %1. Message from database engine:\n%2").arg(type).arg(db.lastErrorMessage);
|
|
QMessageBox::warning(this, QApplication::applicationName(), error);
|
|
} else {
|
|
populateStructure();
|
|
resetBrowser();
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::editTable()
|
|
{
|
|
if (!db.isOpen()){
|
|
QMessageBox::information( this, QApplication::applicationName(), tr("There is no database opened."));
|
|
return;
|
|
}
|
|
if(!ui->dbTreeWidget->selectionModel()->hasSelection()){
|
|
return;
|
|
}
|
|
QString tableToEdit = ui->dbTreeWidget->currentItem()->text(0);
|
|
|
|
EditTableDialog dialog(&db, tableToEdit, this);
|
|
if(dialog.exec())
|
|
{
|
|
populateStructure();
|
|
resetBrowser();
|
|
}
|
|
}
|
|
|
|
void MainWindow::helpWhatsThis()
|
|
{
|
|
QWhatsThis::enterWhatsThisMode ();
|
|
}
|
|
|
|
void MainWindow::helpAbout()
|
|
{
|
|
AboutDialog dialog(this);
|
|
dialog.exec();
|
|
}
|
|
|
|
void MainWindow::updateRecordText(int row, int col, const QByteArray& newtext)
|
|
{
|
|
m_browseTableModel->setData(m_browseTableModel->index(row, col), newtext);
|
|
}
|
|
|
|
void MainWindow::editWinAway()
|
|
{
|
|
editWin->hide();
|
|
activateWindow();
|
|
ui->dataTable->setCurrentIndex(ui->dataTable->currentIndex().sibling(editWin->getCurrentRow(), editWin->getCurrentCol()));
|
|
}
|
|
|
|
void MainWindow::editText(const QModelIndex& index)
|
|
{
|
|
editWin->loadText(index.data().toByteArray(), index.row(), index.column());
|
|
editWin->show();
|
|
}
|
|
|
|
void MainWindow::doubleClickTable(const QModelIndex& index)
|
|
{
|
|
if(!index.isValid())
|
|
{
|
|
qDebug("no cell selected");
|
|
return;
|
|
}
|
|
|
|
// Don't allow editing of other objects than tables
|
|
if(db.getObjectByName(ui->comboBrowseTable->currentText()).gettype() != "table")
|
|
return;
|
|
|
|
editText(index);
|
|
}
|
|
|
|
/*
|
|
* I'm still not happy how the results are represented to the user
|
|
* right now you only see the result of the last executed statement.
|
|
* A better experiance would be tabs on the bottom with query results
|
|
* for all the executed statements.
|
|
* Or at least a some way the use could see results/status message
|
|
* per executed statement.
|
|
*/
|
|
void MainWindow::executeQuery()
|
|
{
|
|
// if a part of the query is selected, we will only execute this part
|
|
QString query = ui->sqlTextEdit->textCursor().selectedText();
|
|
if(query.isEmpty())
|
|
query = ui->sqlTextEdit->toPlainText().trimmed();
|
|
if (query.isEmpty())
|
|
return;
|
|
|
|
//log the query
|
|
db.logSQL(query, kLogMsg_User);
|
|
sqlite3_stmt *vm;
|
|
QByteArray utf8Query = query.toUtf8();
|
|
const char *tail = utf8Query.data();
|
|
int sql3status = 0;
|
|
QString statusMessage;
|
|
bool modified = false;
|
|
bool wasdirty = db.getDirty();
|
|
|
|
// there is no choice, we have to start a transaction before
|
|
// we create the prepared statement, otherwise every executed
|
|
// statement will get committed after the prepared statement
|
|
// gets finalized, see http://www.sqlite.org/lang_transaction.html
|
|
db.setRestorePoint();
|
|
|
|
//Accept multi-line queries, by looping until the tail is empty
|
|
do
|
|
{
|
|
queryResultListModel->removeRows(0, queryResultListModel->rowCount());
|
|
queryResultListModel->removeColumns(0, queryResultListModel->columnCount());
|
|
queryResultListModel->setHorizontalHeaderLabels(QStringList());
|
|
queryResultListModel->setVerticalHeaderLabels(QStringList());
|
|
|
|
const char* qbegin = tail;
|
|
sql3status = sqlite3_prepare_v2(db._db,tail,utf8Query.length(),
|
|
&vm, &tail);
|
|
QString queryPart = QString::fromUtf8(qbegin, tail - qbegin);
|
|
if (sql3status == SQLITE_OK){
|
|
int rownum = 0;
|
|
bool mustCreateColumns = true;
|
|
|
|
sql3status = sqlite3_step(vm);
|
|
switch(sql3status)
|
|
{
|
|
case SQLITE_ROW:
|
|
{
|
|
do
|
|
{
|
|
int ncol = sqlite3_data_count(vm);
|
|
//setup num of cols here for display grid
|
|
if (mustCreateColumns)
|
|
{
|
|
QStringList headerList;
|
|
for (int e=0; e<ncol; ++e)
|
|
headerList = headerList << QString::fromUtf8((const char *)sqlite3_column_name(vm, e));
|
|
queryResultListModel->setHorizontalHeaderLabels(headerList);
|
|
mustCreateColumns = false;
|
|
}
|
|
for (int e=0; e<ncol; ++e){
|
|
QString rv = QString::fromUtf8((const char *) sqlite3_column_text(vm, e));
|
|
//show it here
|
|
QString firstline = rv.section( '\n', 0,0 );
|
|
queryResultListModel->setItem(rownum, e, new QStandardItem(QString(firstline)));
|
|
}
|
|
queryResultListModel->setVerticalHeaderItem(rownum, new QStandardItem(QString::number(rownum + 1)));
|
|
rownum++;
|
|
} while ( sqlite3_step(vm) == SQLITE_ROW );
|
|
sql3status = SQLITE_OK;
|
|
}
|
|
case SQLITE_DONE:
|
|
statusMessage = tr("%1 Rows returned from: %2").arg(rownum).arg(queryPart);
|
|
case SQLITE_OK:
|
|
{
|
|
if( !queryPart.trimmed().startsWith("SELECT", Qt::CaseInsensitive) )
|
|
{
|
|
modified = true;
|
|
statusMessage = tr("Query executed successfully: %1").arg(queryPart);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
statusMessage = QString::fromUtf8((const char*)sqlite3_errmsg(db._db)) +
|
|
": " + queryPart;
|
|
break;
|
|
|
|
}
|
|
sqlite3_finalize(vm);
|
|
}
|
|
else
|
|
{
|
|
statusMessage = QString::fromUtf8((const char*)sqlite3_errmsg(db._db)) +
|
|
": " + queryPart;
|
|
}
|
|
ui->queryErrorLineEdit->setText(statusMessage);
|
|
ui->queryResultTableView->resizeColumnsToContents();
|
|
|
|
} while( tail && *tail != 0 && (sql3status == SQLITE_OK || sql3status == SQLITE_DONE));
|
|
|
|
if(!modified && !wasdirty)
|
|
db.revert(); // better rollback, if the logic is not enough we can tune it.
|
|
}
|
|
|
|
void MainWindow::mainTabSelected(int tabindex)
|
|
{
|
|
if(tabindex == 0)
|
|
{
|
|
populateStructure();
|
|
} else if(tabindex == 1) {
|
|
populateStructure();
|
|
resetBrowser();
|
|
} else if(tabindex == 2) {
|
|
loadPragmas();
|
|
}
|
|
}
|
|
|
|
void MainWindow::importTableFromCSV()
|
|
{
|
|
QString wFile = QFileDialog::getOpenFileName(
|
|
this,
|
|
tr("Choose a text file"),
|
|
PreferencesDialog::getSettingsValue("db", "defaultlocation").toString(),
|
|
tr("Text files(*.csv *.txt);;All files(*)"));
|
|
|
|
if (QFile::exists(wFile) )
|
|
{
|
|
ImportCsvDialog dialog(wFile, &db, this);
|
|
if(dialog.exec())
|
|
{
|
|
populateStructure();
|
|
resetBrowser();
|
|
QMessageBox::information(this, QApplication::applicationName(), tr("Import completed"));
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::exportTableToCSV()
|
|
{
|
|
ExportCsvDialog dialog(&db, this);
|
|
dialog.exec();
|
|
}
|
|
|
|
void MainWindow::dbState( bool dirty )
|
|
{
|
|
ui->fileSaveAction->setEnabled(dirty);
|
|
ui->fileRevertAction->setEnabled(dirty);
|
|
}
|
|
|
|
void MainWindow::fileSave()
|
|
{
|
|
if(db.isOpen())
|
|
db.save();
|
|
}
|
|
|
|
void MainWindow::fileRevert()
|
|
{
|
|
if (db.isOpen()){
|
|
QString msg = tr("Are you sure you want to undo all changes made to the database file '%1' since the last save?").arg(db.curDBFilename);
|
|
if(QMessageBox::question(this, QApplication::applicationName(), msg, QMessageBox::Yes | QMessageBox::Default, QMessageBox::No | QMessageBox::Escape) == QMessageBox::Yes)
|
|
{
|
|
db.revert();
|
|
populateStructure();
|
|
resetBrowser();
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::exportDatabaseToSQL()
|
|
{
|
|
QString fileName = QFileDialog::getSaveFileName(
|
|
this,
|
|
tr("Choose a filename to export"),
|
|
PreferencesDialog::getSettingsValue("db", "defaultlocation").toString(),
|
|
tr("Text files(*.sql *.txt)"));
|
|
|
|
if(fileName.size())
|
|
{
|
|
if(!db.dump(fileName))
|
|
QMessageBox::warning(this, QApplication::applicationName(), tr("Export cancelled or failed."));
|
|
else
|
|
QMessageBox::information(this, QApplication::applicationName(), tr("Export completed."));
|
|
}
|
|
}
|
|
|
|
void MainWindow::importDatabaseFromSQL()
|
|
{
|
|
QString fileName = QFileDialog::getOpenFileName(
|
|
this,
|
|
tr("Choose a file to import"),
|
|
PreferencesDialog::getSettingsValue("db", "defaultlocation").toString(),
|
|
tr("Text files(*.sql *.txt);;All files(*)"));
|
|
|
|
if (fileName.size() > 0)
|
|
{
|
|
QString msg = tr("Do you want to create a new database file to hold the imported data?\nIf you answer NO we will attempt to import data in the .sql file to the current database.");
|
|
if (QMessageBox::question( this, QApplication::applicationName() ,msg, QMessageBox::Yes, QMessageBox::No)==QMessageBox::Yes)
|
|
{
|
|
QString newDBfile = QFileDialog::getSaveFileName(
|
|
this,
|
|
tr("Choose a filename to save under"),
|
|
PreferencesDialog::getSettingsValue("db", "defaultlocation").toString());
|
|
if (QFile::exists(newDBfile) )
|
|
{
|
|
QString err = tr("File %1 already exists. Please choose a different name.").arg(newDBfile);
|
|
QMessageBox::information( this, QApplication::applicationName() ,err);
|
|
return;
|
|
}
|
|
if(!fileName.isNull())
|
|
db.create(newDBfile);
|
|
}
|
|
|
|
// Open, read, execute and close file
|
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
|
QFile f(fileName);
|
|
f.open(QIODevice::ReadOnly);
|
|
if(!db.executeMultiSQL(f.readAll()))
|
|
QMessageBox::warning(this, QApplication::applicationName(), tr("Error importing data: %1").arg(db.lastErrorMessage));
|
|
else
|
|
QMessageBox::information(this, QApplication::applicationName(), tr("Import completed."));
|
|
f.close();
|
|
QApplication::restoreOverrideCursor();
|
|
|
|
// Resfresh window
|
|
populateStructure();
|
|
resetBrowser();
|
|
}
|
|
}
|
|
|
|
void MainWindow::openPreferences()
|
|
{
|
|
PreferencesDialog dialog(this);
|
|
if(dialog.exec())
|
|
{
|
|
createSyntaxHighlighters();
|
|
populateStructure();
|
|
resetBrowser();
|
|
}
|
|
}
|
|
|
|
void MainWindow::createSyntaxHighlighters()
|
|
{
|
|
delete sqliteHighlighterLogApp;
|
|
delete sqliteHighlighterLogUser;
|
|
delete sqliteHighlighterTabSql;
|
|
sqliteHighlighterLogApp = new SQLiteSyntaxHighlighter(ui->editLogApplication->document());
|
|
sqliteHighlighterLogUser = new SQLiteSyntaxHighlighter(ui->editLogUser->document());
|
|
sqliteHighlighterTabSql = new SQLiteSyntaxHighlighter(ui->sqlTextEdit->document());
|
|
}
|
|
|
|
//******************************************************************
|
|
//** Tree Events
|
|
//******************************************************************
|
|
|
|
//** Db Tree Context Menu
|
|
void MainWindow::createTreeContextMenu(const QPoint &qPoint)
|
|
{
|
|
if(!ui->dbTreeWidget->selectionModel()->hasSelection())
|
|
return;
|
|
|
|
QTreeWidgetItem *cItem = ui->dbTreeWidget->currentItem();
|
|
|
|
if(cItem->text(1) == "table" || cItem->text(1) == "view" || cItem->text(1) == "trigger" || cItem->text(1) == "index")
|
|
popupTableMenu->exec(ui->dbTreeWidget->mapToGlobal(qPoint));
|
|
}
|
|
//** Tree selection changed
|
|
void MainWindow::changeTreeSelection()
|
|
{
|
|
// Just assume first that something's selected that can not be edited at all
|
|
ui->editDeleteObjectAction->setEnabled(false);
|
|
ui->editModifyTableAction->setEnabled(false);
|
|
|
|
if(ui->dbTreeWidget->currentItem() == 0)
|
|
return;
|
|
|
|
// Change the text of the actions
|
|
ui->editDeleteObjectAction->setIcon(QIcon(QString(":icons/%1_delete").arg(ui->dbTreeWidget->currentItem()->text(1))));
|
|
if(ui->dbTreeWidget->currentItem()->text(1) == "view")
|
|
ui->editDeleteObjectAction->setText(tr("Delete View"));
|
|
else if(ui->dbTreeWidget->currentItem()->text(1) == "trigger")
|
|
ui->editDeleteObjectAction->setText(tr("Delete Trigger"));
|
|
else if(ui->dbTreeWidget->currentItem()->text(1) == "index")
|
|
ui->editDeleteObjectAction->setText(tr("Delete Index"));
|
|
else
|
|
ui->editDeleteObjectAction->setText(tr("Delete Table"));
|
|
|
|
// Activate actions
|
|
if(ui->dbTreeWidget->currentItem()->text(1) == "table")
|
|
{
|
|
ui->editDeleteObjectAction->setEnabled(true);
|
|
ui->editModifyTableAction->setEnabled(true);
|
|
} else if(ui->dbTreeWidget->currentItem()->text(1) == "view" || ui->dbTreeWidget->currentItem()->text(1) == "trigger" || ui->dbTreeWidget->currentItem()->text(1) == "index") {
|
|
ui->editDeleteObjectAction->setEnabled(true);
|
|
}
|
|
}
|
|
|
|
void MainWindow::openRecentFile()
|
|
{
|
|
QAction *action = qobject_cast<QAction *>(sender());
|
|
if (action)
|
|
fileOpen(action->data().toString());
|
|
}
|
|
|
|
void MainWindow::updateRecentFileActions()
|
|
{
|
|
QStringList files = PreferencesDialog::getSettingsValue("General", "recentFileList").toStringList();
|
|
int numRecentFiles = qMin(files.size(), (int)MaxRecentFiles);
|
|
|
|
for (int i = 0; i < numRecentFiles; ++i) {
|
|
QString text = tr("&%1 %2").arg(i + 1).arg(files[i]);
|
|
recentFileActs[i]->setText(text);
|
|
recentFileActs[i]->setData(files[i]);
|
|
recentFileActs[i]->setVisible(true);
|
|
}
|
|
for (int j = numRecentFiles; j < MaxRecentFiles; ++j)
|
|
recentFileActs[j]->setVisible(false);
|
|
|
|
recentSeparatorAct->setVisible(numRecentFiles > 0);
|
|
}
|
|
|
|
void MainWindow::setCurrentFile(const QString &fileName)
|
|
{
|
|
setWindowFilePath(fileName);
|
|
setWindowTitle( QApplication::applicationName() +" - "+fileName);
|
|
activateFields(true);
|
|
|
|
QStringList files = PreferencesDialog::getSettingsValue("General", "recentFileList").toStringList();
|
|
files.removeAll(fileName);
|
|
files.prepend(fileName);
|
|
while (files.size() > MaxRecentFiles)
|
|
files.removeLast();
|
|
|
|
PreferencesDialog::setSettingsValue("General", "recentFileList", files);
|
|
|
|
foreach (QWidget *widget, QApplication::topLevelWidgets()) {
|
|
MainWindow *mainWin = qobject_cast<MainWindow *>(widget);
|
|
if (mainWin)
|
|
mainWin->updateRecentFileActions();
|
|
}
|
|
}
|
|
|
|
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
|
|
{
|
|
if( event->mimeData()->hasFormat("text/uri-list") )
|
|
event->acceptProposedAction();
|
|
}
|
|
|
|
void MainWindow::dropEvent(QDropEvent *event)
|
|
{
|
|
QList<QUrl> urls = event->mimeData()->urls();
|
|
|
|
if( urls.isEmpty() )
|
|
return;
|
|
|
|
QString fileName = urls.first().toLocalFile();
|
|
|
|
if(!fileName.isEmpty())
|
|
fileOpen(fileName);
|
|
}
|
|
|
|
void MainWindow::activateFields(bool enable)
|
|
{
|
|
ui->fileCloseAction->setEnabled(enable);
|
|
ui->fileCompactAction->setEnabled(enable);
|
|
ui->fileExportCSVAction->setEnabled(enable);
|
|
ui->fileExportSQLAction->setEnabled(enable);
|
|
ui->fileImportCSVAction->setEnabled(enable);
|
|
ui->editCreateTableAction->setEnabled(enable);
|
|
ui->editCreateIndexAction->setEnabled(enable);
|
|
ui->buttonNext->setEnabled(enable);
|
|
ui->buttonPrevious->setEnabled(enable);
|
|
ui->executeQueryButton->setEnabled(enable);
|
|
ui->scrollAreaWidgetContents->setEnabled(enable);
|
|
ui->buttonBoxPragmas->setEnabled(enable);
|
|
ui->buttonGoto->setEnabled(enable);
|
|
ui->editGoto->setEnabled(enable);
|
|
ui->buttonRefresh->setEnabled(enable);
|
|
ui->buttonDeleteRecord->setEnabled(enable);
|
|
ui->buttonNewRecord->setEnabled(enable);
|
|
}
|
|
|
|
void MainWindow::browseTableHeaderClicked(int logicalindex)
|
|
{
|
|
// Abort if there is more than one column selected because this tells us that the user pretty sure wants to do a range selection instead of sorting data
|
|
if(ui->dataTable->selectionModel()->selectedColumns().count() > 1)
|
|
return;
|
|
|
|
// instead of the column name we just use the column index, +2 because 'rowid, *' is the projection
|
|
curBrowseOrderByIndex = logicalindex;
|
|
curBrowseOrderByMode = curBrowseOrderByMode == Qt::AscendingOrder ? Qt::DescendingOrder : Qt::AscendingOrder;
|
|
m_browseTableModel->sort(curBrowseOrderByIndex, curBrowseOrderByMode);
|
|
|
|
// select the first item in the column so the header is bold
|
|
// we might try to select the last selected item
|
|
ui->dataTable->setCurrentIndex(ui->dataTable->currentIndex().sibling(0, logicalindex));
|
|
}
|
|
|
|
void MainWindow::resizeEvent(QResizeEvent*)
|
|
{
|
|
setRecordsetLabel();
|
|
}
|
|
|
|
void MainWindow::loadPragmas()
|
|
{
|
|
pragmaValues.autovacuum = db.getPragma("auto_vacuum").toInt();
|
|
pragmaValues.automatic_index = db.getPragma("automatic_index").toInt();
|
|
pragmaValues.checkpoint_fullsync = db.getPragma("checkpoint_fullfsync").toInt();
|
|
pragmaValues.foreign_keys = db.getPragma("foreign_keys").toInt();
|
|
pragmaValues.fullfsync = db.getPragma("fullfsync").toInt();
|
|
pragmaValues.ignore_check_constraints = db.getPragma("ignore_check_constraints").toInt();
|
|
pragmaValues.journal_mode = db.getPragma("journal_mode").toUpper();
|
|
pragmaValues.journal_size_limit = db.getPragma("journal_size_limit").toInt();
|
|
pragmaValues.locking_mode = db.getPragma("locking_mode").toUpper();
|
|
pragmaValues.max_page_count = db.getPragma("max_page_count").toInt();
|
|
pragmaValues.page_size = db.getPragma("page_size").toInt();
|
|
pragmaValues.recursive_triggers = db.getPragma("recursive_triggers").toInt();
|
|
pragmaValues.secure_delete = db.getPragma("secure_delete").toInt();
|
|
pragmaValues.synchronous = db.getPragma("synchronous").toInt();
|
|
pragmaValues.temp_store = db.getPragma("temp_store").toInt();
|
|
pragmaValues.user_version = db.getPragma("user_version").toInt();
|
|
pragmaValues.wal_autocheckpoint = db.getPragma("wal_autocheckpoint").toInt();
|
|
|
|
updatePragmaUi();
|
|
}
|
|
|
|
void MainWindow::updatePragmaUi()
|
|
{
|
|
ui->comboboxPragmaAutoVacuum->setCurrentIndex(pragmaValues.autovacuum);
|
|
ui->checkboxPragmaAutomaticIndex->setChecked(pragmaValues.automatic_index);
|
|
ui->checkboxPragmaCheckpointFullFsync->setChecked(pragmaValues.checkpoint_fullsync);
|
|
ui->checkboxPragmaForeignKeys->setChecked(pragmaValues.foreign_keys);
|
|
ui->checkboxPragmaFullFsync->setChecked(pragmaValues.fullfsync);
|
|
ui->checkboxPragmaIgnoreCheckConstraints->setChecked(pragmaValues.ignore_check_constraints);
|
|
ui->comboboxPragmaJournalMode->setCurrentIndex(ui->comboboxPragmaJournalMode->findText(pragmaValues.journal_mode, Qt::MatchFixedString));
|
|
ui->spinPragmaJournalSizeLimit->setValue(pragmaValues.journal_size_limit);
|
|
ui->comboboxPragmaLockingMode->setCurrentIndex(ui->comboboxPragmaLockingMode->findText(pragmaValues.locking_mode, Qt::MatchFixedString));
|
|
ui->spinPragmaMaxPageCount->setValue(pragmaValues.max_page_count);
|
|
ui->spinPragmaPageSize->setValue(pragmaValues.page_size);
|
|
ui->checkboxPragmaRecursiveTriggers->setChecked(pragmaValues.recursive_triggers);
|
|
ui->checkboxPragmaSecureDelete->setChecked(pragmaValues.secure_delete);
|
|
ui->comboboxPragmaSynchronous->setCurrentIndex(pragmaValues.synchronous);
|
|
ui->comboboxPragmaTempStore->setCurrentIndex(pragmaValues.temp_store);
|
|
ui->spinPragmaUserVersion->setValue(pragmaValues.user_version);
|
|
ui->spinPragmaWalAutoCheckpoint->setValue(pragmaValues.wal_autocheckpoint);
|
|
}
|
|
|
|
void MainWindow::savePragmas()
|
|
{
|
|
if( db.getDirty() )
|
|
{
|
|
QString msg = tr("Setting PRAGMA values will commit your current transaction.\nAre you sure?");
|
|
if(QMessageBox::question(this, QApplication::applicationName(), msg, QMessageBox::Yes | QMessageBox::Default, QMessageBox::No | QMessageBox::Escape) == QMessageBox::No)
|
|
{
|
|
return; // abort
|
|
}
|
|
}
|
|
db.setPragma("auto_vacuum", ui->comboboxPragmaAutoVacuum->currentIndex(), pragmaValues.autovacuum);
|
|
db.setPragma("automatic_index", ui->checkboxPragmaAutomaticIndex->isChecked(), pragmaValues.automatic_index);
|
|
db.setPragma("checkpoint_fullfsync", ui->checkboxPragmaCheckpointFullFsync->isChecked(), pragmaValues.checkpoint_fullsync);
|
|
db.setPragma("foreign_keys", ui->checkboxPragmaForeignKeys->isChecked(), pragmaValues.foreign_keys);
|
|
db.setPragma("fullfsync", ui->checkboxPragmaFullFsync->isChecked(), pragmaValues.fullfsync);
|
|
db.setPragma("ignore_check_constraints", ui->checkboxPragmaIgnoreCheckConstraints->isChecked(), pragmaValues.ignore_check_constraints);
|
|
db.setPragma("journal_mode", ui->comboboxPragmaJournalMode->currentText().toUpper(), pragmaValues.journal_mode);
|
|
db.setPragma("journal_size_limit", ui->spinPragmaJournalSizeLimit->value(), pragmaValues.journal_size_limit);
|
|
db.setPragma("locking_mode", ui->comboboxPragmaLockingMode->currentText().toUpper(), pragmaValues.locking_mode);
|
|
db.setPragma("max_page_count", ui->spinPragmaMaxPageCount->value(), pragmaValues.max_page_count);
|
|
db.setPragma("page_size", ui->spinPragmaPageSize->value(), pragmaValues.page_size);
|
|
db.setPragma("recursive_triggers", ui->checkboxPragmaRecursiveTriggers->isChecked(), pragmaValues.recursive_triggers);
|
|
db.setPragma("secure_delete", ui->checkboxPragmaSecureDelete->isChecked(), pragmaValues.secure_delete);
|
|
db.setPragma("synchronous", ui->comboboxPragmaSynchronous->currentIndex(), pragmaValues.synchronous);
|
|
db.setPragma("temp_store", ui->comboboxPragmaTempStore->currentIndex(), pragmaValues.temp_store);
|
|
db.setPragma("user_version", ui->spinPragmaUserVersion->value(), pragmaValues.user_version);
|
|
db.setPragma("wal_autocheckpoint", ui->spinPragmaWalAutoCheckpoint->value(), pragmaValues.wal_autocheckpoint);
|
|
|
|
updatePragmaUi();
|
|
}
|
|
|
|
void MainWindow::logSql(const QString& sql, int msgtype)
|
|
{
|
|
if(msgtype == kLogMsg_User)
|
|
{
|
|
ui->editLogUser->append(sql);
|
|
ui->editLogUser->verticalScrollBar()->setValue(ui->editLogUser->verticalScrollBar()->maximum());
|
|
} else {
|
|
ui->editLogApplication->append(sql);
|
|
ui->editLogApplication->verticalScrollBar()->setValue(ui->editLogApplication->verticalScrollBar()->maximum());
|
|
}
|
|
}
|