Module soitool.soi_model_view

GUI-interface towards database-table 'SOI'.

Contains functionality for viewing and opening SOI's from database-table 'SOI', where (some) SOI's are stored.

Expand source code
"""GUI-interface towards database-table 'SOI'.

Contains functionality for viewing and opening SOI's from database-table 'SOI',
where (some) SOI's are stored.
"""
from PySide2.QtWidgets import QTableView
from PySide2.QtSql import QSqlDatabase, QSqlTableModel
from PySide2.QtCore import Qt
from soitool.table_view_style import (
    CODEBOOK_HEADER_FONT,
    CODEBOOK_HEADER_BACKGROUND_CSS,
)
from soitool.serialize_export_import_soi import construct_soi_from_serialized
from soitool.soi_workspace_widget import SOIWorkspaceWidget

# Name and type of database
CONNAME = "SOIDB"
DBTYPE = "QSQLITE"


class SOITableView(QTableView):
    """TableView with a model of the 'SOI'-table from database.

    This modified QTableView creates a SOITableModel, which reads data from the
    SOI-table. When the user double-clicks or presses the enter-key on a cell,
    a tab containing SOIWorkspaceWidget, with the SOI from the current row, is
    opened and selected.

    Parameters
    ----------
    database : soitool.database.Database
        Is used to create a QSqlDatabase from the database-file,
        and to instantiate SOIWorkspaceWidget.
    tab_widget : QTabWidget
        Is used to open a new tab.

    Raises
    ------
    RuntimeError
        If database does not open.
    """

    def __init__(self, database, tab_widget):
        super().__init__()
        self.database = database

        db = QSqlDatabase.addDatabase(DBTYPE, CONNAME)
        db.setDatabaseName(self.database.db_path)
        self.tab_widget = tab_widget

        if not db.open():
            raise RuntimeError("Could not open database.")

        # Enable sorting
        self.setSortingEnabled(True)

        # Create and set model
        model = SOITableModel()
        self.setModel(model)

        # Remove horizontal scrollbar, hide vertical header and 'SOI'-column
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.verticalHeader().hide()
        self.hideColumn(2)

        # Set horizontal header-text and it's style
        self.set_horizontal_header_text()
        header = self.horizontalHeader()
        header.setFont(CODEBOOK_HEADER_FONT)
        header.setStyleSheet(CODEBOOK_HEADER_BACKGROUND_CSS)

        # Resize
        self.resizeColumnsToContents()
        width = (
            self.columnWidth(0) + self.columnWidth(1) + self.columnWidth(3) + 2
        )  # +2 offset
        self.setFixedWidth(width)

        self.doubleClicked.connect(self.open_soi_tab)

    def set_horizontal_header_text(self):
        """Set Norwegian names in horizontal header."""
        self.model().setHeaderData(0, Qt.Horizontal, "Tittel")
        self.model().setHeaderData(1, Qt.Horizontal, "Versjon")
        self.model().setHeaderData(3, Qt.Horizontal, "Dato")

    def keyPressEvent(self, event):
        """Open SOI-tab if enter-key is pressed."""
        if event.key() == Qt.Key_Return:
            self.open_soi_tab()
        super().keyPressEvent(event)

    def open_soi_tab(self):
        """Construct SOI and open SOIWorkspacewidget in new tab."""
        # Get index of the current row and read compressed, serialized SOI
        row = self.currentIndex().row()
        compressed_soi = self.model().index(row, 2).data()

        # Construct SOI and create SOIWorkspaceWidget
        soi = construct_soi_from_serialized(
            compressed_soi, self.database, compressed=True
        )
        tab = SOIWorkspaceWidget(self.database, soi)

        # Add and select tab
        self.tab_widget.addTab(tab, soi.title)
        self.tab_widget.setCurrentWidget(tab)

        # Update tab-title when SOI-title changes
        soi.add_update_property_listener(
            lambda: self.tab_widget.setTabText(
                self.tab_widget.indexOf(tab), soi.title
            )
        )

    def setModel(self, model):
        """Set model, resize and hide 'SOI'-column.

        Parameters
        ----------
        model : soitool.soi_model_view.SOITableModel or None
            Model containing data to display.
        """
        super().setModel(model)
        if model is not None:
            self.hideColumn(2)
            self.resizeColumnsToContents()
            width = (
                self.columnWidth(0)
                + self.columnWidth(1)
                + self.columnWidth(3)
                + 2  # + 2 offset
            )
            self.setFixedWidth(width)
            self.sortByColumn(3, Qt.DescendingOrder)  # Sort by 'Date'-column

    def close_db_connection(self):
        """Close connection to database."""
        self.setModel(None)
        QSqlDatabase.removeDatabase(CONNAME)


class SOITableModel(QSqlTableModel):
    """Uneditable QSqlTableModel of database-table 'SOI'."""

    def __init__(self):
        super().__init__(None, QSqlDatabase.database(CONNAME))
        self.setTable("SOI")
        self.select()
        self.sort(3, Qt.DescendingOrder)  # Sort by 'Date'-column

    def flags(self, index):
        """Disable editing.

        Parameters
        ----------
        index : QModelIndex
            Is used to locate data in a model.
        """
        flags = super().flags(index)
        flags ^= Qt.ItemIsEditable

        return flags

Classes

class SOITableModel

Uneditable QSqlTableModel of database-table 'SOI'.

Expand source code
class SOITableModel(QSqlTableModel):
    """Uneditable QSqlTableModel of database-table 'SOI'."""

    def __init__(self):
        super().__init__(None, QSqlDatabase.database(CONNAME))
        self.setTable("SOI")
        self.select()
        self.sort(3, Qt.DescendingOrder)  # Sort by 'Date'-column

    def flags(self, index):
        """Disable editing.

        Parameters
        ----------
        index : QModelIndex
            Is used to locate data in a model.
        """
        flags = super().flags(index)
        flags ^= Qt.ItemIsEditable

        return flags

Ancestors

  • PySide2.QtSql.QSqlTableModel
  • PySide2.QtSql.QSqlQueryModel
  • PySide2.QtCore.QAbstractTableModel
  • PySide2.QtCore.QAbstractItemModel
  • PySide2.QtCore.QObject
  • Shiboken.Object

Class variables

var staticMetaObject

Methods

def flags(self, index)

Disable editing.

Parameters

index : QModelIndex
Is used to locate data in a model.
Expand source code
def flags(self, index):
    """Disable editing.

    Parameters
    ----------
    index : QModelIndex
        Is used to locate data in a model.
    """
    flags = super().flags(index)
    flags ^= Qt.ItemIsEditable

    return flags
class SOITableView (database, tab_widget)

TableView with a model of the 'SOI'-table from database.

This modified QTableView creates a SOITableModel, which reads data from the SOI-table. When the user double-clicks or presses the enter-key on a cell, a tab containing SOIWorkspaceWidget, with the SOI from the current row, is opened and selected.

Parameters

database : Database
Is used to create a QSqlDatabase from the database-file, and to instantiate SOIWorkspaceWidget.
tab_widget : QTabWidget
Is used to open a new tab.

Raises

RuntimeError
If database does not open.
Expand source code
class SOITableView(QTableView):
    """TableView with a model of the 'SOI'-table from database.

    This modified QTableView creates a SOITableModel, which reads data from the
    SOI-table. When the user double-clicks or presses the enter-key on a cell,
    a tab containing SOIWorkspaceWidget, with the SOI from the current row, is
    opened and selected.

    Parameters
    ----------
    database : soitool.database.Database
        Is used to create a QSqlDatabase from the database-file,
        and to instantiate SOIWorkspaceWidget.
    tab_widget : QTabWidget
        Is used to open a new tab.

    Raises
    ------
    RuntimeError
        If database does not open.
    """

    def __init__(self, database, tab_widget):
        super().__init__()
        self.database = database

        db = QSqlDatabase.addDatabase(DBTYPE, CONNAME)
        db.setDatabaseName(self.database.db_path)
        self.tab_widget = tab_widget

        if not db.open():
            raise RuntimeError("Could not open database.")

        # Enable sorting
        self.setSortingEnabled(True)

        # Create and set model
        model = SOITableModel()
        self.setModel(model)

        # Remove horizontal scrollbar, hide vertical header and 'SOI'-column
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.verticalHeader().hide()
        self.hideColumn(2)

        # Set horizontal header-text and it's style
        self.set_horizontal_header_text()
        header = self.horizontalHeader()
        header.setFont(CODEBOOK_HEADER_FONT)
        header.setStyleSheet(CODEBOOK_HEADER_BACKGROUND_CSS)

        # Resize
        self.resizeColumnsToContents()
        width = (
            self.columnWidth(0) + self.columnWidth(1) + self.columnWidth(3) + 2
        )  # +2 offset
        self.setFixedWidth(width)

        self.doubleClicked.connect(self.open_soi_tab)

    def set_horizontal_header_text(self):
        """Set Norwegian names in horizontal header."""
        self.model().setHeaderData(0, Qt.Horizontal, "Tittel")
        self.model().setHeaderData(1, Qt.Horizontal, "Versjon")
        self.model().setHeaderData(3, Qt.Horizontal, "Dato")

    def keyPressEvent(self, event):
        """Open SOI-tab if enter-key is pressed."""
        if event.key() == Qt.Key_Return:
            self.open_soi_tab()
        super().keyPressEvent(event)

    def open_soi_tab(self):
        """Construct SOI and open SOIWorkspacewidget in new tab."""
        # Get index of the current row and read compressed, serialized SOI
        row = self.currentIndex().row()
        compressed_soi = self.model().index(row, 2).data()

        # Construct SOI and create SOIWorkspaceWidget
        soi = construct_soi_from_serialized(
            compressed_soi, self.database, compressed=True
        )
        tab = SOIWorkspaceWidget(self.database, soi)

        # Add and select tab
        self.tab_widget.addTab(tab, soi.title)
        self.tab_widget.setCurrentWidget(tab)

        # Update tab-title when SOI-title changes
        soi.add_update_property_listener(
            lambda: self.tab_widget.setTabText(
                self.tab_widget.indexOf(tab), soi.title
            )
        )

    def setModel(self, model):
        """Set model, resize and hide 'SOI'-column.

        Parameters
        ----------
        model : soitool.soi_model_view.SOITableModel or None
            Model containing data to display.
        """
        super().setModel(model)
        if model is not None:
            self.hideColumn(2)
            self.resizeColumnsToContents()
            width = (
                self.columnWidth(0)
                + self.columnWidth(1)
                + self.columnWidth(3)
                + 2  # + 2 offset
            )
            self.setFixedWidth(width)
            self.sortByColumn(3, Qt.DescendingOrder)  # Sort by 'Date'-column

    def close_db_connection(self):
        """Close connection to database."""
        self.setModel(None)
        QSqlDatabase.removeDatabase(CONNAME)

Ancestors

  • PySide2.QtWidgets.QTableView
  • PySide2.QtWidgets.QAbstractItemView
  • PySide2.QtWidgets.QAbstractScrollArea
  • PySide2.QtWidgets.QFrame
  • PySide2.QtWidgets.QWidget
  • PySide2.QtCore.QObject
  • PySide2.QtGui.QPaintDevice
  • Shiboken.Object

Class variables

var staticMetaObject

Methods

def close_db_connection(self)

Close connection to database.

Expand source code
def close_db_connection(self):
    """Close connection to database."""
    self.setModel(None)
    QSqlDatabase.removeDatabase(CONNAME)
def keyPressEvent(self, event)

Open SOI-tab if enter-key is pressed.

Expand source code
def keyPressEvent(self, event):
    """Open SOI-tab if enter-key is pressed."""
    if event.key() == Qt.Key_Return:
        self.open_soi_tab()
    super().keyPressEvent(event)
def open_soi_tab(self)

Construct SOI and open SOIWorkspacewidget in new tab.

Expand source code
def open_soi_tab(self):
    """Construct SOI and open SOIWorkspacewidget in new tab."""
    # Get index of the current row and read compressed, serialized SOI
    row = self.currentIndex().row()
    compressed_soi = self.model().index(row, 2).data()

    # Construct SOI and create SOIWorkspaceWidget
    soi = construct_soi_from_serialized(
        compressed_soi, self.database, compressed=True
    )
    tab = SOIWorkspaceWidget(self.database, soi)

    # Add and select tab
    self.tab_widget.addTab(tab, soi.title)
    self.tab_widget.setCurrentWidget(tab)

    # Update tab-title when SOI-title changes
    soi.add_update_property_listener(
        lambda: self.tab_widget.setTabText(
            self.tab_widget.indexOf(tab), soi.title
        )
    )
def setModel(self, model)

Set model, resize and hide 'SOI'-column.

Parameters

model : SOITableModel or None
Model containing data to display.
Expand source code
def setModel(self, model):
    """Set model, resize and hide 'SOI'-column.

    Parameters
    ----------
    model : soitool.soi_model_view.SOITableModel or None
        Model containing data to display.
    """
    super().setModel(model)
    if model is not None:
        self.hideColumn(2)
        self.resizeColumnsToContents()
        width = (
            self.columnWidth(0)
            + self.columnWidth(1)
            + self.columnWidth(3)
            + 2  # + 2 offset
        )
        self.setFixedWidth(width)
        self.sortByColumn(3, Qt.DescendingOrder)  # Sort by 'Date'-column
def set_horizontal_header_text(self)

Set Norwegian names in horizontal header.

Expand source code
def set_horizontal_header_text(self):
    """Set Norwegian names in horizontal header."""
    self.model().setHeaderData(0, Qt.Horizontal, "Tittel")
    self.model().setHeaderData(1, Qt.Horizontal, "Versjon")
    self.model().setHeaderData(3, Qt.Horizontal, "Dato")