From 05da4bfe8ee761bcfd7ed4c07ac85196dbd9b15d Mon Sep 17 00:00:00 2001 From: Peinthor Rene Date: Sat, 16 Mar 2013 20:22:23 +0100 Subject: [PATCH] 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. --- src/EditTableDialog.cpp | 250 +++++++++++++++++++++++++++++++--------- src/EditTableDialog.h | 24 +++- src/EditTableDialog.ui | 92 ++++++--------- 3 files changed, 251 insertions(+), 115 deletions(-) diff --git a/src/EditTableDialog.cpp b/src/EditTableDialog.cpp index 41b30d06..9df2d900 100644 --- a/src/EditTableDialog.cpp +++ b/src/EditTableDialog.cpp @@ -1,9 +1,14 @@ #include "EditTableDialog.h" #include "ui_EditTableDialog.h" -#include "EditFieldDialog.h" +#include "SQLiteSyntaxHighlighter.h" #include #include +#include + #include "sqlitedb.h" +#include "sqlitetypes.h" + +#include 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 tbl_structure; - for(int i=0;itreeWidget->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(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(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()); } diff --git a/src/EditTableDialog.h b/src/EditTableDialog.h index 40711776..567850f3 100644 --- a/src/EditTableDialog.h +++ b/src/EditTableDialog.h @@ -3,6 +3,12 @@ #include 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 diff --git a/src/EditTableDialog.ui b/src/EditTableDialog.ui index 9166d1f4..30805d31 100644 --- a/src/EditTableDialog.ui +++ b/src/EditTableDialog.ui @@ -6,8 +6,8 @@ 0 0 - 414 - 405 + 597 + 471 @@ -17,6 +17,9 @@ :/icons/table:/icons/table + + true + @@ -62,26 +65,6 @@ - - - - false - - - Edit field - - - - :/icons/field_edit:/icons/field_edit - - - Qt::ToolButtonTextBesideIcon - - - true - - - @@ -119,18 +102,45 @@ + + + 0 + 0 + + + + false + - Field name + Name - Field type + Type + + + + + Not null + + + + + Primary key + + + + + Autoincrement + + + @@ -149,7 +159,6 @@ editTableName addFieldButton - renameFieldButton removeFieldButton treeWidget buttonBox @@ -222,22 +231,6 @@ - - renameFieldButton - clicked() - EditTableDialog - editField() - - - 136 - 108 - - - 161 - 65 - - - removeFieldButton clicked() @@ -270,22 +263,6 @@ - - treeWidget - itemChanged(QTreeWidgetItem*,int) - EditTableDialog - checkInput() - - - 138 - 197 - - - 412 - 135 - - - fieldSelectionChanged() @@ -293,5 +270,6 @@ editField() removeField() checkInput() + itemChanged()