CardView 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, CardGrid, GridColumn, GridEditor,
                                    CellButtonClickEventArgs, CellButtonEventArgs, ContextMenuEventArgs,
                                    EditorValidationEventArgs)
from DevMachines.QtitanFastInfoset import getFastInfosetVersion, FastInfosetStreamWriter, FastInfosetStreamReader

if __pyside2__:
    from PySide2 import QtCore
    from PySide2.QtCore import Qt, QFileInfo
    from PySide2.QtWidgets import (QWidget, QApplication, QVBoxLayout, QHBoxLayout, QPushButton,
                                   QSlider, QLabel, QCheckBox, QComboBox, QMessageBox, QFileDialog)
    from PySide2.QtSql import QSqlDatabase, QSqlError, QSqlTableModel

if __pyside6__:
    from PySide6 import QtCore
    from PySide6.QtCore import Qt, QFileInfo
    from PySide6.QtWidgets import (QWidget, QApplication, QVBoxLayout, QHBoxLayout, QPushButton,
                                   QSlider, QLabel, QCheckBox, QComboBox, QMessageBox, QFileDialog)
    from PySide6.QtSql import QSqlDatabase, QSqlError, QSqlTableModel

from DemoMainWindow import DemoMainWindow

class Window(DemoMainWindow):
    def __init__(self):
        DemoMainWindow.__init__(self, "QtitanDataGrid", getGridVersion())

        self.setWindowTitle(self.tr("QtitanDataGrid - CardView"))
        self.setGeometry(150, 150, 1200, 700)

        CardGrid.loadTranslation()

        self.grid = CardGrid(self)

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

        db = QSqlDatabase.addDatabase("QSQLITE", "database_demo")
        db.setDatabaseName(prefix + "/database_yachts.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.grid, db)
        model.setTable("data")
        model.select()
        if model.lastError().type() != QSqlError.NoError:
            QMessageBox.critical(0, "Demo Error", "Error: SQL data base is not valid.")
            QApplication.exit(1)
            return

        # Configure grid view
        self.grid.setViewType(CardGrid.CardView)
        view = self.grid.view()
        # view.options().setScrollRowStyle(ScrollByPixel)
        view.options().setRowAutoHeight(True)
        view.options().setCellWidth(250)

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

        view.setModel(model)

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

        column = view.getColumnByModelColumnName("Description")
        column.setEditorType(GridEditor.Memo)
        # Add cell button to the column.
        column.addButton(GridColumn.ChoiceButtonIcon, Qtitan.AtEnd)
        self.connect(column, QtCore.SIGNAL("buttonClicked(CellButtonClickEventArgs*)"), self,
            QtCore.SLOT("cellButtonClicked(CellButtonClickEventArgs*)"))

        column = view.getColumnByModelColumnName("Built Year")
        column.setEditorType(GridEditor.Date)
        column.editorRepository().setDisplayFormat("yyyy")

        column = view.getColumnByModelColumnName("id")
        view.removeColumn(column.index())

       # Show button menu for all column headers.
        for i in range(0, view.getColumnCount()):
            view.getColumn(i).setMenuButtonVisible(True)

        self.setDemoWidget(self.grid, self.createSettingsWidget())

        # view.bestFit()

        column = view.getColumnByModelColumnName("Registry")
        column.setGroupIndex(0)
        view.expandAll()

    def createSettingsWidget(self):
        # Create settings widget
        settings = QWidget(self)
        l = QVBoxLayout(settings)

        fastScrollCheck = QCheckBox(settings)
        fastScrollCheck.setText("Fast scroll effect")
        self.connect(fastScrollCheck, QtCore.SIGNAL("stateChanged(int)"), self, QtCore.SLOT("fastScrollChanged(int)"))
        l.addWidget(fastScrollCheck)
        fastScrollCheck.setChecked(True)

        dottedLineCheck = QCheckBox(settings)
        dottedLineCheck.setText("Dotted grid line")
        self.connect(dottedLineCheck, QtCore.SIGNAL("stateChanged(int)"), self, QtCore.SLOT("dottedLineChanged(int)"))
        l.addWidget(dottedLineCheck)
        dottedLineCheck.setChecked(True)

        label = QLabel(self)
        hl = QHBoxLayout()
        label.setText("Grid line style:")
        lineStylesSelect = QComboBox(settings)

        lineStylesSelect.addItem("None")
        lineStylesSelect.addItem("Both")
        lineStylesSelect.addItem("Both2D")
        lineStylesSelect.addItem("Horizontal")
        lineStylesSelect.addItem("Horizontal2D")
        lineStylesSelect.addItem("Vertical")
        lineStylesSelect.addItem("Vertical2D")
        self.connect(lineStylesSelect, QtCore.SIGNAL("currentIndexChanged(int)"), self, QtCore.SLOT("selectGridLineStyles(int)"))
        hl.addWidget(label)
        hl.addWidget(lineStylesSelect)
        l.addLayout(hl)
        lineStylesSelect.setCurrentIndex(2)

        alignLabel = QLabel(self)
        alignLayout = QHBoxLayout()
        alignLabel.setText("Items alignement:")
        alignSelect = QComboBox(settings)

        alignSelect.addItem("Left")
        alignSelect.addItem("Center")
        alignSelect.addItem("Right")
        self.connect(alignSelect, QtCore.SIGNAL("currentIndexChanged(int)"), self, QtCore.SLOT("alignSelectChanged(int)"))
        alignLayout.addWidget(alignLabel)
        alignLayout.addWidget(alignSelect)
        l.addLayout(alignLayout)
        alignSelect.setCurrentIndex(0)

        l2 = QHBoxLayout()
        button1 = QPushButton(settings)
        button1.setText(self.tr("Save to XML/FastInfoset"))
        self.connect(button1, QtCore.SIGNAL("clicked()"), self, QtCore.SLOT("saveLayout()"))
        l2.addWidget(button1)
        button2 = QPushButton(settings)
        button2.setText(self.tr("Load from XML/FastInfoset"))
        self.connect(button2, QtCore.SIGNAL("clicked()"), self, QtCore.SLOT("loadLayout()"))
        l2.addWidget(button2)
        l.addLayout(l2)

        zoomEnable = QCheckBox(settings)
        zoomEnable.setText(self.tr("Zoom enabled"))
        zoomEnable.setChecked(True)
        self.connect(zoomEnable, QtCore.SIGNAL("stateChanged(int)"), self, QtCore.SLOT("zoomEnabledChanged(int)"))
        l.addWidget(zoomEnable)

        zoomIndicator = QCheckBox(settings)
        zoomIndicator.setText(self.tr("Show zoom indicator"))
        zoomIndicator.setChecked(True)
        self.connect(zoomIndicator, QtCore.SIGNAL("stateChanged(int)"), self, QtCore.SLOT("zoomIndicatorChanged(int)"))
        l.addWidget(zoomIndicator)

        zoomSlider = QSlider(settings)
        zoomSlider.setOrientation(Qt.Horizontal)
        zoomSlider.setTickPosition(QSlider.TicksBothSides)
        zoomSlider.setMinimum(25)
        zoomSlider.setMaximum(300)
        zoomSlider.setTickInterval(25)
        zoomSlider.setSingleStep(25)
        zoomSlider.setValue(100)
        self.connect(zoomSlider, QtCore.SIGNAL("sliderMoved(int)"), self, QtCore.SLOT("zoomValueChanged(int)"))
        self.connect(self.grid.view(), QtCore.SIGNAL("zoomChanged(int)"), zoomSlider, QtCore.SLOT("setValue(int)"))
        l.addWidget(zoomSlider)

        cellAutoRaise = QCheckBox(settings)
        cellAutoRaise.setText(self.tr("Auto raise cell button"))
        self.connect(cellAutoRaise, QtCore.SIGNAL("stateChanged(int)"), self, QtCore.SLOT("cellButtonAutoRaiseEnabled(int)"))
        cellAutoRaise.setChecked(True)
        l.addWidget(cellAutoRaise)

        transparentBox = QCheckBox(settings)
        transparentBox.setText(self.tr("Transparent Background"))
        self.connect(transparentBox, QtCore.SIGNAL("stateChanged(int)"), self, QtCore.SLOT("transparentBackgroundEnabled(int)"))
        transparentBox.setChecked(False)
        l.addWidget(transparentBox)

        printButton = QPushButton(settings)
        printButton.setText(self.tr("Print Preview"))
        self.connect(printButton, QtCore.SIGNAL("clicked()"), self, QtCore.SLOT("printPreview()"))
        l.addWidget(printButton)

        return settings

    @QtCore.Slot(int)
    def fastScrollChanged(self, state):
        view = self.grid.view()
        view.options().setFastScrollEffect(Qt.CheckState(state) == Qt.Checked)

    @QtCore.Slot(int)
    def dottedLineChanged(self, state):
        view = self.grid.view()
        pen = view.options().gridLinePen()
        if Qt.CheckState(state) == Qt.Checked:
            pen.setStyle(Qt.DotLine)
        else:
            pen.setStyle(Qt.SolidLine)
        view.options().setGridLinePen(pen)

    @QtCore.Slot(int)
    def selectGridLineStyles(self, index):
        view = self.grid.view()
        if index == 0:
            view.options().setGridLines(Qtitan.LinesNone)
        elif index == 1:
            view.options().setGridLines(Qtitan.LinesBoth)
        elif index == 2:
            view.options().setGridLines(Qtitan.LinesBoth2D)
        elif index == 3:
            view.options().setGridLines(Qtitan.LinesHorizontal)
        elif index == 4:
            view.options().setGridLines(Qtitan.LinesHorizontal2D)
        elif index == 5:
            view.options().setGridLines(Qtitan.LinesVertical)
        elif index == 6:
            view.options().setGridLines(Qtitan.LinesVertical2D)
        else:
            view.options().setGridLines(Qtitan.LinesBoth)

    def alignSelectChanged(self, index):
        view = self.grid.view()
        if index == 0:
            view.options().setItemAlignment(Qt.AlignLeft)
        elif index == 1:
            view.options().setItemAlignment(Qt.AlignCenter)
        elif index == 2:
            view.options().setItemAlignment(Qt.AlignRight)
        else:
            view.options().setItemAlignment(Qt.Alignment())

    @QtCore.Slot()
    def saveLayout(self):
        fileName = QFileDialog.getSaveFileName(self, self.tr("Save QtitanDataGrid Layout to File"),
            "qtitan-layout", "XML (*.xml);;FastInfoset (*.fi)")[0]
        if fileName == "":
            return
        if "xml" in QFileInfo(fileName).completeSuffix():
            self.grid.saveLayoutToFile(fileName)
        else:
            writer = FastInfosetStreamWriter(fileName)
            self.grid.saveLayoutToXML(writer)

    @QtCore.Slot()
    def loadLayout(self):
        fileName = QFileDialog.getOpenFileName(self, self.tr("Open QtitanDataGrid Layout File"),
        "", "XML (*.xml);;FastInfoset (*.fi)")[0]
        if fileName == "":
            return
        if "xml" in QFileInfo(fileName).completeSuffix():
            self.grid.loadLayoutFromFile(fileName)
        else:
            reader = FastInfosetStreamReader(fileName)
            self.grid.loadLayoutFromXML(reader)

    @QtCore.Slot(int)
    def zoomEnabledChanged(self, state):
        view = self.grid.view()
        view.options().setZoomEnabled(Qt.CheckState(state) == Qt.Checked)

    @QtCore.Slot(int)
    def zoomIndicatorChanged(self, state):
        view = self.grid.view()
        view.options().setZoomIndicatorActive(Qt.CheckState(state) == Qt.Checked)

    @QtCore.Slot(int)
    def zoomValueChanged(self, value):
        factor = (float(value) / 25) * 25
        view = self.grid.view()
        view.options().setZoomFactor(factor / 100)

    @QtCore.Slot(int)
    def cellButtonAutoRaiseEnabled(self, state):
        view = self.grid.view()
        view.options().setCellButtonAutoRaise(Qt.CheckState(state) == Qt.Checked)

    @QtCore.Slot(int)
    def transparentBackgroundEnabled(self, state):
        view = self.grid.view()
        view.options().setTransparentBackground(Qt.CheckState(state) == Qt.Checked)
        view.options().setAlternatingRowColors(not view.options().alternatingRowColors())

    @QtCore.Slot(ContextMenuEventArgs)
    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()"))

    @QtCore.Slot(CellButtonClickEventArgs)
    def cellButtonClicked(self, args):
        QMessageBox.information(self, "Cell button clicked",
            "Clicked: Button - " + str(args.buttonIndex()) + ", Column Title - " + args.column().caption() + ", RowIndex - " + str(args.row().rowIndex()))

    @QtCore.Slot(CellButtonEventArgs)
    def cellButtonStateChanged(self, args):
        if args.row().rowIndex() == 1 or args.row().rowIndex() == 2:
            args.setEnabled(False)

    @QtCore.Slot()
    def printPreview(self):
        self.grid.view().printPreview()

    def setShadeColor(self, color):
        self.grid.themeManager().setShadeColor(color)

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