增加部分log日志文件处理
Showing
1 changed file
with
146 additions
and
96 deletions
| ... | @@ -379,7 +379,8 @@ class HistoryManager: | ... | @@ -379,7 +379,8 @@ class HistoryManager: |
| 379 | # 保存生成的图片 - 使用PNG格式验证 | 379 | # 保存生成的图片 - 使用PNG格式验证 |
| 380 | generated_image_path = record_dir / "generated.png" | 380 | generated_image_path = record_dir / "generated.png" |
| 381 | if not save_png_with_validation(str(generated_image_path), image_bytes): | 381 | if not save_png_with_validation(str(generated_image_path), image_bytes): |
| 382 | # Pillow处理失败,回退到原始方法 | 382 | # |
| 383 | # ¬,回退到原始方法 | ||
| 383 | with open(generated_image_path, 'wb') as f: | 384 | with open(generated_image_path, 'wb') as f: |
| 384 | f.write(image_bytes) | 385 | f.write(image_bytes) |
| 385 | self.logger.warning(f"使用原始保存方法: {generated_image_path}") | 386 | self.logger.warning(f"使用原始保存方法: {generated_image_path}") |
| ... | @@ -1679,6 +1680,7 @@ class ImageGeneratorWindow(QMainWindow): | ... | @@ -1679,6 +1680,7 @@ class ImageGeneratorWindow(QMainWindow): |
| 1679 | 1680 | ||
| 1680 | def upload_images(self): | 1681 | def upload_images(self): |
| 1681 | """Upload reference images""" | 1682 | """Upload reference images""" |
| 1683 | self.logger.info("开始上传参考图片") | ||
| 1682 | files, _ = QFileDialog.getOpenFileNames( | 1684 | files, _ = QFileDialog.getOpenFileNames( |
| 1683 | self, | 1685 | self, |
| 1684 | "选择参考图片", | 1686 | "选择参考图片", |
| ... | @@ -1687,134 +1689,205 @@ class ImageGeneratorWindow(QMainWindow): | ... | @@ -1687,134 +1689,205 @@ class ImageGeneratorWindow(QMainWindow): |
| 1687 | ) | 1689 | ) |
| 1688 | 1690 | ||
| 1689 | if files: | 1691 | if files: |
| 1692 | self.logger.info(f"选择了 {len(files)} 个文件: {files}") | ||
| 1693 | valid_count = 0 | ||
| 1690 | for file_path in files: | 1694 | for file_path in files: |
| 1691 | try: | 1695 | try: |
| 1696 | if self.validate_image_file(file_path): | ||
| 1692 | self.uploaded_images.append(file_path) | 1697 | self.uploaded_images.append(file_path) |
| 1698 | valid_count += 1 | ||
| 1699 | self.logger.info(f"成功添加图片: {file_path}") | ||
| 1700 | else: | ||
| 1701 | self.logger.warning(f"图片验证失败: {file_path}") | ||
| 1693 | except Exception as e: | 1702 | except Exception as e: |
| 1703 | self.logger.error(f"加载图片失败: {file_path}, 错误: {str(e)}", exc_info=True) | ||
| 1694 | QMessageBox.critical(self, "错误", f"无法加载图片: {file_path}\n{str(e)}") | 1704 | QMessageBox.critical(self, "错误", f"无法加载图片: {file_path}\n{str(e)}") |
| 1695 | 1705 | ||
| 1696 | self.update_image_preview() | 1706 | self.update_image_preview() |
| 1697 | self.image_count_label.setText(f"已选择 {len(self.uploaded_images)} 张") | 1707 | self.image_count_label.setText(f"已选择 {len(self.uploaded_images)} 张") |
| 1698 | self.status_label.setText(f"● 已添加 {len(files)} 张参考图片") | 1708 | self.status_label.setText(f"● 已添加 {valid_count} 张参考图片") |
| 1699 | self.status_label.setStyleSheet("QLabel { color: #34C759; }") | 1709 | self.status_label.setStyleSheet("QLabel { color: #34C759; }") |
| 1710 | self.logger.info(f"图片上传完成,有效图片: {valid_count} 张") | ||
| 1711 | else: | ||
| 1712 | self.logger.info("用户取消了图片选择") | ||
| 1700 | 1713 | ||
| 1701 | def add_image_files(self, file_paths): | 1714 | def add_image_files(self, file_paths): |
| 1702 | """添加图像文件到上传列表(用于拖拽功能)""" | 1715 | """添加图像文件到上传列表(用于拖拽功能)""" |
| 1716 | self.logger.info(f"开始处理拖拽文件,共 {len(file_paths) if file_paths else 0} 个") | ||
| 1703 | if not file_paths: | 1717 | if not file_paths: |
| 1718 | self.logger.warning("拖拽文件列表为空") | ||
| 1704 | return | 1719 | return |
| 1705 | 1720 | ||
| 1706 | added_count = 0 | 1721 | added_count = 0 |
| 1707 | for file_path in file_paths: | 1722 | for file_path in file_paths: |
| 1723 | self.logger.info(f"处理拖拽文件: {file_path}") | ||
| 1708 | try: | 1724 | try: |
| 1709 | if self.validate_image_file(file_path): | 1725 | if self.validate_image_file(file_path): |
| 1710 | self.uploaded_images.append(file_path) | 1726 | self.uploaded_images.append(file_path) |
| 1711 | added_count += 1 | 1727 | added_count += 1 |
| 1728 | self.logger.info(f"成功添加拖拽图片: {file_path}") | ||
| 1712 | else: | 1729 | else: |
| 1713 | self.logger.warning(f"无效的图像文件: {file_path}") | 1730 | self.logger.warning(f"无效的图像文件: {file_path}") |
| 1714 | except Exception as e: | 1731 | except Exception as e: |
| 1715 | self.logger.error(f"添加图片失败: {file_path}, 错误: {str(e)}") | 1732 | self.logger.error(f"添加图片失败: {file_path}, 错误: {str(e)}", exc_info=True) |
| 1716 | 1733 | ||
| 1717 | if added_count > 0: | 1734 | if added_count > 0: |
| 1735 | self.logger.info(f"拖拽添加成功,共 {added_count} 张图片") | ||
| 1718 | self.update_image_preview() | 1736 | self.update_image_preview() |
| 1719 | self.image_count_label.setText(f"已选择 {len(self.uploaded_images)} 张") | 1737 | self.image_count_label.setText(f"已选择 {len(self.uploaded_images)} 张") |
| 1720 | self.status_label.setText(f"● 已通过拖拽添加 {added_count} 张参考图片") | 1738 | self.status_label.setText(f"● 已通过拖拽添加 {added_count} 张参考图片") |
| 1721 | self.status_label.setStyleSheet("QLabel { color: #34C759; }") | 1739 | self.status_label.setStyleSheet("QLabel { color: #34C759; }") |
| 1722 | else: | 1740 | else: |
| 1741 | self.logger.warning("没有找到有效的拖拽图片文件") | ||
| 1723 | QMessageBox.warning(self, "警告", "没有找到有效的图片文件") | 1742 | QMessageBox.warning(self, "警告", "没有找到有效的图片文件") |
| 1724 | 1743 | ||
| 1725 | def add_clipboard_image(self, image): | 1744 | def add_clipboard_image(self, image): |
| 1726 | """添加剪贴板图像(用于拖拽和粘贴功能)""" | 1745 | """添加剪贴板图像(用于拖拽和粘贴功能)""" |
| 1727 | try: | 1746 | try: |
| 1747 | self.logger.info("开始处理剪贴板图像") | ||
| 1728 | # 生成临时文件名 | 1748 | # 生成临时文件名 |
| 1729 | timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") | 1749 | timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") |
| 1730 | temp_dir = Path(tempfile.gettempdir()) / "nano_banana_app" | 1750 | temp_dir = Path(tempfile.gettempdir()) / "nano_banana_app" |
| 1731 | temp_dir.mkdir(exist_ok=True) | 1751 | temp_dir.mkdir(exist_ok=True) |
| 1752 | self.logger.info(f"临时目录: {temp_dir}") | ||
| 1732 | 1753 | ||
| 1733 | # 根据图像格式选择文件扩展名 | 1754 | # 统一使用PNG格式保存,确保跨平台兼容 |
| 1734 | file_extension = ".png" # 默认使用PNG格式 | 1755 | file_extension = ".png" |
| 1735 | if image.format() == QImage.Format_RGB32: | ||
| 1736 | file_extension = ".bmp" | ||
| 1737 | elif image.format() == QImage.Format_RGB888: | ||
| 1738 | file_extension = ".jpg" | ||
| 1739 | |||
| 1740 | temp_file_path = temp_dir / f"clipboard_{timestamp}{file_extension}" | 1756 | temp_file_path = temp_dir / f"clipboard_{timestamp}{file_extension}" |
| 1741 | 1757 | ||
| 1742 | # 保存图像到临时文件 | 1758 | # 尝试多种保存方式,确保兼容性 |
| 1743 | if image.save(str(temp_file_path)): | 1759 | success = False |
| 1760 | try: | ||
| 1761 | # 方法1: 指定PNG格式 | ||
| 1762 | success = image.save(str(temp_file_path), "PNG") | ||
| 1763 | self.logger.info(f"方法1保存结果: {success}") | ||
| 1764 | except: | ||
| 1765 | try: | ||
| 1766 | # 方法2: 自动格式 | ||
| 1767 | success = image.save(str(temp_file_path)) | ||
| 1768 | self.logger.info(f"方法2保存结果: {success}") | ||
| 1769 | except: | ||
| 1770 | # 方法3: 转换格式再保存 | ||
| 1771 | converted_image = QImage(image) | ||
| 1772 | success = converted_image.save(str(temp_file_path), "PNG") | ||
| 1773 | self.logger.info(f"方法3保存结果: {success}") | ||
| 1774 | |||
| 1775 | if success and temp_file_path.exists(): | ||
| 1744 | self.uploaded_images.append(str(temp_file_path)) | 1776 | self.uploaded_images.append(str(temp_file_path)) |
| 1745 | self.update_image_preview() | 1777 | self.update_image_preview() |
| 1746 | self.image_count_label.setText(f"已选择 {len(self.uploaded_images)} 张") | 1778 | self.image_count_label.setText(f"已选择 {len(self.uploaded_images)} 张") |
| 1747 | self.status_label.setText("● 已添加剪贴板图片") | 1779 | self.status_label.setText("● 已添加剪贴板图片") |
| 1748 | self.status_label.setStyleSheet("QLabel { color: #34C759; }") | 1780 | self.status_label.setStyleSheet("QLabel { color: #34C759; }") |
| 1749 | self.logger.info(f"剪贴板图片已保存到: {temp_file_path}") | 1781 | self.logger.info(f"剪贴板图片已成功保存到: {temp_file_path}") |
| 1750 | else: | 1782 | else: |
| 1783 | self.logger.error("图片保存失败") | ||
| 1751 | QMessageBox.critical(self, "错误", "无法保存剪贴板图片") | 1784 | QMessageBox.critical(self, "错误", "无法保存剪贴板图片") |
| 1752 | 1785 | ||
| 1753 | except Exception as e: | 1786 | except Exception as e: |
| 1754 | self.logger.error(f"添加剪贴板图片失败: {str(e)}") | 1787 | self.logger.error(f"添加剪贴板图片失败: {str(e)}", exc_info=True) |
| 1755 | QMessageBox.critical(self, "错误", f"添加剪贴板图片失败: {str(e)}") | 1788 | QMessageBox.critical(self, "错误", f"添加剪贴板图片失败: {str(e)}") |
| 1756 | 1789 | ||
| 1757 | def paste_from_clipboard(self): | 1790 | def paste_from_clipboard(self): |
| 1758 | """从剪贴板粘贴图像""" | 1791 | """从剪贴板粘贴图像""" |
| 1792 | try: | ||
| 1793 | self.logger.info("开始粘贴剪贴板图片") | ||
| 1759 | clipboard = QApplication.clipboard() | 1794 | clipboard = QApplication.clipboard() |
| 1760 | 1795 | ||
| 1796 | # 获取剪贴板MIME数据 | ||
| 1797 | mime_data = clipboard.mimeData() | ||
| 1798 | self.logger.info(f"剪贴板MIME类型: {[mime for mime in mime_data.formats()]}") | ||
| 1799 | |||
| 1761 | # 检查剪贴板中是否有图像 | 1800 | # 检查剪贴板中是否有图像 |
| 1762 | if clipboard.mimeData().hasImage(): | 1801 | if mime_data.hasImage(): |
| 1802 | self.logger.info("检测到剪贴板中有图像数据") | ||
| 1763 | image = clipboard.image() | 1803 | image = clipboard.image() |
| 1804 | |||
| 1764 | if not image.isNull(): | 1805 | if not image.isNull(): |
| 1806 | self.logger.info(f"图像尺寸: {image.width()}x{image.height()}, 格式: {image.format()}") | ||
| 1765 | self.add_clipboard_image(image) | 1807 | self.add_clipboard_image(image) |
| 1766 | else: | 1808 | else: |
| 1809 | self.logger.warning("剪贴板图像为空") | ||
| 1767 | QMessageBox.information(self, "信息", "剪贴板中没有有效的图片") | 1810 | QMessageBox.information(self, "信息", "剪贴板中没有有效的图片") |
| 1768 | else: | 1811 | else: |
| 1812 | self.logger.warning(f"剪贴板中没有图像,可用格式: {mime_data.formats()}") | ||
| 1769 | QMessageBox.information(self, "信息", "剪贴板中没有图片,请先复制一张图片") | 1813 | QMessageBox.information(self, "信息", "剪贴板中没有图片,请先复制一张图片") |
| 1770 | 1814 | ||
| 1815 | except Exception as e: | ||
| 1816 | self.logger.error(f"粘贴剪贴板图片时发生错误: {str(e)}", exc_info=True) | ||
| 1817 | QMessageBox.critical(self, "错误", f"粘贴失败: {str(e)}") | ||
| 1818 | |||
| 1771 | def validate_image_file(self, file_path: str) -> bool: | 1819 | def validate_image_file(self, file_path: str) -> bool: |
| 1772 | """验证图像文件""" | 1820 | """验证图像文件""" |
| 1821 | self.logger.info(f"开始验证图像文件: {file_path}") | ||
| 1773 | try: | 1822 | try: |
| 1774 | # 检查文件是否存在 | 1823 | # 检查文件是否存在 |
| 1775 | if not Path(file_path).exists(): | 1824 | if not Path(file_path).exists(): |
| 1825 | self.logger.warning(f"文件不存在: {file_path}") | ||
| 1776 | return False | 1826 | return False |
| 1777 | 1827 | ||
| 1778 | # 检查文件扩展名 | 1828 | # 检查文件扩展名 |
| 1779 | valid_extensions = {'.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp'} | 1829 | valid_extensions = {'.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp'} |
| 1780 | if Path(file_path).suffix.lower() not in valid_extensions: | 1830 | file_extension = Path(file_path).suffix.lower() |
| 1831 | if file_extension not in valid_extensions: | ||
| 1832 | self.logger.warning(f"不支持的文件格式: {file_extension}, 文件: {file_path}") | ||
| 1781 | return False | 1833 | return False |
| 1782 | 1834 | ||
| 1783 | # 尝试加载图像以验证文件完整性 | 1835 | # 检查文件大小 |
| 1784 | pixmap = QPixmap(file_path) | ||
| 1785 | if pixmap.isNull(): | ||
| 1786 | return False | ||
| 1787 | |||
| 1788 | # 检查文件大小(限制为10MB) | ||
| 1789 | file_size = Path(file_path).stat().st_size | 1836 | file_size = Path(file_path).stat().st_size |
| 1837 | self.logger.info(f"文件大小: {file_size} bytes, 格式: {file_extension}") | ||
| 1838 | |||
| 1790 | if file_size > 10 * 1024 * 1024: # 10MB | 1839 | if file_size > 10 * 1024 * 1024: # 10MB |
| 1840 | self.logger.warning(f"文件过大: {file_size} bytes, 文件: {file_path}") | ||
| 1791 | QMessageBox.warning(self, "警告", f"图片文件过大: {file_path}\n请选择小于10MB的图片") | 1841 | QMessageBox.warning(self, "警告", f"图片文件过大: {file_path}\n请选择小于10MB的图片") |
| 1792 | return False | 1842 | return False |
| 1793 | 1843 | ||
| 1844 | if file_size == 0: | ||
| 1845 | self.logger.warning(f"文件为空: {file_path}") | ||
| 1846 | return False | ||
| 1847 | |||
| 1848 | # 尝试加载图像以验证文件完整性 | ||
| 1849 | self.logger.info(f"尝试加载图片验证完整性: {file_path}") | ||
| 1850 | pixmap = QPixmap(file_path) | ||
| 1851 | if pixmap.isNull(): | ||
| 1852 | self.logger.error(f"图片加载失败或损坏: {file_path}") | ||
| 1853 | return False | ||
| 1854 | |||
| 1855 | self.logger.info(f"图片验证成功,尺寸: {pixmap.width()}x{pixmap.height()}, 文件: {file_path}") | ||
| 1794 | return True | 1856 | return True |
| 1795 | 1857 | ||
| 1796 | except Exception as e: | 1858 | except Exception as e: |
| 1797 | self.logger.error(f"图像文件验证失败: {file_path}, 错误: {str(e)}") | 1859 | self.logger.error(f"图像文件验证异常: {file_path}, 错误: {str(e)}", exc_info=True) |
| 1798 | return False | 1860 | return False |
| 1799 | 1861 | ||
| 1800 | def keyPressEvent(self, event): | 1862 | def keyPressEvent(self, event): |
| 1801 | """处理键盘事件""" | 1863 | """处理键盘事件""" |
| 1864 | # 检测键盘组合键 | ||
| 1865 | key_text = event.text() | ||
| 1866 | key_int = event.key() | ||
| 1867 | modifiers = event.modifiers() | ||
| 1868 | self.logger.info(f"键盘事件: key={key_int}, text='{key_text}', modifiers={modifiers}") | ||
| 1869 | |||
| 1802 | # Ctrl+V 粘贴 | 1870 | # Ctrl+V 粘贴 |
| 1803 | if event.key() == Qt.Key_V and event.modifiers() == Qt.ControlModifier: | 1871 | if event.key() == Qt.Key_V and event.modifiers() == Qt.ControlModifier: |
| 1872 | self.logger.info("检测到 Ctrl+V 粘贴组合键") | ||
| 1804 | self.paste_from_clipboard() | 1873 | self.paste_from_clipboard() |
| 1805 | event.accept() | 1874 | event.accept() |
| 1806 | return | 1875 | return |
| 1807 | 1876 | ||
| 1808 | # Cmd+V 粘贴 (macOS) | 1877 | # Cmd+V 粘贴 (macOS) |
| 1809 | elif event.key() == Qt.Key_V and event.modifiers() == Qt.MetaModifier: | 1878 | elif event.key() == Qt.Key_V and event.modifiers() == Qt.MetaModifier: |
| 1879 | self.logger.info("检测到 Cmd+V 粘贴组合键 (macOS)") | ||
| 1810 | self.paste_from_clipboard() | 1880 | self.paste_from_clipboard() |
| 1811 | event.accept() | 1881 | event.accept() |
| 1812 | return | 1882 | return |
| 1813 | 1883 | ||
| 1884 | self.logger.debug(f"未处理的键盘事件: {key_text}") | ||
| 1814 | super().keyPressEvent(event) | 1885 | super().keyPressEvent(event) |
| 1815 | 1886 | ||
| 1816 | def update_image_preview(self): | 1887 | def update_image_preview(self): |
| 1817 | """Update image preview thumbnails""" | 1888 | """Update image preview thumbnails""" |
| 1889 | self.logger.info(f"更新图片预览,共 {len(self.uploaded_images)} 张图片") | ||
| 1890 | try: | ||
| 1818 | # Clear existing previews | 1891 | # Clear existing previews |
| 1819 | while self.img_layout.count() > 1: # Keep the stretch | 1892 | while self.img_layout.count() > 1: # Keep the stretch |
| 1820 | item = self.img_layout.takeAt(0) | 1893 | item = self.img_layout.takeAt(0) |
| ... | @@ -1823,10 +1896,16 @@ class ImageGeneratorWindow(QMainWindow): | ... | @@ -1823,10 +1896,16 @@ class ImageGeneratorWindow(QMainWindow): |
| 1823 | 1896 | ||
| 1824 | # Add thumbnails | 1897 | # Add thumbnails |
| 1825 | for idx, file_path in enumerate(self.uploaded_images): | 1898 | for idx, file_path in enumerate(self.uploaded_images): |
| 1899 | self.logger.info(f"创建第 {idx + 1} 张图片缩略图: {file_path}") | ||
| 1826 | try: | 1900 | try: |
| 1827 | # Load and create thumbnail | 1901 | # Load and create thumbnail |
| 1828 | pixmap = QPixmap(file_path) | 1902 | pixmap = QPixmap(file_path) |
| 1903 | if pixmap.isNull(): | ||
| 1904 | self.logger.warning(f"无法加载图片进行预览: {file_path}") | ||
| 1905 | continue | ||
| 1906 | |||
| 1829 | pixmap = pixmap.scaled(100, 100, Qt.KeepAspectRatio, Qt.SmoothTransformation) | 1907 | pixmap = pixmap.scaled(100, 100, Qt.KeepAspectRatio, Qt.SmoothTransformation) |
| 1908 | self.logger.info(f"缩略图创建成功: {pixmap.width()}x{pixmap.height()}") | ||
| 1830 | 1909 | ||
| 1831 | # Container | 1910 | # Container |
| 1832 | container = QWidget() | 1911 | container = QWidget() |
| ... | @@ -1868,17 +1947,27 @@ class ImageGeneratorWindow(QMainWindow): | ... | @@ -1868,17 +1947,27 @@ class ImageGeneratorWindow(QMainWindow): |
| 1868 | container.setLayout(container_layout) | 1947 | container.setLayout(container_layout) |
| 1869 | 1948 | ||
| 1870 | self.img_layout.insertWidget(self.img_layout.count() - 1, container) | 1949 | self.img_layout.insertWidget(self.img_layout.count() - 1, container) |
| 1950 | self.logger.info(f"缩略图UI组件创建完成: {file_path}") | ||
| 1951 | |||
| 1952 | except Exception as e: | ||
| 1953 | self.logger.error(f"创建缩略图失败: {file_path}, 错误: {str(e)}", exc_info=True) | ||
| 1954 | |||
| 1871 | except Exception as e: | 1955 | except Exception as e: |
| 1872 | print(f"Failed to create thumbnail for {file_path}: {e}") | 1956 | self.logger.error(f"更新图片预览失败: {str(e)}", exc_info=True) |
| 1873 | 1957 | ||
| 1874 | def delete_image(self, index): | 1958 | def delete_image(self, index): |
| 1875 | """Delete an image by index""" | 1959 | """Delete an image by index""" |
| 1960 | self.logger.info(f"尝试删除第 {index + 1} 张图片") | ||
| 1876 | if 0 <= index < len(self.uploaded_images): | 1961 | if 0 <= index < len(self.uploaded_images): |
| 1962 | deleted_file = self.uploaded_images[index] | ||
| 1877 | self.uploaded_images.pop(index) | 1963 | self.uploaded_images.pop(index) |
| 1964 | self.logger.info(f"已删除图片: {deleted_file}") | ||
| 1878 | self.update_image_preview() | 1965 | self.update_image_preview() |
| 1879 | self.image_count_label.setText(f"已选择 {len(self.uploaded_images)} 张") | 1966 | self.image_count_label.setText(f"已选择 {len(self.uploaded_images)} 张") |
| 1880 | self.status_label.setText("● 已删除图片") | 1967 | self.status_label.setText("● 已删除图片") |
| 1881 | self.status_label.setStyleSheet("QLabel { color: #FF9500; }") | 1968 | self.status_label.setStyleSheet("QLabel { color: #FF9500; }") |
| 1969 | else: | ||
| 1970 | self.logger.warning(f"无效的图片索引: {index}") | ||
| 1882 | 1971 | ||
| 1883 | def update_saved_prompts_list(self): | 1972 | def update_saved_prompts_list(self): |
| 1884 | """Update the saved prompts dropdown""" | 1973 | """Update the saved prompts dropdown""" |
| ... | @@ -2749,98 +2838,57 @@ class JewelryLibraryManager: | ... | @@ -2749,98 +2838,57 @@ class JewelryLibraryManager: |
| 2749 | self.logger = logging.getLogger(__name__) | 2838 | self.logger = logging.getLogger(__name__) |
| 2750 | self.config_dir = config_dir | 2839 | self.config_dir = config_dir |
| 2751 | self.config_path = config_dir / "jewelry_library.json" | 2840 | self.config_path = config_dir / "jewelry_library.json" |
| 2752 | # 获取默认词库文件的路径 | ||
| 2753 | self.default_library_path = Path(__file__).parent / "data" / "default_jewelry_library.json" | ||
| 2754 | self.library = self.load_library() | 2841 | self.library = self.load_library() |
| 2755 | 2842 | ||
| 2756 | def load_library(self) -> Dict[str, List[str]]: | 2843 | def load_library(self) -> Dict[str, List[str]]: |
| 2757 | """加载词库,不存在则创建默认词库""" | 2844 | """加载词库,优先使用用户配置,不存在则使用默认词库""" |
| 2758 | if self.config_path.exists(): | 2845 | if self.config_path.exists(): |
| 2759 | try: | 2846 | try: |
| 2760 | with open(self.config_path, 'r', encoding='utf-8') as f: | 2847 | with open(self.config_path, 'r', encoding='utf-8') as f: |
| 2761 | library = json.load(f) | 2848 | library = json.load(f) |
| 2762 | 2849 | ||
| 2763 | # 检查是否需要进行数据迁移 | 2850 | # 验证数据完整性,补全缺失的类别 |
| 2764 | library = self._migrate_library_if_needed(library) | 2851 | needs_update = False |
| 2852 | for category, default_items in DEFAULT_JEWELRY_LIBRARY.items(): | ||
| 2853 | if category not in library: | ||
| 2854 | self.logger.warning(f"检测到缺失类别: {category},从默认配置补全") | ||
| 2855 | library[category] = default_items.copy() | ||
| 2856 | needs_update = True | ||
| 2857 | elif not library[category] or len(library[category]) == 0: | ||
| 2858 | self.logger.warning(f"检测到空类别: {category},从默认配置补全") | ||
| 2859 | library[category] = default_items.copy() | ||
| 2860 | needs_update = True | ||
| 2861 | elif len(library[category]) < len(default_items) * 0.5: | ||
| 2862 | # 如果类别数据量少于默认值的50%,认为数据不完整,使用默认数据 | ||
| 2863 | self.logger.warning(f"检测到类别 {category} 数据不完整(仅{len(library[category])}项,默认{len(default_items)}项),从默认配置补全") | ||
| 2864 | library[category] = default_items.copy() | ||
| 2865 | needs_update = True | ||
| 2866 | |||
| 2867 | # 如果数据被补全,保存更新后的配置 | ||
| 2868 | if needs_update: | ||
| 2869 | self.logger.info("词库数据已补全,保存更新") | ||
| 2870 | self.save_library(library) | ||
| 2765 | 2871 | ||
| 2766 | self.logger.info(f"珠宝词库加载成功: {self.config_path}") | 2872 | self.logger.info(f"珠宝词库加载成功: {self.config_path}") |
| 2767 | return library | 2873 | return library |
| 2768 | except Exception as e: | 2874 | except Exception as e: |
| 2769 | self.logger.error(f"珠宝词库加载失败: {e},使用默认词库") | 2875 | self.logger.error(f"珠宝词库加载失败: {e},使用默认词库") |
| 2770 | return DEFAULT_JEWELRY_LIBRARY.copy() | ||
| 2771 | else: | ||
| 2772 | # 首次使用,创建默认词库 | ||
| 2773 | self.logger.info("未找到珠宝词库文件,创建默认词库") | ||
| 2774 | library = DEFAULT_JEWELRY_LIBRARY.copy() | 2876 | library = DEFAULT_JEWELRY_LIBRARY.copy() |
| 2877 | # 尝试保存默认配置,覆盖损坏的文件 | ||
| 2878 | try: | ||
| 2775 | self.save_library(library) | 2879 | self.save_library(library) |
| 2880 | except: | ||
| 2881 | pass | ||
| 2776 | return library | 2882 | return library |
| 2777 | 2883 | else: | |
| 2778 | def _migrate_library_if_needed(self, library: Dict[str, List[str]]) -> Dict[str, List[str]]: | 2884 | # 首次使用,从代码中的默认配置创建用户配置文件 |
| 2779 | """检查并执行数据迁移""" | 2885 | self.logger.info("首次使用,创建用户配置文件") |
| 2780 | # 如果存在旧的"主石"字段,需要拆分 | 2886 | library = DEFAULT_JEWELRY_LIBRARY.copy() |
| 2781 | if "主石" in library: | ||
| 2782 | self.logger.info("检测到旧版主石字段,执行数据迁移...") | ||
| 2783 | |||
| 2784 | # 创建新字段 | ||
| 2785 | shapes = [] | ||
| 2786 | materials = [] | ||
| 2787 | |||
| 2788 | # 分析现有数据 | ||
| 2789 | for item in library["主石"]: | ||
| 2790 | # 提取形状信息 | ||
| 2791 | shape = self._extract_shape(item) | ||
| 2792 | if shape and shape not in shapes: | ||
| 2793 | shapes.append(shape) | ||
| 2794 | |||
| 2795 | # 提取材质信息 | ||
| 2796 | material = self._extract_material(item) | ||
| 2797 | if material and material not in materials: | ||
| 2798 | materials.append(material) | ||
| 2799 | |||
| 2800 | # 更新词库 | ||
| 2801 | library["主石形状"] = shapes if shapes else DEFAULT_JEWELRY_LIBRARY["主石形状"] | ||
| 2802 | library["主石材质"] = materials if materials else DEFAULT_JEWELRY_LIBRARY["主石材质"] | ||
| 2803 | |||
| 2804 | # 保留旧字段作为备份 | ||
| 2805 | # library.pop("主石", None) # 可以选择是否移除 | ||
| 2806 | |||
| 2807 | # 保存迁移后的数据 | ||
| 2808 | self.save_library(library) | 2887 | self.save_library(library) |
| 2809 | self.logger.info(f"数据迁移完成:形状 {len(shapes)} 个,材质 {len(materials)} 个") | ||
| 2810 | |||
| 2811 | return library | 2888 | return library |
| 2812 | 2889 | ||
| 2813 | def _extract_shape(self, item: str) -> Optional[str]: | ||
| 2814 | """从主石描述中提取形状""" | ||
| 2815 | # 直接从 DEFAULT_JEWELRY_LIBRARY 获取形状列表,确保同步 | ||
| 2816 | shapes = DEFAULT_JEWELRY_LIBRARY.get("主石形状", []) | ||
| 2817 | for shape in shapes: | ||
| 2818 | # 处理带括号的形状(如"子弹形(Baguette 子弹刻面)") | ||
| 2819 | if "(" in shape: | ||
| 2820 | shape_base = shape.split("(")[0] | ||
| 2821 | if item.startswith(shape_base): | ||
| 2822 | return shape_base | ||
| 2823 | elif item.startswith(shape): | ||
| 2824 | return shape | ||
| 2825 | return None | ||
| 2826 | |||
| 2827 | def _extract_material(self, item: str) -> Optional[str]: | ||
| 2828 | """从主石描述中提取材质""" | ||
| 2829 | # 直接从 DEFAULT_JEWELRY_LIBRARY 获取形状列表,确保同步 | ||
| 2830 | shapes = DEFAULT_JEWELRY_LIBRARY.get("主石形状", []) | ||
| 2831 | for shape in shapes: | ||
| 2832 | # 处理带括号的形状(如"子弹形(Baguette 子弹刻面)") | ||
| 2833 | shape_base = shape.split("(")[0] if "(" in shape else shape | ||
| 2834 | if item.startswith(shape_base): | ||
| 2835 | material = item[len(shape_base):] | ||
| 2836 | # 去除可能的连接词 | ||
| 2837 | if material.startswith("的"): | ||
| 2838 | material = material[1:] | ||
| 2839 | return material if material else None | ||
| 2840 | return item # 如果没有形状前缀,返回整个字符串 | ||
| 2841 | |||
| 2842 | def save_library(self, library: Dict[str, List[str]] = None): | 2890 | def save_library(self, library: Dict[str, List[str]] = None): |
| 2843 | """保存词库到配置文件 | 2891 | """保存词库到用户配置目录 |
| 2844 | 2892 | ||
| 2845 | Args: | 2893 | Args: |
| 2846 | library: 要保存的词库,如果为None则保存当前词库 | 2894 | library: 要保存的词库,如果为None则保存当前词库 |
| ... | @@ -3096,6 +3144,8 @@ class StyleDesignerTab(QWidget): | ... | @@ -3096,6 +3144,8 @@ class StyleDesignerTab(QWidget): |
| 3096 | self.prompt_preview.setReadOnly(True) | 3144 | self.prompt_preview.setReadOnly(True) |
| 3097 | prompt_layout.addWidget(self.prompt_preview) | 3145 | prompt_layout.addWidget(self.prompt_preview) |
| 3098 | prompt_group.setLayout(prompt_layout) | 3146 | prompt_group.setLayout(prompt_layout) |
| 3147 | prompt_group.setStyleSheet("font-size: 16px;") | ||
| 3148 | |||
| 3099 | content_row.addWidget(prompt_group, 2) | 3149 | content_row.addWidget(prompt_group, 2) |
| 3100 | 3150 | ||
| 3101 | # Settings section | 3151 | # Settings section | ... | ... |
-
Please register or sign in to post a comment