Module soitool.modules.module_authentication_board

Module containing SOI-module 'Autentiseringstavle'.

Expand source code
"""Module containing SOI-module 'Autentiseringstavle'."""
import string
from secrets import choice
from PySide2.QtWidgets import QTableWidgetItem
from PySide2 import QtGui
from PySide2.QtCore import Qt
from soitool.modules.module_base import (
    resize_table,
    qfont_with_pixel_size,
    DEFAULT_FONT,
)
from soitool.modules.code_table_base import CodeTableBase

# Characters for first column,
# it's length determines maximum number of codes (rows).
ROW_IDENTIFIERS = string.ascii_uppercase

# Maximum number of codes depends on ROW_IDENTIFIERS
MAXIMUM_NO_OF_CODES = len(ROW_IDENTIFIERS)
START_NO_OF_CODES = 10
CODE_LENGTH = 25

# Has to be 'ascii', 'digits' or 'combo'
# Codes will consist of A-Z if 'ascii', 0-9 if 'digits' and A-Z+0-9 if 'combo'
CODE_CHARACTER_TYPE = "ascii"

# Font for authentication codes, should be a monospaced font
CODE_FONT = qfont_with_pixel_size("Consolas", DEFAULT_FONT.pixelSize())

# Adds space between sets of characters, 0 => no spaces
# If code is 123456 and interval is 2, code will be 12 34 56
SPACE_INTERVAL = 5
SPACE_AMOUNT = 2

HEADLINE_TEXT = "AUTENTISERINGSTAVLE"


class AuthenticationBoardModule(CodeTableBase):
    """Modified QTableWidget representing SOI-module 'Autentiseringstavle'.

    The default widget-initialization has a headline, a row-count of
    START_NO_OF_CODES and three columns.
    Row x in the first column contains the character ROW_IDENTIFIERS[x].
    Row x in the second column contains the character x, for x = 0-9.
    Row x in the third column contains an authentication code of length
    CODE_LENGTH, spaced out for readability if SPACE_INTERVAL and SPACE_AMOUNT
    is larger than 0.

    The authentication codes have their own monospaced font for increased
    readability, meaning each character has the same width.

    If parameter 'data' is given, the widget initializes based on the content.
    'data' is a dict with keys "cells", "code_length", "space_interval",
    "space_amount" and "code_character_type". "cells" is a 2D list where
    cells[0] is the headline and cells[x][y] represents the value in row x,
    column y. The other keys contain an integer.

    The widget does not use more room than needed, and resizes dynamically.
    It has shortcuts for adding and removing rows.
    """

    def __init__(self, data=None):
        self.type = "AuthenticationBoardModule"

        if CODE_CHARACTER_TYPE == "ascii":
            self.code_characters = string.ascii_uppercase
        elif CODE_CHARACTER_TYPE == "digits":
            self.code_characters = string.digits
        elif CODE_CHARACTER_TYPE == "combo":
            self.code_characters = string.ascii_uppercase + string.digits
        else:
            raise ValueError(
                "Invalid value for CONSTANT 'CODE_CHARACTER_TYPE': "
                "'{}'".format(CODE_CHARACTER_TYPE)
            )
        self.code_font = CODE_FONT
        self.maximum_no_of_codes = MAXIMUM_NO_OF_CODES

        # Set default values for table to be generated
        if data is None:
            self.start_no_of_codes = START_NO_OF_CODES
            self.code_length = CODE_LENGTH
            self.space_interval = SPACE_INTERVAL
            self.space_amount = SPACE_AMOUNT
            self.code_character_type = CODE_CHARACTER_TYPE

            numbers = self.generate_authentication_numbers()
            self.start_headline = (
                HEADLINE_TEXT
                + " ("
                + str(numbers[0])
                + " & "
                + str(numbers[1])
                + ")"
            )

        CodeTableBase.__init__(self, data)

        # Make cell-borders black for increased readability
        self.setStyleSheet("QTableView { gridline-color: black; }")

    def insert_row_identifiers(self):
        """Insert values in column one and two."""
        for i in range(self.rowCount()):
            # Insert non-editable row identifier in first column
            item_first = QTableWidgetItem(ROW_IDENTIFIERS[i])
            item_first.setTextAlignment(Qt.AlignCenter)
            item_first.setFlags(item_first.flags() ^ Qt.ItemIsEditable)
            self.setItem(i, 0, item_first)

            # Insert non-editable row identifier (int) in second column
            text_second = str(i) if i < 10 else ""
            item_second = QTableWidgetItem(text_second)
            item_second.setTextAlignment(Qt.AlignCenter)
            item_second.setFlags(item_second.flags() ^ Qt.ItemIsEditable)
            self.setItem(i, 1, item_second)

    def add_row(self, selected_row_index):
        """Insert row below the selected row and add data.

        Parameters
        ----------
        selected_row_index : int
            Index of the selected row.
        """
        # If maximum amount of rows not reached (- 1 to skip headline)
        if self.rowCount() - 1 < len(ROW_IDENTIFIERS):
            # Generate unique code and insert row
            code = self.generate_unique_code()
            self.insertRow(selected_row_index + 1)

            # Loop through all rows starting with the new row
            for i in range(selected_row_index + 1, self.rowCount()):
                # Insert row identifier in first column
                item_first = QTableWidgetItem(self.code_characters[i - 1])
                item_first.setTextAlignment(Qt.AlignCenter)
                item_first.setFlags(item_first.flags() ^ Qt.ItemIsEditable)
                self.setItem(i, 0, item_first)

                # Insert row identifier (int) in second column
                text_second = str(i - 1) if i <= 10 else ""
                item_second = QTableWidgetItem(text_second)
                item_second.setTextAlignment(Qt.AlignCenter)
                item_second.setFlags(item_second.flags() ^ Qt.ItemIsEditable)
                self.setItem(i, 1, item_second)

            # Insert authentication-code in third column
            item_third = QTableWidgetItem(code)
            item_third.setFont(self.code_font)
            item_third.setTextAlignment(Qt.AlignCenter)
            item_third.setFlags(item_third.flags() ^ Qt.ItemIsEditable)
            self.setItem(selected_row_index + 1, 2, item_third)

            self.resizeRowToContents(selected_row_index + 1)

            resize_table(self, columns=False, has_headline=True)

    def remove_row(self, row_index):
        """Remove selected row.

        Parameters
        ----------
        row_index : int
            Index of the row to remove.
        """
        self.removeRow(row_index)

        # 'Decrease' row identifiers below the removed row
        # If first row is removed, identifier A,B,C becomes A,B (not B,C)
        for i in range(row_index, self.rowCount()):
            self.item(i, 0).setText(self.code_characters[i - 1])
            text_second = str(i - 1) if i <= 10 else ""
            self.item(i, 1).setText(text_second)
        resize_table(self, columns=False, has_headline=True)

    def generate_authentication_numbers(self):
        """Generate two non-equal numbers between 1 and self.code_length.

        Returns
        -------
        list
            Containing two integers, sorted in ascending order.
        """
        available_numbers = list(range(1, self.code_length + 1))

        numbers = []
        numbers.append(choice(available_numbers))
        numbers.append(choice(available_numbers))

        while numbers[0] == numbers[1]:
            numbers[1] = choice(available_numbers)

        numbers.sort()

        return numbers

    @staticmethod
    def get_user_friendly_name():
        """Get user-friendly name of module."""
        return "Autentiseringstavle"

    @staticmethod
    def get_icon():
        """Get icon of module."""
        return QtGui.QIcon("soitool/media/authenticationboardmodule.png")

Classes

class AuthenticationBoardModule (data=None)

Modified QTableWidget representing SOI-module 'Autentiseringstavle'.

The default widget-initialization has a headline, a row-count of START_NO_OF_CODES and three columns. Row x in the first column contains the character ROW_IDENTIFIERS[x]. Row x in the second column contains the character x, for x = 0-9. Row x in the third column contains an authentication code of length CODE_LENGTH, spaced out for readability if SPACE_INTERVAL and SPACE_AMOUNT is larger than 0.

The authentication codes have their own monospaced font for increased readability, meaning each character has the same width.

If parameter 'data' is given, the widget initializes based on the content. 'data' is a dict with keys "cells", "code_length", "space_interval", "space_amount" and "code_character_type". "cells" is a 2D list where cells[0] is the headline and cells[x][y] represents the value in row x, column y. The other keys contain an integer.

The widget does not use more room than needed, and resizes dynamically. It has shortcuts for adding and removing rows.

Class-variable 'type' should be set by derived class.

Expand source code
class AuthenticationBoardModule(CodeTableBase):
    """Modified QTableWidget representing SOI-module 'Autentiseringstavle'.

    The default widget-initialization has a headline, a row-count of
    START_NO_OF_CODES and three columns.
    Row x in the first column contains the character ROW_IDENTIFIERS[x].
    Row x in the second column contains the character x, for x = 0-9.
    Row x in the third column contains an authentication code of length
    CODE_LENGTH, spaced out for readability if SPACE_INTERVAL and SPACE_AMOUNT
    is larger than 0.

    The authentication codes have their own monospaced font for increased
    readability, meaning each character has the same width.

    If parameter 'data' is given, the widget initializes based on the content.
    'data' is a dict with keys "cells", "code_length", "space_interval",
    "space_amount" and "code_character_type". "cells" is a 2D list where
    cells[0] is the headline and cells[x][y] represents the value in row x,
    column y. The other keys contain an integer.

    The widget does not use more room than needed, and resizes dynamically.
    It has shortcuts for adding and removing rows.
    """

    def __init__(self, data=None):
        self.type = "AuthenticationBoardModule"

        if CODE_CHARACTER_TYPE == "ascii":
            self.code_characters = string.ascii_uppercase
        elif CODE_CHARACTER_TYPE == "digits":
            self.code_characters = string.digits
        elif CODE_CHARACTER_TYPE == "combo":
            self.code_characters = string.ascii_uppercase + string.digits
        else:
            raise ValueError(
                "Invalid value for CONSTANT 'CODE_CHARACTER_TYPE': "
                "'{}'".format(CODE_CHARACTER_TYPE)
            )
        self.code_font = CODE_FONT
        self.maximum_no_of_codes = MAXIMUM_NO_OF_CODES

        # Set default values for table to be generated
        if data is None:
            self.start_no_of_codes = START_NO_OF_CODES
            self.code_length = CODE_LENGTH
            self.space_interval = SPACE_INTERVAL
            self.space_amount = SPACE_AMOUNT
            self.code_character_type = CODE_CHARACTER_TYPE

            numbers = self.generate_authentication_numbers()
            self.start_headline = (
                HEADLINE_TEXT
                + " ("
                + str(numbers[0])
                + " & "
                + str(numbers[1])
                + ")"
            )

        CodeTableBase.__init__(self, data)

        # Make cell-borders black for increased readability
        self.setStyleSheet("QTableView { gridline-color: black; }")

    def insert_row_identifiers(self):
        """Insert values in column one and two."""
        for i in range(self.rowCount()):
            # Insert non-editable row identifier in first column
            item_first = QTableWidgetItem(ROW_IDENTIFIERS[i])
            item_first.setTextAlignment(Qt.AlignCenter)
            item_first.setFlags(item_first.flags() ^ Qt.ItemIsEditable)
            self.setItem(i, 0, item_first)

            # Insert non-editable row identifier (int) in second column
            text_second = str(i) if i < 10 else ""
            item_second = QTableWidgetItem(text_second)
            item_second.setTextAlignment(Qt.AlignCenter)
            item_second.setFlags(item_second.flags() ^ Qt.ItemIsEditable)
            self.setItem(i, 1, item_second)

    def add_row(self, selected_row_index):
        """Insert row below the selected row and add data.

        Parameters
        ----------
        selected_row_index : int
            Index of the selected row.
        """
        # If maximum amount of rows not reached (- 1 to skip headline)
        if self.rowCount() - 1 < len(ROW_IDENTIFIERS):
            # Generate unique code and insert row
            code = self.generate_unique_code()
            self.insertRow(selected_row_index + 1)

            # Loop through all rows starting with the new row
            for i in range(selected_row_index + 1, self.rowCount()):
                # Insert row identifier in first column
                item_first = QTableWidgetItem(self.code_characters[i - 1])
                item_first.setTextAlignment(Qt.AlignCenter)
                item_first.setFlags(item_first.flags() ^ Qt.ItemIsEditable)
                self.setItem(i, 0, item_first)

                # Insert row identifier (int) in second column
                text_second = str(i - 1) if i <= 10 else ""
                item_second = QTableWidgetItem(text_second)
                item_second.setTextAlignment(Qt.AlignCenter)
                item_second.setFlags(item_second.flags() ^ Qt.ItemIsEditable)
                self.setItem(i, 1, item_second)

            # Insert authentication-code in third column
            item_third = QTableWidgetItem(code)
            item_third.setFont(self.code_font)
            item_third.setTextAlignment(Qt.AlignCenter)
            item_third.setFlags(item_third.flags() ^ Qt.ItemIsEditable)
            self.setItem(selected_row_index + 1, 2, item_third)

            self.resizeRowToContents(selected_row_index + 1)

            resize_table(self, columns=False, has_headline=True)

    def remove_row(self, row_index):
        """Remove selected row.

        Parameters
        ----------
        row_index : int
            Index of the row to remove.
        """
        self.removeRow(row_index)

        # 'Decrease' row identifiers below the removed row
        # If first row is removed, identifier A,B,C becomes A,B (not B,C)
        for i in range(row_index, self.rowCount()):
            self.item(i, 0).setText(self.code_characters[i - 1])
            text_second = str(i - 1) if i <= 10 else ""
            self.item(i, 1).setText(text_second)
        resize_table(self, columns=False, has_headline=True)

    def generate_authentication_numbers(self):
        """Generate two non-equal numbers between 1 and self.code_length.

        Returns
        -------
        list
            Containing two integers, sorted in ascending order.
        """
        available_numbers = list(range(1, self.code_length + 1))

        numbers = []
        numbers.append(choice(available_numbers))
        numbers.append(choice(available_numbers))

        while numbers[0] == numbers[1]:
            numbers[1] = choice(available_numbers)

        numbers.sort()

        return numbers

    @staticmethod
    def get_user_friendly_name():
        """Get user-friendly name of module."""
        return "Autentiseringstavle"

    @staticmethod
    def get_icon():
        """Get icon of module."""
        return QtGui.QIcon("soitool/media/authenticationboardmodule.png")

Ancestors

  • CodeTableBase
  • ModuleBase
  • abc.ABC
  • PySide2.QtWidgets.QTableWidget
  • 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

Static methods

def get_icon()

Get icon of module.

Expand source code
@staticmethod
def get_icon():
    """Get icon of module."""
    return QtGui.QIcon("soitool/media/authenticationboardmodule.png")
def get_user_friendly_name()

Get user-friendly name of module.

Expand source code
@staticmethod
def get_user_friendly_name():
    """Get user-friendly name of module."""
    return "Autentiseringstavle"

Methods

def add_row(self, selected_row_index)

Insert row below the selected row and add data.

Parameters

selected_row_index : int
Index of the selected row.
Expand source code
def add_row(self, selected_row_index):
    """Insert row below the selected row and add data.

    Parameters
    ----------
    selected_row_index : int
        Index of the selected row.
    """
    # If maximum amount of rows not reached (- 1 to skip headline)
    if self.rowCount() - 1 < len(ROW_IDENTIFIERS):
        # Generate unique code and insert row
        code = self.generate_unique_code()
        self.insertRow(selected_row_index + 1)

        # Loop through all rows starting with the new row
        for i in range(selected_row_index + 1, self.rowCount()):
            # Insert row identifier in first column
            item_first = QTableWidgetItem(self.code_characters[i - 1])
            item_first.setTextAlignment(Qt.AlignCenter)
            item_first.setFlags(item_first.flags() ^ Qt.ItemIsEditable)
            self.setItem(i, 0, item_first)

            # Insert row identifier (int) in second column
            text_second = str(i - 1) if i <= 10 else ""
            item_second = QTableWidgetItem(text_second)
            item_second.setTextAlignment(Qt.AlignCenter)
            item_second.setFlags(item_second.flags() ^ Qt.ItemIsEditable)
            self.setItem(i, 1, item_second)

        # Insert authentication-code in third column
        item_third = QTableWidgetItem(code)
        item_third.setFont(self.code_font)
        item_third.setTextAlignment(Qt.AlignCenter)
        item_third.setFlags(item_third.flags() ^ Qt.ItemIsEditable)
        self.setItem(selected_row_index + 1, 2, item_third)

        self.resizeRowToContents(selected_row_index + 1)

        resize_table(self, columns=False, has_headline=True)
def generate_authentication_numbers(self)

Generate two non-equal numbers between 1 and self.code_length.

Returns

list
Containing two integers, sorted in ascending order.
Expand source code
def generate_authentication_numbers(self):
    """Generate two non-equal numbers between 1 and self.code_length.

    Returns
    -------
    list
        Containing two integers, sorted in ascending order.
    """
    available_numbers = list(range(1, self.code_length + 1))

    numbers = []
    numbers.append(choice(available_numbers))
    numbers.append(choice(available_numbers))

    while numbers[0] == numbers[1]:
        numbers[1] = choice(available_numbers)

    numbers.sort()

    return numbers
def insert_row_identifiers(self)

Insert values in column one and two.

Expand source code
def insert_row_identifiers(self):
    """Insert values in column one and two."""
    for i in range(self.rowCount()):
        # Insert non-editable row identifier in first column
        item_first = QTableWidgetItem(ROW_IDENTIFIERS[i])
        item_first.setTextAlignment(Qt.AlignCenter)
        item_first.setFlags(item_first.flags() ^ Qt.ItemIsEditable)
        self.setItem(i, 0, item_first)

        # Insert non-editable row identifier (int) in second column
        text_second = str(i) if i < 10 else ""
        item_second = QTableWidgetItem(text_second)
        item_second.setTextAlignment(Qt.AlignCenter)
        item_second.setFlags(item_second.flags() ^ Qt.ItemIsEditable)
        self.setItem(i, 1, item_second)
def remove_row(self, row_index)

Remove selected row.

Parameters

row_index : int
Index of the row to remove.
Expand source code
def remove_row(self, row_index):
    """Remove selected row.

    Parameters
    ----------
    row_index : int
        Index of the row to remove.
    """
    self.removeRow(row_index)

    # 'Decrease' row identifiers below the removed row
    # If first row is removed, identifier A,B,C becomes A,B (not B,C)
    for i in range(row_index, self.rowCount()):
        self.item(i, 0).setText(self.code_characters[i - 1])
        text_second = str(i - 1) if i <= 10 else ""
        self.item(i, 1).setText(text_second)
    resize_table(self, columns=False, has_headline=True)

Inherited members