mirror of
https://github.com/sqlitebrowser/sqlitebrowser.git
synced 2026-01-20 02:50:46 -06:00
Rewrite some code to use a QTableView widget instead of a QTableWidget in the browse tab of the main window, or more presicely in the new extended table widget class. This way the widget and the data model are separated which on the one hand means a bit more work on our side but on the other hand also gives us a bit more flexibility. And more importantly at the moment: This means both, the browse tab and the sql tab, use a table view now - that's going to be helpful for the next commit...
1233 lines
44 KiB
C++
1233 lines
44 KiB
C++
#include "MainWindow.h"
|
|
#include "ui_MainWindow.h"
|
|
#include <QtGui/QFileDialog>
|
|
#include <QSettings>
|
|
#include <QFile>
|
|
#include <QApplication>
|
|
#include <QTextStream>
|
|
#include <QWhatsThis>
|
|
#include <QMessageBox>
|
|
#include <QUrl>
|
|
#include <QStandardItemModel>
|
|
#include <QDragEnterEvent>
|
|
#include <QScrollBar>
|
|
|
|
#include "CreateIndexDialog.h"
|
|
#include "AboutDialog.h"
|
|
#include "EditTableDialog.h"
|
|
#include "EditFieldDialog.h"
|
|
#include "ImportCsvDialog.h"
|
|
#include "ExportCsvDialog.h"
|
|
#include "PreferencesDialog.h"
|
|
#include "EditDialog.h"
|
|
#include "FindDialog.h"
|
|
#include "SQLiteSyntaxHighlighter.h"
|
|
#include "sqltextedit.h"
|
|
|
|
MainWindow::MainWindow(QWidget* parent)
|
|
: QMainWindow(parent),
|
|
ui(new Ui::MainWindow),
|
|
browseTableModel(new QStandardItemModel(this)),
|
|
editWin(new EditDialog(this)),
|
|
findWin(0)
|
|
{
|
|
ui->setupUi(this);
|
|
init();
|
|
|
|
activateFields(false);
|
|
updatePreferences();
|
|
resetBrowser();
|
|
updateRecentFileActions();
|
|
}
|
|
|
|
MainWindow::~MainWindow()
|
|
{
|
|
delete gotoValidator;
|
|
delete ui;
|
|
}
|
|
|
|
void MainWindow::init()
|
|
{
|
|
// Init the SQL log dock
|
|
db.mainWindow = this;
|
|
sqliteHighlighterLogUser = new SQLiteSyntaxHighlighter(ui->editLogUser->document());
|
|
sqliteHighlighterLogApp = new SQLiteSyntaxHighlighter(ui->editLogApplication->document());
|
|
|
|
// Set up the db tree widget
|
|
ui->dbTreeWidget->setColumnHidden(1, true);
|
|
ui->dbTreeWidget->setColumnWidth(0, 300);
|
|
|
|
// Create the validator for the goto line edit
|
|
gotoValidator = new QIntValidator(0, 0, this);
|
|
ui->editGoto->setValidator(gotoValidator);
|
|
|
|
// Create the SQL sytax highlighter
|
|
sqliteHighlighterTabSql = new SQLiteSyntaxHighlighter(ui->sqlTextEdit->document());
|
|
|
|
// Set up DB models
|
|
ui->dataTable->setModel(browseTableModel);
|
|
|
|
queryResultListModel = new QStandardItemModel(this);
|
|
ui->queryResultTableView->setModel(queryResultListModel);
|
|
|
|
// 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->addAction(ui->editAddFieldActionPopup);
|
|
popupTableMenu->addSeparator();
|
|
popupTableMenu->addAction(ui->editDeleteObjectAction);
|
|
popupFieldMenu = new QMenu(this);
|
|
popupFieldMenu->addAction(ui->editModifyFieldActionPopup);
|
|
popupFieldMenu->addAction(ui->editDeleteFieldActionPopup);
|
|
|
|
// 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(ui->dataTable->horizontalHeader(), 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 , QString)), this, SLOT(updateRecordText(int, int , QString)));
|
|
|
|
// Load window settings
|
|
QSettings settings(QApplication::organizationName(), QApplication::organizationName());
|
|
restoreGeometry(settings.value("MainWindow/geometry").toByteArray());
|
|
restoreState(settings.value("MainWindow/windowState").toByteArray());
|
|
ui->comboLogSubmittedBy->setCurrentIndex(ui->comboLogSubmittedBy->findText(settings.value("SQLLogDock/Log", "Application").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"),
|
|
defaultlocation);
|
|
}
|
|
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"), defaultlocation);
|
|
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, bool keepColumnWidths)
|
|
{
|
|
bool mustreset = false;
|
|
QApplication::setOverrideCursor( Qt::WaitCursor );
|
|
if (tablename.compare(db.curBrowseTableName)!=0)
|
|
{
|
|
mustreset = true;
|
|
curBrowseOrderByIndex = 1;
|
|
curBrowseOrderByMode = ORDERMODE_ASC;
|
|
}
|
|
|
|
QString orderby = QString::number(curBrowseOrderByIndex) + " " + (curBrowseOrderByMode == ORDERMODE_ASC ? "ASC" : "DESC");
|
|
if(!db.browseTable(tablename, orderby))
|
|
{
|
|
browseTableModel->setRowCount(0);
|
|
browseTableModel->setColumnCount(0);
|
|
QApplication::restoreOverrideCursor();
|
|
if(findWin)
|
|
findWin->resetFields(db.getTableFields(""));
|
|
return;
|
|
}
|
|
|
|
// 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);
|
|
|
|
if (mustreset){
|
|
updateTableView(0, keepColumnWidths);
|
|
if (findWin) findWin->resetFields(db.getTableFields(db.curBrowseTableName));
|
|
} else {
|
|
updateTableView(-1, keepColumnWidths);
|
|
}
|
|
//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 = 1;
|
|
curBrowseOrderByMode = ORDERMODE_ASC;
|
|
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 )
|
|
{
|
|
QSettings settings(QApplication::organizationName(), QApplication::organizationName());
|
|
settings.setValue("MainWindow/geometry", saveGeometry());
|
|
settings.setValue("MainWindow/windowState", saveState());
|
|
settings.setValue("SQLLogDock/Log", ui->comboLogSubmittedBy->currentText());
|
|
fileExit();
|
|
QMainWindow::closeEvent(event);
|
|
}
|
|
|
|
void MainWindow::addRecord()
|
|
{
|
|
if (db.addRecord()){
|
|
populateTable(db.curBrowseTableName);
|
|
//added record will be the last one in view
|
|
updateTableView(db.getRecordCount()-1);
|
|
}else{
|
|
QMessageBox::information( this, QApplication::applicationName(),
|
|
tr("Error adding record, make sure a table is selected.\n\n"
|
|
"If the table contain fields declared as NOT NULL\n"
|
|
"please select EDIT->PREFERENCES and adjust the\n"
|
|
"default value for new records to insert an empty string."));
|
|
}
|
|
}
|
|
|
|
|
|
void MainWindow::deleteRecord()
|
|
{
|
|
if(ui->dataTable->currentIndex().row() != -1)
|
|
{
|
|
int lastselected = ui->dataTable->currentIndex().row();
|
|
db.deleteRecord(lastselected);
|
|
populateTable(db.curBrowseTableName);
|
|
int nextselected = lastselected ;
|
|
if (nextselected > db.getRecordCount()){
|
|
nextselected = db.getRecordCount();
|
|
}
|
|
if (nextselected>0){
|
|
selectTableLine(nextselected);
|
|
}
|
|
} else {
|
|
QMessageBox::information( this, QApplication::applicationName(), tr("Please select a record first"));
|
|
}
|
|
}
|
|
|
|
#define WRAP_SIZE 80
|
|
QString wrapText(const QString& text)
|
|
{
|
|
QString wrap;
|
|
int textSize = text.size();
|
|
|
|
int cur = 0;
|
|
while( wrap.size() < textSize)
|
|
{
|
|
wrap += text.mid(cur, WRAP_SIZE);
|
|
cur += WRAP_SIZE;
|
|
if( textSize - cur > WRAP_SIZE)
|
|
wrap += '\n';
|
|
}
|
|
|
|
return wrap;
|
|
}
|
|
|
|
void MainWindow::updateTableView(int lineToSelect, bool keepColumnWidths)
|
|
{
|
|
QApplication::setOverrideCursor( Qt::WaitCursor );
|
|
|
|
browseTableModel->setRowCount(db.getRecordCount());
|
|
browseTableModel->setColumnCount(db.browseFields.count());
|
|
browseTableModel->setHorizontalHeaderLabels(db.browseFields);
|
|
|
|
rowList tab = db.browseRecs;
|
|
int maxRecs = db.getRecordCount();
|
|
gotoValidator->setRange(0, maxRecs);
|
|
|
|
if ( maxRecs > 0 ) {
|
|
|
|
int rowNum = 0;
|
|
int colNum = 0;
|
|
QString rowLabel;
|
|
for (int i = 0; i < tab.size(); ++i)
|
|
{
|
|
rowLabel.setNum(rowNum+1);
|
|
browseTableModel->setVerticalHeaderItem(rowNum, new QStandardItem(rowLabel));
|
|
colNum = 0;
|
|
QStringList& rt = tab[i];
|
|
for (int e = 1; e < rt.size(); ++e)
|
|
{
|
|
QString& content = rt[e];
|
|
|
|
QStandardItem* item = new QStandardItem(content);
|
|
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
|
item->setToolTip(wrapText(content));
|
|
browseTableModel->setItem( rowNum, colNum, item);
|
|
colNum++;
|
|
}
|
|
rowNum++;
|
|
if (rowNum==maxRecs) break;
|
|
}
|
|
}
|
|
|
|
if(!keepColumnWidths) {
|
|
for(int i=0;i<browseTableModel->columnCount();++i)
|
|
{
|
|
ui->dataTable->resizeColumnToContents(i);
|
|
if( ui->dataTable->columnWidth(i) > 400 )
|
|
ui->dataTable->setColumnWidth(i, 400);
|
|
}
|
|
}
|
|
if (lineToSelect!=-1){
|
|
selectTableLine(lineToSelect);
|
|
}
|
|
setRecordsetLabel();
|
|
QApplication::restoreOverrideCursor();
|
|
}
|
|
|
|
void MainWindow::selectTableLine(int lineToSelect)
|
|
{
|
|
ui->dataTable->clearSelection();
|
|
ui->dataTable->selectRow(lineToSelect);
|
|
ui->dataTable->setCurrentIndex(ui->dataTable->currentIndex().sibling(lineToSelect, 0));
|
|
ui->dataTable->scrollTo(ui->dataTable->currentIndex().sibling(lineToSelect, 0));
|
|
}
|
|
|
|
void MainWindow::navigatePrevious()
|
|
{
|
|
int curRow = ui->dataTable->currentIndex().row();
|
|
curRow -= 100;
|
|
if(curRow < 0) curRow = 0;
|
|
updateTableView(curRow);
|
|
}
|
|
|
|
|
|
void MainWindow::navigateNext()
|
|
{
|
|
int curRow = ui->dataTable->currentIndex().row();
|
|
curRow += 100;
|
|
if(curRow >= browseTableModel->rowCount())
|
|
curRow = browseTableModel->rowCount()-1;
|
|
updateTableView(curRow);
|
|
}
|
|
|
|
|
|
void MainWindow::navigateGoto()
|
|
{
|
|
QString typed = ui->editGoto->text();
|
|
bool ok;
|
|
int dec = typed.toInt( &ok);
|
|
if (dec==0) dec=1;
|
|
if (dec>db.getRecordCount()) dec = db.getRecordCount();
|
|
|
|
updateTableView(dec-1);
|
|
ui->editGoto->setText(QString::number(dec,10));
|
|
}
|
|
|
|
void MainWindow::setRecordsetLabel()
|
|
{
|
|
int from = ui->dataTable->verticalHeader()->visualIndexAt(0) + 1;
|
|
int to = ui->dataTable->verticalHeader()->visualIndexAt(ui->dataTable->height()) - 1;
|
|
int total = browseTableModel->rowCount();
|
|
if(to == -2)
|
|
to = total;
|
|
|
|
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(updateTableView(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(), true);
|
|
}
|
|
|
|
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 = "SELECT rowid, ";
|
|
statement.append(wfield);
|
|
statement.append(" FROM ");
|
|
statement.append(db.curBrowseTableName);
|
|
statement.append(" WHERE ");
|
|
statement.append(wfield);
|
|
statement.append(" ");
|
|
statement.append(finaloperator);
|
|
statement.append(" ");
|
|
//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 QString& newtext)
|
|
{
|
|
if (!db.updateRecord(row, col, newtext)){
|
|
QMessageBox::information( this, QApplication::applicationName(), tr("Data could not be updated"));
|
|
}
|
|
|
|
rowList tab = db.browseRecs;
|
|
QStringList& rt = tab[row];
|
|
QString& cv = rt[col+1];//must account for rowid
|
|
|
|
QStandardItem* item = new QStandardItem(cv);
|
|
item->setToolTip( wrapText(cv) );
|
|
browseTableModel->setItem(row, col, item);
|
|
|
|
}
|
|
|
|
void MainWindow::editWinAway()
|
|
{
|
|
editWin->hide();
|
|
activateWindow();
|
|
ui->dataTable->setCurrentIndex(ui->dataTable->currentIndex().sibling(editWin->getCurrentRow(), editWin->getCurrentCol()));
|
|
}
|
|
|
|
void MainWindow::editText(int row, int col)
|
|
{
|
|
rowList tab = db.browseRecs;
|
|
QStringList& rt = tab[row];
|
|
QString cv = rt[col+1];//must account for rowid
|
|
|
|
editWin->loadText(cv , row, col);
|
|
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.row(), index.column());
|
|
}
|
|
|
|
void MainWindow::executeQuery()
|
|
{
|
|
QString query = ui->sqlTextEdit->toPlainText().trimmed();
|
|
if (query.isEmpty())
|
|
{
|
|
QMessageBox::information( this, QApplication::applicationName(), tr("Query string is empty"));
|
|
return;
|
|
}
|
|
//log the query
|
|
db.logSQL(query, kLogMsg_User);
|
|
sqlite3_stmt *vm;
|
|
QByteArray utf8Query = query.toUtf8();
|
|
const char *tail = utf8Query.data();
|
|
int ncol;
|
|
int err=0;
|
|
QString lastErrorMessage = tr("No error");
|
|
//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());
|
|
|
|
QString queryPart = tail;
|
|
err=sqlite3_prepare(db._db,tail,utf8Query.length(),
|
|
&vm, &tail);
|
|
if (err == SQLITE_OK){
|
|
if( !queryPart.trimmed().startsWith("SELECT", Qt::CaseInsensitive))
|
|
db.setRestorePoint();
|
|
int rownum = 0;
|
|
bool mustCreateColumns = true;
|
|
while ( sqlite3_step(vm) == SQLITE_ROW ){
|
|
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++;
|
|
}
|
|
sqlite3_finalize(vm);
|
|
}else{
|
|
lastErrorMessage = QString::fromUtf8((const char*)sqlite3_errmsg(db._db));
|
|
}
|
|
ui->queryErrorLineEdit->setText(lastErrorMessage);
|
|
ui->queryResultTableView->resizeColumnsToContents();
|
|
|
|
if(err!=SQLITE_OK) break;
|
|
} while( tail && *tail != 0 );
|
|
}
|
|
|
|
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"),
|
|
defaultlocation,
|
|
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, defaultlocation, 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"),
|
|
defaultlocation,
|
|
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"),
|
|
defaultlocation,
|
|
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"),
|
|
defaultlocation);
|
|
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);
|
|
}
|
|
int lineErr;
|
|
if (!db.reload(fileName, &lineErr))
|
|
QMessageBox::information(this, QApplication::applicationName(), tr("Error importing data at line %1").arg(lineErr) );
|
|
else
|
|
QMessageBox::information(this, QApplication::applicationName(), tr("Import completed"));
|
|
populateStructure();
|
|
resetBrowser();
|
|
}
|
|
}
|
|
|
|
void MainWindow::openPreferences()
|
|
{
|
|
PreferencesDialog dialog(this);
|
|
if(dialog.exec())
|
|
{
|
|
updatePreferences();
|
|
resetBrowser();
|
|
}
|
|
}
|
|
|
|
void MainWindow::updatePreferences()
|
|
{
|
|
PreferencesDialog prefs(this);
|
|
|
|
db.setDefaultNewData(prefs.defaultnewdata);
|
|
defaultlocation= prefs.defaultlocation;
|
|
editWin->defaultlocation = defaultlocation;
|
|
}
|
|
|
|
//******************************************************************
|
|
//** 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));
|
|
else if(cItem->text(1) == "field")
|
|
popupFieldMenu->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);
|
|
ui->editAddFieldActionPopup->setEnabled(false);
|
|
ui->editModifyFieldActionPopup->setEnabled(false);
|
|
ui->editDeleteFieldActionPopup->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);
|
|
ui->editAddFieldActionPopup->setEnabled(true);
|
|
} else if(ui->dbTreeWidget->currentItem()->text(1) == "field" && ui->dbTreeWidget->currentItem()->parent()->text(1) == "table") {
|
|
ui->editModifyFieldActionPopup->setEnabled(true);
|
|
ui->editDeleteFieldActionPopup->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::addField()
|
|
{
|
|
EditFieldDialog dialog(&db, true, ui->dbTreeWidget->currentItem()->text(0), "", "TEXT", this);
|
|
if(dialog.exec())
|
|
populateStructure();
|
|
}
|
|
|
|
void MainWindow::editField()
|
|
{
|
|
QTreeWidgetItem *item = ui->dbTreeWidget->currentItem();
|
|
EditFieldDialog dialog(&db, false, item->parent()->text(0), item->text(0), item->text(2), this);
|
|
if(dialog.exec())
|
|
{
|
|
item->setText(0, dialog.getFieldName());
|
|
item->setText(2, dialog.getFieldType());
|
|
}
|
|
}
|
|
|
|
void MainWindow::deleteField()
|
|
{
|
|
if(!ui->dbTreeWidget->currentItem())
|
|
return;
|
|
|
|
// Ask user wether he really wants to delete that column first
|
|
QString msg = tr("Are you sure you want to delete the field '%1'?\nAll data currently stored in this field will be lost.").arg(ui->dbTreeWidget->currentItem()->text(0));
|
|
if(QMessageBox::warning(this, QApplication::applicationName(), msg, QMessageBox::Yes | QMessageBox::Default, QMessageBox::No | QMessageBox::Escape) == QMessageBox::Yes)
|
|
{
|
|
db.dropColumn(ui->dbTreeWidget->currentItem()->parent()->text(0), ui->dbTreeWidget->currentItem()->text(0));
|
|
delete ui->dbTreeWidget->currentItem();
|
|
}
|
|
}
|
|
|
|
void MainWindow::openRecentFile()
|
|
{
|
|
QAction *action = qobject_cast<QAction *>(sender());
|
|
if (action)
|
|
fileOpen(action->data().toString());
|
|
}
|
|
|
|
void MainWindow::updateRecentFileActions()
|
|
{
|
|
QSettings settings(QApplication::organizationName(), QApplication::organizationName());
|
|
QStringList files = settings.value("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);
|
|
|
|
QSettings settings(QApplication::organizationName(), QApplication::organizationName());
|
|
QStringList files = settings.value("recentFileList").toStringList();
|
|
files.removeAll(fileName);
|
|
files.prepend(fileName);
|
|
while (files.size() > MaxRecentFiles)
|
|
files.removeLast();
|
|
|
|
settings.setValue("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)
|
|
{
|
|
// instead of the column name we just use the column index, +2 because 'rowid, *' is the projection
|
|
curBrowseOrderByIndex = logicalindex + 2;
|
|
curBrowseOrderByMode = curBrowseOrderByMode == ORDERMODE_ASC ? ORDERMODE_DESC : ORDERMODE_ASC;
|
|
populateTable(ui->comboBrowseTable->currentText(), true);
|
|
|
|
// 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());
|
|
}
|
|
}
|