RelationMode Example

import sys, os
sys.path.append(os.path.dirname(os.path.realpath(__file__)) + "/../../shared")

from DevMachines import __pyside2__, __pyside6__
from DevMachines import QtitanBase
from DevMachines.QtitanBase import Qtitan
from DevMachines.QtitanGrid import (getGridVersion, qtn_variant_to_pixmap, Grid, GridRow,
                                    GridColumn, GridEditor, GridModelDataBinding,
                                    GridViewOptions,
                                    ContextMenuEventArgs, CellButtonClickEventArgs)

if __pyside2__:
    from PySide2 import QtCore
    from PySide2.QtCore import Qt
    from PySide2.QtWidgets import (QWidget, QApplication, QTextEdit, QDialog, QTabWidget,
                                   QVBoxLayout, QHBoxLayout, QPushButton,
                                   QSlider, QLabel, QCheckBox, QComboBox, QMessageBox, QSplitter)
    from PySide2.QtSql import QSqlDatabase, QSqlError, QSqlTableModel, QSqlQuery

if __pyside6__:
    from PySide6 import QtCore
    from PySide6.QtCore import Qt
    from PySide6.QtWidgets import (QWidget, QApplication, QTextEdit, QDialog, QTabWidget,
                                   QVBoxLayout, QHBoxLayout, QPushButton,
                                   QSlider, QLabel, QCheckBox, QComboBox, QMessageBox, QSplitter)
    from PySide6.QtSql import QSqlDatabase, QSqlError, QSqlTableModel, QSqlQuery

from DemoMainWindow import DemoMainWindow

class CountriesDemoModel(QSqlTableModel):
    def __init__(self, parent, db):
        QSqlTableModel.__init__(self, parent, db)

    def data(self, index, role):
        if role == Qt.DecorationRole:
            pixmapindex = QSqlTableModel.index(index.row(), 1, index.parent())
            v = QSqlTableModel.data(self, pixmapindex, Qt.DisplayRole)
            pixmap = qtn_variant_to_pixmap(v)
            return pixmap
        return QSqlTableModel.data(self, index, role)

class Window(DemoMainWindow):
    def __init__(self):
        DemoMainWindow.__init__(self, "QtitanDataGrid", getGridVersion())
        self.setWindowTitle(self.tr("QtitanDataGrid - Relation/MasterDetails modes"))
        self.setGeometry(250, 250, 800, 500)

        Grid.loadTranslation()

        self.tabs = QTabWidget(self)
        self.createRelationGrid()
        self.createMasterDetailsGrid()

        self.setDemoWidget(self.tabs, None)

    def createRelationGrid(self):
        self.relationGrid = Grid(self)

        model = QSqlTableModel(self.relationGrid)
        model.setTable("employee")
        model.select()
        model.setEditStrategy(QSqlTableModel.OnFieldChange)

        # Configure grid view
        self.relationGrid.setViewType(Grid.TableView)
        view = self.relationGrid.view()
        view.setModel(model)

        view.options().setNewRowPlace(Qtitan.AtEnd)
        column = view.getColumnByCaption("id")
        column.editorRepository().setEditable(True)

        # Connect Grid's context menu handler.
        self.connect(view, QtCore.SIGNAL("contextMenu(ContextMenuEventArgs*)"), self, QtCore.SLOT("contextMenu(ContextMenuEventArgs* )"))

        city = QSqlTableModel(self.relationGrid)
        city.setTable("city")
        city.select()

        country = QSqlTableModel(self.relationGrid)
        country.setTable("country")
        country.select()

        column = view.getColumnByCaption("city")
        # column.setEditorType(GridEditor.ComboBox)
        column.setEditorType(GridEditor.Table)
        column.dataBinding().setRelationMode(GridModelDataBinding.Relation)
        column.dataBinding().setRelationModel(city)
        column.dataBinding().setForeignKey("id")
        column.dataBinding().setRoleMapping(Qt.DisplayRole, "name")

        column = view.getColumnByCaption("country")
        column.setEditorType(GridEditor.ComboBox)
        column.dataBinding().setRelationMode(GridModelDataBinding.Relation)
        column.dataBinding().setRelationModel(country)
        column.dataBinding().setForeignKey("id")
        column.dataBinding().setRoleMapping(Qt.DisplayRole, "name")

        self.tabs.insertTab(0, self.relationGrid, self.tr("Relation Mode"))

    def createMasterDetailsGrid(self):
        self.masterDetailsGrid = Grid(self)

        prefix = os.path.dirname(os.path.realpath(__file__))
        prefix += "/../../SQLFiles/assets"

        db = QSqlDatabase.addDatabase("QSQLITE", "database_demo")

        db.setDatabaseName(prefix + "/films.sqlite")
        db.setHostName("")
        db.setPort(-1)
        if not db.open("", ""):
            err = db.lastError()
            QSqlDatabase.removeDatabase("database_demo")
            QMessageBox.critical(self, "Demo Error", "Error: Can't open database " + db.databaseName() + " , error - " + err.text())
            QApplication.exit(1)
            return

        model = QSqlTableModel(self.masterDetailsGrid, db)
        model.setTable("Films")
        model.select()
        if model.lastError().type() != QSqlError.NoError:
            QMessageBox.critical(0, "Demo Error", "Error: SQL data base is not valid.")
            QApplication.exit(1)
            return

        countriesModel = CountriesDemoModel(self.masterDetailsGrid, db)
        countriesModel.setTable("Countries")
        countriesModel.select()
        if countriesModel.lastError().type() != QSqlError.NoError:
            QMessageBox.critical(0, "Demo Error", "Error: SQL data base is not valid.")
            QApplication.exit(1)
            return

        # Configure grid view
        self.masterDetailsGrid.setViewType(Grid.TableView)
        view = self.masterDetailsGrid.view()
        view.options().setBorderWidth(0)
        view.options().setRowAutoHeight(True)
        view.options().setScrollRowStyle(Qtitan.ScrollByPixel)

        self.connect(view, QtCore.SIGNAL("editorEditModeChanged(GridEditor *)"), self, QtCore.SLOT("editorModeChanged(GridEditor *)"))

        view.setModel(model)

        column = view.getColumnByModelColumnName("Goofs")
        column.setEditorType(GridEditor.Memo)

        column = view.getColumnByModelColumnName("Plot")
        column.setEditorType(GridEditor.Memo)

        column = view.getColumnByModelColumnName("Photo")
        column.setEditorType(GridEditor.Picture)

        column = view.getColumnByModelColumnName("Country")
        column.editorRepository().setEditorActivationPolicy(GridEditor.ActivateByAnyEvents)
        column.dataBinding().setRelationMode(GridModelDataBinding.Relation)
        column.dataBinding().setRelationModel(countriesModel)
        column.dataBinding().setForeignKey("id")
        column.dataBinding().setRoleMapping(Qt.DisplayRole, "Name")
        column.dataBinding().setRoleMapping(Qt.DecorationRole, "Flag")
        column.setEditorType(GridEditor.ComboBox)

        actorsModel = QSqlTableModel(None, db)
        actorsModel.setTable("Actors")
        actorsModel.select()
        column = view.getColumnByModelColumnName("Cast")
        column.dataBinding().setRelationMode(GridModelDataBinding.MasterDetailsRelation)
        column.dataBinding().setRelationModel(actorsModel)
        column.dataBinding().setForeignKey("filself.id")
        column.dataBinding().setRoleMapping(Qt.DisplayRole, "Name")
        column.setEditorType(GridEditor.Table)

        view.bestFit()

        self.tabs.insertTab(1, self.masterDetailsGrid, self.tr("MasterDetails Mode"))

    def setShadeColor(self, color):
        self.relationGrid.themeManager().setShadeColor(color)
        self.masterDetailsGrid.themeManager().setShadeColor(color)

    def editorModeChanged(self, editor):
        if editor.site().dataBinding().columnName() != "Cast":
            return
        # Customize grid editor here
        box = editor.getCellWidget()
        if box == None:
            return
        grid = box.grid()
        view = grid.view()
        view.options().setRowAutoHeight(True)
        view.options().setNewRowText(self.tr("Click here to add actor"))
        # view.options().setFocusFollowsMouse(True)

        column = view.getColumnByModelColumnName("Actor photo")
        column.setEditorType(GridEditor.Picture)

    def contextMenu(self, args):
        args.contextMenu().addAction("Print Preview", self, QtCore.SLOT(printPreview()))
        args.contextMenu().addSeparator()
        args.contextMenu().addAction("Developer Machines on the Web", self, QtCore.SLOT("showCompanyWebSite()"))

    def printPreview(self):
        self.masterDetailsGrid.view().printPreview()

def createConnection():
    db = QSqlDatabase.addDatabase("QSQLITE")
    db.setDatabaseName(":memory:")
    if not db.open():
        QMessageBox.critical(None, qApp.tr("Cannot open database"),
            qApp.tr("Unable to establish a database connection.\n"
                     "This example needs SQLite support. Please read "
                     "the Qt SQL driver documentation for information how "
                     "to build it.\n\n"
                     "Click Cancel to exit."), QMessageBox.Cancel)
        return False

    query = QSqlQuery()
    query.exec_("create table employee(id integer primary key, 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, 1)")

    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(1, 'USA')")
    query.exec_("insert into country values(47, 'Norway')")
    query.exec_("insert into country values(49, 'Germany')")
    return True

if __name__ == "__main__":
    app = QApplication(sys.argv)
    if not createConnection():
        sys.exit(1)
    w = Window()
    w.show()
    sys.exit(app.exec_())