feat(gui): add shared zoomable image preview
This commit is contained in:
@@ -54,8 +54,10 @@ from app.gui import (
|
||||
GenerateWorker,
|
||||
GenerateTab,
|
||||
ForcedUpdateDialog,
|
||||
ImageStudioPreviewDialog,
|
||||
ImageStudioTab,
|
||||
MainWindow,
|
||||
ProductSuitePreviewDialog,
|
||||
ProductSuiteTab,
|
||||
SettingsTab,
|
||||
TAB_STYLE,
|
||||
@@ -4515,6 +4517,121 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
|
||||
self.assert_removed(temp_dir)
|
||||
|
||||
def test_shared_image_preview_defaults_to_fit_and_keeps_fixed_zoom_on_resize(self):
|
||||
with self.make_temp_dir() as temp_dir:
|
||||
image_path = self.write_test_image(
|
||||
os.path.join(temp_dir, "suite-large.jpg"),
|
||||
width=1200,
|
||||
height=800,
|
||||
)
|
||||
dialog = ProductSuitePreviewDialog(image_path, "商品原图预览")
|
||||
self.addCleanup(dialog.close)
|
||||
dialog.resize(600, 450)
|
||||
dialog.show()
|
||||
QApplication.processEvents()
|
||||
dialog._resize_timer.stop()
|
||||
dialog._render()
|
||||
|
||||
fit_pixmap = dialog.image_label.pixmap()
|
||||
viewport = dialog.scroll.viewport().size()
|
||||
self.assertTrue(dialog.fit_to_window)
|
||||
self.assertEqual("适应窗口", dialog.zoom_label.text())
|
||||
self.assertIn("1200x800", dialog.windowTitle())
|
||||
self.assertLessEqual(fit_pixmap.width(), viewport.width())
|
||||
self.assertLessEqual(fit_pixmap.height(), viewport.height())
|
||||
self.assertAlmostEqual(1.5, fit_pixmap.width() / fit_pixmap.height(), places=1)
|
||||
|
||||
dialog.show_actual_size()
|
||||
QApplication.processEvents()
|
||||
self.assertFalse(dialog.fit_to_window)
|
||||
self.assertEqual("100%", dialog.zoom_label.text())
|
||||
self.assertEqual(QSize(1200, 800), dialog.image_label.pixmap().size())
|
||||
self.assertEqual(QSize(1200, 800), dialog.image_label.size())
|
||||
self.assertGreater(dialog.scroll.horizontalScrollBar().maximum(), 0)
|
||||
self.assertGreater(dialog.scroll.verticalScrollBar().maximum(), 0)
|
||||
|
||||
dialog.resize(520, 360)
|
||||
QApplication.processEvents()
|
||||
dialog._resize_timer.stop()
|
||||
dialog._render()
|
||||
self.assertEqual(QSize(1200, 800), dialog.image_label.pixmap().size())
|
||||
|
||||
dialog.show_fit()
|
||||
self.assertTrue(dialog.fit_to_window)
|
||||
self.assertEqual("适应窗口", dialog.zoom_label.text())
|
||||
self.assertLessEqual(
|
||||
dialog.image_label.pixmap().width(),
|
||||
dialog.scroll.viewport().width(),
|
||||
)
|
||||
self.assertLessEqual(
|
||||
dialog.image_label.pixmap().height(),
|
||||
dialog.scroll.viewport().height(),
|
||||
)
|
||||
|
||||
self.assert_removed(temp_dir)
|
||||
|
||||
def test_shared_image_preview_bounds_zoom_and_does_not_enlarge_small_fit_image(self):
|
||||
with self.make_temp_dir() as temp_dir:
|
||||
image_path = self.write_test_image(
|
||||
os.path.join(temp_dir, "suite-small.jpg"),
|
||||
width=200,
|
||||
height=100,
|
||||
)
|
||||
dialog = ProductSuitePreviewDialog(image_path, "图片预览")
|
||||
self.addCleanup(dialog.close)
|
||||
dialog.resize(700, 500)
|
||||
dialog.show()
|
||||
QApplication.processEvents()
|
||||
dialog._resize_timer.stop()
|
||||
dialog._render()
|
||||
|
||||
self.assertEqual(QSize(200, 100), dialog.image_label.pixmap().size())
|
||||
for _index in range(20):
|
||||
dialog.zoom_out()
|
||||
self.assertEqual(0.25, dialog.zoom_factor)
|
||||
self.assertEqual("25%", dialog.zoom_label.text())
|
||||
self.assertFalse(dialog.zoom_out_button.isEnabled())
|
||||
|
||||
for _index in range(20):
|
||||
dialog.zoom_in()
|
||||
self.assertEqual(4.0, dialog.zoom_factor)
|
||||
self.assertEqual("400%", dialog.zoom_label.text())
|
||||
self.assertFalse(dialog.zoom_in_button.isEnabled())
|
||||
self.assertEqual(QSize(800, 400), dialog.image_label.pixmap().size())
|
||||
|
||||
self.assert_removed(temp_dir)
|
||||
|
||||
def test_shared_image_preview_legacy_wrapper_and_missing_file_state(self):
|
||||
with self.make_temp_dir() as temp_dir:
|
||||
image_path = self.write_test_image(
|
||||
os.path.join(temp_dir, "legacy.jpg"),
|
||||
width=320,
|
||||
height=240,
|
||||
)
|
||||
asset = SimpleNamespace(id=7, kind="original", local_path=image_path)
|
||||
legacy = ImageStudioPreviewDialog(asset)
|
||||
self.addCleanup(legacy.close)
|
||||
legacy.show()
|
||||
QApplication.processEvents()
|
||||
legacy._resize_timer.stop()
|
||||
legacy._render()
|
||||
|
||||
self.assertIn("AI工场图片预览", legacy.windowTitle())
|
||||
self.assertIn("320x240", legacy.windowTitle())
|
||||
self.assertEqual("适应窗口", legacy.zoom_label.text())
|
||||
|
||||
missing_path = os.path.join(temp_dir, "missing-private-name.jpg")
|
||||
missing = ProductSuitePreviewDialog(missing_path, "商品原图预览")
|
||||
self.addCleanup(missing.close)
|
||||
missing._render()
|
||||
self.assertEqual("图片文件不存在或无法读取", missing.image_label.text())
|
||||
self.assertEqual("无法预览", missing.zoom_label.text())
|
||||
self.assertFalse(missing.fit_button.isEnabled())
|
||||
self.assertFalse(missing.actual_size_button.isEnabled())
|
||||
self.assertNotIn(missing_path, missing.windowTitle())
|
||||
|
||||
self.assert_removed(temp_dir)
|
||||
|
||||
def test_cover_gallery_previous_next_switch_visible_tasks_without_resizing(self):
|
||||
with self.make_temp_dir() as temp_dir:
|
||||
cfg, account, tasks, canonicals, _archives = self._cover_gallery_task_set(temp_dir, count=3)
|
||||
|
||||
Reference in New Issue
Block a user