From b8e16c3bddb706ecc195e86eaafb89ed90f9bfc3 Mon Sep 17 00:00:00 2001 From: Arno Date: Fri, 24 Feb 2012 20:35:27 +0100 Subject: Implement MappingTreeWidget This is a rather large commit. It implements MappingTreeWidget using MappingTreeModel unsurprisingly this uncovered some exciting bugs. Fixes the following bugs in MappingTreeModel: * use insertRows() and removeRows() when addings children, because dataChanged() won't do it. * don't use a prepared QSqlQuery when fetching children recursively. This won't work because the query is still active when we invoke ourselves again. Put the query on the stack instead * Keep the model sorted. Also add an entry for a MappingTreeEditor to the File-Menu. --- mappingtreemodel.cpp | 78 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 28 deletions(-) (limited to 'mappingtreemodel.cpp') diff --git a/mappingtreemodel.cpp b/mappingtreemodel.cpp index e48c608..78a5fb9 100644 --- a/mappingtreemodel.cpp +++ b/mappingtreemodel.cpp @@ -15,14 +15,12 @@ MappingTreeModel::MappingTreeModel(QStringList &headers, QObject *parent) : SmTr //init database mDb = QSqlDatabase::database("treedb"); mTypesQ = new QSqlQuery(mDb); - mTypesQ->prepare("SELECT imappings_type_id, tmappings_type_name FROM mapppings_type"); + mTypesQ->prepare("SELECT imappings_type_id, tmappings_type_name FROM mappings_type"); getMappingTypes(); //prepare Queries mTypeParentsQ = new QSqlQuery(mDb); - mTypeParentsQ->prepare("SELECT imapping_id, tmapping_name, tscreated FROM mappings WHERE imapping_id NOT IN (SELECT imapping_id FROM mappings_parents) AND imapping_type = :type"); - mChildrenQ = new QSqlQuery(mDb); - mChildrenQ->prepare("SELECT mappings.imapping_id, mappings.tmapping_name, mappings.tscreated FROM mappings, mappings_parents WHERE mappings_parents.iparent_id = :id AND mappings.imapping_id = mappings_parents.imapping_id"); + mTypeParentsQ->prepare("SELECT imapping_id, tmapping_name, tscreated FROM mappings WHERE imapping_id NOT IN (SELECT imapping_id FROM mappings_parents) AND imapping_type = :type ORDER BY tmapping_name"); mUpdateTypeQ = new QSqlQuery(mDb); mUpdateTypeQ->prepare("UPDATE mappings_type SET tmappings_type_name = :value WHERE imappings_type_id = :id"); mUpdateChildQ = new QSqlQuery(mDb); @@ -36,7 +34,7 @@ MappingTreeModel::MappingTreeModel(QStringList &headers, QObject *parent) : SmTr mSelectChildQ = new QSqlQuery(mDb); mSelectChildQ->prepare("SELECT imapping_id, tmapping_name, tscreated FROM mappings WHERE tmapping_name = :name AND imapping_type = :type"); mAddParentQ = new QSqlQuery(mDb); - mAddParentQ->prepare("INSERT INTO mappings_parents VALUES(:id, :parentid"); + mAddParentQ->prepare("INSERT INTO mappings_parents (imapping_id, iparent_id) VALUES(:id, :parentid)"); mDeleteChildQ = new QSqlQuery(mDb); mDeleteChildQ->prepare("DELETE FROM mappings WHERE imapping_id = :id"); } @@ -44,7 +42,6 @@ MappingTreeModel::MappingTreeModel(QStringList &headers, QObject *parent) : SmTr MappingTreeModel::~MappingTreeModel(){ delete mTypesQ; delete mTypeParentsQ; - delete mChildrenQ; delete mUpdateTypeQ; delete mUpdateChildQ; delete mAddMappingTypeQ; @@ -104,9 +101,9 @@ bool MappingTreeModel::setData(const QModelIndex &index, const QVariant &value, if(!index.isValid()){ return false; } - if(role == Qt::EditRole || role == NameRole){ + SmTreeItem *item = itemAt(index); + if(role == Qt::EditRole){ mDb.transaction(); - SmTreeItem *item = itemAt(index); QSqlQuery *q = 0; if(item == root()){ q = mUpdateTypeQ; @@ -123,6 +120,15 @@ bool MappingTreeModel::setData(const QModelIndex &index, const QVariant &value, } mDb.rollback(); } + if(role == NameRole){ + item->setData(Name, value); + } + if(role == IdRole){ + item->setData(Id, value); + } + if(role == AddedRole){ + item->setData(Added, value); + } return false; } @@ -160,15 +166,20 @@ bool MappingTreeModel::addChild(const QVariant &name, const QModelIndex &parent) if(mAddChildQ->exec()){ mSelectChildQ->bindValue(":name", name); mSelectChildQ->bindValue(":type", mType); + mSelectChildQ->exec(); while(mSelectChildQ->next()){ - QList newData; - newData << mSelectChildQ->value(1) << mSelectChildQ->value(0) << mSelectChildQ->value(2); - SmTreeItem *childItem = new SmTreeItem(newData, pItem); - pItem->appendChild(childItem); - mAddParentQ->bindValue(":id", childItem->data(Id)); - mAddParentQ->bindValue(":parentid", pItem->data(Id)); - mAddParentQ->exec(); - emit dataChanged(parent, parent); + int where = lowerBound(pItem, mSelectChildQ->value(1), Name); + if(insertRows(where, 1, parent)){ + QModelIndex newIdx = index(where, 0, parent); + setData(newIdx, mSelectChildQ->value(1), NameRole); + setData(newIdx, mSelectChildQ->value(0), IdRole); + setData(newIdx, mSelectChildQ->value(2), AddedRole); + } + if(pItem->parent() != root()){ + mAddParentQ->bindValue(":id", mSelectChildQ->value(0)); //Id + mAddParentQ->bindValue(":parentid", pItem->data(Id)); + mAddParentQ->exec(); + } return true; } } @@ -185,10 +196,7 @@ bool MappingTreeModel::deleteChild(const QModelIndex &idx){ } mDeleteChildQ->bindValue(":id", item->data(Id)); if(mDeleteChildQ->exec()){ - const QModelIndex &parent = idx.parent(); - SmTreeItem *pItem = itemAt(parent); - pItem->removeChild(item->row()); - emit dataChanged(parent, parent); + removeRows(idx.row(), 1, idx.parent()); return true; } return false; @@ -202,14 +210,16 @@ void MappingTreeModel::populate(){ mTypeParentsQ->bindValue(":type", mType); if(mTypeParentsQ->exec()){ SmTreeItem *rootItem = new SmTreeItem(NumFields); - rootItem->setData(Name, mappingTypeNameFromId(mType)); - rootItem->setData(Id, mType); + SmTreeItem *firstChild = new SmTreeItem(NumFields, rootItem); + firstChild->setData(Name, mappingTypeNameFromId(mType)); + firstChild->setData(Id, mType); + rootItem->appendChild(firstChild); //collect children recursive while(mTypeParentsQ->next()){ QList childData; childData << mTypeParentsQ->value(1) << mTypeParentsQ->value(0) << mTypeParentsQ->value(2); - SmTreeItem *childItem = new SmTreeItem(childData, rootItem); - rootItem->appendChild(childItem); + SmTreeItem *childItem = new SmTreeItem(childData, firstChild); + firstChild->appendChild(childItem); getChildrenRecursive(childItem); } setRoot(rootItem); @@ -231,14 +241,26 @@ void MappingTreeModel::getMappingTypes(){ } void MappingTreeModel::getChildrenRecursive(SmTreeItem *item){ - mChildrenQ->bindValue(":id", item->data(Id)); - if(mChildrenQ->exec()){ - while(mChildrenQ->next()){ + QSqlQuery cq(mDb); + cq.prepare("SELECT mappings.imapping_id, mappings.tmapping_name, mappings.tscreated FROM mappings, mappings_parents WHERE mappings_parents.iparent_id = :id AND mappings.imapping_id = mappings_parents.imapping_id ORDER BY mappings.tmapping_name"); + cq.bindValue(":id", item->data(Id)); + if(cq.exec()){ + while(cq.next()){ QList childData; - childData << mChildrenQ->value(1) << mChildrenQ->value(0) << mChildrenQ->value(2); + childData << cq.value(1) << cq.value(0) << cq.value(2); SmTreeItem *child = new SmTreeItem(childData, item); item->appendChild(child); getChildrenRecursive(child); } } } + +int MappingTreeModel::lowerBound(SmTreeItem *item, const QVariant &value, int column) const { + for(int i = 0; i < item->childCount(); ++i){ + SmTreeItem *child = item->child(i); + if(child->data(column).toString() > value.toString()){ + return i; + } + } + return item->childCount(); +} -- cgit v1.2.3-70-g09d2