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
+138 -17
View File
@@ -2973,6 +2973,74 @@ class ProductSuiteGuiTests(TempDirMixin, unittest.TestCase):
original_list.set_reordering_enabled(False)
self.assertFalse(original_list._begin_internal_drag(original_list.item(0)))
def test_original_list_start_drag_owns_move_without_qt_source_cleanup(self):
original_list = ProductOriginalList()
self.addCleanup(original_list.close)
original_list.setFixedSize(360, 120)
for asset_id in (11, 12, 13):
item = QListWidgetItem("原图%d" % asset_id)
item.setData(Qt.UserRole, asset_id)
item.setIcon(QIcon(QPixmap(24, 18)))
original_list.addItem(item)
original_list.show()
self.app.processEvents()
original_list.setCurrentItem(original_list.item(1))
changes = []
restores = []
original_list.orderChanged.connect(changes.append)
original_list.orderRestoreRequested.connect(lambda: restores.append(True))
with mock.patch("app.gui.tabs.product_suite.QDrag") as drag_type:
drag = drag_type.return_value
def execute_drag(*args):
first_rect = original_list.visualItemRect(original_list.item(0))
self.assertTrue(original_list._move_dragged_item_to(first_rect.center()))
self.assertEqual([], changes)
return Qt.MoveAction
drag.exec.side_effect = execute_drag
original_list.startDrag(Qt.MoveAction)
drag_type.assert_called_once_with(original_list)
mime_data = drag.setMimeData.call_args.args[0]
self.assertTrue(mime_data.hasFormat(original_list.INTERNAL_MIME_TYPE))
self.assertEqual([12, 11, 13], original_list.asset_ids())
self.assertEqual(3, original_list.count())
self.assertEqual([[12, 11, 13]], changes)
self.assertEqual([], restores)
def test_original_list_start_drag_requests_restore_after_unexpected_item_loss(self):
original_list = ProductOriginalList()
self.addCleanup(original_list.close)
original_list.setFixedSize(360, 120)
for asset_id in (11, 12, 13):
item = QListWidgetItem("原图%d" % asset_id)
item.setData(Qt.UserRole, asset_id)
original_list.addItem(item)
original_list.show()
self.app.processEvents()
original_list.setCurrentItem(original_list.item(1))
changes = []
restores = []
original_list.orderChanged.connect(changes.append)
original_list.orderRestoreRequested.connect(lambda: restores.append(True))
with mock.patch("app.gui.tabs.product_suite.QDrag") as drag_type:
drag = drag_type.return_value
def execute_drag(*args):
first_rect = original_list.visualItemRect(original_list.item(0))
self.assertTrue(original_list._move_dragged_item_to(first_rect.center()))
original_list.takeItem(original_list.count() - 1)
return Qt.MoveAction
drag.exec.side_effect = execute_drag
original_list.startDrag(Qt.MoveAction)
self.assertEqual([], changes)
self.assertEqual([True], restores)
def test_original_list_repeated_primary_moves_keep_every_asset_and_label(self):
with self.make_temp_dir() as temp_dir:
config = self._config(temp_dir)
@@ -2992,24 +3060,33 @@ class ProductSuiteGuiTests(TempDirMixin, unittest.TestCase):
expected_labels = ["主图", "参考1", "参考2", "参考3", "参考4"]
for asset in assets[1:]:
row = tab.original_list.asset_ids().index(asset.id)
self.assertTrue(
tab.original_list._begin_internal_drag(tab.original_list.item(row))
)
first_rect = tab.original_list.visualItemRect(tab.original_list.item(0))
self.assertTrue(
tab.original_list._move_dragged_item_to(first_rect.center())
)
database_ids_before_finish = [
stored.id
for stored in image_studio.list_assets(
project.id,
kind=image_studio.ASSET_KIND_ORIGINAL,
path=config["db_path"],
)
]
self.assertNotEqual(tab.original_list.asset_ids(), database_ids_before_finish)
tab.original_list.setCurrentItem(tab.original_list.item(row))
with mock.patch("app.gui.tabs.product_suite.QDrag") as drag_type:
drag = drag_type.return_value
self.assertTrue(tab.original_list._finish_internal_drag())
def execute_drag(*args):
first_rect = tab.original_list.visualItemRect(
tab.original_list.item(0)
)
self.assertTrue(
tab.original_list._move_dragged_item_to(first_rect.center())
)
database_ids_before_finish = [
stored.id
for stored in image_studio.list_assets(
project.id,
kind=image_studio.ASSET_KIND_ORIGINAL,
path=config["db_path"],
)
]
self.assertNotEqual(
tab.original_list.asset_ids(),
database_ids_before_finish,
)
return Qt.MoveAction
drag.exec.side_effect = execute_drag
tab.original_list.startDrag(Qt.MoveAction)
visible_ids = tab.original_list.asset_ids()
database_ids = [
stored.id
@@ -3031,6 +3108,50 @@ class ProductSuiteGuiTests(TempDirMixin, unittest.TestCase):
self.assert_removed(temp_dir)
def test_original_list_restores_database_order_after_drag_item_loss(self):
with self.make_temp_dir() as temp_dir:
config = self._config(temp_dir)
project, assets = self._create_project_with_assets(temp_dir, config, 3)
tab = ProductSuiteTab(config=config, db_path=config["db_path"])
self.addCleanup(tab.close)
state = tab._displayed_state
state.account_alias = "alias-a"
state.item_id = "51100639510"
state.project_id = project.id
tab._load_state(state)
tab.resize(1180, 760)
tab.show()
self.app.processEvents()
statuses = []
tab._status = lambda message, level=None: statuses.append((message, level))
tab.original_list.setCurrentItem(tab.original_list.item(1))
with mock.patch("app.gui.tabs.product_suite.QDrag") as drag_type:
drag = drag_type.return_value
def execute_drag(*args):
first_rect = tab.original_list.visualItemRect(
tab.original_list.item(0)
)
self.assertTrue(
tab.original_list._move_dragged_item_to(first_rect.center())
)
tab.original_list.takeItem(tab.original_list.count() - 1)
return Qt.MoveAction
drag.exec.side_effect = execute_drag
tab.original_list.startDrag(Qt.MoveAction)
expected_ids = [asset.id for asset in assets]
self.assertEqual(expected_ids, tab.original_list.asset_ids())
self.assertEqual(3, tab.original_list.count())
self.assertEqual(
("原图排序未完成,已恢复原顺序,请重试", "warning"),
statuses[-1],
)
self.assert_removed(temp_dir)
def test_temporary_draft_allows_local_work_but_blocks_shopee_pull_and_recovers(self):
with self.make_temp_dir() as temp_dir:
config = self._config(temp_dir)