2
votes

I need to enable a button in my app whenever something is dropped to my custom QTreeWidget.

I sub-classed QTreeWidget to implement drag and drop of custom data. But I'm not able to find a way to get notified when something is dropped into my custom QTreeWidget. I couldn't find a QTreeWidget signal to do this. Of course, the QTreeWidget's dropEvent() will be called each time something is dropped but that doesn't help much to achieve what I'm trying to do.

Here's where I instantiate the custom QTreeWidget that accepts drops from another widget,

from PyQt4 import QtCore, QtGui
import MyTreeWidget

class TestWindow(QtGui.QDialog):
  def __init__(self, parent=None):
    super(TestWindow, self).__init__(parent)
    self.myTreeWidget = MyTreeWidget.MyTreeWidget()
    ...
    #self.myTreeWidget.onItemDropped.connect(self.doSomethingOnItemDropped) <== I am looking for something like this

  def doSomethingOnItemDropped(self):
    # Enable certain button 

  ...

And then, here is how I sub-classed QTreeWidget,

import sys
from PyQt4 import QtGui, QtCore

class MyTreeWidget(QtGui.QTreeWidget):
  def __init__(self, parent=None):
    super(MyTreeWidget, self).__init__(parent)
    self.setAcceptDrops(True)

  def dropEvent(self, event): 
    if (event.mimeData().hasFormat('application/x-icon-and-text')):
      event.acceptProposedAction()
      data = event.mimeData().data("application/x-icon-and-text")
      stream= QtCore.QDataStream(data, QtCore.QIODevice.ReadOnly)
      text = QtCore.QString()
      icon = QtGui.QIcon()
      stream >> text >> icon
      item = QtGui.QTreeWidgetItem(self)
      item.setText(0, text)
      item.setIcon(0, icon)
      self.addTopLevelItem(item)      
    else:
      event.ignore() 

  def dragEnterEvent(self, event):
    if (event.mimeData().hasFormat('application/x-icon-and-text')):
      event.accept()
    else:
      event.ignore() 

  def dragMoveEvent(self, event):
    if event.mimeData().hasFormat("application/x-icon-and-text"):
      event.setDropAction(QtCore.Qt.CopyAction)
      event.accept()
    else:
      event.ignore()

Any ideas? Thanks!

UPDATE : This is what worked for me

Based on comment by @ekhumoro I defined a custom signal itemDropped for my custom QTreeWidget which emits in dropEvent() event handler.

    import sys
    from PyQt4 import QtGui, QtCore

    class MyTreeWidget(QtGui.QTreeWidget):

      itemDropped = QtCore.pyqtSignal()

      def __init__(self, parent=None):
        super(MyTreeWidget, self).__init__(parent)
        self.setAcceptDrops(True)

      def dropEvent(self, event): 
        if (event.mimeData().hasFormat('application/x-icon-and-text')):
          event.acceptProposedAction()
          data = event.mimeData().data("application/x-icon-and-text")
          stream= QtCore.QDataStream(data, QtCore.QIODevice.ReadOnly)
          text = QtCore.QString()
          icon = QtGui.QIcon()
          stream >> text >> icon
          item = QtGui.QTreeWidgetItem(self)
          item.setText(0, text)
          item.setIcon(0, icon)
          self.addTopLevelItem(item)
          self.itemDropped.emit()
        else:
          event.ignore() 

And in my app,

    from PyQt4 import QtCore, QtGui
    import MyTreeWidget

    class TestWindow(QtGui.QDialog):
      def __init__(self, parent=None):
        super(TestWindow, self).__init__(parent)
        self.myTreeWidget = MyTreeWidget.MyTreeWidget()
        self.myTreeWidget.itemDropped.connect(self.doSomethingOnItemDropped) 
        ...

      def doSomethingOnItemDropped(self):
        # Enable certain button 

      ...
2
Without actually going and looking myself, standard answer re missing signals: try looking for events also. I assume you also clicked the link to see all inherited members?Croad Langshan
I can't understand why you would think dropEvent doesn't help: it could hardly be better suited to what you want to do. Just define your own itemDropped signal and emit it from dropEvent at whatever point you feel is appropriate.ekhumoro
@ekhumoro : You are right. I defined a new signal that emits it in dropEvent. If you post it as an answer, I'll accept it.NGambit

2 Answers

2
votes

You could define a custom signal and emit it from dropEvent:

class MyTreeWidget(QtGui.QTreeWidget):
    itemDropped = QtCore.pyqtSignal()

    def dropEvent(self, event): 
        if (event.mimeData().hasFormat('application/x-icon-and-text')):
            ...
            self.itemDropped.emit()
0
votes

In PySide2 you can use this:

class MyTreeWidget(QtGui.QTreeWidget):

    itemDropped = QtCore.Signal()

    def dropEvent(self, event): 
        if (event.mimeData().hasFormat('application/x-icon-and-text')):

            self.itemDropped.emit()