PDA

View Full Version : how to change the selection of a parent QTableView from a sub QTableView



flapjack
25th November 2009, 07:53
I have a special table that's related to it's self like so


CREATE TABLE people (
ID INTEGER PRIMARY KEY AUTOINCREMENT
, Name TEXT
, BlaBla TEXT)

CREATE TABLE children (
parentID INTEGER
, childID INTEGER
, Whatever TEXT)


so I'd like to have 1 QTableView that's a master list and lists all people. I'd like a sub QTableView that will list only the children of the selected person. So far no big deal. What I can't figure out is how to make it so that when the user double clicks on a child that child becomes the new selection of the master list of all people.

I've hacked together a quick example of what I'm talking about that works OK on my machine using python 2.6 and pyqt 4.5.3 though this should be general to all qt more or less. In the example it's the childrenClicked method that I can't figure out.

Thanks,
Aaron





from PyQt4.QtSql import (QSqlDatabase, QSqlQuery, QSqlTableModel,
QSqlRelation, QSqlRelationalTableModel)
from PyQt4.QtGui import (QApplication, QMainWindow)
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import (QObject, SIGNAL, SLOT, QVariant, Qt)
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class PeopleTableModel(QSqlTableModel):
def __init__(self):
QSqlTableModel.__init__(self)
self.setTable("people")

self.setHeaderData(0, Qt.Horizontal, QVariant("ID"))
self.setHeaderData(1, Qt.Horizontal, QVariant("Name"))
self.setHeaderData(2, Qt.Horizontal, QVariant("BlaBla"))

self.setEditStrategy(QSqlTableModel.OnFieldChange)

self.select()

class ChildrenModel(QSqlRelationalTableModel):
def __init__(self):
QSqlRelationalTableModel.__init__(self)

self.setTable("children")

self.setRelation(0, QSqlRelation("people", "ID", "Name"))
self.setRelation(1, QSqlRelation("people", "ID", "Name"))
self.setHeaderData(2, Qt.Horizontal, QVariant("Whatever"))
self.select()

class aMainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)

self.setObjectName("MainWindow")
self.resize(714, 690)

self.centralwidget = QtGui.QWidget(self)
self.centralwidget.setObjectName("centralwidget")
self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
self.horizontalLayout.setObjectName("horizontalLayout")

self.peopleView = QtGui.QTableView(self)
self.peopleView.setEditTriggers(QtGui.QAbstractIte mView.NoEditTriggers)
self.peopleView.setAlternatingRowColors(True)
self.peopleView.setSelectionMode(QtGui.QAbstractIt emView.SingleSelection)
self.peopleView.setSelectionBehavior(QtGui.QAbstra ctItemView.SelectRows)
self.horizontalLayout.addWidget(self.peopleView)
self.childrenView = QtGui.QTableView(self)
self.childrenView.setEditTriggers(QtGui.QAbstractI temView.NoEditTriggers)
self.childrenView.setAlternatingRowColors(True)
self.childrenView.setSelectionMode(QtGui.QAbstract ItemView.SingleSelection)
self.childrenView.setSelectionBehavior(QtGui.QAbst ractItemView.SelectRows)
self.horizontalLayout.addWidget(self.childrenView)

self.setCentralWidget(self.centralwidget)


self.db = QSqlDatabase.addDatabase('QSQLITE')
self.db.setDatabaseName(':memory:')
self.db.open()

#I added extra columns just to be sure to show row selection not just cell.
query = QSqlQuery(self.db)
query.prepare('CREATE TABLE people ( \
ID INTEGER PRIMARY KEY AUTOINCREMENT \
, Name TEXT \
, BlaBla TEXT);')
query.exec_()
query.prepare('CREATE TABLE children ( \
parentID INTEGER \
, childID INTEGER \
, Whatever TEXT);')
query.exec_()

query.prepare('INSERT INTO people VALUES(?, ?, ?)')
ids = [1,2,3,4,5]
names = ['Mary', 'John', 'Sam', 'Kate', 'Mark']
bla = ['hmm', 'hmm', 'hmm', 'hmm', 'hmm']

query.addBindValue(ids)
query.addBindValue(names)
query.addBindValue(bla)
query.execBatch()

query.prepare('INSERT INTO children VALUES(?, ?, ?)')
parents = [1,1,2,2]
children = [4,5,1,3]
yada = ['hmm', 'hmm', 'hmm', 'hmm']

query.addBindValue(parents)
query.addBindValue(children)
query.addBindValue(yada)
query.execBatch()

self.peopleModel = PeopleTableModel()
self.peopleView.setModel(self.peopleModel)
self.peopleView.setColumnHidden(0, True)
self.childrenModel = ChildrenModel()
self.childrenView.setModel(self.childrenModel)
self.childrenView.setColumnHidden(0, True)

QObject.connect(self.peopleView.selectionModel(),
SIGNAL("currentRowChanged(QModelIndex,QModelIndex)"),
self.peopleChanged)

QObject.connect(self.childrenView,
SIGNAL("doubleClicked(QModelIndex)"),
self.childrenClicked)

self.childrenView.horizontalHeader().moveSection(1 ,0)
self.peopleChanged(self.peopleView.currentIndex())


def peopleChanged(self, index):
if index.isValid():
record = self.peopleModel.record(index.row())
id = record.value("ID").toInt()[0]
self.childrenModel.setFilter(QString("parentID = %1").arg(id))
else:
self.childrenModel.setFilter("parentID = -1")
#self.childrenModel.reset() # workaround for Qt <= 4.3.3/SQLite bug
self.childrenModel.select()
self.childrenView.horizontalHeader().setVisible(
self.childrenModel.rowCount() > 0)

def childrenClicked(self, index):
print 'childrenClicked'
#newIndex = index.sibling(3,0)
#self.tableView.selectionModel().select(newIndex)
print index
record = self.childrenModel.record(index.row())
print record
print record.value(1).toString()

#works but how do I get the row from the childs index?
self.peopleView.selectRow(4)

#seems to select (look at row numbers carefully) but doesn't change children.
#self.peopleView.selectionModel().select(self.peop leModel.index(1,0), QItemSelectionModel.SelectCurrent)


if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
MainWindow = aMainWindow()

MainWindow.show()
sys.exit(app.exec_())

caduel
25th November 2009, 08:36
Well, unless you query the "parent's row" in the sql query (so the child record would contain the row already) you will have to search your people model for the entry selected in the children model.

flapjack
26th November 2009, 05:45
yes exactly but I can't figure out how to do that. The children model only returns the values not the ids and even if I had the id (column value) I don't know how to get the index of a specific row from a db value. like I said I can't seem to connect the two halves in that one method.