0

I am making a program for translating text (see screenshot)

screenshot

I have three classes

class for displaying a window that edits item :

class StyleDelegate(QStyledItemDelegate):
        def __init__(self, parent=None):
            super(StyleDelegate, self).__init__()
        def createEditor(self, widget, style, index):
            self.mainWidget = QWidget(widget)
            self.line = QLineEdit() # line for input text 
            self.delButton= QPushButton('❌')  # button for delete current item
            self.trnButton = QPushButton('➕')  # button for make translation text in another QListView
            self.qhbLayout = QHBoxLayout()
            self.qhbLayout.addWidget(self.line)
            self.qhbLayout.addWidget(self.delButton)
            self.qhbLayout.addWidget(self.trnButton)
            self.mainWidget.setLayout(self.qhbLayout)
            return self.mainWidget
        # there is still a lot of code in this place

class for storing, adding, deleting and editing data:

    class TranslateListModel(QAbstractListModel):
        def __init__(self, parent=None):
            super(TranslateListModel, self).__init__()
            self.words = ['1', '2', '3', '4']

        def removeItem(self, index):
            self.beginRemoveRows(index, index.row(), index.row())
            del self.words[index.row()]
            self.endRemoveRows()
            return True
        # there is still a lot of code in this place

main class of the program:

class QTranslate(QtWidgets.QDialog, log.Ui_Dialog):
     def __init__(self):
        super().__init__()
        self.originalModel = TranslateListModel() 
        self.translateModel = TranslateListModel() 

        self.styleDelegate = StyleDelegate()

        self.originalLV.setModel(self.originalModel) 
        #QListView from Ui_Dialog

        self.translateLV.setModel(self.translateModel)
        #QListView from Ui_Dialog

        self.originalLV.setItemDelegate(self.styleDelegate)
        self.translateLV.setItemDelegate(self.styleDelegate)
    # there is still a lot of code in this place

How to implement buttons to delete the current item and change the translation in another QListView using QStyledItemDelegate? I cannot access these buttons outside the StyleDelegate class to associate them with the methods of the TranslateListModel class.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Artem072
  • 123
  • 1
  • 8
  • 1
    you would have to first create `QListView` - ie, `mylist = QListView()` - and use its instance as argument when you create `QStyledItemDelegate` - ie. `QStyledItemDelegate(..., mylist)` - this way `QStyledItemDelegate` will have access to `QListView` – furas Apr 20 '20 at 12:57
  • most widgets get `parent` object as first value and later this widget may use `self.parent` to access its parent. If you create both classes in the same class and both gets parent as argument then in `QStyledItemDelegate` you could use `self.parent.mylist` to get access to instace of `QListView` – furas Apr 20 '20 at 13:00

1 Answers1

1

A possible solution is to create signals for the delegate and connect them to the functions that will delete or add items, then emit those signals when the buttons are clicked:

class StyleDelegate(QStyledItemDelegate):
    deleteRequested = QtCore.pyqtSignal(int)
    translateRequested = QtCore.pyqtSignal(int)

    def __init__(self, parent=None):
        super(StyleDelegate, self).__init__()
    def createEditor(self, widget, style, index):
        # note: I removed the "self" references as they're unnecessary
        mainWidget = QWidget(widget)
        line = QLineEdit()
        delButton= QPushButton('❌')
        trnButton = QPushButton('➕')
        qhbLayout = QHBoxLayout()
        qhbLayout.addWidget(line)
        qhbLayout.addWidget(delButton)
        qhbLayout.addWidget(trnButton)
        mainWidget.setLayout(qhbLayout)
        delButton.clicked.connect(
            lambda _, row=index.row(): self.deleteRequested.emit(row))
        trnButton.clicked.connect(
            lambda _, row=index.row(): self.translateRequested.emit(row))
        return mainWidget


class QTranslate(QtWidgets.QDialog, log.Ui_Dialog):
    def __init__(self):
        # ...
        self.originalLV.setItemDelegate(self.styleDelegate)
        self.styleDelegate.deleteRequested.connect(self.deleteRow)
        self.styleDelegate.translateRequested.connect(self.translateRow)

    def deleteRow(self, row):
        # ...

    def translateRow(self, row):
        # ...

Note that you should always use an unique delegate instance for each view, as explained in the documentation:

Warning: You should not share the same instance of a delegate between views. Doing so can cause incorrect or unintuitive editing behavior since each view connected to a given delegate may receive the closeEditor() signal, and attempt to access, modify or close an editor that has already been closed.

musicamante
  • 41,230
  • 6
  • 33
  • 58