MultiSelection Example

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

from PySide2 import QtCore
from PySide2.QtCore import Qt, SIGNAL, SLOT
from PySide2.QtGui import QPixmap, QIcon
from PySide2.QtWidgets import (QWidget, QApplication, QTextEdit, QDialog, QVBoxLayout, QHBoxLayout, QPushButton,
                               QSlider, QLabel, QCheckBox, QComboBox, QMessageBox, QSplitter)

from PySide2.QtSql import QSqlDatabase, QSqlError, QSqlTableModel

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

from DemoMainWindow import DemoMainWindow

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

        self.setWindowTitle(self.tr("QtitanDataGrid Demo (Multi-selection)"))
        self.setGeometry(150, 150, 1000, 800)

        Grid.loadTranslation()

        self.grid = Grid(self)

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

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

        db.setDatabaseName(prefix + "/database.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

        model.setEditStrategy(QSqlTableModel.OnFieldChange)

        # Configure grid view
        self.grid.setViewType(Grid.BandedTableView)
        view = self.grid.view()
        view.options().setShowFocusDecoration(True)
        view.tableOptions().setColumnAutoWidth(True)

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

        characteristicsBand = view.addBand("Characteristics")
        engineeringBand = view.addBand("Engineering")

        view.setModel(model)

        column = view.getColumnByModelColumnName("id")
        column.setBandIndex(characteristicsBand.index())
        column.setRowSpan(2)
        column.addButton(GridColumn.ClearButtonIcon, Qtitan.AtBeginning, GridColumn.FluentFixedPolicy)
        self.connect(column, SIGNAL("buttonClicked(CellButtonClickEventArgs*)"), self, SLOT("cellButtonClicked(CellButtonClickEventArgs*)"))

        column = view.getColumnByModelColumnName("Airline")
        column.setBandIndex(characteristicsBand.index())
        column.setRowSpan(2)

        column = view.getColumnByModelColumnName("Registration")
        column.setBandIndex(characteristicsBand.index())
        column.setRowSpan(2)

        column = view.getColumnByModelColumnName("Aircraft")
        column.setBandIndex(characteristicsBand.index())
        column.setRowSpan(2)

        column = view.getColumnByModelColumnName("Location")
        column.setBandIndex(characteristicsBand.index())
        column.setRowSpan(2)

        column = view.getColumnByModelColumnName("Date")
        column.setBandIndex(characteristicsBand.index())
        column.setRowSpan(2)

        # Add cell button to the column.
        column.addButton(GridColumn.ClearButtonIcon, Qtitan.AtEnd, GridColumn.MouseOverPolicy)
        self.connect(column, SIGNAL("buttonClicked(CellButtonClickEventArgs*)"), self, SLOT("cellButtonClicked(CellButtonClickEventArgs*)"))

        column = view.getColumnByModelColumnName("Photo")
        column.setEditorType(GridEditor.ComboBoxPicture)
        column.setBandIndex(engineeringBand.index())
        column.setRowSpan(2)

        column = view.getColumnByModelColumnName("History")
        column.setEditorType(GridEditor.Memo)
        column.setBandIndex(engineeringBand.index())
        column.setRowSpan(2)

        column = view.getColumnByModelColumnName("Info")
        column.setEditorType(GridEditor.Memo)
        column.setBandIndex(engineeringBand.index())
        column.setRowSpan(2)

        # 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):
        # Create settings widget
        settings = QWidget(self)
        l = QVBoxLayout(settings)
        hl = QHBoxLayout()
        label = QLabel(self)
        label.setText("Multi-select mode:")
        policyBox = QComboBox(self)
        policyBox.addItem("Single Row")
        policyBox.addItem("Single Cell")
        policyBox.addItem("Multi Rows")
        policyBox.addItem("Multi Rows (Using RubberBand)")
        policyBox.addItem("Multi Cells")
        policyBox.addItem("Multi Cells (Using RubberBand)")
        self.connect(policyBox, SIGNAL("currentIndexChanged(int)"), self, SLOT("newPolicyActivated(int)"))
        hl.addWidget(label)
        hl.addWidget(policyBox)
        l.addLayout(hl)

        showSelectedButton = QPushButton(settings)
        showSelectedButton.setText("Show Selected")
        self.connect(showSelectedButton, SIGNAL("clicked()"), self, SLOT("showSelected()"))
        l.addWidget(showSelectedButton)

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

        dottedLineCheck = QCheckBox(settings)
        dottedLineCheck.setText("Dotted grid line")
        self.connect(dottedLineCheck, SIGNAL("stateChanged(int)"), self, 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, SIGNAL("currentIndexChanged(int)"), self, SLOT("selectGridLineStyles(int)"))
        hl.addWidget(label)
        hl.addWidget(lineStylesSelect)
        l.addLayout(hl)
        lineStylesSelect.setCurrentIndex(5)

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

        zoomIndicator = QCheckBox(settings)
        zoomIndicator.setText(self.tr("Show zoom indicator"))
        zoomIndicator.setChecked(True)
        self.connect(zoomIndicator, SIGNAL("stateChanged(int)"), self, 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, SIGNAL("sliderMoved(int)"), self, SLOT("zoomValueChanged(int)"))
        self.connect(self.grid.view(), SIGNAL("zoomChanged(int)"), zoomSlider, SLOT("setValue(int)"))
        l.addWidget(zoomSlider)

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

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

        rowsQuickSelectBox = QCheckBox(settings)
        rowsQuickSelectBox.setText(self.tr("Rows Quick Selection"))
        self.connect(rowsQuickSelectBox, SIGNAL("stateChanged(int)"), self, SLOT("rowsQuickSelectEnabled(int)"))
        rowsQuickSelectBox.setChecked(True)
        l.addWidget(rowsQuickSelectBox)

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

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

        policyBox.setCurrentIndex(3)

        return settings

    @QtCore.Slot(int)
    def newPolicyActivated(self, index):
        view = self.grid.view()
        if index == 0:
            view.options().setSelectionPolicy(GridViewOptions.RowSelection)
            view.options().setRubberBandSelection(True)
            view.tableOptions().setRowsQuickSelection(True)
        elif index == 1:
            view.options().setSelectionPolicy(GridViewOptions.CellSelection)
            view.options().setRubberBandSelection(False)
            view.tableOptions().setRowsQuickSelection(True)
        elif index == 2:
            view.options().setSelectionPolicy(GridViewOptions.MultiRowSelection)
            view.options().setRubberBandSelection(False)
            view.tableOptions().setRowsQuickSelection(True)
        elif index == 3:
            view.options().setSelectionPolicy(GridViewOptions.MultiRowSelection)
            view.options().setRubberBandSelection(True)
            view.tableOptions().setRowsQuickSelection(True)
        elif index == 4:
            view.options().setSelectionPolicy(GridViewOptions.MultiCellSelection)
            view.options().setRubberBandSelection(False)
            view.tableOptions().setRowsQuickSelection(True)
        elif index == 5:
            view.options().setSelectionPolicy(GridViewOptions.MultiCellSelection)
            view.options().setRubberBandSelection(True)
            view.tableOptions().setRowsQuickSelection(True)
        else:
            view.options().setSelectionPolicy(GridViewOptions.RowSelection)
            view.options().setRubberBandSelection(False)
            view.tableOptions().setRowsQuickSelection(False)

    @QtCore.Slot()
    def showSelected(self):
        text = ""
        view = self.grid.view()
        selection = view.selection()
        # Iteration by Rows
        while not selection.end():
            row = selection.row()
            if row.type() == GridRow.GroupRow:
                v = row.groupValue()
                text = text + "[Group " + str(v) + "]\r\n"
                selection.next()
            else:
                cellstext = ""
                currentRowIndex = row.rowIndex()
                # Iteration by Cells
                while not selection.end() and currentRowIndex == selection.row().rowIndex():
                    if cellstext != "":
                        cellstext = cellstext + ", "
                    cellstext = cellstext + str(selection.cell().columnIndex())
                    selection.next()
                text = text + "[Row " + str(currentRowIndex) + "] cells(" + cellstext +")\r\n"

        edit = QTextEdit()
        edit.setText(text)
        dlg = QDialog(self)
        vbl = QVBoxLayout(dlg)
        vbl.addWidget(edit)
        dlg.exec()

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

    @QtCore.Slot(int)
    def dottedLineChanged(self, state):
        view = self.grid.view()
        pen = view.options().gridLinePen()
        if 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(state == Qt.Checked)

    @QtCore.Slot(int)
    def zoomIndicatorChanged(self, state):
        view = self.grid.view()
        view.options().setZoomIndicatorActive(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(state == Qt.Checked)

    @QtCore.Slot(int)
    def frozenRowsEnabled(self, state):
        view = self.grid.view()
        view.tableOptions().setRowFrozenButtonVisible(state == Qt.Checked)
        view.tableOptions().setFrozenPlaceQuickSelection(state == Qt.Checked)

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

    @QtCore.Slot(int)
    def rowsQuickSelectEnabled(self, state):
        view = self.grid.view()
        view.tableOptions().setRowsQuickSelection(state == Qt.Checked)

    @QtCore.Slot(ContextMenuEventArgs)
    def contextMenu(self, args):
        args.contextMenu().addAction("Print Preview", self, SLOT("printPreview()"))
        args.contextMenu().addSeparator()
        args.contextMenu().addAction("Developer Machines on the Web", self, 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()))

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

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

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