HtmlManipulation 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, Grid, GridColumn, GridSummary, GridEditor,
                                    GridViewOptions,
                                    CellButtonClickEventArgs, ContextMenuEventArgs,
                                    ColumnLinkEventArgs, PreviewRowLinkEventArgs, EditorLinkEventArgs)

if __pyside2__:
    from PySide2 import QtCore
    from PySide2.QtCore import Qt, QDate, QAbstractItemModel, QModelIndex
    from PySide2.QtWidgets import (QWidget, QApplication, QVBoxLayout, QHBoxLayout, QPushButton,
                                   QSlider, QLabel, QCheckBox, QComboBox, QMessageBox)

if __pyside6__:
    from PySide6 import QtCore
    from PySide6.QtCore import Qt, QDate, QAbstractItemModel, QModelIndex
    from PySide6.QtWidgets import (QWidget, QApplication, QVBoxLayout, QHBoxLayout, QPushButton,
                                   QSlider, QLabel, QCheckBox, QComboBox, QMessageBox)

from DemoMainWindow import DemoMainWindow

class DataItem:
    v0 = None
    v1 = None
    v2 = None
    v3 = None
    v4memo = None
    v5 = None

class HthmlManipulationModel(QAbstractItemModel):
    def __init__(self, parent):
        QAbstractItemModel.__init__(self, parent)

        self.values = list(range(0, 100))
        y = 2009
        m = 1
        d = 1
        for i in self.values:
            item = DataItem()
            item.v0 = True
            item.v1 = i
            item.v2 = "String-1: " + str(i)
            item.v3 = "String-2: " + str(i)
            item.v4memo = """<a href='#link_""" + str(i) + """"'>Lorem ipsum</a> dolor sit amet, consectetur adipiscing elit. Nullam sodales,
                  libero at hendrerit commodo, urna velit vestibulum purus, cursus dignissim tellus ante non leo."""

            if d > 28:
                d = 1
                m = m + 1
                if m > 12:
                    m = 1
                    y = y + 1

            item.v5 = QDate(y, m, d)
            if not ((i + 1) % 10):
                d = d + 1
            self.values[i] = item

    def headerData(self, section, orientation, role):
        if section == 0:
            return "Boolean"
        elif section == 1:
            return "Integer"
        elif section == 2:
            return "String"
        elif section == 3:
            return "String"
        elif section == 4:
            return "Memo"
        elif section == 5:
            return "Date"
        return None

    def parent(self, child):
        return QModelIndex()

    def hasChildren(self, parent):
        if parent.model() == self or not parent.isValid():
            return self.rowCount(parent) > 0 and self.columnCount(parent) > 0
        return False

    def rowCount(self, parent):
        if parent.isValid():
            return 0
        return len(self.values)

    def columnCount(self, parent):
        if parent.isValid():
            return 0
        return 6

    def index(self, row, column, parent):
        if parent.isValid():
            return QModelIndex()

        if row < 0 or row >= self.rowCount(parent):
            return QModelIndex()

        if column < 0 or column >= self.columnCount(parent):
            return QModelIndex()

        return self.createIndex(row, column, parent)

    def data(self, index, role):
        if not index.isValid():
            return None

        if index.row() < 0 or index.row() >= self.rowCount(index.parent()):
            return None

        if index.column() < 0 or index.column() >= self.columnCount(index.parent()):
            return None

        if role == Qt.WhatsThisRole:
            previewText = """Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam sodales,
                             libero at hendrerit commodo, urna velit vestibulum purus, cursus dignissim tellus ante non leo.
                             <h2>Duis quam lorem, bibendum id luctus eu, consequat at purus</h2>.
                             <a href='#preview_link'>Test Preview Link</a>
                             Duis quam lorem, bibendum id luctus eu, consequat at purus. Curabitur posuere ligula eu turpis porttitor faucibus rhoncus neque pretium.
                             Aenean ut urna felis."""
            return previewText

        elif role == Qt.DisplayRole or role == Qt.EditRole:
            if index.column() == 0:
                return self.values[index.row()].v0
            elif index.column() == 1:
                return self.values[index.row()].v1
            elif index.column() == 2:
                return self.values[index.row()].v2
            elif index.column() == 3:
                return self.values[index.row()].v3
            elif index.column() == 4:
                return self.values[index.row()].v4memo
            elif index.column() == 5:
                return self.values[index.row()].v5
        elif role == Qt.CheckStateRole:
            if index.column() == 0:
                return self.values[index.row()].v0
        return None

    def setData(self, index, value, role):
        if not index.isValid():
            return False

        if index.row() < 0 or index.row() >= self.rowCount(index.parent()):
            return False

        if index.column() < 0 or index.column() >= self.columnCount(index.parent()):
            return False

        if role != Qt.EditRole:
            return False

        if index.column() == 0:
            self.values[index.row()].v0 = bool(value)
        elif index.column() == 1:
            self.values[index.row()].v1 = int(value)
        elif index.column() == 2:
            self.values[index.row()].v2 = str(value)
        elif index.column() == 3:
            self.values[index.row()].v3 = str(value)
        elif index.column() == 4:
            self.values[index.row()].v4memo = str(value)
        elif index.column() == 5:
            self.values[index.row()].v5 = value

        self.dataChanged.emit(index, index)
        return True

    def flags(self, index):
        if not index.isValid():
            return Qt.ItemFlags()
        return Qt.ItemIsEnabled | Qt.ItemIsEditable

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

        self.setWindowTitle(self.tr("QtitanDataGrid - HTML Manipulation"))
        self.setGeometry(150, 150, 1100, 900)

        Grid.loadTranslation()

        self.grid = Grid()
        model = HthmlManipulationModel(self.grid)

        # Configure grid view
        self.grid.setViewType(Grid.BandedTableView)
        view = self.grid.view()
        view.addBand("Section 1")
        view.addBand("Section 2")
        view.addBand("Section 3")
        view.options().setFooterSummaryVisible(False)
        view.options().setGroupSummaryPlace(GridViewOptions.SummaryRow)
        view.options().setPreviewRowEnabled(True)
        view.options().setPreviewExpandButtonVisible(False)
        view.modelController().previewRowDataBinding().setDisplayRole(Qt.WhatsThisRole)
        view.options().setPreviewRowHeight(150)
        view.options().setScrollRowStyle(Qtitan.ScrollByPixel)

        band = view.getBand(0)
        band.setHtmlCaption("<i>Section</i> <b>One</b> <a href='#test1'>Link 1</a>")
        band = view.getBand(1)
        band.setHtmlCaption("<i>Section</i> <b>Two</b> <a href='#test2'>Link 2</a>")
        band = view.getBand(2)
        band.setHtmlCaption("<i>Section</i> <b>Three</b> <a href='#test3'>Link 3</a>")

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

        # Connect link activation handlers.
        self.connect(view, QtCore.SIGNAL("previewLinkActivated(PreviewRowLinkEventArgs*)"), self,
            QtCore.SLOT("previewLinkActivated(PreviewRowLinkEventArgs*)"))
        self.connect(view, QtCore.SIGNAL("columnLinkActivated(ColumnLinkEventArgs*)"), self,
            QtCore.SLOT("columnLinkActivated(ColumnLinkEventArgs*)"))
        self.connect(view, QtCore.SIGNAL("editorLinkActivated(EditorLinkEventArgs*)"), self,
            QtCore.SLOT("editorLinkActivated(EditorLinkEventArgs*)"))
        self.connect(view, QtCore.SIGNAL("summaryGroupTextChanging(SummaryGroupTextEventArgs*)"), self,
            QtCore.SLOT("summaryGroupTextChanging(SummaryGroupTextEventArgs*)"))
        view.setModel(model)

        column = view.getColumn(0)
        column.setBandIndex(0)
        # Configure the summary
        column.setDefaultGroupSummary(GridSummary.Max)
        column.setDecorationColor(Qt.yellow)

        column = view.getColumn(1)
        column.setBandIndex(1)
        column.setRowIndex(0)
        # Configure the summary
        column.setDefaultGroupSummary(GridSummary.Avg)
        column.setFooterSummary(GridSummary.Avg)

        column = view.getColumn(2)
        column.setBandIndex(1)
        column.setRowIndex(1)
        column.setHtmlCaption("<font color='red'>Column</font> with <a href='#string_column1'>HTML Caption</a>")
        # Configure the summary
        column.setDefaultGroupSummary(GridSummary.Count)
        column.setFooterSummary(GridSummary.Count)

        column = view.getColumn(3)
        column.setBandIndex(1)
        column.setRowIndex(2)
        # Add cell button to the column.
        column.addButton()
        self.connect(column, QtCore.SIGNAL("buttonClicked(CellButtonClickEventArgs*)"), self,
            QtCore.SLOT("cellButtonClicked(CellButtonClickEventArgs*)"))

        column = view.getColumn(4)
        column.setBandIndex(2)
        column.setEditorType(GridEditor.Memo)
        column.editorRepository().setHTML(True)
        column.setRowSpan(3)

        column = view.getColumn(5)
        column.setBandIndex(0)
        column.setRowSpan(2)
        column.setRowIndex(1)
        column.setGroupIndex(0)
        # Configure the summary
        column.setDefaultGroupSummary(GridSummary.Min)
        column.setFooterSummary(GridSummary.Max)
        view.expandAll()

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

    def createSettingsWidget(self):
        settings = QWidget(self)
        l = QVBoxLayout(settings)
        autoWidthCheck = QCheckBox(settings)
        l.addWidget(autoWidthCheck)
        autoWidthCheck.setText("Column auto width")
        self.connect(autoWidthCheck, QtCore.SIGNAL("stateChanged(int)"), self, QtCore.SLOT("autoWidthStateChanged(int)"))
        autoWidthCheck.setChecked(True)

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

        label = QLabel(settings)
        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)

        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)

        frozenRowsBox = QCheckBox(settings)
        frozenRowsBox.setText(self.tr("Frozen Rows"))
        self.connect(frozenRowsBox, QtCore.SIGNAL("stateChanged(int)"), self, QtCore.SLOT("frozenRowsEnabled(int)"))
        frozenRowsBox.setChecked(True)
        l.addWidget(frozenRowsBox)

        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

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

    @QtCore.Slot(PreviewRowLinkEventArgs)
    def previewLinkActivated(self, args):
         QMessageBox.information(self, self.tr("Preview link clicked"), "Clicked: RowIndex " + str(args.row().rowIndex()) + ", Link " + args.anchor())

    @QtCore.Slot(ColumnLinkEventArgs)
    def columnLinkActivated(self, args):
        if args.column().inherits("Qtitan::GridTableBand"):
            QMessageBox.information(self, self.tr("Band Column HTML link clicked"), "Clicked: Band " + args.column().caption() + ", Link " + args.anchor())
        else:
            QMessageBox.information(self, self.tr("Column HTML link clicked"), "Clicked: Column " + args.column().caption() + ", Link " + args.anchor())

    @QtCore.Slot(EditorLinkEventArgs)
    def editorLinkActivated(self, args):
        QMessageBox.information(self, self.tr("Cell Editor link clicked"),
            "Column " + args.column().caption() + ", RowIndex " + str(args.row().rowIndex()) + ", Link " + args.anchor())

    @QtCore.Slot(EditorLinkEventArgs)
    def summaryGroupTextChanging(self, args):
        if args.dataBinding().column() == 1:
            args.setTextColor(Qt.red)

    @QtCore.Slot(int)
    def autoWidthStateChanged(self, state):
        view = self.grid.view()
        view.tableOptions().setColumnAutoWidth(Qt.CheckState(state) == Qt.Checked)

    @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)

    @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 frozenRowsEnabled(self, state):
        view = self.grid.view()
        view.tableOptions().setRowFrozenButtonVisible(Qt.CheckState(state) == Qt.Checked)
        view.tableOptions().setFrozenPlaceQuickSelection(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()
    def printPreview(self):
        self.grid.view().printPreview()

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