QSqlRelationalTableModel with QSqlRelationalDelegate not working behind QAbstractProxyModel

十年热恋 提交于 2019-12-12 01:55:38

问题


I need to swap the rows and columns of a QSqlRelationalTableModel. After a lot of searching, I wrote a little proxymodel to flip the rows and the columns.

It is partly working. The relations in the table are resolved and showed but the dropboxes to choose them gets lost. Also, how do I get them to update?

Here is a little self-contained script that reproduces the behavior.

Where is my error? I have strong suspicion that it has to do with the signals and slots of the models but I haven't found any hint which ones and how to reimplement them.

Is there another easier way to swap rows and columns?

EDIT: to clarify the delegational model isn't completely not working its just partial working.

from PySide import QtCore, QtGui, QtSql
from PySide.QtCore import Qt, QModelIndex
from PySide.QtGui import QAbstractProxyModel, QWidget, QHBoxLayout, QTableView
from PySide.QtSql import QSqlRelationalDelegate


class FlipProxyModel(QAbstractProxyModel):
    def __init__(self, parent=None):
        super(FlipProxyModel, self).__init__(parent)

    def mapFromSource(self, index):
        return self.createIndex(index.column(), index.row())

    def mapToSource(self, index):
        return self.sourceModel().index(index.column(), index.row(), QModelIndex())

    def columnCount(self, parent):
        return self.sourceModel().rowCount(QModelIndex())

    def rowCount(self, parent):
        return self.sourceModel().columnCount(QModelIndex())

    def index(self, row, column, parent):
        return self.createIndex(row, column)

    def parent(self, index):
        # tables have no parent object so return empty
        return QModelIndex()

    def data(self, index, role):
        return self.sourceModel().data(self.mapToSource(index), role)

    def headerData(self, section, orientation, role):
        if orientation == Qt.Horizontal:
            return self.sourceModel().headerData(section, Qt.Vertical, role)
        if orientation == Qt.Vertical:
            return self.sourceModel().headerData(section, Qt.Horizontal, role)


def createConnection():
    db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
    db.setDatabaseName(":memory:")
    if not db.open():
        print 'fatal'
        return False
    return True

def createView(title, model):
    view = QtGui.QTableView()
    view.setModel(model)
    view.setItemDelegate(QtSql.QSqlRelationalDelegate(view))
    view.setWindowTitle(title)

    return view

if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    if not createConnection():
        sys.exit(1)

    # createRelationalTables()
    query = QtSql.QSqlQuery()
    query.exec_("create table employee(id int, name varchar(20), city int, country int)")
    query.exec_("insert into employee values(1, 'Espen', 5000, 47)")
    query.exec_("insert into employee values(2, 'Harald', 80000, 49)")
    query.exec_("insert into employee values(3, 'Sam', 100, 41)")
    query.exec_("create table city(id int, name varchar(20))")
    query.exec_("insert into city values(100, 'San Jose')")
    query.exec_("insert into city values(5000, 'Oslo')")
    query.exec_("insert into city values(80000, 'Munich')")
    query.exec_("create table country(id int, name varchar(20))")
    query.exec_("insert into country values(41, 'USA')")
    query.exec_("insert into country values(47, 'Norway')")
    query.exec_("insert into country values(49, 'Germany')")

    model = QtSql.QSqlRelationalTableModel()
    model.setTable("employee")
    model.setEditStrategy(QtSql.QSqlTableModel.OnManualSubmit)
    model.setRelation(2, QtSql.QSqlRelation('city', 'id', 'name'))
    model.setRelation(3, QtSql.QSqlRelation('country', 'id', 'name'))
    model.setHeaderData(0, QtCore.Qt.Horizontal, "ID")
    model.setHeaderData(1, QtCore.Qt.Horizontal, "Name")
    model.setHeaderData(2, QtCore.Qt.Horizontal, "City")
    model.setHeaderData(3, QtCore.Qt.Horizontal, "Country")
    model.select()

    proxy = FlipProxyModel()
    proxy.setSourceModel(model)

    w = QWidget()
    layout = QHBoxLayout(w)
    view = QTableView()
    view.setModel(model)
    view.setItemDelegate(QSqlRelationalDelegate(view))
    layout.addWidget(view)

    view2 = QTableView()
    view2.setModel(proxy)
    view2.setItemDelegate(QSqlRelationalDelegate(view2))
    layout.addWidget(view2)

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

回答1:


big thanks to some friendly stranger on the #pyqt irc. this is solved.

the answer is that the delegates also need an proxymodel class.

the class looks like:

class FlipProxyDelegate(QSqlRelationalDelegate):
def createEditor(self, parent, option, index):
    proxy = index.model()
    base_index = proxy.mapToSource(index)
    return super(FlipProxyDelegate, self).createEditor(parent, option, base_index)

def setEditorData(self, editor, index):
    proxy = index.model()
    base_index = proxy.mapToSource(index)
    return super(FlipProxyDelegate, self).setEditorData(editor, base_index)

def setModelData(self, editor, model, index):
    base_model = model.sourceModel()
    base_index = model.mapToSource(index)
    return super(FlipProxyDelegate, self).setModelData(editor, base_model, base_index)

its used then replacing the delegates as:

view.setItemDelegate(FlipProxyDelegate(self.tableView))


来源:https://stackoverflow.com/questions/28231773/qsqlrelationaltablemodel-with-qsqlrelationaldelegate-not-working-behind-qabstrac

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!