Qt.py icon indicating copy to clipboard operation
Qt.py copied to clipboard

Table Drop Event and loadUi with PySide2

Open MagicRedDeer opened this issue 2 years ago • 3 comments

I am having this issue with loadUi with Pyside2 where I am not able to override a dropEvent in the following situation:


#!/usr/bin/env python
# -*- coding: utf-8 -*-

from Qt.QtCompat import loadUi
from Qt.QtWidgets import QWidget, QApplication
import tempfile
import os


ui = b'''<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout">
   <item>
    <widget class="QListWidget" name="listWidget">
     <property name="dragEnabled">
      <bool>true</bool>
     </property>
    </widget>
   </item>
   <item>
    <widget class="QTableWidget" name="tableWidget">
     <property name="acceptDrops">
      <bool>true</bool>
     </property>
     <property name="dragDropMode">
      <enum>QAbstractItemView::DropOnly</enum>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>
'''


class Widget(QWidget):

    def __init__(self):
        super().__init__(parent=None)
        with tempfile.NamedTemporaryFile("w+b", delete=False) as f:
            f.write(ui)
        loadUi(f.name, self)
        os.unlink(f.name)


        self.tableWidget.setRowCount(3)
        self.tableWidget.setColumnCount(3)
        self.tableWidget.dropEvent = self.tableDrop

        for x in range(4):
            self.listWidget.addItem("item" + str(x))

    def tableDrop(self, event):
        print('tableDrop', event)


if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

When we run this code using PySide2 we get unexpected (default) behaviour when we drag and drop an element from the list into the table below

$ QT_PREFERRED_BINDING=PySide2 python droptable.py

but when we run it using PyQt5 we catch the event in our assigned function.

$ QT_PREFERRED_BINDING=PyQt5 python droptable.py
tableDrop <PyQt5.QtGui.QDropEvent object at 0x7f37e0f93be0>

This looks like a gap in the shim, that can be looked into.

Can you please recommend a bindling agnostic way to load a .ui form containing an element whose dropEvent we want to override?

MagicRedDeer avatar Nov 22 '21 06:11 MagicRedDeer

Look like a gap indeed. I'm not sure why it happens, does it happen with native PySide2? If so, might be worth reaching out to the PySide2 devs for a fix. If not, then the problem must reside in Qt.py. If you find anything, a pull-request would be great.

mottosso avatar Nov 22 '21 07:11 mottosso

No it does not happen with native PySide2 meaning if I use pyside2uic to compile ui into py I can go back to catching dropEvents.

So there is one way around it for now.

MagicRedDeer avatar Nov 22 '21 07:11 MagicRedDeer

FYI! I find similar behaviour with QtPy!

MagicRedDeer avatar Nov 22 '21 07:11 MagicRedDeer