Skip to content

Commit 326079d

Browse files
committed
App: autoscroll on drag to edge
[skip ci]
1 parent 133a54e commit 326079d

1 file changed

Lines changed: 86 additions & 19 deletions

File tree

scripts/gdrive_app.py

Lines changed: 86 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
from PySide6.QtSvg import QSvgRenderer
2323
from PySide6.QtCore import QByteArray, Qt, QRunnable, Signal, QThreadPool, Slot, QTimer, QThread, QStringListModel, QObject
24-
from PySide6.QtGui import QPainter, QImage
24+
from PySide6.QtGui import QPainter, QImage, QPen
2525

2626
from collections import OrderedDict
2727
from functools import lru_cache
@@ -360,14 +360,41 @@ def __init__(self, parent=None):
360360
self.setDefaultDropAction(Qt.DropAction.MoveAction)
361361
self.setSelectionMode(QListView.SelectionMode.ExtendedSelection)
362362
self.hovered_item = None
363+
self.scroll_timer = QTimer(self)
364+
self.scroll_timer.timeout.connect(self._auto_scroll)
365+
self.scroll_direction = 0
366+
self.scroll_speed = 0
367+
368+
def _auto_scroll(self):
369+
sb = self.verticalScrollBar()
370+
sb.setValue(sb.value() + self.scroll_direction * self.scroll_speed)
363371

364372
def dragEnterEvent(self, event):
373+
super().dragEnterEvent(event)
365374
if event.source() == self:
366375
event.accept()
367-
else:
368-
super().dragEnterEvent(event)
369376

370377
def dragMoveEvent(self, event):
378+
super().dragMoveEvent(event)
379+
380+
outer_margin = 60
381+
inner_margin = 20
382+
y = event.pos().y()
383+
height = self.viewport().height()
384+
385+
if y < outer_margin:
386+
self.scroll_direction = -1
387+
self.scroll_speed = 75 if y < inner_margin else 25
388+
if not self.scroll_timer.isActive():
389+
self.scroll_timer.start(50)
390+
elif y > height - outer_margin:
391+
self.scroll_direction = 1
392+
self.scroll_speed = 75 if y > height - inner_margin else 25
393+
if not self.scroll_timer.isActive():
394+
self.scroll_timer.start(50)
395+
else:
396+
self.scroll_timer.stop()
397+
371398
if event.source() == self:
372399
target_item = self.itemAt(event.pos())
373400
if target_item != self.hovered_item:
@@ -391,16 +418,16 @@ def dragMoveEvent(self, event):
391418
event.accept()
392419
return
393420
event.ignore()
394-
else:
395-
super().dragMoveEvent(event)
396421

397422
def dragLeaveEvent(self, event):
423+
self.scroll_timer.stop()
398424
if self.hovered_item:
399425
self._restore_icon(self.hovered_item)
400426
self.hovered_item = None
401427
super().dragLeaveEvent(event)
402428

403429
def dropEvent(self, event):
430+
self.scroll_timer.stop()
404431
if self.hovered_item:
405432
self._restore_icon(self.hovered_item)
406433
self.hovered_item = None
@@ -435,6 +462,54 @@ def _restore_icon(self, item):
435462
item.setIcon(self.original_icon)
436463
self.original_icon = None
437464

465+
class PieProgressBar(QWidget):
466+
def __init__(self, parent=None):
467+
super().__init__(parent)
468+
self.setFixedSize(24, 24)
469+
self._value = 0
470+
self._maximum = 1
471+
472+
def setValue(self, value):
473+
self._value = value
474+
self.update()
475+
476+
def setMaximum(self, maximum):
477+
self._maximum = maximum
478+
self.update()
479+
480+
def paintEvent(self, event):
481+
painter = QPainter(self)
482+
painter.setRenderHint(QPainter.RenderHint.Antialiasing)
483+
484+
rect = self.rect().adjusted(2, 2, -2, -2)
485+
486+
# Draw background circle
487+
bg_color = QApplication.palette().alternateBase().color()
488+
painter.setPen(Qt.PenStyle.NoPen)
489+
painter.setBrush(bg_color)
490+
painter.drawEllipse(rect)
491+
492+
# Draw pie
493+
if self._maximum > 0:
494+
fg_color = QApplication.palette().highlight().color()
495+
painter.setBrush(fg_color)
496+
497+
start_angle = 90 * 16
498+
progress = self._value / self._maximum
499+
span_angle = int(-progress * 360 * 16)
500+
501+
painter.drawPie(rect, start_angle, span_angle)
502+
503+
# Draw a subtle outline
504+
outline_pen = QPen(QApplication.palette().text().color(), 1)
505+
c = outline_pen.color()
506+
c.setAlpha(64)
507+
outline_pen.setColor(c)
508+
painter.setPen(outline_pen)
509+
painter.setBrush(Qt.BrushStyle.NoBrush)
510+
painter.drawEllipse(rect)
511+
512+
438513
class ClickSelectLineEdit(QLineEdit):
439514
escPressed = Signal()
440515

@@ -481,7 +556,6 @@ def __init__(self):
481556
self.gdrive_pool.setMaxThreadCount(10)
482557
self.gdrive_tasks_total = 0
483558
self.gdrive_tasks_completed = 0
484-
self.gdrive_progress_dialog: QProgressDialog | None = None
485559

486560
self.gcache: DriveCache | None = None
487561
self.init_ui()
@@ -569,6 +643,9 @@ def init_ui(self):
569643
top_bar.addWidget(self.up_btn)
570644
top_bar.addWidget(self.address_bar)
571645

646+
self.gdrive_progress_widget = PieProgressBar()
647+
top_bar.addWidget(self.gdrive_progress_widget)
648+
572649
self.folder_menu_btn = QPushButton()
573650
self.folder_menu_btn.setIcon(get_icon(OutlineIcon.DOTS))
574651
self.folder_menu_btn.setToolTip("Folder actions")
@@ -1073,20 +1150,10 @@ def queue_gdrive_action(self, action: GDriveAction):
10731150

10741151
def _update_gdrive_progress(self):
10751152
if self.gdrive_tasks_total > self.gdrive_tasks_completed:
1076-
if not self.gdrive_progress_dialog:
1077-
self.gdrive_progress_dialog = QProgressDialog("Processing operations...", "Cancel", 0, self.gdrive_tasks_total, self)
1078-
self.gdrive_progress_dialog.setWindowTitle("GDrive Operations")
1079-
self.gdrive_progress_dialog.setWindowModality(Qt.WindowModality.NonModal)
1080-
self.gdrive_progress_dialog.setCancelButton(None)
1081-
self.gdrive_progress_dialog.setMinimumDuration(0)
1082-
self.gdrive_progress_dialog.show()
1083-
1084-
self.gdrive_progress_dialog.setMaximum(self.gdrive_tasks_total)
1085-
self.gdrive_progress_dialog.setValue(self.gdrive_tasks_completed)
1153+
self.gdrive_progress_widget.setMaximum(self.gdrive_tasks_total)
1154+
self.gdrive_progress_widget.setValue(self.gdrive_tasks_completed)
1155+
self.gdrive_progress_widget.setToolTip(f"Processing... ({self.gdrive_tasks_completed}/{self.gdrive_tasks_total})")
10861156
else:
1087-
if self.gdrive_progress_dialog:
1088-
self.gdrive_progress_dialog.close()
1089-
self.gdrive_progress_dialog = None
10901157
self.gdrive_tasks_total = 0
10911158
self.gdrive_tasks_completed = 0
10921159

0 commit comments

Comments
 (0)