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_())
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_())