1

I'm using a QSqlRelationalTableModel with a QSqlRelationalDelegate for a simple database editing application.

I would like to create a signal when user modify a value (item) in a record with delegate editor.

codes releases: PyQt4 and python 3.5.6

here you can find my code. Thanks for our help.

libraries and constants

import os
import sys
import random

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtSql import *

MAC = True
try:
    from PyQt4.QtGui import qt_mac_set_native_menubar
except ImportError:
    MAC = False



#Columns View Rooms
ID = 0
ROOMNAME = 1
ROOMAREA = 2
TEMPLID = 3
TEMPLNAMEREL =4
TEMPLLIGHTGAINRATIOREL = 5
ROOMLIGHTGAINKW=6

Relational delegate class of table :

class RoomDelegate(QSqlRelationalDelegate):

    def __init__(self, parent=None):
        super(RoomDelegate, self).__init__(parent)

    def createEditor(self, parent, option, index):

        if index.column() in (-1,ROOMNAME): # Editables columns with text
            editor = QLineEdit(parent)
            return editor
        if index.column() in (-1,ROOMAREA): #Editables columns with doubles values
            doubSpinbox=QDoubleSpinBox(parent)
            doubSpinbox.setAlignment(Qt.AlignRight|Qt.AlignVCenter)
            return doubSpinbox

        if index.column()==TEMPLID: # Editables columns with ComboBox

            return QSqlRelationalDelegate.createEditor(self, parent,option, index)

        if index.column() in (TEMPLNAMEREL,TEMPLLIGHTGAINRATIOREL,ROOMLIGHTGAINKW): # no editables columns
            return # nothing because no ediatable

        else:
            return QSqlRelationalDelegate.createEditor(self, parent,option, index)



    def setEditorData(self, editor, index):
        text = index.model().data(index, Qt.DisplayRole) #instatiate value from courrent cell

        if index.column() in(-1, ROOMNAME): # Editables columns with text
            editor.setText(text)
        elif index.column() in(-1,ROOMAREA): #Editables columns with doubles values
            editor.setValue(text)
        else:
            QSqlRelationalDelegate.setEditorData(self, editor, index)


    def setModelData(self, editor, model, index):

        if index.column() in (ROOMNAME,TEMPLNAMEREL): #columns with text
            model.setData(index, editor.text())

        elif index.column() in (ROOMAREA,TEMPLLIGHTGAINRATIOREL,ROOMLIGHTGAINKW): #columns with doubles values
            model.setData(index, editor.value())
        else:
            QSqlRelationalDelegate.setModelData(self, editor, model,index)

Main form of application:

class MainForm(QDialog):

    def __init__(self):
        super(MainForm, self).__init__()

        #Model Rooms
        self.roomsModel = QSqlRelationalTableModel(self)
        self.roomsModel.setTable("rooms")
        self.roomsModel.setRelation(TEMPLID,
                QSqlRelation("templates", "id", "TemplCode"))

        self.roomsModel.setRelation(TEMPLNAMEREL,
                QSqlRelation("templates", "id", "TemplName"))

        self.roomsModel.setRelation(TEMPLLIGHTGAINRATIOREL,
                QSqlRelation("templates", "id", "TemplLightGainRatio"))

        self.roomsModel.setSort(ROOMNAME, Qt.AscendingOrder)
        self.roomsModel.setHeaderData(ID, Qt.Horizontal, "ID")
        self.roomsModel.setHeaderData(ROOMNAME, Qt.Horizontal,"RoomName")
        self.roomsModel.setHeaderData(ROOMAREA, Qt.Horizontal,"RoomArea [m²]")
        self.roomsModel.setHeaderData(TEMPLID, Qt.Horizontal,"Code Templ")
        self.roomsModel.setHeaderData(TEMPLNAMEREL, Qt.Horizontal,"Template Name")
        self.roomsModel.setHeaderData(TEMPLLIGHTGAINRATIOREL, Qt.Horizontal,"LightGainRatio [W/m²]")
        self.roomsModel.setHeaderData(ROOMLIGHTGAINKW, Qt.Horizontal,"LightGain [kW]")
        self.roomsModel.select()



        #View Rooms

        self.roomsView = QTableView()
        self.roomsView.setModel(self.roomsModel)
        self.roomsView.setItemDelegate(RoomDelegate(self))
        self.roomsView.setSelectionMode(QTableView.SingleSelection)
        self.roomsView.setSelectionBehavior(QTableView.SelectItems)
        self.roomsView.setColumnHidden(ID, False)
        self.roomsView.resizeColumnsToContents()
        self.roomsView.horizontalHeader().setStretchLastSection(True)


        #Tabs --------------
        tabs    = QTabWidget()

        # Create tabs
        tabTempl    = QWidget() 
        tabRoom = QWidget()
        # Resize width and height
        tabs.resize(250, 150)

        # Add tabs
        tabs.addTab(tabRoom,"Rooms")

        # Layout Rooms
        roomsLayout = QGridLayout()
        roomsLayout.addWidget(self.roomsView, 0,0)
        tabRoom.setLayout(roomsLayout)

        dataLayout = QGridLayout()
        dataLayout.addWidget(self.roomsView, 0,0)


        layout = QHBoxLayout()
        layout.addWidget(tabs, 1)

        self.setLayout(layout)


        self.setMinimumWidth(650)
        self.setWindowTitle("Mini Database")

method for create and add data into my database :

def createDataMiniDataBase():

    # delete existing tables  (Drop)
    print("Dropping tables...")
    query = QSqlQuery()
    query.exec_("DROP TABLE templates")
    query.exec_("DROP TABLE rooms")

    QApplication.processEvents()

    print("Creating tables...")

    query.exec_("""CREATE TABLE templates (
                id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL,
                TemplCode VARCHAR(20) NOT NULL UNIQUE,
                TemplName VARCHAR(20) NOT NULL UNIQUE,
                TemplLightGainRatio REAL NOT NULL)""")

    query.exec_("""CREATE TABLE rooms (
                id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL,
                RoomName VARCHAR(20) NOT NULL,
                RoomArea REAL NOT NULL,
                TemplId INTEGER NOT NULL,
                TemplName INTEGER NOT NULL,
                TemplLightGainRatio INTEGER NOT NULL,
                RoomLightGainkW REAL NOT NULL,
                FOREIGN KEY (TemplId) REFERENCES templates,
                FOREIGN KEY (TemplName) REFERENCES templates,
                FOREIGN KEY (TemplLightGainRatio) REFERENCES templates)""")


    QApplication.processEvents()


    print("Populating tables...")

    #Default Template:
    DefTempId ='0'
    DefTempTemplCode='def'
    DefTempTemplName='Default'
    DefTempTemplLightGainRatio='0'


    # templates table -----------------
    query.prepare("INSERT INTO templates (id,TemplCode, TemplName,TemplLightGainRatio) "
                  "VALUES (:id,:TemplCode, :TemplName,:TemplLightGainRatio)")

    query.bindValue(":id", DefTempId)
    query.bindValue(":TemplCode", DefTempTemplCode)
    query.bindValue(":TemplName", DefTempTemplName)
    query.bindValue(":TemplLightGainRatio", DefTempTemplLightGainRatio)

    query.exec_()

    query.exec_("INSERT INTO templates (TemplCode, TemplName,TemplLightGainRatio) "
                "VALUES ('CH01', 'NameTemp 01','15')")
    query.exec_("INSERT INTO templates (TemplCode, TemplName,TemplLightGainRatio) "
                "VALUES ('CH02', 'NameTemp 02','25')")


    #rooms table --------------------------
    query.prepare("INSERT INTO rooms (RoomName, RoomArea, TemplId,TemplName,TemplLightGainRatio,RoomLightGainkW) "
                  "VALUES (:RoomName, :RoomArea, :TemplId,:TemplName,:TemplLightGainRatio, :RoomLightGainkW)")



    nb=0
    for i in range(10):
        nb+=1
        RoomName="Room"+" "+str(nb)
        RoomArea=random.uniform(0, 150)
        RoomArea=round(RoomArea,2)

        query.bindValue(":RoomName", RoomName)
        query.bindValue(":RoomArea", RoomArea)
        query.bindValue(":TemplId", DefTempId)
        query.bindValue(":TemplName", DefTempId)
        query.bindValue(":TemplLightGainRatio", DefTempId)

        query.bindValue(":RoomLightGainkW", 0)
        query.exec_()       



def main():

    # Create Mini Data Base File

    app = QApplication(sys.argv)

    filename = os.path.join(os.path.dirname(__file__), "MiniDataBase.db")
    create = not QFile.exists(filename)
    db = QSqlDatabase.addDatabase("QSQLITE")
    db.setDatabaseName(filename)
    if not db.open():
        QMessageBox.warning(None, "MiniDataBase Manager",
            "Database Error: {}".format(db.lastError().text()))
        sys.exit(1)


    # Populate Mini Data Base File
    createDataMiniDataBase()

    form = MainForm()
    form.show()

    app.exec_()

main()
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • What kind of help do you exactly need here? – dvelopp Nov 07 '18 at 10:39
  • I would like the code to create the signal. Something like this: self.connect(self.roomsView.selectionModel(), SIGNAL(("currentRowChanged(QModelIndex,QModelIndex)")), self.roomsRowChanged) – Simone ARAGNO Nov 07 '18 at 10:43
  • @SimoneARAGNO Do you want a signal that tells you when the text has been modified in the editor or when it is finished editing? Besides, what information do you want to transmit the signal? – eyllanesc Nov 07 '18 at 22:10
  • I would like a signal only when data have been modified. The slot will activate an other method that do a calculation. – Simone ARAGNO Nov 08 '18 at 12:30
  • @SimoneARAGNO What exactly do you mean with data? When you modify something in the editor, the database is not necessarily modified unless you press enter or similar. – eyllanesc Nov 09 '18 at 01:37
  • @eyllanesc The signal is triggered after editor validation (e.i. push enter or cell focus change or click outside the cell). I would like update database in accord with edition and start a calculation with this signal. – Simone ARAGNO Nov 09 '18 at 13:12
  • @SimoneARAGNO What information should that signal carry? – eyllanesc Nov 09 '18 at 14:42
  • @eyllanesc The signal should carry the new value of cell and some values from a database query. – Simone ARAGNO Nov 09 '18 at 15:02

0 Answers0