В QTableWidget, как определить, является ли пустая ячейка редактируемой?

Я работаю над QAction, чтобы вставить структурированный текст из буфера обмена в QTableWidget. Это мой текущий код:

class PasteCellsAction(qt.QAction):
    def __init__(self, table):
        if not isinstance(table, qt.QTableWidget):
            raise ValueError('CopySelectedCellsAction must be initialised ' +
                             'with a QTableWidget.')
        super(PasteCellsAction, self).__init__(table)
        self.table = table
        self.setText("Paste")
        self.setShortcut(qt.QKeySequence('Ctrl+V'))
        self.triggered.connect(self.pasteCellFromClipboard)

    def pasteCellFromClipboard(self):
        """Paste text from cipboard into the table.

        If the text contains tabulations and
        newlines, they are interpreted as column and row separators.
        In such a case, the text is split into multiple texts to be paste
        into multiple cells.

        :return: *True* in case of success, *False* if pasting data failed.
        """
        selected_idx = self.table.selectedIndexes()
        if len(selected_idx) != 1:
            msgBox = qt.QMessageBox(parent=self.table)
            msgBox.setText("A single cell must be selected to paste data")
            msgBox.exec_()
            return False

        selected_row = selected_idx[0].row()
        selected_col = selected_idx[0].column()

        qapp = qt.QApplication.instance()
        clipboard_text = qapp.clipboard().text()
        table_data = _parseTextAsTable(clipboard_text)

        protected_cells = 0
        out_of_range_cells = 0

        # paste table data into cells, using selected cell as origin
        for row in range(len(table_data)):
            for col in range(len(table_data[row])):
                if selected_row + row >= self.table.rowCount() or\
                   selected_col + col >= self.table.columnCount():
                    out_of_range_cells += 1
                    continue
                item = self.table.item(selected_row + row,
                                       selected_col + col)
                # ignore empty strings
                if table_data[row][col] != "":
                    if not item.flags() & qt.Qt.ItemIsEditable:
                        protected_cells += 1
                        continue
                    item.setText(table_data[row][col])

        if protected_cells or out_of_range_cells:
            msgBox = qt.QMessageBox(parent=self.table)
            msg = "Some data could not be inserted, "
            msg += "due to out-of-range or write-protected cells."
            msgBox.setText(msg)
            msgBox.exec_()
            return False
        return True

Я хочу проверить, является ли ячейка редактируемой, прежде чем вставлять в нее данные, и для этого я получаю элемент, используя QTableWidget.item(row, col) и затем я проверяю флаги предмета.

Моя проблема в том, что .item метод возвращает None для пустых ячеек, поэтому я не могу проверить флаги пустых ячеек. Мой код в настоящее время работает, только когда в области вставки нет пустой ячейки.

Ошибка в строках 46 (None вернулся) и 50 (AttributeError: 'NoneType' object has no attribute 'flags'):

            item = self.table.item(selected_row + row,
                                   selected_col + col)
            # ignore empty strings
            if table_data[row][col] != "":
                if not item.flags() & qt.Qt.ItemIsEditable:
                    ...

Есть ли другой способ узнать, является ли ячейка редактируемой, кроме проверки флагов элемента?

2 ответа

Размеры QTableWidget может указывать без явного добавления каких-либо элементов. В этом случае ячейки будут полностью пустыми - т.е. и данные, и элемент будут None, Если пользователь редактирует ячейку, данные будут добавлены в модель таблицы, и будет добавлен элемент. Это произойдет, даже если введенное значение является пустой строкой. По умолчанию все ячейки будут доступны для редактирования, если вы не предпримете явных шагов, чтобы сделать их доступными только для чтения.

Существует множество способов сделать ячейки доступными только для чтения - например, установить триггеры редактирования или переопределить метод редактирования таблиц. Но если ваш единственный метод явно устанавливает флаги для отдельных элементов таблицы-виджета, вы можете смело предполагать, что ячейка без элемента является редактируемой и пустой. (Обратите внимание, что если вы устанавливаете данные напрямую через модель таблицы, а не с помощью, например, setItemячейка все равно будет автоматически иметь элемент).

Я нашел решение, которое, кажется, работает: создайте новый элемент и добавьте его в таблицу, когда item() метод возвращает None,

У меня все еще есть некоторые сомнения относительно того, существует ли риск, что это может изменить флаги защищенной от записи ячейки. В настоящее время я просто предполагаю, что если ячейка защищена от записи, это означает, что она обязательно уже содержит элемент.

            item = self.table.item(target_row,
                                   target_col)
            # item may not exist for empty cells
            if item is None:
                item = qt.QTableWidgetItem()
                self.table.setItem(target_row,
                                   target_col,
                                   item)
            # ignore empty strings
            if table_data[row_offset][col_offset] != "":
                if not item.flags() & qt.Qt.ItemIsEditable:
                    protected_cells += 1
                    continue
                item.setText(table_data[row_offset][col_offset])

РЕДАКТИРОВАТЬ: target_row = selected_row + row_offset...

Другие вопросы по тегам