LineChartDataModel Example

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

from DevMachines import __pyside2__, __pyside6__
from DevMachines.QtitanBase import Qtitan
from DevMachines.QtitanChart import (Chart, ChartSplineSeries2D)

if __pyside2__:
    from PySide2 import QtCore
    from PySide2.QtCore import Qt
    from PySide2.QtGui import QBrush, QIcon
    from PySide2.QtWidgets import (QApplication, QComboBox, QToolBar,
        QTableWidget, QTableWidgetItem, QTableWidgetSelectionRange, QLabel, QHeaderView, QAbstractItemView)

if __pyside6__:
    from PySide6 import QtCore
    from PySide6.QtCore import Qt
    from PySide6.QtGui import QBrush, QIcon
    from PySide6.QtWidgets import (QApplication, QComboBox, QToolBar,
        QTableWidget, QTableWidgetItem, QTableWidgetSelectionRange, QLabel, QHeaderView, QAbstractItemView)

from DemoChartWindow import DemoChartWindow

import LineChartDataModel_rc

class MainWindow(DemoChartWindow):
    SelectionDataModel = 0
    EditDataModel = 1

    def __init__(self):
        DemoChartWindow.__init__(self, "Line Chart with Model")
        self.columnCount = 3
        self.rowCount = 12
        self.orientation = Qt.Vertical

        self.setChart(self.createChart(), self.createDataBindingWidget())

        self.createSeriesParametrs()
        self.seriesChanged(self.seriesSwitcher.currentIndex())

    def createChart(self):
        return Chart(self)

    def createDataBindingWidget(self):
        self.tableWidget = QTableWidget(self)
        self.tableWidget.setMaximumWidth(250)
        self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        return self.tableWidget

    def createSeriesParametrs(self):
        dataBindingGroup = self.createGroupParameters(self.tr("Data Binding"))
        formLayout = dataBindingGroup.layout()
        self.seriesSwitcher = QComboBox(dataBindingGroup)
        self.seriesSwitcher.addItem("Selection Model", MainWindow.SelectionDataModel)
        self.seriesSwitcher.addItem("Edit Model", MainWindow.EditDataModel)
        self.connect(self.seriesSwitcher, QtCore.SIGNAL("currentIndexChanged(int)"), self, QtCore.SLOT("seriesChanged(int)"))
        formLayout.addRow(self.seriesSwitcher)

        self.seriesOrientationLabel = QLabel(self.tr("Data Orientation:"), self)
        self.seriesOrientationSwitcher = QComboBox(dataBindingGroup)
        self.seriesOrientationSwitcher.addItem(self.tr("Vertical"), Qt.Vertical)
        self.seriesOrientationSwitcher.addItem(self.tr("Horizontal"), Qt.Horizontal)
        self.connect(self.seriesOrientationSwitcher, QtCore.SIGNAL("currentIndexChanged(int)"), self, QtCore.SLOT("orientationChanged(int)"))
        formLayout.addRow(self.seriesOrientationLabel, self.seriesOrientationSwitcher)

        self.toolBar = QToolBar(self)
        self.actAppendRow = self.toolBar.addAction(QIcon(":\\shared\\res\\appendrow.png"), self.tr("Append Row"))
        self.actAppendRow.setEnabled(False)
        self.connect(self.actAppendRow, QtCore.SIGNAL("triggered()"), self, QtCore.SLOT("appendRow()"))
        self.actDeleteRow = self.toolBar.addAction(QIcon(":\\shared\\res\\deleterow.png"), self.tr("Delete Row"))
        self.actDeleteRow.setEnabled(False)
        self.connect(self.actDeleteRow, QtCore.SIGNAL("triggered()"), self, QtCore.SLOT("deleteRow()"))

        formLayout.addRow(self.toolBar)

    def createSelectionModelSeries(self):
        self.disconnect(self.tableWidget, QtCore.SIGNAL("itemSelectionChanged()"), self, QtCore.SLOT("updateEnableButtons()"))
        self.connect(self.tableWidget, QtCore.SIGNAL("itemSelectionChanged()"), self, QtCore.SLOT("setSelectionData()"))

        self.createTitle(self.tr("Selection Data Model"))
        self.chart.legend().setVisible(True)

        series = ChartSplineSeries2D()
        series.setName(self.tr("Input Series"))
        self.chart.appendSeries(series)
        series.modelController().setModel(self.tableWidget.model())

    def createEditModelSeries(self):
        self.disconnect(self.tableWidget, QtCore.SIGNAL("itemSelectionChanged()"), self, QtCore.SLOT("setSelectionData()"))
        self.connect(self.tableWidget, QtCore.SIGNAL("itemSelectionChanged()"), self, QtCore.SLOT("updateEnableButtons()"))

        self.createTitle(self.tr("Edit Data Model"))
        self.chart.legend().setVisible(True)

        series = ChartSplineSeries2D()
        series.setName(self.tr("Input Series"))
        self.chart.appendSeries(series)
        series.modelController().setModel(self.tableWidget.model())

    def fill2DDataTable(self):
        self.tableWidget.clear()
        self.tableWidget.setColumnCount(self.columnCount)
        self.tableWidget.setRowCount(self.rowCount)

        for i in range(0, self.rowCount):
            for k in range(0, self.columnCount):
                item = QTableWidgetItem()
                value = 0
                if k % 2 == 0:
                    value = i * 50 + QtCore.QRandomGenerator.global_().generate() % 20
                else:
                    value = QtCore.QRandomGenerator.global_().generate() % 100

                item.setText("{}".format(value))
                self.tableWidget.setItem(i, k, item)

    def initOrientationChanged(self):
        if len(self.chart.series()) == 0:
            return
        if self.seriesOrientationSwitcher.isHidden():
            return
        series = self.chart.series()[0]
        series.modelController().setOrientation(self.orientation)
        self.tableWidget.clearSelection()

        if self.orientation == Qt.Horizontal:
            _range = QTableWidgetSelectionRange(0, 0, 1, self.columnCount - 1)
            self.tableWidget.setRangeSelected(_range, True)
        else:
            _range = QTableWidgetSelectionRange(0, 0, self.rowCount-1, 1)
            self.tableWidget.setRangeSelected(_range, True)

    def updateValueParameters(self):
        DemoChartWindow.updateValueParameters(self)
        self.initOrientationChanged()
        self.orientationChanged(self.seriesOrientationSwitcher.currentIndex())

    def seriesChanged(self, index):
        self.chart.clearSeries()
        self.chart.clearTitles()
        self.chart.setBackgroundBrush(QBrush())
        v = self.seriesSwitcher.itemData(index)
        if int(v) == MainWindow.SelectionDataModel:
            self.tableWidget.clearSelection()
            self.tableWidget.setSelectionMode(QAbstractItemView.ContiguousSelection)
            self.tableWidget.setSelectionBehavior(QAbstractItemView.SelectItems)
            self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
            self.seriesOrientationLabel.show()
            self.seriesOrientationSwitcher.show()
            self.toolBar.hide()
            self.columnCount = 3
            self.rowCount = 12
            self.fill2DDataTable()
            self.createSelectionModelSeries()
        elif int(v) == MainWindow.EditDataModel:
            self.tableWidget.clearSelection()
            self.tableWidget.setSelectionMode(QAbstractItemView.SingleSelection)
            self.tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows)
            self.tableWidget.setEditTriggers(QAbstractItemView.AllEditTriggers)
            self.seriesOrientationLabel.hide()
            self.seriesOrientationSwitcher.hide()
            self.toolBar.show()
            self.columnCount = 2
            self.rowCount = 24
            self.fill2DDataTable()
            self.createEditModelSeries()
        self.updateValueParameters()

    @QtCore.Slot(int)
    def orientationChanged(self, index):
        v = self.seriesOrientationSwitcher.itemData(index)
        self.orientation = Qt.Orientation(v)
        self.initOrientationChanged()

    @QtCore.Slot()
    def setSelectionData(self):
        if len(self.chart.series()) == 0:
            return
        series = self.chart.series()[0]
        selectedRanges = self.tableWidget.selectedRanges()
        if len(selectedRanges) == 1:
            selected = selectedRanges[0]
            if self.orientation == Qt.Horizontal:
                if selected.topRow() == selected.bottomRow():
                    series.modelController().setAxisXRow(-1)
                else:
                    series.modelController().setAxisXRow(selected.topRow())
                series.modelController().setAxisYRow(selected.bottomRow())
                series.modelController().setColumnRange(selected.leftColumn(), selected.rightColumn())
            else:
                if selected.leftColumn() == selected.rightColumn():
                    series.modelController().setAxisXColumn(-1)
                else:
                    series.modelController().setAxisXColumn(selected.leftColumn())
                series.modelController().setAxisYColumn(selected.rightColumn())
                series.modelController().setRowRange(selected.topRow(), selected.bottomRow())
        else:
            series.modelController().setAxisXRow(-1)
            series.modelController().setAxisYRow(-1)
            series.modelController().setAxisXColumn(-1)
            series.modelController().setAxisYColumn(-1)
            series.modelController().setColumnRange(-1, -1)
            series.modelController().setRowRange(-1, -1)

    @QtCore.Slot()
    def appendRow(self):
        if len(self.chart.series()) == 0:
            return

        numNewRow = 0
        selectedRanges = self.tableWidget.selectedRanges()
        if len(selectedRanges) > 0:
            indexEdit = self.tableWidget.currentIndex()
            if indexEdit.isValid():
                itemEdit = self.tableWidget.item(indexEdit.row(), indexEdit.column())
                if not itemEdit is None:
                    self.tableWidget.closePersistentEditor(itemEdit)

            self.tableWidget.reset()
            selected = selectedRanges[len(selectedRanges) - 1]
            numNewRow = selected.topRow() + 1

        self.rowCount = self.rowCount + 1
        self.tableWidget.insertRow(numNewRow)

        itemX = QTableWidgetItem()
        itemX.setText("{}".format(0))
        self.tableWidget.setItem(numNewRow, 0, itemX)

        itemY = QTableWidgetItem()
        itemY.setText("{}".format(0))
        self.tableWidget.setItem(numNewRow, 1, itemY)

        _range = QTableWidgetSelectionRange(numNewRow, 0, numNewRow, self.columnCount - 1)
        self.tableWidget.setRangeSelected(_range, True)
        index = self.tableWidget.model().index(numNewRow, 0)
        if index.isValid():
            self.tableWidget.setCurrentIndex(index)
            self.tableWidget.edit(index)
        series = self.chart.series()[0]
        series.modelController().setColumnRange(0, self.rowCount-1)

    @QtCore.Slot()
    def deleteRow(self):
        if len(self.chart.series()) == 0:
            return
        selectedRanges = self.tableWidget.selectedRanges()
        for selected in selectedRanges:
            self.tableWidget.removeRow(selected.topRow())
            self.rowCount = self.rowCount - 1
            series = self.chart.series()[0]
            series.modelController().setColumnRange(0, self.rowCount-1)
        self.updateEnableButtons()

    @QtCore.Slot()
    def updateEnableButtons(self):
        if len(self.chart.series()) == 0:
            return
        if self.orientation == Qt.Horizontal:
            isEmpty = self.tableWidget.model().columnCount() == 0
        else:
            isEmpty = self.tableWidget.model().rowCount() == 0
        selectedRanges = self.tableWidget.selectedRanges()
        self.actDeleteRow.setEnabled(len(selectedRanges) > 0)
        self.actAppendRow.setEnabled(isEmpty or len(selectedRanges) > 0)

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