I have a python qt5 program with a QTreeWidget. Each QTreeWidgetItem represents files. I have the logic working correctly within mouseMoveEvent so that QDrag CopyAction passes the file mime data successfully to windows when the user drags it to windows explorer or the desktop. However, I need to know what that target path is. The QDrag target() function only returns a widget if the user drags within the application. If the user drags outside the application (like the desktop), then target() returns None.
Is there anyway to know the path the user dragged to in windows?
The reason I need to know the target path is because the file will actually be generated at runtime and the generation can take as long as a minute to complete. In this mvce example I am using touch command to instantly create an empty file so the user doesn't have to wait or see a long delay. Then after the actual file is generated a minute later, I want to replace the empty file with the actual file. My application can then tell the user that the file is now available. I can not pre-generate the file because there will be many in the list and each will take minutes to generate.
Here is my mvce (minimum reproducible example):
example.py
#!python3
import sys
from PyQt5.QtWidgets import QMainWindow, QApplication, QTreeWidgetItem
from main_ui import Ui_MainWindow
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self, parent = None):
super(MainWindow, self).__init__(parent) # initialization of the superclass
self.setupUi(self) # setup the GUI --> function generated by pyuic4
self.tree1.blockSignals(True)
self.tree1.clear()
self.tree1.setHeaderHidden(True)
self.tree1.setColumnCount(2)
self.tree1.setRootIsDecorated(True) # show expansion icon
level1 = QTreeWidgetItem(self.tree1)
level1.setText(0, "root")
level1.setExpanded(True)
level2 = QTreeWidgetItem(level1)
level2.setExpanded(False)
level2.setText(0, "dragme to desktop")
level2.setExpanded(True)
self.tree1.show()
self.tree1.resizeColumnToContents(0)
self.tree1.blockSignals(False)
self.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
myapp = MainWindow() # instantiate the main window
rc = app.exec_()
sys.exit(rc) # exit with the same return code of Qt application
main.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>415</width>
<height>451</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="mytree" name="tree1">
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="autoScrollMargin">
<number>16</number>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
<property name="dragEnabled">
<bool>true</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::DragDrop</enum>
</property>
<property name="alternatingRowColors">
<bool>false</bool>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<property name="columnCount">
<number>0</number>
</property>
<attribute name="headerVisible">
<bool>true</bool>
</attribute>
<attribute name="headerCascadingSectionResizes">
<bool>false</bool>
</attribute>
<attribute name="headerDefaultSectionSize">
<number>100</number>
</attribute>
<attribute name="headerStretchLastSection">
<bool>false</bool>
</attribute>
</widget>
</item>
</layout>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>mytree</class>
<extends>QTreeWidget</extends>
<header>mytree.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
mytree.py
#!python3
import tempfile
from pathlib import Path
from PyQt5 import QtGui
from PyQt5 import QtCore
from PyQt5 import QtWidgets
from PyQt5.QtCore import Qt
class mytree(QtWidgets.QTreeWidget): # mytree is now a subclass of qlineedit class
def __init__(self, parent=None):
super(mytree, self).__init__(parent) # The use of "super" is a slightly better method of calling the parent for initialization
self.setDragEnabled(True)
def mouseMoveEvent(self, event): # is called whenever the mouse moves while a mouse button is held down
super(mytree, self).mouseMoveEvent(event) #propagate
tempdir = tempfile.gettempdir() # temp directory aka %temp%
realfile = tempdir + "/empty.txt"
Path(realfile).touch() # create empty file
fileurl = "file:///%s" % realfile # build url
url = QtCore.QUrl(fileurl)
urllist = []
urllist.append(url) # only 1 file
drag = QtGui.QDrag(self)
md = QtCore.QMimeData()
md.setUrls(urllist)
drag.setMimeData(md)
result = drag.exec_(Qt.CopyAction)
source = drag.source()
print("source = %s" % source)
target = drag.target() # returns widget if inside the application, returns None if windows desktop ... etc.
print("target = %s" % target)
from How to get the drop target when the drop occurs outside the application?
No comments:
Post a Comment