I want to be able to copy and paste to and from a Pyside6 table (QTableWidget) with control-C control-V, mainly from and to Excel. I found @Momo's post of January 2023. 1 That did not appear to work for me, possibly because I am working with Pyside6 instead of PyQt5. What would be a solution for that?
Asked
Active
Viewed 36 times
1
-
If your code works and your actual question is "is this fine" or "can it be done better/in other ways", then sorry but that kind of posts are considered off topic on SO, since they usually resolve to opinion based answers. Also note that creating a subclass that is named *exactly* like an existing one (specifically, the same one from which it inherits) is a *terrible* idea, even if you're using a different namespace. – musicamante Jul 17 '23 at 23:17
-
@musicamante: I split my post into a question and an answer and adjusted my answer a bit in response to what you think is a terrible idea. – ROB Jul 19 '23 at 19:03
-
It's not just a personal opinion: you can obviously do anything you want with *your* code, but using the same name may lead to confusion to people collaborating with you. Including *you*: as the project grows you may need to use *standard* QTableWidgets, and you may get to the point where you have to get back to your code (maybe months or years after writing some sections), so it would be extremely easy to confuse your class with the original. There's very little point and no practical benefit in doing so, as opposed to the drawbacks it may lead to. – musicamante Jul 19 '23 at 19:55
-
1musicamante: I edited my answer accordingly. Thanks! – ROB Jul 25 '23 at 20:42
1 Answers
1
An answer to my own question: I changed Momo's code to make it work for me, and I added the possibility to delete multiple cells and to undo mistakes with this paste or delete. The undo works within the table where your cursor is only.
Are there better ways to do this, or might you have advice for improvement?
import PySide6.QtWidgets as QtWidgets
from PySide6 import QtCore, QtGui
from PySide6.QtGui import QGuiApplication
class CopyPasteDelTableWidget(QtWidgets.QTableWidget):
def __init__(self, n_rows, n_columns):
super().__init__(n_rows, n_columns)
self.forundo = []
self.setSelectionMode(QtWidgets.QAbstractItemView.ContiguousSelection)
self.installEventFilter(self)
def eventFilter(self, source, event):
if event.type() == QtCore.QEvent.KeyPress:
if event == QtGui.QKeySequence.Copy:
self.copySelection()
return True
elif event == QtGui.QKeySequence.Paste:
self.pasteSelection()
return True
elif event == QtGui.QKeySequence.Delete:
self.deleteSelection()
return True
elif event == QtGui.QKeySequence.Cut:
self.copySelection()
self.deleteSelection()
return True
elif event == QtGui.QKeySequence.Undo:
self.undoSelection()
return True
return super(QTableWidget, self).eventFilter(source, event)
def deleteSelection(self):
self.forundo.append([self.selectedRanges()[0].topRow(), self.selectedRanges()[0].leftColumn(), []])
for i_row in range(self.selectedRanges()[0].topRow(), self.selectedRanges()[0].bottomRow() + 1):
undorow = []
for i_col in range(self.selectedRanges()[0].leftColumn(), self.selectedRanges()[0].rightColumn() + 1):
undorow.append(self.item(i_row, i_col).text())
self.setItem(i_row, i_col, QtWidgets.QTableWidgetItem(''))
self.forundo[-1][2].append(undorow)
def copySelection(self):
copied = ''
for row in range(self.selectedRanges()[0].topRow(), self.selectedRanges()[0].bottomRow() + 1):
for col in range(self.selectedRanges()[0].leftColumn(), self.selectedRanges()[0].rightColumn() + 1):
copied += self.item(row, col).text() + '\t'
copied = copied[:-1] + '\n'
QGuiApplication.clipboard().setText(copied)
def pasteSelection(self):
if not QGuiApplication.clipboard():
return
copied = QGuiApplication.clipboard().text().split('\n')
self.forundo.append([self.selectedRanges()[0].topRow(), self.selectedRanges()[0].leftColumn(), []])
if copied[-1] == '':
copied = copied[:-1]
for i_line, line in enumerate(copied):
copied[i_line] = line.split('\t')
for i_row, row in enumerate(copied):
undorow = []
k_row = i_row + self.selectedRanges()[0].topRow()
if k_row < self.rowCount():
for i_col, col in enumerate(row):
k_col = i_col + self.selectedRanges()[0].leftColumn()
if k_col < self.columnCount():
undorow.append(self.item(k_row, k_col).text())
self.setItem(k_row, k_col, QtWidgets.QTableWidgetItem(col))
self.forundo[-1][2].append(undorow)
def undoSelection(self):
if len(self.forundo) > 0:
prevundo = self.forundo.pop()
self.setCurrentCell(prevundo[0], prevundo[1])
for i_row, row in enumerate(prevundo[2]):
for i_col, col in enumerate(row):
self.setItem(i_row + prevundo[0], i_col + prevundo[1], QtWidgets.QTableWidgetItem(col))

ROB
- 181
- 2
- 12