def test_columnCount(good_states):
    for data in good_states:
        table_model = DigitalStateTableModel(allow_is_used=False)
        table_model.setHalPins(data[0])
        table_model.setStates(data[1])

        if len(data[1]) == 2: assert table_model.columnCount() == 2
        elif len(data[1]) == 4: assert table_model.columnCount() == 3
        elif len(data[1]) == 8: assert table_model.columnCount() == 4
        elif len(data[1]) == 16: assert table_model.columnCount() == 5
def test_getModel(qtbot):
    table_view = DigitalStateTableView()
    table_model = DigitalStateTableModel()
    qtbot.addWidget(table_view)

    table_view.setModel(table_model)
    assert table_model == table_view.getModel()
def test_rowCount(good_states):
    for data in good_states:
        table_model = DigitalStateTableModel(allow_is_used=True)
        table_model.setHalPins(data[0])
        table_model.setStates(data[1])

        assert table_model.rowCount() == len(data[1])
def test_dataArray(good_states):
    #Check if we get the array back and start editing it that we're editing a copy and not the classes actual _data
    for data in good_states:
        table_model = DigitalStateTableModel(allow_is_used=True)
        table_model.setHalPins(data[0])
        table_model.setStates(data[1])

        returned_array = table_model.states()
        returned_array_copy = copy.deepcopy(returned_array)

        returned_array.pop()
        assert returned_array_copy == table_model.states()
def test_noIsUsed(qtbot, open_window, good_data):
    table_model = DigitalStateTableModel(allow_is_used=False)
    table_model.setHalPins(good_data[0])
    table_model.setStates(good_data[1])

    table_model.setAllowedHalPins(
        ['None', 'pin_1', 'pin_2', 'pin_33', 'pin_4'])

    table_view = open_window(DigitalStateTableView)
    table_view.setWindowTitle("Digital State Table View")
    table_view.setModel(table_model)
    table_view.resize(table_view.sizeHint() * 2)
    assert table_view.isVisible()

    if TestingFlags.ENABLE_MANUAL_TESTING:
        MessageBox("Digital State Table Manual Testing", "No is used column")
        qtbot.stopForInteraction()
Пример #6
0
class DigitalStateTableView(QtWidgets.QTableView):
    """Table view of possible states of digital input"""

    def __init__(self, parent=None):
        super().__init__(parent)
        self.menu_add_bit    = "Add bit"
        self.menu_remove_bit = "Remove bit"

        self.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
        self.horizontalHeader().setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.horizontalHeader().customContextMenuRequested.connect(self.halPinMenu)
        font = QtGui.QFont("Helvetica", 14)
        self.setFont(font)

    def setModel(self, value):
        super().setModel(value)
        self.__setupGUI()

    def getModel(self):
        return self.model()

    def __setupGUI(self):
        for row in range(1, self.model().rowCount()):
            if self.model().isUsedColumn():
                self.openPersistentEditor(self.model().index(row, self.model().isUsedColumn()))

        header = self.horizontalHeader()
        for section in range(header.count()):
            header.setSectionResizeMode(section, QtWidgets.QHeaderView.ResizeToContents)

    def addBit(self):
        self.model().setNumberOfBits(self.model().numberOfBits() + 1)
        self.__setupGUI()

    def removeBit(self):
        self.model().setNumberOfBits(self.model().numberOfBits() - 1)
        self.__setupGUI()

    def setHalPin(self, bit, text):
        self.model().setHalPin(bit, text)
        self.__setupGUI()

    def halPinMenu(self, pos):
        col = self.horizontalHeader().logicalIndexAt(pos)

        if col < self.model().numberOfBits():
            bit = self.model().bitAtColumn(col)

            menu = QtWidgets.QMenu()

            for value in self.model().allowedHalPins():
                menu.addAction(value)

            action = menu.exec_(self.mapToGlobal(pos))
            if action is not None:
                self.model().setHalPin(bit, action.text())

            self.__setupGUI()


    def generateContextMenu(self):
        menu = QtWidgets.QMenu(self)

        if self.model().numberOfBits() < 4:
            menu.addAction(self.menu_add_bit)

        if self.model().numberOfBits() > 1:
            menu.addAction(self.menu_remove_bit)

        return menu


    def contextMenuEvent(self, event):
        menu = self.generateContextMenu()
        action = menu.exec_(self.mapToGlobal(event.pos()))

        if action is not None:
            if   action.text() == self.menu_add_bit    : self.addBit()
            elif action.text() == self.menu_remove_bit : self.removeBit()


    digitalStateTableView = QtCore.pyqtProperty(type(DigitalStateTableModel()), getModel, setModel)
def test_addRemoveBits(qtbot, open_window, good_data):
    table_model = DigitalStateTableModel(allow_is_used=True)
    table_model.setHalPins(good_data[0])
    table_model.setStates(good_data[1])
    table_model.setIsUsed(good_data[2])

    table_view = open_window(DigitalStateTableView)
    table_view.setWindowTitle("Digital State Table View")
    table_view.setModel(table_model)
    table_view.resize(table_view.sizeHint() * 2)
    assert table_view.isVisible()

    starting_rows = table_model.rowCount()

    #Add One
    table_view.addBit()
    qtbot.wait(TestingFlags.TEST_WAIT_SHORT)
    assert starting_rows << 1 == table_model.rowCount()

    #Remove One
    table_view.removeBit()
    qtbot.wait(TestingFlags.TEST_WAIT_SHORT)
    assert starting_rows == table_model.rowCount()

    #Remove Another
    table_view.removeBit()
    qtbot.wait(TestingFlags.TEST_WAIT_SHORT)
    assert starting_rows >> 1 == table_model.rowCount()

    #Remove One Too Many!
    with pytest.raises(ValueError):
        table_view.removeBit()
        qtbot.wait(TestingFlags.TEST_WAIT_SHORT)

    #Add One
    table_view.addBit()
    qtbot.wait(TestingFlags.TEST_WAIT_SHORT)
    assert starting_rows == table_model.rowCount()

    table_model.setAllowedHalPins(
        ['None', 'pin_1', 'pin_2', 'pin_33', 'pin_4'])

    table_view.setHalPin(0, 'pin_1')
    table_view.setHalPin(1, 'pin_2')

    menu = table_view.generateContextMenu()
    assert isinstance(menu, QtWidgets.QMenu)

    if TestingFlags.ENABLE_MANUAL_TESTING:
        MessageBox(
            "Digital State Table Manual Testing",
            "Test that the GUI Name and is Used can be edited\n Row 0 is used must be True\n Right click add and remove bits"
        )
        qtbot.stopForInteraction()
def test_setDataArray(good_states):
    for data in good_states:
        table_model = DigitalStateTableModel(allow_is_used=True)
        table_model.setHalPins(data[0])
        table_model.setStates(data[1])
        table_model.setIsUsed(data[2])

        assert data[0] == table_model.halPins()
        assert data[1] == table_model.states()
        assert data[2] == table_model.isUsed()

    table_model.setHalPins(['pin_a'])

    with pytest.raises(ValueError):
        data = ['btn_1', 'btn_2', 'btn_1_too_many']
        table_model.setStates(data)

    with pytest.raises(TypeError):
        data = [True, 'false']
        table_model.setIsUsed(data)

    with pytest.raises(TypeError):
        data = [("BTN 1", True), ("BTN 4", True)]
        table_model.setStates(data)
def test_setNumberOfBits():
    table_model = DigitalStateTableModel(allow_is_used=True)

    data_1 = ['BTN 1', 'BTN 2']

    table_model.setHalPins(['my_pin'])
    table_model.setStates(data_1)

    table_model.setNumberOfBits(1)

    assert data_1 == table_model.states()

    #set it to different number of bits
    for i in [2, 3, 4, 1, 1]:
        table_model.setNumberOfBits(i)
        arr = table_model.states()
        assert len(arr) == 2 << (i - 1)
        assert arr[0] == "BTN 1"
        assert arr[1] == "BTN 2"

    last_good_arr = table_model.states()

    #Set to some not allowed numbers
    for i in [0, -1, 5, 10]:
        with pytest.raises(ValueError):
            table_model.setNumberOfBits(i)
def test_flags(good_states):
    for data in good_states:
        table_model = DigitalStateTableModel(allow_is_used=True)
        table_model.setHalPins(data[0])
        table_model.setStates(data[1])

        is_used_col = table_model.isUsedColumn()
        name_col = table_model.nameColumn()

        flags = table_model.flags(table_model.index(0, 0,
                                                    QtCore.QModelIndex()))
        assert flags == QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable

        flags = table_model.flags(
            table_model.index(0, is_used_col, QtCore.QModelIndex()))
        assert flags == QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable

        flags = table_model.flags(
            table_model.index(1, name_col, QtCore.QModelIndex()))
        assert flags == QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable

        flags = table_model.flags(
            table_model.index(1, is_used_col, QtCore.QModelIndex()))
        assert flags == QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable
def test_setData(good_states):
    for data in good_states:
        table_model = DigitalStateTableModel(allow_is_used=True)
        table_model.setHalPins(data[0])
        table_model.setStates(data[1])
        table_model.setIsUsed(data[2])

        is_used_col = table_model.isUsedColumn()
        name_col = table_model.nameColumn()
        num_bits = table_model.numberOfBits()
        num_rows = len(data[1])

        #Try setting some of the isUsed column
        table_model.setData(
            table_model.index(0, is_used_col, QtCore.QModelIndex()), False,
            QtCore.Qt.EditRole)
        val = table_model.data(
            table_model.index(0, is_used_col, QtCore.QModelIndex()),
            QtCore.Qt.DisplayRole)
        assert val == True

        table_model.setData(
            table_model.index(num_rows - 1, is_used_col, QtCore.QModelIndex()),
            False, QtCore.Qt.EditRole)
        val = table_model.data(
            table_model.index(num_rows - 1, is_used_col, QtCore.QModelIndex()),
            QtCore.Qt.DisplayRole)
        assert val == False

        table_model.setData(
            table_model.index(0, is_used_col, QtCore.QModelIndex()), True,
            QtCore.Qt.EditRole)
        val = table_model.data(
            table_model.index(0, is_used_col, QtCore.QModelIndex()),
            QtCore.Qt.DisplayRole)
        assert val == True

        table_model.setData(
            table_model.index(num_rows - 1, is_used_col, QtCore.QModelIndex()),
            True, QtCore.Qt.EditRole)
        val = table_model.data(
            table_model.index(num_rows - 1, is_used_col, QtCore.QModelIndex()),
            QtCore.Qt.DisplayRole)
        assert val == True

        #Try setting some of the name column
        table_model.setData(
            table_model.index(0, name_col, QtCore.QModelIndex()), "Fast Off",
            QtCore.Qt.EditRole)
        val = table_model.data(
            table_model.index(0, name_col, QtCore.QModelIndex()),
            QtCore.Qt.DisplayRole)
        assert val == "Fast Off"

        table_model.setData(
            table_model.index(num_rows - 1, name_col, QtCore.QModelIndex()),
            "Start", QtCore.Qt.EditRole)
        val = table_model.data(
            table_model.index(num_rows - 1, name_col, QtCore.QModelIndex()),
            QtCore.Qt.DisplayRole)
        assert val == "Start"

        #Try setting 0,0 to True, this should always be false
        table_model.setData(table_model.index(0, 0, QtCore.QModelIndex()),
                            True, QtCore.Qt.EditRole)
        val = table_model.data(table_model.index(0, 0, QtCore.QModelIndex()),
                               QtCore.Qt.DisplayRole)
        assert val == False

        #Try setting 0,0 to True, this should always be false
        table_model.setData(
            table_model.index(0, num_bits - 1, QtCore.QModelIndex()), False,
            QtCore.Qt.EditRole)
        val = table_model.data(
            table_model.index(0, num_bits - 1, QtCore.QModelIndex()),
            QtCore.Qt.DisplayRole)
        assert val == False
def test_data(good_states):
    for data in good_states:
        table_model = DigitalStateTableModel(allow_is_used=True)
        table_model.setHalPins(data[0])
        table_model.setStates(data[1])
        table_model.setIsUsed(data[2])

        for i, itm in enumerate(data[1]):
            assert itm == table_model.data(
                table_model.index(i, table_model.nameColumn(),
                                  QtCore.QModelIndex()), QtCore.Qt.DisplayRole)

        for i, itm in enumerate(data[2]):
            assert itm == table_model.data(
                table_model.index(i, table_model.isUsedColumn(),
                                  QtCore.QModelIndex()), QtCore.Qt.DisplayRole)
def test_headerData(good_states):
    for data in good_states:
        table_model = DigitalStateTableModel(allow_is_used=True)
        table_model.setHalPins(data[0])
        table_model.setStates(data[1])
        table_model.setIsUsed(data[2])

        assert 'GUI Name' == table_model.headerData(table_model.nameColumn(),
                                                    QtCore.Qt.Horizontal,
                                                    QtCore.Qt.DisplayRole)
        assert 'Is Used' == table_model.headerData(table_model.isUsedColumn(),
                                                   QtCore.Qt.Horizontal,
                                                   QtCore.Qt.DisplayRole)
        assert 'Is Used' != table_model.headerData(0, QtCore.Qt.Horizontal,
                                                   QtCore.Qt.DisplayRole)

        #check vertical header
        num_rows = len(data[1])
        for row in range(num_rows):
            assert str(row) == table_model.headerData(row, QtCore.Qt.Vertical,
                                                      QtCore.Qt.DisplayRole)