fix(product-suite): own original image drag lifecycle

This commit is contained in:
chengma
2026-07-23 09:49:01 +08:00
parent e6fdb661fc
commit 7d39ab5c90
5 changed files with 191 additions and 28 deletions
+45 -7
View File
@@ -12,6 +12,7 @@ from PySide6.QtCore import (
QByteArray,
QBuffer,
QIODevice,
QMimeData,
QPointF,
QRect,
QRegularExpression,
@@ -23,6 +24,7 @@ from PySide6.QtCore import (
)
from PySide6.QtGui import (
QColor,
QDrag,
QFont,
QIcon,
QImage,
@@ -283,10 +285,12 @@ class ProductOriginalDelegate(QStyledItemDelegate):
class ProductOriginalList(QListWidget):
MAX_VISIBLE_ASSETS = 16
EMPTY_STATE_TEXT = "暂无商品原图"
INTERNAL_MIME_TYPE = "application/x-cmshopee-product-original"
filesDropped = Signal(list)
clipboardImage = Signal(bytes)
orderChanged = Signal(list)
orderRestoreRequested = Signal()
deleteRequested = Signal(int)
deleteAssetsRequested = Signal(list)
checkedAssetsChanged = Signal(list)
@@ -369,7 +373,12 @@ class ProductOriginalList(QListWidget):
if event.mimeData().hasUrls():
event.acceptProposedAction()
return
if event.source() is self and self._reordering_enabled and self._dragged_item is not None:
if (
event.source() is self
and event.mimeData().hasFormat(self.INTERNAL_MIME_TYPE)
and self._reordering_enabled
and self._dragged_item is not None
):
event.setDropAction(Qt.MoveAction)
event.accept()
return
@@ -382,7 +391,11 @@ class ProductOriginalList(QListWidget):
if not self._reordering_enabled:
event.ignore()
return
if event.source() is self and self._dragged_item is not None:
if (
event.source() is self
and event.mimeData().hasFormat(self.INTERNAL_MIME_TYPE)
and self._dragged_item is not None
):
event.setDropAction(Qt.MoveAction)
event.accept()
return
@@ -397,7 +410,10 @@ class ProductOriginalList(QListWidget):
if not self._reordering_enabled:
event.ignore()
return
if event.source() is not self:
if (
event.source() is not self
or not event.mimeData().hasFormat(self.INTERNAL_MIME_TYPE)
):
event.ignore()
return
if not self._move_dragged_item_to(event.position().toPoint()):
@@ -410,10 +426,22 @@ class ProductOriginalList(QListWidget):
item = self.currentItem()
if not self._begin_internal_drag(item):
return
drag = QDrag(self)
mime_data = QMimeData()
mime_data.setData(
self.INTERNAL_MIME_TYPE,
QByteArray(str(int(item.data(Qt.UserRole))).encode("ascii")),
)
drag.setMimeData(mime_data)
pixmap = item.icon().pixmap(self.iconSize())
if not pixmap.isNull():
drag.setPixmap(pixmap)
drag.setHotSpot(pixmap.rect().center())
completed_action = Qt.IgnoreAction
try:
super().startDrag(Qt.MoveAction)
completed_action = drag.exec(Qt.MoveAction, Qt.MoveAction)
finally:
self._finish_internal_drag()
self._finish_internal_drag(completed_action == Qt.MoveAction)
def _begin_internal_drag(self, item):
if (
@@ -430,7 +458,7 @@ class ProductOriginalList(QListWidget):
self._pending_order = None
return True
def _finish_internal_drag(self):
def _finish_internal_drag(self, move_completed=True):
pending_order = self._pending_order
drag_start_ids = self._drag_start_ids
self._dragged_item = None
@@ -440,11 +468,13 @@ class ProductOriginalList(QListWidget):
return False
current_ids = self.asset_ids()
if (
current_ids != pending_order
not move_completed
or current_ids != pending_order
or len(pending_order) != len(set(pending_order))
or len(pending_order) != len(drag_start_ids)
or set(pending_order) != set(drag_start_ids)
):
self.orderRestoreRequested.emit()
return False
self.orderChanged.emit(list(pending_order))
return True
@@ -2574,6 +2604,7 @@ class ProductSuiteTab(QWidget):
self.original_list.filesDropped.connect(self.import_files)
self.original_list.clipboardImage.connect(self.import_clipboard_image)
self.original_list.orderChanged.connect(self.reorder_originals)
self.original_list.orderRestoreRequested.connect(self._restore_original_order_after_drag)
self.original_list.deleteRequested.connect(self.delete_original)
self.original_list.deleteAssetsRequested.connect(self.delete_originals)
self.original_list.checkedAssetsChanged.connect(self._on_original_checks_changed)
@@ -3738,6 +3769,13 @@ class ProductSuiteTab(QWidget):
self._status("已更新商品原图顺序,第一张图片为主图", "success")
self._refresh_originals(state)
def _restore_original_order_after_drag(self):
state = self._displayed_state
if state is None or state.project_id is None:
return
self._refresh_originals(state)
self._status("原图排序未完成,已恢复原顺序,请重试", "warning")
def _asset_for_item(self, item):
state = self._displayed_state
if state is None or item is None: