8b46fb30 by 柴进

清理无用代码

1 parent e554cf55
......@@ -1889,69 +1889,25 @@ class ImageGeneratorWindow(QMainWindow):
QMessageBox.warning(self, "警告", "没有找到有效的图片文件")
def add_clipboard_image(self, image):
"""添加剪贴板图像(用于拖拽和粘贴功能)"""
"""添加剪贴板图像(用于拖拽图像数据)"""
try:
self.logger.info("开始处理剪贴板图像")
# 生成临时文件名
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
temp_dir = Path(tempfile.gettempdir()) / "nano_banana_app"
temp_dir.mkdir(exist_ok=True)
self.logger.info(f"临时目录: {temp_dir}")
temp_file_path = temp_dir / f"clipboard_{timestamp}.png"
# 统一使用PNG格式保存,确保跨平台兼容
file_extension = ".png"
temp_file_path = temp_dir / f"clipboard_{timestamp}{file_extension}"
# 尝试多种保存方式,确保兼容性
self.logger.info(f"QImage信息: {image.width()}x{image.height()}, format={image.format()}, isNull={image.isNull()}")
success = False
# 方法1: 先转换为 RGB32 格式再保存(避免格式不兼容导致保存异常)
try:
normalized = image.convertToFormat(QImage.Format.Format_ARGB32)
success = normalized.save(str(temp_file_path), "PNG")
self.logger.info(f"方法1(ARGB32转换)保存结果: {success}")
except Exception as e:
self.logger.warning(f"方法1保存失败: {e}")
# 方法2: 直接保存原始格式
if not success:
try:
success = image.save(str(temp_file_path), "PNG")
self.logger.info(f"方法2(原始格式)保存结果: {success}")
except Exception as e:
self.logger.warning(f"方法2保存失败: {e}")
# 方法3: 通过 QPixmap 中转保存
normalized = image.convertToFormat(QImage.Format.Format_ARGB32)
success = normalized.save(str(temp_file_path), "PNG")
if not success:
try:
pixmap = QPixmap.fromImage(image)
success = pixmap.save(str(temp_file_path), "PNG")
self.logger.info(f"方法3(QPixmap中转)保存结果: {success}")
except Exception as e:
self.logger.warning(f"方法3保存失败: {e}")
success = image.save(str(temp_file_path), "PNG")
# 验证保存的文件确实可被加载为缩略图
if success and temp_file_path.exists():
file_size = temp_file_path.stat().st_size
self.logger.info(f"保存文件大小: {file_size} bytes")
if file_size == 0:
self.logger.error("保存的文件为空(0字节)")
success = False
if success and temp_file_path.exists():
if success and temp_file_path.exists() and temp_file_path.stat().st_size > 0:
self.uploaded_images.append(str(temp_file_path))
self.update_image_preview()
self.image_count_label.setText(f"已选择 {len(self.uploaded_images)} 张")
self.status_label.setText("● 已添加剪贴板图片")
self.status_label.setStyleSheet("QLabel { color: #34C759; }")
self.logger.info(f"剪贴板图片已成功保存到: {temp_file_path}")
# 延迟到下一个事件循环刷新预览,避免 macOS 剪贴板上下文阻塞 UI 更新
QTimer.singleShot(0, self.update_image_preview)
# 检查极速模式下的多图限制
# self.check_multi_image_mode_conflict()
else:
self.logger.error("图片保存失败")
QMessageBox.critical(self, "错误", "无法保存剪贴板图片")
except Exception as e:
......@@ -1959,42 +1915,34 @@ class ImageGeneratorWindow(QMainWindow):
QMessageBox.critical(self, "错误", f"添加剪贴板图片失败: {str(e)}")
def _safe_get_clipboard_image(self):
"""安全地从剪贴板获取图像,兼容 macOS 高低版本"""
"""安全地从剪贴板获取纯图像数据(如截图),兼容 macOS 高低版本
注意:Finder 复制的文件应通过 paste_from_clipboard 中的 hasUrls 分支处理,
不会走到这里。此方法只处理纯图像数据(截图、从应用复制的图片等)。
"""
clipboard = QApplication.clipboard()
# 方法1: 从 MIME data 的 image formats 读取原始字节构造 QImage
# 方法1: 从 MIME data 读取图像
# 避免直接调用 clipboard.image(),该方法在 macOS 26 可能导致 native crash
try:
mime_data = clipboard.mimeData()
if mime_data is None:
self.logger.warning("clipboard.mimeData() 返回 None")
else:
formats = list(mime_data.formats())
self.logger.info(f"剪贴板MIME类型: {formats}")
# 尝试从常见图像 MIME 格式读取字节数据
image_mime_types = [
"image/png", "image/jpeg", "image/bmp", "image/tiff",
"application/x-qt-image",
]
for mime_type in image_mime_types:
if mime_type in formats:
if mime_data is not None:
# 尝试从图像 MIME 格式读取原始字节
for mime_type in ("image/png", "image/jpeg", "image/bmp", "image/tiff", "application/x-qt-image"):
if mime_type in mime_data.formats():
raw_data = mime_data.data(mime_type)
if raw_data and len(raw_data) > 0:
image = QImage()
if image.loadFromData(raw_data):
self.logger.info(f"方法1成功: 从 {mime_type} 构造图像 {image.width()}x{image.height()}")
return image
# 尝试 hasImage + imageData(比 clipboard.image() 更安全)
# 尝试 hasImage + imageData
if mime_data.hasImage():
image_data = mime_data.imageData()
if image_data is not None:
if isinstance(image_data, QImage) and not image_data.isNull():
self.logger.info(f"方法1b成功: imageData() {image_data.width()}x{image_data.height()}")
return image_data
if isinstance(image_data, QImage) and not image_data.isNull():
return image_data
except Exception as e:
self.logger.warning(f"方法1 (MIME data) 失败: {e}")
self.logger.warning(f"MIME data 方式获取剪贴板图像失败: {e}")
# 方法2: macOS 专用 - 用 osascript 将剪贴板图片写入临时文件
if platform.system() == "Darwin":
......@@ -2002,7 +1950,6 @@ class ImageGeneratorWindow(QMainWindow):
import subprocess
temp_path = Path(tempfile.gettempdir()) / "nano_banana_app" / "_clipboard_tmp.png"
temp_path.parent.mkdir(exist_ok=True)
# 删除旧文件
if temp_path.exists():
temp_path.unlink()
......@@ -2020,48 +1967,38 @@ class ImageGeneratorWindow(QMainWindow):
' error "no image"\n'
'end try\n'
)
result = subprocess.run(
["osascript", "-e", script],
capture_output=True, timeout=5
)
result = subprocess.run(["osascript", "-e", script], capture_output=True, timeout=5)
if result.returncode == 0 and temp_path.exists() and temp_path.stat().st_size > 0:
image = QImage(str(temp_path))
if not image.isNull():
self.logger.info(f"方法2成功: osascript 读取剪贴板 {image.width()}x{image.height()}")
return image
except Exception as e:
self.logger.warning(f"方法2 (osascript) 失败: {e}")
self.logger.warning(f"osascript 方式获取剪贴板图像失败: {e}")
# 方法3: 最后手段 - 直接调用 clipboard.image()(低版本 macOS 可靠
# 方法3: 直接调用 clipboard.image()(低版本 macOS / Windows / Linux
try:
image = clipboard.image()
if image and not image.isNull():
self.logger.info(f"方法3成功: clipboard.image() {image.width()}x{image.height()}")
return image
except Exception as e:
self.logger.warning(f"方法3 (clipboard.image) 失败: {e}")
self.logger.warning(f"clipboard.image() 失败: {e}")
return None
def paste_from_clipboard(self):
"""从剪贴板粘贴图像"""
try:
self.logger.info("开始粘贴剪贴板图片")
clipboard = QApplication.clipboard()
mime_data = clipboard.mimeData()
# 优先处理文件URL(如 Finder 中复制的图片文件)
# 优先处理文件URL(如 Finder / 资源管理器中复制的图片文件)
if mime_data and mime_data.hasUrls():
image_files = []
for url in mime_data.urls():
if url.isLocalFile():
file_path = url.toLocalFile()
self.logger.info(f"剪贴板包含文件: {file_path}")
if Path(file_path).suffix.lower() in {'.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp'}:
image_files.append(file_path)
valid_ext = {'.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp'}
image_files = [
url.toLocalFile() for url in mime_data.urls()
if url.isLocalFile() and Path(url.toLocalFile()).suffix.lower() in valid_ext
]
if image_files:
self.logger.info(f"从剪贴板文件URL添加 {len(image_files)} 张图片")
added = 0
for fp in image_files:
if self.validate_image_file(fp):
......@@ -2074,16 +2011,12 @@ class ImageGeneratorWindow(QMainWindow):
self.status_label.setStyleSheet("QLabel { color: #34C759; }")
return
# 没有文件URL,尝试获取剪贴板中的图像数据(如截图、从应用复制的图片
# 没有文件URL,尝试获取纯图像数据(截图、从应用复制的图片等
image = self._safe_get_clipboard_image()
if image is None:
self.logger.warning("剪贴板中没有可用的图像")
QMessageBox.information(self, "信息", "剪贴板中没有图片,请先复制一张图片")
return
self.logger.info(f"成功获取剪贴板图像数据: {image.width()}x{image.height()}")
# 保存到临时文件
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S_%f")
temp_dir = Path(tempfile.gettempdir()) / "nano_banana_app"
......@@ -2093,11 +2026,9 @@ class ImageGeneratorWindow(QMainWindow):
normalized = image.convertToFormat(QImage.Format.Format_ARGB32)
if not normalized.save(temp_file_path, "PNG"):
if not image.save(temp_file_path, "PNG"):
self.logger.error("剪贴板图片保存失败")
QMessageBox.critical(self, "错误", "无法保存剪贴板图片")
return
self.logger.info(f"剪贴板图片已保存: {temp_file_path}")
self.uploaded_images.append(temp_file_path)
self.update_image_preview()
self.image_count_label.setText(f"已选择 {len(self.uploaded_images)} 张")
......@@ -2105,7 +2036,7 @@ class ImageGeneratorWindow(QMainWindow):
self.status_label.setStyleSheet("QLabel { color: #34C759; }")
except Exception as e:
self.logger.error(f"粘贴剪贴板图片时发生错误: {str(e)}", exc_info=True)
self.logger.error(f"粘贴失败: {e}", exc_info=True)
QMessageBox.critical(self, "错误", f"粘贴失败: {str(e)}")
def validate_image_file(self, file_path: str) -> bool:
......@@ -2153,53 +2084,31 @@ class ImageGeneratorWindow(QMainWindow):
def keyPressEvent(self, event):
"""处理键盘事件"""
# 检测键盘组合键
key_text = event.text()
key_int = event.key()
modifiers = event.modifiers()
self.logger.info(f"键盘事件: key={key_int}, text='{key_text}', modifiers={modifiers}")
# Ctrl+V 粘贴
if event.key() == Qt.Key_V and event.modifiers() == Qt.ControlModifier:
self.logger.info("检测到 Ctrl+V 粘贴组合键")
# Ctrl+V / Cmd+V 粘贴
if event.key() == Qt.Key_V and event.modifiers() in (Qt.ControlModifier, Qt.MetaModifier):
self.paste_from_clipboard()
event.accept()
return
# Cmd+V 粘贴 (macOS)
elif event.key() == Qt.Key_V and event.modifiers() == Qt.MetaModifier:
self.logger.info("检测到 Cmd+V 粘贴组合键 (macOS)")
self.paste_from_clipboard()
event.accept()
return
self.logger.debug(f"未处理的键盘事件: {key_text}")
super().keyPressEvent(event)
def update_image_preview(self):
"""Update image preview thumbnails"""
self.logger.info(f"更新图片预览,共 {len(self.uploaded_images)} 张图片")
try:
# Clear existing previews - 立即删除而非 deleteLater,避免布局刷新时序问题
# Clear existing previews
while self.img_layout.count() > 1: # Keep the stretch
item = self.img_layout.takeAt(0)
widget = item.widget()
if widget:
widget.setParent(None)
widget.deleteLater()
if item.widget():
item.widget().deleteLater()
# Add thumbnails
for idx, file_path in enumerate(self.uploaded_images):
self.logger.info(f"创建第 {idx + 1} 张图片缩略图: {file_path}")
try:
# Load and create thumbnail
pixmap = QPixmap(file_path)
if pixmap.isNull():
self.logger.warning(f"无法加载图片进行预览: {file_path}")
continue
pixmap = pixmap.scaled(100, 100, Qt.KeepAspectRatio, Qt.SmoothTransformation)
self.logger.info(f"缩略图创建成功: {pixmap.width()}x{pixmap.height()}")
# Container
container = QWidget()
......@@ -2241,48 +2150,10 @@ class ImageGeneratorWindow(QMainWindow):
container.setLayout(container_layout)
self.img_layout.insertWidget(self.img_layout.count() - 1, container)
container.show()
self.logger.info(f"缩略图UI组件创建完成: {file_path}")
except Exception as e:
self.logger.error(f"创建缩略图失败: {file_path}, 错误: {str(e)}", exc_info=True)
# 强制刷新布局和滚动区域
self.img_layout.activate()
self.img_container.adjustSize()
self.img_container.repaint()
self.img_scroll.viewport().repaint()
# === 诊断日志:排查缩略图不可见问题 ===
self.logger.info(f"[诊断] img_layout.count = {self.img_layout.count()}")
self.logger.info(f"[诊断] img_container.size = {self.img_container.size().width()}x{self.img_container.size().height()}")
self.logger.info(f"[诊断] img_container.isVisible = {self.img_container.isVisible()}")
self.logger.info(f"[诊断] img_scroll.size = {self.img_scroll.size().width()}x{self.img_scroll.size().height()}")
self.logger.info(f"[诊断] img_scroll.isVisible = {self.img_scroll.isVisible()}")
self.logger.info(f"[诊断] img_scroll.widget = {self.img_scroll.widget()}")
self.logger.info(f"[诊断] img_scroll.widgetResizable = {self.img_scroll.widgetResizable()}")
for i in range(self.img_layout.count()):
item = self.img_layout.itemAt(i)
w = item.widget()
if w:
self.logger.info(
f"[诊断] layout[{i}]: widget={w.__class__.__name__}, "
f"size={w.size().width()}x{w.size().height()}, "
f"sizeHint={w.sizeHint().width()}x{w.sizeHint().height()}, "
f"visible={w.isVisible()}, "
f"geometry={w.geometry()}"
)
# 检查子 widget
for child in w.findChildren(QLabel):
pm = child.pixmap()
self.logger.info(
f"[诊断] QLabel: size={child.size().width()}x{child.size().height()}, "
f"visible={child.isVisible()}, "
f"hasPixmap={pm is not None and not pm.isNull() if pm else False}"
)
else:
self.logger.info(f"[诊断] layout[{i}]: spacer/stretch")
except Exception as e:
self.logger.error(f"更新图片预览失败: {str(e)}", exc_info=True)
......