kblst
kblst

Reputation: 519

How to connect to the QSqlDriver notification signal

How can I bind the SQLite driver notification signal to include the notification source and payload in a PyQt5 project as seen in the C++ docs from QT? As far as I can see overloading the signal with the driver[str].connect syntax will only accept one argument.

connect(sqlDriver, QOverload<const QString &, QSqlDriver::NotificationSource, const QVariant &>::of(&QSqlDriver::notification),
    [=](const QString &name, QSqlDriver::NotificationSource source, const QVariant &payload){ /* ... */ });

Can be found at https://doc.qt.io/qt-5/qsqldriver.html#notification-1

Minimal example:

import sys
from PyQt5 import QtSql, QtGui, QtWidgets

def createDB():
    db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
    db.setDatabaseName(':memory:')

    if not db.open():
        print('could not open')
        return False

    query = QtSql.QSqlQuery()

    query.exec_("create table sportsmen(id int primary key, "
                "firstname varchar(20), lastname varchar(20))")

    query.exec_("insert into sportsmen values(101, 'Roger', 'Federer')")
    query.exec_("insert into sportsmen values(102, 'Christiano', 'Ronaldo')")
    query.exec_("insert into sportsmen values(103, 'Ussain', 'Bolt')")
    query.exec_("insert into sportsmen values(104, 'Sachin', 'Tendulkar')")
    query.exec_("insert into sportsmen values(105, 'Saina', 'Nehwal')")
    return db


class Table(QtSql.QSqlTableModel):

    def __init__(self):
        super(Table, self).__init__()
        self.setTable('sportsmen')
        self.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange)

        self.database().driver().subscribeToNotification('sportsmen')

        self.database().driver().notification[str].connect(self.onNotification)
        # signal = pyqtSignal([str], [QSqlDriver.NotificationSource], ['QVariant'])

    # @pyqtSlot(str, int, str)
    def onNotification(self, name, source=None, payout=None):
        """
        Only sends the name of the signal, need to bind the full; name, source, paylad signal
        """
        print(self.sender)
        print(name, source, payout)
        print('it worked')


def addrow():
    print(model.rowCount())
    record = model.record()
    model.insertRecord(-1, record)


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)

    db = createDB()

    model = Table()
    view = QtWidgets.QTableView()
    view.setModel(model)
    model.select()

    dlg = QtWidgets.QDialog()
    layout = QtWidgets.QVBoxLayout()
    layout.addWidget(view)

    button = QtWidgets.QPushButton("Add a row")
    button.clicked.connect(addrow)
    layout.addWidget(button)

    btn1 = QtWidgets.QPushButton("del a row")
    btn1.clicked.connect(lambda: model.removeRow(view.currentIndex().row()))
    layout.addWidget(btn1)

    dlg.setLayout(layout)
    dlg.show()
    sys.exit(app.exec_())

Some relevant links:

Upvotes: 2

Views: 794

Answers (1)

eyllanesc
eyllanesc

Reputation: 244093

You have to use the signature to use the overload signal:

class Table(QtSql.QSqlTableModel):
    def __init__(self):
        super(Table, self).__init__()
        self.setTable("sportsmen")
        self.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange)

        self.database().driver().notification[
            str, QtSql.QSqlDriver.NotificationSource, "QVariant"
        ].connect(self.onNotification)
        self.database().driver().subscribeToNotification("sportsmen")

    @QtCore.pyqtSlot(str, QtSql.QSqlDriver.NotificationSource, "QVariant")
    def onNotification(self, name, source, payload):
        print(name, source, payload)

Upvotes: 2

Related Questions