QSqlRelationalTableModel 与 QSqlRelationalDelegate 不在 QAbstractProxyModel 后面工作

QSqlRelationalTableModel with QSqlRelationalDelegate not working behind QAbstractProxyModel

我需要交换 QSqlRelationalTableModel 的行和列。经过大量搜索,我写了一个小代理模型来翻转行和列。

部分有效。 table 中的关系已解析并显示,但选择它们的下拉框丢失了。另外,如何让它们更新?

这是一个重现该行为的独立脚本。

我的错误在哪里?我强烈怀疑它与模型的信号和插槽有关,但我没有找到任何提示,说明哪些信号和插槽以及如何重新实现它们。

还有其他更简单的交换行和列的方法吗?

编辑:澄清委托模型并非完全不起作用,它只是部分起作用。

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

非常感谢#pyqt irc 上的一些友好的陌生人。这已经解决了。

答案是委托人还需要一个代理模型class。

class 看起来像:

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)

它用于然后将代表替换为:

view.setItemDelegate(FlipProxyDelegate(self.tableView))