Search code examples
pythonpython-3.xpyqt5qtexteditqlistview

PyQt5: How to drag text from QTextEdit into a QlistView?


I'm currently building a GUI, to which I would like to add the possibility to drag a string from a QTextEdit, and drop it into a QListView so that the dropped string creates a new row.

But sadly I'm a bit confused with what I should be doing. There are tons of examples, but I can't see clearly what I should be doing.

From what I understand I have to reimplement functions but right now I'm more of an headless chicken.


from PyQt5 import QtCore, QtGui, QtWidgets
import testing_ground_lib, sys


class ListModel(QtGui.QStandardItemModel):
    def supportedDropActions(self):
        <MAYBE DO STUFF HERE>

    def dropMimeData(self, data, action, row, column, modelIndex):
        <MAYBE DO STUFF HERE>

class testing_ground(QtWidgets.QMainWindow, testing_ground_lib.Ui_TestWindow):

    def __init__(self, parent=None):
        QtWidgets.QMainWindow.__init__(self, parent)
        self.setupUi(self)

        self.list_model = ListModel(0, 1, self)
        self.inputs_list.setModel(self.list_model)



sys.argv = ['']
app = QtWidgets.QApplication(sys.argv)
testing_ground = testing_ground()
testing_ground.show()
app.exec_()

testing_ground_lib is just the UI generated through QtDesigner, in which we have self.inputs_list.setDragDropMode(QtWidgets.QAbstractItemView.DragDrop) and where my QTextEdit widget is defined (self.req_editor)

In reimplemented dropMimeData, I tried to print stuff just to see how it works but it did not do anything when I was trying to drop my string within QListView.

It is clear to me that I have to implement something that would append a row in ListView on drop of the string, and set the new item with the text from the string, I just can't get what is the starting point.

EDIT : after further investigation, I managed to make the item acceptable by adding :

    def mimeTypes(self):
        return ['text/plain']

in my ListModel class. Now I think I just have to properly reimplement dropMimeData and I think all will be good. I'll update this post if I manage to do so.


Solution

  • Here is a solution to drag the highlighted text in a QTextEdit and drop it into a QListView, adding a new row with that text. Subclass QListView and reimplement dragEnterEvent, dragMoveEvent, and dropEvent. In the dropEvent, add the new item with QStandardItemModel.appendRow().

    import sys
    from PyQt5.QtWidgets import *
    from PyQt5.QtCore import *
    from PyQt5.QtGui import *
    
    class ListView(QListView):
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.setAcceptDrops(True)
            self.setModel(QStandardItemModel(0, 1))
    
        def dragEnterEvent(self, event):
            event.accept() if event.mimeData().hasText() else event.ignore()
    
        def dragMoveEvent(self, event):
            event.accept() if event.mimeData().hasText() else event.ignore()
    
        def dropEvent(self, event):
            if event.mimeData().hasText():
                event.setDropAction(Qt.CopyAction)
                self.model().appendRow(QStandardItem(event.mimeData().text()))
                event.accept()
            else:
                event.ignore()
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        window = QWidget()
        hbox = QHBoxLayout(window)
        hbox.addWidget(QTextEdit())
        hbox.addWidget(ListView())
        window.show()
        sys.exit(app.exec_())
    

    Result:

    enter image description here