import sys from PyQt5.QtCore import QEvent, Qt from PyQt5.QtWidgets import QApplication, QTableWidget class CopyPastableCrudQTableWidget(QTableWidget): crud = None def eventFilter(self, target, event): if event.type() == QEvent.KeyPress: if event.key() == Qt.Key_C and (event.modifiers() & Qt.ControlModifier): if event.key() == Qt.Key_C and (event.modifiers() & Qt.ControlModifier): copied_cells = sorted(self.selectedIndexes()) min_row, max_row, min_col, max_col = sys.maxsize, 0, sys.maxsize, 0 for cell in copied_cells: row = cell.row() min_row, max_row = min(row, min_row), max(row, max_row) col = cell.column() min_col, max_col = min(col, min_col), max(col, max_col) if min_row == 0: # if filters row return False copy_sparse = {} for cell in copied_cells: row = cell.row() col = cell.column() if row not in copy_sparse: copy_sparse[row] = {} cell = self.cellWidget(row, col) if cell is not None: copy_sparse[row][col] = cell.parse(row_number=row, crud=self.crud) copy_dense = [["" for col in range(max_col - min_col + 1)] for row in range(max_row - min_row + 1)] for row, row_cells in copy_sparse.items(): for col, cell_text in row_cells.items(): if cell_text is not None: copy_dense[row - min_row][col - min_col] = str(cell_text) copy_text = "\n".join(["\t".join(row) for row in copy_dense]) QApplication.clipboard().setText(copy_text) super().keyPressEvent(event) QApplication.sendEvent(self, event) return True elif event.key() == Qt.Key_V and (event.modifiers() & Qt.ControlModifier): min_row = self.currentRow() min_col = self.currentColumn() if min_row == 0: # if filters row return False copy_text = QApplication.clipboard().text() copy_dense = [row.split("\t") for row in copy_text.split("\n")] if len(copy_dense) > 1 and len(copy_dense[-1]) == 1 and not len(copy_dense[-1][-1]): copy_dense.pop(-1) for row, row_cells in enumerate(copy_dense): for col, cell_text in enumerate(row_cells): r = min_row + row c = min_col + col cell = self.cellWidget(r, c) if cell is not None: cell.render(cell_text, field_name=self.crud.select[c] if self.crud is not None else None, row_number=r, crud=self.crud) super().keyPressEvent(event) QApplication.sendEvent(self, event) return True return super().eventFilter(target, event) def setCellWidget(self, row, column, widget): widget.installEventFilter(self) super().setCellWidget(row, column, widget) if __name__ == "__main__": app = QApplication(sys.argv) table = CopyPastableCrudQTableWidget() table.setRowCount(10) table.setColumnCount(10) table.show() sys.exit(app.exec())