Skip to content

Commit 056a159

Browse files
committed
Fix spring-loaded folders; use QGraphicsScene to have more than 1 icon during drag
1 parent 4b2405d commit 056a159

File tree

1 file changed

+52
-19
lines changed

1 file changed

+52
-19
lines changed

spatial.py

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
import math
1111
import shutil
1212

13-
from PyQt6.QtCore import Qt, QPoint, QSize, QDir, QRect, QMimeData, QUrl, QFileSystemWatcher, QFileInfo, QTimer, QRegularExpression
13+
from PyQt6.QtCore import Qt, QPoint, QSize, QDir, QRect, QMimeData, QUrl, QFileSystemWatcher, QFileInfo, QTimer, QRegularExpression, QObject, QEvent
1414
from PyQt6.QtGui import QFontMetrics, QPainter, QPen, QAction, QDrag, QColor, QPainter, QPen, QBrush, QPixmap, QKeySequence, QFont, QIcon, QShortcut, QRegularExpressionValidator, QCursor
1515
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QScrollArea, QLabel, QSizePolicy, QMainWindow, QDialogButtonBox
16-
from PyQt6.QtWidgets import QStatusBar, QComboBox, QFileIconProvider, QMenuBar, QGridLayout, QMessageBox, QMenu, QDialog, QLineEdit, QInputDialog
16+
from PyQt6.QtWidgets import QStatusBar, QComboBox, QFileIconProvider, QMenuBar, QGridLayout, QMessageBox, QMenu, QDialog, QLineEdit, QGraphicsScene, QGraphicsPixmapItem
1717

1818
if sys.platform == "win32":
1919
from win32com.client import Dispatch
@@ -129,6 +129,21 @@ def __init__(self, path=None, is_desktop_window=False):
129129
self.file_watcher.fileChanged.connect(self.file_changed)
130130
self.file_watcher.addPath(self.path)
131131

132+
# To keep track of spring-loaded folders needing to be closed
133+
self.installEventFilter(self)
134+
135+
# To keep track of spring-loaded folders needing to be closed
136+
def eventFilter(self, obj: QObject, event: QEvent) -> bool:
137+
if event.type() == QEvent.Type.DragLeave:
138+
# Check whether mouse coordinates are inside or outside of the window, and print the result
139+
mouse_is_inside = self.rect().contains(self.mapFromGlobal(QCursor.pos()))
140+
print("Mouse is inside:", mouse_is_inside)
141+
if not mouse_is_inside and self.is_spring_opened:
142+
self.close()
143+
# Handle the drag leave event here
144+
return True # Return True if the event is handled
145+
return super().eventFilter(obj, event)
146+
132147
def keyPressEvent(self, event):
133148
# Handle Tab and Shift-Tab to select the next and previous item
134149
if event.key() == Qt.Key.Key_Tab:
@@ -532,16 +547,37 @@ def mousePressEvent(self, event):
532547
self.dragging = True
533548
self.last_pos = adjusted_pos
534549
self.update_menu_state()
535-
# Set mime data for all selected items
550+
551+
# Create a QGraphicsScene to hold the icons
552+
scene = QGraphicsScene()
553+
icon_spacing = 10 # Space between icons
554+
x_offset = 0
555+
556+
# Add each selected item's icon to the scene
557+
for item in self.selected_files:
558+
icon_pixmap = item.icon_label.pixmap()
559+
pixmap_item = QGraphicsPixmapItem(icon_pixmap)
560+
pixmap_item.setPos(x_offset, 0) # Position the icon
561+
scene.addItem(pixmap_item)
562+
x_offset += icon_pixmap.width() + icon_spacing # Update offset for next icon
563+
# FIXME: Use the items' real positions instead; can this be done without using a QGraphicsView?
564+
565+
# Create a QPixmap from the scene
566+
scene_rect = scene.itemsBoundingRect()
567+
combined_pixmap = QPixmap(scene_rect.size().toSize())
568+
combined_pixmap.fill(QColor(0, 0, 0, 0))
569+
painter = QPainter(combined_pixmap)
570+
scene.render(painter, target=scene_rect, source=scene_rect)
571+
painter.end()
572+
573+
# Set the combined pixmap for the drag
574+
drag = QDrag(self)
536575
mime_data = QMimeData()
537576
for item in self.selected_files:
538577
mime_data.setUrls([QUrl.fromLocalFile(f.path) for f in self.selected_files])
539-
drag = QDrag(self)
540578
drag.setMimeData(mime_data)
541-
drag.setPixmap(self.selected_files[0].icon_label.pixmap())
542-
# TODO: Make it so that the icon doesn't jump to be at the top left corner of the mouse cursor
543-
# FIXME: Instead of hardcoding the hot spot to be half the icon size, it should be the position of the mouse cursor relative to the item
544-
drag.setHotSpot(QPoint(int(app.icon_size/2), int(app.icon_size/2)))
579+
drag.setPixmap(combined_pixmap)
580+
drag.setHotSpot(QPoint(int(app.icon_size / 2), int(app.icon_size / 2)))
545581
drag.exec()
546582
else:
547583
self.is_selecting = True
@@ -658,17 +694,6 @@ def dragEnterEvent(self, event):
658694

659695
def startDrag(self, event):
660696
self.initial_position = event.pos()
661-
662-
def dragLeaveEvent(self, event):
663-
# If this window was spring-loaded, close it when the drag leaves the window
664-
if self.is_spring_opened:
665-
# FIXME: For some reason, the following line does not work. May need to iterate through all item rects
666-
# to see if the mouse is within them (and possibly some margin)
667-
if any(item.underMouse() for item in self.items):
668-
event.ignore()
669-
else:
670-
self.close()
671-
event.accept()
672697

673698
def dropEvent(self, event):
674699
initial_position = self.initial_position
@@ -1128,6 +1153,14 @@ def get_info(self):
11281153

11291154
def spring_open(self):
11301155
self.open(event=None, spring_open=True)
1156+
1157+
parent = self.parent()
1158+
while parent:
1159+
parent = parent.parent()
1160+
print(parent.__class__.__name__)
1161+
if parent.__class__.__name__ == "SpatialFiler" and not parent.is_desktop_window:
1162+
parent.close()
1163+
11311164

11321165
def open(self, event=None, spring_open=False):
11331166
print(f"Asked to open {self.path}")

0 commit comments

Comments
 (0)