mirror of
https://github.com/sqlitebrowser/sqlitebrowser.git
synced 2026-01-20 02:50:46 -06:00
Rework the create/modify table dialog.
In the crusade to remove the ugly edit field dialog. Editing tables does currently not work because of a locking issue.
This commit is contained in:
@@ -1,9 +1,14 @@
|
||||
#include "EditTableDialog.h"
|
||||
#include "ui_EditTableDialog.h"
|
||||
#include "EditFieldDialog.h"
|
||||
#include "SQLiteSyntaxHighlighter.h"
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#include <QComboBox>
|
||||
|
||||
#include "sqlitedb.h"
|
||||
#include "sqlitetypes.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
EditTableDialog::EditTableDialog(DBBrowserDB* db, const QString& tableName, QWidget* parent)
|
||||
: QDialog(parent),
|
||||
@@ -14,41 +19,78 @@ EditTableDialog::EditTableDialog(DBBrowserDB* db, const QString& tableName, QWid
|
||||
// Create UI
|
||||
ui->setupUi(this);
|
||||
|
||||
m_sqliteSyntaxHighlighter = new SQLiteSyntaxHighlighter(ui->sqlTextEdit->document());
|
||||
|
||||
// Editing an existing table?
|
||||
if(curTable != "")
|
||||
{
|
||||
// Existing table, so load and set the current layout
|
||||
QString sTablesql = pdb->getTableSQL(curTable);
|
||||
//qDebug() << sTablesql;
|
||||
m_table = new sqlb::Table(sqlb::Table::parseSQL(sTablesql));
|
||||
populateFields();
|
||||
|
||||
// And create a savepoint
|
||||
pdb->executeSQL(QString("SAVEPOINT edittable_%1_save;").arg(curTable));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_table = new sqlb::Table(tableName);
|
||||
}
|
||||
|
||||
// And create a savepoint
|
||||
pdb->executeSQL(QString("SAVEPOINT edittable_%1_save;").arg(curTable), false);
|
||||
|
||||
// Update UI
|
||||
ui->editTableName->setText(curTable);
|
||||
updateColumnWidth();
|
||||
|
||||
checkInput();
|
||||
|
||||
//connect itemchanged signal now
|
||||
//if we do it before populateFields additem will interfere
|
||||
connect(ui->treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)),this,SLOT(itemChanged(QTreeWidgetItem*,int)));
|
||||
|
||||
}
|
||||
|
||||
EditTableDialog::~EditTableDialog()
|
||||
{
|
||||
delete m_table;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void EditTableDialog::updateColumnWidth()
|
||||
{
|
||||
ui->treeWidget->setColumnWidth(kName, 200);
|
||||
ui->treeWidget->setColumnWidth(kType, 80);
|
||||
ui->treeWidget->setColumnWidth(kNotNull, 50);
|
||||
ui->treeWidget->setColumnWidth(kPrimaryKey, 50);
|
||||
ui->treeWidget->setColumnWidth(kAutoIncrement, 50);
|
||||
}
|
||||
|
||||
void EditTableDialog::populateFields()
|
||||
{
|
||||
//make sure we are not using cached information
|
||||
pdb->updateSchema();
|
||||
sqlb::FieldList fields = m_table->fields();
|
||||
foreach(sqlb::FieldPtr f, fields)
|
||||
{
|
||||
QTreeWidgetItem *tbitem = new QTreeWidgetItem(ui->treeWidget);
|
||||
tbitem->setFlags(tbitem->flags() | Qt::ItemIsEditable);
|
||||
tbitem->setText(kName, f->name());
|
||||
QComboBox* typeBox = new QComboBox(ui->treeWidget);
|
||||
QObject::connect(typeBox, SIGNAL(activated(int)), this, SLOT(updateTypes()));
|
||||
typeBox->setEditable(false);
|
||||
typeBox->addItems(sqlb::Field::Datatypes);
|
||||
int index = typeBox->findText(f->type(), Qt::MatchExactly);
|
||||
if(index == -1)
|
||||
{
|
||||
// non standard named type
|
||||
typeBox->addItem(f->type());
|
||||
index = typeBox->count() - 1;
|
||||
}
|
||||
typeBox->setCurrentIndex(index);
|
||||
ui->treeWidget->setItemWidget(tbitem, kType, typeBox);
|
||||
|
||||
fields= pdb->getTableFields(curTable);
|
||||
types= pdb->getTableTypes(curTable);
|
||||
ui->treeWidget->model()->removeRows(0, ui->treeWidget->model()->rowCount());
|
||||
QStringList::Iterator tt = types.begin();
|
||||
for ( QStringList::Iterator ct = fields.begin(); ct != fields.end(); ++ct ) {
|
||||
QTreeWidgetItem *fldItem = new QTreeWidgetItem();
|
||||
fldItem->setText( 0, *ct );
|
||||
fldItem->setText( 1, *tt );
|
||||
ui->treeWidget->addTopLevelItem(fldItem);
|
||||
++tt;
|
||||
tbitem->setCheckState(kNotNull, f->notnull() ? Qt::Checked : Qt::Unchecked);
|
||||
tbitem->setCheckState(kPrimaryKey, m_table->primarykey().contains(f) ? Qt::Checked : Qt::Unchecked);
|
||||
tbitem->setCheckState(kAutoIncrement, f->autoIncrement() ? Qt::Checked : Qt::Unchecked);
|
||||
ui->treeWidget->addTopLevelItem(tbitem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,16 +101,13 @@ void EditTableDialog::accept()
|
||||
if(curTable == "")
|
||||
{
|
||||
// Creation of new table
|
||||
|
||||
// Prepare creation of the table
|
||||
QList<DBBrowserField> tbl_structure;
|
||||
for(int i=0;i<ui->treeWidget->topLevelItemCount();i++)
|
||||
tbl_structure.push_back(DBBrowserField(ui->treeWidget->topLevelItem(i)->text(0), ui->treeWidget->topLevelItem(i)->text(1)));
|
||||
|
||||
// Create table
|
||||
if(!pdb->createTable(ui->editTableName->text(), tbl_structure))
|
||||
// we commit immediatly so no need to setdirty
|
||||
if(!pdb->executeSQL(m_table->sql(), false))
|
||||
{
|
||||
QMessageBox::warning(this, QApplication::applicationName(), tr("Error creating table. Message from database engine:\n%1").arg(pdb->lastErrorMessage));
|
||||
QMessageBox::warning(
|
||||
this,
|
||||
QApplication::applicationName(),
|
||||
tr("Error creating table. Message from database engine:\n%1").arg(pdb->lastErrorMessage));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@@ -87,63 +126,152 @@ void EditTableDialog::accept()
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
}
|
||||
|
||||
// Release the savepoint
|
||||
pdb->executeSQL(QString("RELEASE SAVEPOINT edittable_%1_save;").arg(curTable));
|
||||
}
|
||||
|
||||
// Release the savepoint
|
||||
pdb->executeSQL(QString("RELEASE SAVEPOINT edittable_%1_save;").arg(curTable), false);
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void EditTableDialog::reject()
|
||||
{
|
||||
// Have we been in the process of editing an old table?
|
||||
if(curTable != "")
|
||||
{
|
||||
// Then rollback to our savepoint
|
||||
pdb->executeSQL(QString("ROLLBACK TO SAVEPOINT edittable_%1_save;").arg(curTable));
|
||||
}
|
||||
{
|
||||
// Then rollback to our savepoint
|
||||
pdb->executeSQL(QString("ROLLBACK TO SAVEPOINT edittable_%1_save;").arg(curTable), false);
|
||||
|
||||
QDialog::reject();
|
||||
}
|
||||
|
||||
void EditTableDialog::updateSqlText()
|
||||
{
|
||||
ui->sqlTextEdit->clear();
|
||||
ui->sqlTextEdit->insertPlainText(m_table->sql());
|
||||
}
|
||||
|
||||
void EditTableDialog::updateTableObject()
|
||||
{
|
||||
sqlb::FieldList fields;
|
||||
sqlb::FieldList pk;
|
||||
for(int i = 0; i < ui->treeWidget->topLevelItemCount(); ++i)
|
||||
{
|
||||
QTreeWidgetItem* item = ui->treeWidget->topLevelItem(i);
|
||||
QComboBox* typeBox = qobject_cast<QComboBox*>(ui->treeWidget->itemWidget(item, kType));
|
||||
QString sType = "INTEGER";
|
||||
if(typeBox)
|
||||
sType = typeBox->currentText();
|
||||
sqlb::FieldPtr f(new sqlb::Field(
|
||||
item->text(kName),
|
||||
sType,
|
||||
item->checkState(kNotNull) == Qt::Checked
|
||||
));
|
||||
f->setAutoIncrement(item->checkState(kAutoIncrement) == Qt::Checked);
|
||||
if(item->checkState(kPrimaryKey) == Qt::Checked)
|
||||
pk.append(f);
|
||||
fields.append(f);
|
||||
}
|
||||
|
||||
m_table->setFields(fields);
|
||||
m_table->setPrimaryKey(pk);
|
||||
}
|
||||
|
||||
void EditTableDialog::checkInput()
|
||||
{
|
||||
ui->editTableName->setText(ui->editTableName->text().trimmed());
|
||||
QString normTableName = ui->editTableName->text().trimmed();
|
||||
ui->editTableName->setText(normTableName);
|
||||
bool valid = true;
|
||||
if(ui->editTableName->text().isEmpty() || ui->editTableName->text().contains(" "))
|
||||
if(normTableName.isEmpty() || normTableName.contains(" "))
|
||||
valid = false;
|
||||
if(ui->treeWidget->topLevelItemCount() == 0)
|
||||
valid = false;
|
||||
m_table->setName(normTableName);
|
||||
updateSqlText();
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(valid);
|
||||
}
|
||||
|
||||
void EditTableDialog::editField()
|
||||
void EditTableDialog::updateTypes()
|
||||
{
|
||||
if(!ui->treeWidget->currentItem())
|
||||
return;
|
||||
|
||||
// Show the edit dialog
|
||||
QTreeWidgetItem *item = ui->treeWidget->currentItem();
|
||||
EditFieldDialog dialog(pdb, curTable == "", curTable, item->text(0), item->text(1), this);
|
||||
if(dialog.exec())
|
||||
for(int i = 0; i < ui->treeWidget->topLevelItemCount(); ++i)
|
||||
{
|
||||
item->setText(0, dialog.getFieldName());
|
||||
item->setText(1, dialog.getFieldType());
|
||||
QTreeWidgetItem* item = ui->treeWidget->topLevelItem(i);
|
||||
QComboBox* typeBox = qobject_cast<QComboBox*>(ui->treeWidget->itemWidget(item, kType));
|
||||
QString sType = "INTEGER";
|
||||
if(typeBox)
|
||||
sType = typeBox->currentText();
|
||||
m_table->fields().at(i)->setType(sType);
|
||||
}
|
||||
checkInput();
|
||||
}
|
||||
|
||||
void EditTableDialog::itemChanged(QTreeWidgetItem *item, int column)
|
||||
{
|
||||
int index = ui->treeWidget->indexOfTopLevelItem(item);
|
||||
if(index < m_table->fields().count())
|
||||
{
|
||||
sqlb::FieldPtr field = m_table->fields().at(index);
|
||||
switch(column)
|
||||
{
|
||||
case kName:
|
||||
{
|
||||
field->setName(item->text(column));
|
||||
}
|
||||
break;
|
||||
case kType:
|
||||
{
|
||||
// we don't know which combobox got update
|
||||
// so we have to update all at once
|
||||
// see updateTypes() SLOT
|
||||
}
|
||||
break;
|
||||
case kPrimaryKey:
|
||||
{
|
||||
sqlb::FieldList pks = m_table->primarykey();
|
||||
if(item->checkState(column) == Qt::Checked)
|
||||
pks.append(field);
|
||||
else
|
||||
pks.remove(pks.indexOf(field));
|
||||
m_table->setPrimaryKey(pks);
|
||||
}
|
||||
break;
|
||||
case kNotNull:
|
||||
{
|
||||
field->setNotNull(item->checkState(column) == Qt::Checked);
|
||||
}
|
||||
break;
|
||||
case kAutoIncrement:
|
||||
{
|
||||
field->setAutoIncrement(item->checkState(column) == Qt::Checked);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
checkInput();
|
||||
}
|
||||
|
||||
void EditTableDialog::addField()
|
||||
{
|
||||
EditFieldDialog dialog(pdb, true, curTable, "", "", this);
|
||||
if(dialog.exec())
|
||||
{
|
||||
QTreeWidgetItem *tbitem = new QTreeWidgetItem(ui->treeWidget);
|
||||
tbitem->setText(0, dialog.getFieldName());
|
||||
tbitem->setText(1, dialog.getFieldType());
|
||||
ui->treeWidget->addTopLevelItem(tbitem);
|
||||
checkInput();
|
||||
}
|
||||
QTreeWidgetItem *tbitem = new QTreeWidgetItem(ui->treeWidget);
|
||||
tbitem->setFlags(tbitem->flags() | Qt::ItemIsEditable);
|
||||
tbitem->setText(kName, "Field" + QString::number(ui->treeWidget->topLevelItemCount()));
|
||||
QComboBox* typeBox = new QComboBox(ui->treeWidget);
|
||||
QObject::connect(typeBox, SIGNAL(activated(int)), this, SLOT(updateTypes()));
|
||||
typeBox->setEditable(false);
|
||||
typeBox->addItems(sqlb::Field::Datatypes);
|
||||
ui->treeWidget->setItemWidget(tbitem, kType, typeBox);
|
||||
|
||||
tbitem->setCheckState(kNotNull, Qt::Unchecked);
|
||||
tbitem->setCheckState(kPrimaryKey, Qt::Unchecked);
|
||||
tbitem->setCheckState(kAutoIncrement, Qt::Unchecked);
|
||||
ui->treeWidget->addTopLevelItem(tbitem);
|
||||
|
||||
// add field to table object
|
||||
sqlb::FieldPtr f(new sqlb::Field(
|
||||
tbitem->text(kName),
|
||||
typeBox->currentText()
|
||||
));
|
||||
m_table->addField(f);
|
||||
|
||||
checkInput();
|
||||
}
|
||||
|
||||
void EditTableDialog::removeField()
|
||||
@@ -158,6 +286,9 @@ void EditTableDialog::removeField()
|
||||
// Creating a new one
|
||||
|
||||
// Just delete that item. At this point there is no DB table to edit or data to be lost anyway
|
||||
sqlb::FieldList fields = m_table->fields();
|
||||
fields.remove(ui->treeWidget->indexOfTopLevelItem(ui->treeWidget->currentItem()));
|
||||
m_table->setFields(fields);
|
||||
delete ui->treeWidget->currentItem();
|
||||
} else {
|
||||
// Editing an old one
|
||||
@@ -166,10 +297,16 @@ void EditTableDialog::removeField()
|
||||
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->treeWidget->currentItem()->text(0));
|
||||
if(QMessageBox::warning(this, QApplication::applicationName(), msg, QMessageBox::Yes | QMessageBox::Default, QMessageBox::No | QMessageBox::Escape) == QMessageBox::Yes)
|
||||
{
|
||||
// TODO seems this doesn't work, db table is locked.
|
||||
if(!pdb->dropColumn(curTable, ui->treeWidget->currentItem()->text(0)))
|
||||
{
|
||||
QMessageBox::warning(0, QApplication::applicationName(), pdb->lastErrorMessage);
|
||||
} else {
|
||||
//relayout
|
||||
QString sTablesql = pdb->getTableSQL(curTable);
|
||||
m_table = new sqlb::Table(sqlb::Table::parseSQL(sTablesql));
|
||||
populateFields();
|
||||
|
||||
delete ui->treeWidget->currentItem();
|
||||
}
|
||||
}
|
||||
@@ -180,6 +317,5 @@ void EditTableDialog::removeField()
|
||||
|
||||
void EditTableDialog::fieldSelectionChanged()
|
||||
{
|
||||
ui->renameFieldButton->setEnabled(ui->treeWidget->selectionModel()->hasSelection());
|
||||
ui->removeFieldButton->setEnabled(ui->treeWidget->selectionModel()->hasSelection());
|
||||
}
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
|
||||
#include <QDialog>
|
||||
class DBBrowserDB;
|
||||
class SQLiteSyntaxHighlighter;
|
||||
class QTreeWidgetItem;
|
||||
|
||||
namespace sqlb {
|
||||
class Table;
|
||||
}
|
||||
|
||||
namespace Ui {
|
||||
class EditTableDialog;
|
||||
@@ -16,22 +22,38 @@ public:
|
||||
explicit EditTableDialog(DBBrowserDB* pdb, const QString& tableName, QWidget* parent = 0);
|
||||
~EditTableDialog();
|
||||
|
||||
private:
|
||||
enum Columns {
|
||||
kName = 0,
|
||||
kType = 1,
|
||||
kNotNull = 2,
|
||||
kPrimaryKey = 3,
|
||||
kAutoIncrement = 4
|
||||
};
|
||||
|
||||
void updateColumnWidth();
|
||||
void updateTableObject();
|
||||
void updateSqlText();
|
||||
|
||||
private slots:
|
||||
virtual void populateFields();
|
||||
virtual void editField();
|
||||
virtual void addField();
|
||||
virtual void removeField();
|
||||
virtual void fieldSelectionChanged();
|
||||
virtual void accept();
|
||||
virtual void reject();
|
||||
virtual void checkInput();
|
||||
virtual void itemChanged(QTreeWidgetItem* item, int column);
|
||||
virtual void updateTypes();
|
||||
|
||||
private:
|
||||
Ui::EditTableDialog* ui;
|
||||
DBBrowserDB* pdb;
|
||||
QString curTable;
|
||||
sqlb::Table* m_table;
|
||||
QStringList types;
|
||||
QStringList fields;
|
||||
SQLiteSyntaxHighlighter* m_sqliteSyntaxHighlighter;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>414</width>
|
||||
<height>405</height>
|
||||
<width>597</width>
|
||||
<height>471</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -17,6 +17,9 @@
|
||||
<iconset resource="icons/icons.qrc">
|
||||
<normaloff>:/icons/table</normaloff>:/icons/table</iconset>
|
||||
</property>
|
||||
<property name="sizeGripEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupTable">
|
||||
@@ -62,26 +65,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="renameFieldButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Edit field</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="icons/icons.qrc">
|
||||
<normaloff>:/icons/field_edit</normaloff>:/icons/field_edit</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="removeFieldButton">
|
||||
<property name="enabled">
|
||||
@@ -119,18 +102,45 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="treeWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Field name</string>
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Field type</string>
|
||||
<string>Type</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Not null</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Primary key</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Autoincrement</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="sqlTextEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -149,7 +159,6 @@
|
||||
<tabstops>
|
||||
<tabstop>editTableName</tabstop>
|
||||
<tabstop>addFieldButton</tabstop>
|
||||
<tabstop>renameFieldButton</tabstop>
|
||||
<tabstop>removeFieldButton</tabstop>
|
||||
<tabstop>treeWidget</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
@@ -222,22 +231,6 @@
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>renameFieldButton</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>EditTableDialog</receiver>
|
||||
<slot>editField()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>136</x>
|
||||
<y>108</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>161</x>
|
||||
<y>65</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>removeFieldButton</sender>
|
||||
<signal>clicked()</signal>
|
||||
@@ -270,22 +263,6 @@
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>treeWidget</sender>
|
||||
<signal>itemChanged(QTreeWidgetItem*,int)</signal>
|
||||
<receiver>EditTableDialog</receiver>
|
||||
<slot>checkInput()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>138</x>
|
||||
<y>197</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>412</x>
|
||||
<y>135</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<slots>
|
||||
<slot>fieldSelectionChanged()</slot>
|
||||
@@ -293,5 +270,6 @@
|
||||
<slot>editField()</slot>
|
||||
<slot>removeField()</slot>
|
||||
<slot>checkInput()</slot>
|
||||
<slot>itemChanged()</slot>
|
||||
</slots>
|
||||
</ui>
|
||||
|
||||
Reference in New Issue
Block a user