fix(product-suite): prevent duplicate drag sorting

This commit is contained in:
chengma
2026-07-23 09:18:18 +08:00
parent de8dbc7754
commit 1d2bb4489a
5 changed files with 117 additions and 14 deletions
+63 -9
View File
@@ -309,6 +309,7 @@ class ProductOriginalList(QListWidget):
self.setDropIndicatorShown(True)
self.setDragDropMode(QListWidget.InternalMove)
self.setDefaultDropAction(Qt.MoveAction)
self._dragged_item = None
self.setContextMenuPolicy(Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self._show_menu)
self.itemChanged.connect(lambda item: self.checkedAssetsChanged.emit(self.checked_asset_ids()))
@@ -366,6 +367,10 @@ 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:
event.setDropAction(Qt.MoveAction)
event.accept()
return
super().dragEnterEvent(event)
def dragMoveEvent(self, event):
@@ -375,6 +380,10 @@ class ProductOriginalList(QListWidget):
if not self._reordering_enabled:
event.ignore()
return
if event.source() is self and self._dragged_item is not None:
event.setDropAction(Qt.MoveAction)
event.accept()
return
super().dragMoveEvent(event)
def dropEvent(self, event):
@@ -386,12 +395,59 @@ class ProductOriginalList(QListWidget):
if not self._reordering_enabled:
event.ignore()
return
internal_move = event.source() is self
if internal_move:
event.setDropAction(Qt.MoveAction)
super().dropEvent(event)
if internal_move and event.isAccepted() and event.dropAction() == Qt.MoveAction:
self.orderChanged.emit(self.asset_ids())
if event.source() is not self:
event.ignore()
return
self._move_dragged_item_to(event.position().toPoint())
event.setDropAction(Qt.MoveAction)
event.accept()
def startDrag(self, supported_actions):
item = self.currentItem()
if (
not self._reordering_enabled
or item is None
or item.data(Qt.UserRole) is None
):
return
self._dragged_item = item
try:
super().startDrag(Qt.MoveAction)
finally:
self._dragged_item = None
def _move_dragged_item_to(self, position):
item = self._dragged_item
if item is None:
return False
source_row = self.row(item)
before_ids = self.asset_ids()
if source_row < 0 or len(before_ids) != len(set(before_ids)):
return False
target = self.itemAt(position)
if target is None:
target_row = self.count()
else:
target_row = self.row(target)
if position.x() > self.visualItemRect(target).center().x():
target_row += 1
if target_row > source_row:
target_row -= 1
moved_item = self.takeItem(source_row)
target_row = max(0, min(target_row, self.count()))
self.insertItem(target_row, moved_item)
self.setCurrentItem(moved_item)
moved_item.setSelected(True)
after_ids = self.asset_ids()
if len(after_ids) != len(set(after_ids)):
self.takeItem(target_row)
self.insertItem(source_row, moved_item)
self.setCurrentItem(moved_item)
return False
if after_ids == before_ids:
return False
self.orderChanged.emit(after_ids)
return True
def resizeEvent(self, event):
super().resizeEvent(event)
@@ -3389,9 +3445,7 @@ class ProductSuiteTab(QWidget):
for index, asset in enumerate(assets, 1):
label = "主图" if index == 1 else "参考%d" % (index - 1)
item = QListWidgetItem(label)
item.setFlags(
item.flags() | Qt.ItemIsDragEnabled | Qt.ItemIsDropEnabled
)
item.setFlags(item.flags() | Qt.ItemIsDragEnabled)
if index == 1:
font = QFont(item.font())
font.setBold(True)