diff --git a/src/CreateIndexForm.cpp b/src/CreateIndexForm.cpp index 66afa381..ef98f4ad 100644 --- a/src/CreateIndexForm.cpp +++ b/src/CreateIndexForm.cpp @@ -34,7 +34,7 @@ void createIndexForm::languageChange() void createIndexForm::tableSelected( const QString & entry ) { - tableMap::Iterator it; + objectMap::Iterator it; for ( it = mtablemap.begin(); it != mtablemap.end(); ++it ) { QString tname = it.value().getname() ; @@ -86,20 +86,20 @@ void createIndexForm::confirmCreate() } } -void createIndexForm::populateTable(const tableMap& rmap) +void createIndexForm::populateTable(const QList& rmap) { - tableMap::ConstIterator it; + QList::ConstIterator it; for ( it = rmap.begin(); it != rmap.end(); ++it ) { - comboTables->addItem( it.value().getname() ); + comboTables->addItem( (*it).getname() ); //populate the fields with first table name - if (it==mtablemap.begin()){ + /*if (it==mtablemap.begin()){ fieldMap::Iterator fit; - fieldMap fmap = it.value().fldmap; + fieldMap fmap = (*it).value().fldmap; for ( fit = fmap.begin(); fit != fmap.end(); ++fit ) { comboFields->addItem( fit.value().getname() ); } - } + }*/ } } diff --git a/src/CreateIndexForm.h b/src/CreateIndexForm.h index 57ce5823..9d637575 100644 --- a/src/CreateIndexForm.h +++ b/src/CreateIndexForm.h @@ -241,13 +241,13 @@ public: createIndexForm(QWidget* parent = 0, Qt::WindowFlags fl = Qt::Window); ~createIndexForm(); - tableMap mtablemap; + objectMap mtablemap; QString createStatement; public slots: virtual void tableSelected( const QString & entry ); virtual void confirmCreate(); - virtual void populateTable( const tableMap& rmap ); + virtual void populateTable(const QList &rmap ); protected slots: virtual void languageChange(); diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index af6321d0..c3b22685 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -173,56 +173,34 @@ void MainWindow::populateStructure() return; } db.updateSchema(); - QStringList tblnames = db.getTableNames(); + QStringList tblnames = db.getBrowsableObjectNames(); sqliteHighlighter->setTableNames(tblnames); - tableMap::ConstIterator it; + objectMap::ConstIterator it; - for ( it = db.tbmap.begin(); it != db.tbmap.end(); ++it ) { - - //* Table node + for ( it = db.objMap.begin(); it != db.objMap.end(); ++it ) + { + // Object node QTreeWidgetItem *tableItem = new QTreeWidgetItem(); - tableItem->setText(0, it.value().getname()); - tableItem->setText(1, "table"); - tableItem->setText(3, it.value().getsql()); - tableItem->setIcon(0, QIcon(":/icons/table")); + 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()); ui->dbTreeWidget->addTopLevelItem(tableItem); - //* Field Nodes - fieldMap::ConstIterator fit; - for ( fit = it.value().fldmap.begin(); fit != it.value().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")); + // 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")); + } + // TODO make an options/setting autoexpand + ui->dbTreeWidget->setItemExpanded(tableItem, true); } - // TODO make an options/setting autoexpand - ui->dbTreeWidget->setItemExpanded(tableItem, true); - } - objectMap::ConstIterator it2; - for ( it2 = db.idxmap.begin(); it2 != db.idxmap.end(); ++it2 ) { - QTreeWidgetItem *item = new QTreeWidgetItem(); - item->setText( 0, it2.value().getname() ); - item->setText( 1, "index" ); - item->setText( 3, it2.value().getsql() ); - item->setIcon(0, QIcon(":/icons/index")); - ui->dbTreeWidget->addTopLevelItem(item); - } - for ( it2 = db.viewmap.begin(); it2 != db.viewmap.end(); ++it2 ) { - QTreeWidgetItem *item = new QTreeWidgetItem(); - item->setText( 0, it2.value().getname() ); - item->setText( 1, "view" ); - item->setText( 3, it2.value().getsql() ); - item->setIcon(0, QIcon(":/icons/view")); - ui->dbTreeWidget->addTopLevelItem(item); - } - for ( it2 = db.trgmap.begin(); it2 != db.trgmap.end(); ++it2 ) { - QTreeWidgetItem *item = new QTreeWidgetItem(); - item->setText( 0, it2.value().getname() ); - item->setText( 1, "trigger" ); - item->setText( 3, it2.value().getsql() ); - item->setIcon(0, QIcon(":/icons/trigger")); - ui->dbTreeWidget->addTopLevelItem(item); } } @@ -245,6 +223,12 @@ void MainWindow::populateTable( const QString & tablename, bool keepColumnWidths 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)); @@ -266,9 +250,12 @@ void MainWindow::resetBrowser() { QString sCurrentTable = ui->comboBrowseTable->currentText(); ui->comboBrowseTable->clear(); - QStringList tab = db.getTableNames(); - if(!tab.isEmpty()) { - ui->comboBrowseTable->addItems(tab); + 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); @@ -577,7 +564,7 @@ void MainWindow::createIndex() return; } createIndexForm dialog(this); - dialog.populateTable(db.tbmap); + dialog.populateTable(db.objMap.values("table")); if(dialog.exec()) { if (!db.executeSQL(dialog.createStatement)){ @@ -763,6 +750,10 @@ void MainWindow::doubleClickTable( int row, int col ) return; } + // Don't allow editing of other objects than tables + if(db.getObjectByName(ui->comboBrowseTable->currentText()).gettype() != "table") + return; + int realRow = row; editText(realRow , col); @@ -869,7 +860,7 @@ void MainWindow::importTableFromCSV() void MainWindow::exportTableToCSV() { exportTableCSVForm dialog(this); - dialog.populateOptions(db.getTableNames()); + dialog.populateOptions(db.getBrowsableObjectNames()); if(dialog.exec()) { //load our table @@ -1081,26 +1072,18 @@ void MainWindow::on_tree_context_menu(const QPoint &qPoint){ } //** Tree selection changed void MainWindow::on_tree_selection_changed(){ - if (!ui->dbTreeWidget->selectionModel()->hasSelection()){ - ui->editDeleteTableAction->setEnabled(false); - ui->editModifyTableAction->setEnabled(false); - ui->editAddFieldActionPopup->setEnabled(false); - ui->editModifyFieldActionPopup->setEnabled(false); - ui->editDeleteFieldActionPopup->setEnabled(false); - return; - } + // Just assume first that something's selected that can not be edited at all + ui->editDeleteTableAction->setEnabled(false); + ui->editModifyTableAction->setEnabled(false); + ui->editAddFieldActionPopup->setEnabled(false); + ui->editModifyFieldActionPopup->setEnabled(false); + ui->editDeleteFieldActionPopup->setEnabled(false); if(ui->dbTreeWidget->currentItem()->text(1) == "table"){ ui->editDeleteTableAction->setEnabled(true); ui->editModifyTableAction->setEnabled(true); ui->editAddFieldActionPopup->setEnabled(true); - ui->editModifyFieldActionPopup->setEnabled(false); - ui->editDeleteFieldActionPopup->setEnabled(false); - - }else if(ui->dbTreeWidget->currentItem()->text(1) == "field"){ - ui->editAddFieldActionPopup->setEnabled(false); - ui->editDeleteTableAction->setEnabled(false); - ui->editModifyTableAction->setEnabled(false); + }else if(ui->dbTreeWidget->currentItem()->text(1) == "field" && ui->dbTreeWidget->currentItem()->parent()->text(1) == "table"){ ui->editModifyFieldActionPopup->setEnabled(true); ui->editDeleteFieldActionPopup->setEnabled(true); } diff --git a/src/sqlitedb.cpp b/src/sqlitedb.cpp index adae46be..d5952477 100644 --- a/src/sqlitedb.cpp +++ b/src/sqlitedb.cpp @@ -8,7 +8,7 @@ #include "SQLLogDock.h" #include -void DBBrowserTable::addField(int order, const QString& wfield,const QString& wtype) +void DBBrowserObject::addField(int order, const QString& wfield,const QString& wtype) { fldmap[order] = DBBrowserField(wfield,wtype); } @@ -217,10 +217,7 @@ void DBBrowserDB::close (){ sqlite3_close(_db); } _db = 0; - idxmap.clear(); - trgmap.clear(); - viewmap.clear(); - tbmap.clear(); + objMap.clear(); idmap.clear(); browseRecs.clear(); browseFields.clear(); @@ -543,26 +540,42 @@ resultMap DBBrowserDB::getFindResults( const QString & wstatement) } -QStringList DBBrowserDB::getTableNames() +QStringList DBBrowserDB::getBrowsableObjectNames() { - tableMap::ConstIterator it; + objectMap::ConstIterator it; QStringList res; - for ( it = tbmap.begin(); it != tbmap.end(); ++it ) { - res.append( it.value().getname() ); + for(it=objMap.begin();it!=objMap.end();++it) + { + if(it.key() == "table" || it.key() == "view") + res.append(it.value().getname()); } return res; } +objectMap DBBrowserDB::getBrowsableObjects() +{ + objectMap::ConstIterator it; + objectMap res; + + for(it=objMap.begin();it!=objMap.end();++it) + { + if(it.key() == "table" || it.key() == "view") + res.insert(it.key(), it.value()); + } + + return res; +} + QStringList DBBrowserDB::getIndexNames() { - objectMap::Iterator it; - objectMap tmap = idxmap; + QList tmap = objMap.values("index"); + QList::ConstIterator it; QStringList res; for ( it = tmap.begin(); it != tmap.end(); ++it ) { - res.append( it.value().getname() ); + res.append( (*it).getname() ); } return res; @@ -570,14 +583,16 @@ QStringList DBBrowserDB::getIndexNames() QStringList DBBrowserDB::getTableFields(const QString & tablename) { - tableMap::ConstIterator it; + objectMap::ConstIterator it; QStringList res; - for ( it = tbmap.begin(); it != tbmap.end(); ++it ) { - if (tablename.compare(it.value().getname())==0 ){ + for ( it = objMap.begin(); it != objMap.end(); ++it ) + { + if((*it).getname() == tablename) + { fieldMap::ConstIterator fit; - for ( fit = it.value().fldmap.begin(); fit != it.value().fldmap.end(); ++fit ) { + for ( fit = (*it).fldmap.begin(); fit != (*it).fldmap.end(); ++fit ) { res.append( fit.value().getname() ); } } @@ -587,14 +602,16 @@ QStringList DBBrowserDB::getTableFields(const QString & tablename) QStringList DBBrowserDB::getTableTypes(const QString & tablename) { - tableMap::ConstIterator it; + objectMap::ConstIterator it; QStringList res; - for ( it = tbmap.begin(); it != tbmap.end(); ++it ) { - if (tablename.compare(it.value().getname())==0 ){ + for ( it = objMap.begin(); it != objMap.end(); ++it ) + { + if((*it).getname() == tablename) + { fieldMap::ConstIterator fit; - for ( fit = it.value().fldmap.begin(); fit != it.value().fldmap.end(); ++fit ) { + for ( fit = (*it).fldmap.begin(); fit != (*it).fldmap.end(); ++fit ) { res.append( fit.value().gettype() ); } } @@ -602,6 +619,19 @@ QStringList DBBrowserDB::getTableTypes(const QString & tablename) return res; } +DBBrowserObject DBBrowserDB::getObjectByName(const QString& name) +{ + objectMap::ConstIterator it; + QStringList res; + + for ( it = objMap.begin(); it != objMap.end(); ++it ) + { + if((*it).getname() == name) + return *it; + } + return DBBrowserObject(); +} + int DBBrowserDB::getRecordCount() { return browseRecs.count(); @@ -629,10 +659,7 @@ void DBBrowserDB::updateSchema( ) const char *tail; int err=0; - idxmap.clear(); - tbmap.clear(); - viewmap.clear(); - trgmap.clear(); + objMap.clear(); lastErrorMessage = QString("no error"); QString statement = "SELECT type, name, sql FROM sqlite_master;"; @@ -647,14 +674,8 @@ void DBBrowserDB::updateSchema( ) val2 = QString((const char *) sqlite3_column_text(vm, 1)); val3 = QString((const char *) sqlite3_column_text(vm, 2)); - if(val1 == "table") - tbmap[val2] = DBBrowserTable(GetDecodedQString(val2), GetDecodedQString(val3)); - else if(val1 == "index") - idxmap[val2] = DBBrowserObject(GetDecodedQString(val2), GetDecodedQString(val3)); - else if(val1 == "view") - viewmap[val2] = DBBrowserObject(GetDecodedQString(val2), GetDecodedQString(val3)); - else if(val1 == "trigger") - trgmap[val2] = DBBrowserObject(GetDecodedQString(val2), GetDecodedQString(val3)); + if(val1 == "table" || val1 == "index" || val1 == "view" || val1 == "trigger") + objMap.insert(val1, DBBrowserObject(GetDecodedQString(val2), GetDecodedQString(val3), GetDecodedQString(val1))); else qDebug("unknown object type %s", val1.toStdString().c_str()); } @@ -664,35 +685,39 @@ void DBBrowserDB::updateSchema( ) } qDebug(sqlite3_errmsg(_db)); - //now get the field list for each table in tbmap - tableMap::Iterator it; - for ( it = tbmap.begin(); it != tbmap.end(); ++it ) { - statement = "PRAGMA TABLE_INFO("; - statement.append( it.value().getname()); - statement.append(");"); - logSQL(statement, kLogMsg_App); - err=sqlite3_prepare(_db,statement.toUtf8(),statement.length(), - &vm, &tail); - if (err == SQLITE_OK){ - it.value(). fldmap.clear(); - int e = 0; - while ( sqlite3_step(vm) == SQLITE_ROW ){ - if (sqlite3_column_count(vm)==6) { - QString val1, val2; - int ispk= 0; - val1 = QString((const char *) sqlite3_column_text(vm, 1)); - val2 = QString((const char *) sqlite3_column_text(vm, 2)); - ispk = sqlite3_column_int(vm, 5); - if (ispk==1){ - val2.append(QString(" PRIMARY KEY")); + //now get the field list for each table + objectMap::Iterator it; + for ( it = objMap.begin(); it != objMap.end(); ++it ) + { + if((*it).gettype() == "table" || (*it).gettype() == "view") + { + statement = "PRAGMA TABLE_INFO("; + statement.append( (*it).getname()); + statement.append(");"); + logSQL(statement, kLogMsg_App); + err=sqlite3_prepare(_db,statement.toUtf8(),statement.length(), + &vm, &tail); + if (err == SQLITE_OK){ + (*it).fldmap.clear(); + int e = 0; + while ( sqlite3_step(vm) == SQLITE_ROW ){ + if (sqlite3_column_count(vm)==6) { + QString val1, val2; + int ispk= 0; + val1 = QString((const char *) sqlite3_column_text(vm, 1)); + val2 = QString((const char *) sqlite3_column_text(vm, 2)); + ispk = sqlite3_column_int(vm, 5); + if (ispk==1){ + val2.append(QString(" PRIMARY KEY")); + } + (*it).addField(e,GetDecodedQString(val1),GetDecodedQString(val2)); + e++; } - it.value().addField(e,GetDecodedQString(val1),GetDecodedQString(val2)); - e++; } + sqlite3_finalize(vm); + } else{ + lastErrorMessage = QString ("could not get types"); } - sqlite3_finalize(vm); - } else{ - lastErrorMessage = QString ("could not get types"); } } } diff --git a/src/sqlitedb.h b/src/sqlitedb.h index a575b8a9..306ee9c6 100644 --- a/src/sqlitedb.h +++ b/src/sqlitedb.h @@ -3,6 +3,7 @@ #include #include +#include #include "sqlite3.h" class SQLLogDock; @@ -33,8 +34,7 @@ static QString g_sApplicationNameShort = QString("sqlitebrowser"); static QString g_applicationIconName = QString(":/oldimages/icon16"); typedef QMap fieldMap; -typedef QMap tableMap; -typedef QMap objectMap; +typedef QMultiMap objectMap; typedef QMap rowIdMap; typedef QList rowList; @@ -58,32 +58,20 @@ class DBBrowserObject { public: DBBrowserObject() : name( "" ) { } - DBBrowserObject( const QString& wname,const QString& wsql ) - : name( wname), sql( wsql ) - { } - QString getname() const { return name; } - QString getsql() const { return sql; } -private: - QString name; - QString sql; -}; - -class DBBrowserTable -{ -public: - DBBrowserTable() : name( "" ) { } - DBBrowserTable( const QString& wname,const QString& wsql ) - : name( wname), sql( wsql ) + DBBrowserObject( const QString& wname,const QString& wsql, const QString& wtype ) + : name( wname), sql( wsql ), type(wtype) { } void addField(int order, const QString& wfield,const QString& wtype); QString getname() const { return name; } QString getsql() const { return sql; } + QString gettype() const { return type; } fieldMap fldmap; private: QString name; QString sql; + QString type; }; @@ -114,7 +102,9 @@ public: QStringList getTableFields(const QString & tablename); QStringList getTableTypes(const QString & tablename); - QStringList getTableNames(); + QStringList getBrowsableObjectNames(); + objectMap getBrowsableObjects(); + DBBrowserObject getObjectByName(const QString& name); QStringList getIndexNames(); resultMap getFindResults( const QString & wstatement); int getRecordCount(); @@ -135,10 +125,7 @@ public: QStringList decodeCSV(const QString & csvfilename, char sep, char quote, int maxrecords, int * numfields); - tableMap tbmap; - objectMap idxmap; - objectMap viewmap; - objectMap trgmap; + objectMap objMap; rowIdMap idmap; rowList browseRecs;