diff --git a/src/mcp_feedback_enhanced/feedback_ui.py b/src/mcp_feedback_enhanced/feedback_ui.py index 795d1e4..c0d885f 100644 --- a/src/mcp_feedback_enhanced/feedback_ui.py +++ b/src/mcp_feedback_enhanced/feedback_ui.py @@ -45,6 +45,33 @@ class FeedbackResult(TypedDict): images: List[dict] +# ===== 自定義文字輸入框 ===== +class SmartTextEdit(QTextEdit): + """支援智能 Ctrl+V 的文字輸入框""" + image_paste_requested = Signal() + + def __init__(self, parent=None): + super().__init__(parent) + + def keyPressEvent(self, event): + """處理按鍵事件,實現智能 Ctrl+V""" + if event.key() == Qt.Key_V and event.modifiers() == Qt.ControlModifier: + # 檢查剪貼簿是否有圖片 + clipboard = QApplication.clipboard() + + if clipboard.mimeData().hasImage(): + # 如果有圖片,發送信號通知主窗口處理圖片貼上 + self.image_paste_requested.emit() + # 不執行預設的文字貼上行為 + return + else: + # 如果沒有圖片,執行正常的文字貼上 + super().keyPressEvent(event) + else: + # 其他按鍵正常處理 + super().keyPressEvent(event) + + # ===== 圖片預覽元件 ===== class ImagePreviewWidget(QLabel): """圖片預覽元件""" @@ -832,9 +859,11 @@ class FeedbackWindow(QMainWindow): feedback_layout.addWidget(self.feedback_description) # 文字輸入框 - self.feedback_input = QTextEdit() + self.feedback_input = SmartTextEdit() self.feedback_input.setPlaceholderText(t('feedback_placeholder')) self.feedback_input.setMinimumHeight(120) + # 連接智能貼上信號 + self.feedback_input.image_paste_requested.connect(self._handle_image_paste_from_textarea) feedback_layout.addWidget(self.feedback_input) layout.addWidget(feedback_group, stretch=2) # 給更多空間 @@ -990,6 +1019,19 @@ class FeedbackWindow(QMainWindow): } """) + def _handle_image_paste_from_textarea(self) -> None: + """處理從文字框智能貼上圖片的功能""" + try: + # 調用圖片上傳組件的剪貼簿貼上功能 + self.image_upload.paste_from_clipboard() + + # 顯示智能貼上提示 + # 可以在這裡添加狀態提示,比如狀態欄或臨時通知 + debug_log("智能貼上:已將圖片從文字框貼到圖片區域") + + except Exception as e: + debug_log(f"智能貼上失敗: {e}") + def _run_command(self) -> None: """執行命令""" command = self.command_input.text().strip() diff --git a/src/mcp_feedback_enhanced/locales/en/translations.json b/src/mcp_feedback_enhanced/locales/en/translations.json index a6f2a29..357bf3b 100644 --- a/src/mcp_feedback_enhanced/locales/en/translations.json +++ b/src/mcp_feedback_enhanced/locales/en/translations.json @@ -20,7 +20,7 @@ "feedback": { "title": "Your Feedback", "description": "Please describe your thoughts, suggestions, or changes needed for the AI work results.", - "placeholder": "Please enter your feedback, suggestions, or questions here...\n\n💡 Tip: Press Ctrl+Enter to submit quickly" + "placeholder": "Please enter your feedback, suggestions, or questions here...\n\n💡 Tips:\n• Press Ctrl+Enter to submit quickly\n• Press Ctrl+V to paste images from clipboard" }, "command": { "title": "Command Execution", @@ -35,11 +35,16 @@ "clear": "Clear", "status": "{count} images selected", "statusWithSize": "{count} images selected (Total {size})", - "dragHint": "🎯 Drag images here (PNG, JPG, JPEG, GIF, BMP, WebP)", + "dragHint": "🎯 Drag images here or press Ctrl+V to paste from clipboard (PNG, JPG, JPEG, GIF, BMP, WebP)", "deleteConfirm": "Are you sure you want to remove image \"{filename}\"?", "deleteTitle": "Confirm Delete", "sizeWarning": "Image file size cannot exceed 1MB", - "formatError": "Unsupported image format" + "formatError": "Unsupported image format", + "paste_images": "📋 Paste from Clipboard", + "paste_failed": "Paste failed, no image in clipboard", + "paste_no_image": "No image in clipboard to paste", + "paste_image_from_textarea": "Image intelligently pasted from text area to image area", + "images_clear": "Clear all images" }, "buttons": { "submit": "Submit Feedback", diff --git a/src/mcp_feedback_enhanced/locales/zh-CN/translations.json b/src/mcp_feedback_enhanced/locales/zh-CN/translations.json index fd5a4da..41d4934 100644 --- a/src/mcp_feedback_enhanced/locales/zh-CN/translations.json +++ b/src/mcp_feedback_enhanced/locales/zh-CN/translations.json @@ -20,7 +20,7 @@ "feedback": { "title": "您的反馈", "description": "请描述您对 AI 工作结果的想法、建议或需要修改的地方。", - "placeholder": "请在这里输入您的反馈、建议或问题...\n\n💡 小提示:按 Ctrl+Enter 可快速提交反馈" + "placeholder": "请在这里输入您的反馈、建议或问题...\n\n💡 小提示:\n• 按 Ctrl+Enter 可快速提交反馈\n• 按 Ctrl+V 可直接贴上剪贴板图片" }, "command": { "title": "命令执行", @@ -35,11 +35,16 @@ "clear": "清除", "status": "已选择 {count} 张图片", "statusWithSize": "已选择 {count} 张图片 (总计 {size})", - "dragHint": "🎯 拖拽图片到这里 (PNG、JPG、JPEG、GIF、BMP、WebP)", + "dragHint": "🎯 拖拽图片到这里 或 按 Ctrl+V 贴上剪贴板图片 (PNG、JPG、JPEG、GIF、BMP、WebP)", "deleteConfirm": "确定要移除图片 \"{filename}\" 吗?", "deleteTitle": "确认删除", "sizeWarning": "图片文件大小不能超过 1MB", - "formatError": "不支持的图片格式" + "formatError": "不支持的图片格式", + "paste_images": "📋 从剪贴板粘贴", + "paste_failed": "粘贴失败,剪贴板中没有图片", + "paste_no_image": "剪贴板中没有图片可粘贴", + "paste_image_from_textarea": "已将图片从文本框智能贴到图片区域", + "images_clear": "清除所有图片" }, "buttons": { "submit": "提交反馈", diff --git a/src/mcp_feedback_enhanced/locales/zh-TW/translations.json b/src/mcp_feedback_enhanced/locales/zh-TW/translations.json index 7c35cf2..ba69ad0 100644 --- a/src/mcp_feedback_enhanced/locales/zh-TW/translations.json +++ b/src/mcp_feedback_enhanced/locales/zh-TW/translations.json @@ -20,7 +20,7 @@ "feedback": { "title": "您的回饋", "description": "請描述您對 AI 工作結果的想法、建議或需要修改的地方。", - "placeholder": "請在這裡輸入您的回饋、建議或問題...\n\n💡 小提示:按 Ctrl+Enter 可快速提交回饋" + "placeholder": "請在這裡輸入您的回饋、建議或問題...\n\n💡 小提示:\n• 按 Ctrl+Enter 可快速提交回饋\n• 按 Ctrl+V 可直接貼上剪貼簿圖片" }, "command": { "title": "命令執行", @@ -35,11 +35,16 @@ "clear": "清除", "status": "已選擇 {count} 張圖片", "statusWithSize": "已選擇 {count} 張圖片 (總計 {size})", - "dragHint": "🎯 拖拽圖片到這裡 (PNG、JPG、JPEG、GIF、BMP、WebP)", + "dragHint": "🎯 拖拽圖片到這裡 或 按 Ctrl+V 貼上剪貼簿圖片 (PNG、JPG、JPEG、GIF、BMP、WebP)", "deleteConfirm": "確定要移除圖片 \"{filename}\" 嗎?", "deleteTitle": "確認刪除", "sizeWarning": "圖片文件大小不能超過 1MB", - "formatError": "不支援的圖片格式" + "formatError": "不支援的圖片格式", + "paste_images": "📋 從剪貼簿貼上", + "paste_failed": "貼上失敗,剪貼簿中沒有圖片", + "paste_no_image": "剪貼簿中沒有圖片可貼上", + "paste_image_from_textarea": "已將圖片從文字框智能貼到圖片區域", + "images_clear": "清除所有圖片" }, "buttons": { "submit": "提交回饋", diff --git a/src/mcp_feedback_enhanced/static/i18n.js b/src/mcp_feedback_enhanced/static/i18n.js index cfb866a..a913792 100644 --- a/src/mcp_feedback_enhanced/static/i18n.js +++ b/src/mcp_feedback_enhanced/static/i18n.js @@ -43,7 +43,7 @@ class I18nManager { feedback: { title: '💬 您的回饋', description: '請在這裡輸入您的回饋、建議或問題。您的意見將幫助 AI 更好地理解您的需求。', - placeholder: '請在這裡輸入您的回饋、建議或問題...\n\n💡 小提示:按 Ctrl+Enter 可快速提交回饋' + placeholder: '請在這裡輸入您的回饋、建議或問題...\n\n💡 小提示:\n• 按 Ctrl+Enter 可快速提交回饋\n• 按 Ctrl+V 可直接貼上剪貼簿圖片' }, command: { title: '⚡ 命令執行', @@ -55,7 +55,7 @@ class I18nManager { title: '🖼️ 圖片附件(可選)', status: '已選擇 {count} 張圖片', statusWithSize: '已選擇 {count} 張圖片 (總計 {size})', - dragHint: '🎯 拖拽圖片到這裡 (PNG、JPG、JPEG、GIF、BMP、WebP)', + dragHint: '🎯 拖拽圖片到這裡 或 按 Ctrl+V 貼上剪貼簿圖片 (PNG、JPG、JPEG、GIF、BMP、WebP)', deleteConfirm: '確定要移除圖片 "{filename}" 嗎?', deleteTitle: '確認刪除' }, @@ -75,6 +75,8 @@ class I18nManager { commandFinished: '命令執行完成', pasteSuccess: '已從剪貼板貼上圖片', pasteFailed: '無法從剪貼板獲取圖片', + paste_no_image: '剪貼簿中沒有圖片可貼上', + paste_image_from_textarea: '已將圖片從文字框智能貼到圖片區域', invalidFileType: '不支援的文件類型', fileTooLarge: '文件過大(最大 1MB)' }, @@ -100,7 +102,7 @@ class I18nManager { feedback: { title: '💬 Your Feedback', description: 'Please enter your feedback, suggestions, or questions here. Your input helps AI better understand your needs.', - placeholder: 'Please enter your feedback, suggestions, or questions here...\n\n💡 Tip: Press Ctrl+Enter to submit quickly' + placeholder: 'Please enter your feedback, suggestions, or questions here...\n\n💡 Tips:\n• Press Ctrl+Enter to submit quickly\n• Press Ctrl+V to paste images from clipboard' }, command: { title: '⚡ Command Execution', @@ -112,7 +114,7 @@ class I18nManager { title: '🖼️ Image Attachments (Optional)', status: '{count} images selected', statusWithSize: '{count} images selected (Total {size})', - dragHint: '🎯 Drag images here (PNG, JPG, JPEG, GIF, BMP, WebP)', + dragHint: '🎯 Drag images here or press Ctrl+V to paste from clipboard (PNG, JPG, JPEG, GIF, BMP, WebP)', deleteConfirm: 'Are you sure you want to remove image "{filename}"?', deleteTitle: 'Confirm Delete' }, @@ -132,6 +134,8 @@ class I18nManager { commandFinished: 'Command finished', pasteSuccess: 'Image pasted from clipboard', pasteFailed: 'Failed to get image from clipboard', + paste_no_image: 'No image to paste from clipboard', + paste_image_from_textarea: 'Image pasted from text area to image area', invalidFileType: 'Unsupported file type', fileTooLarge: 'File too large (max 1MB)' }, @@ -157,7 +161,7 @@ class I18nManager { feedback: { title: '💬 您的反馈', description: '请在这里输入您的反馈、建议或问题。您的意见将帮助 AI 更好地理解您的需求。', - placeholder: '请在这里输入您的反馈、建议或问题...\n\n💡 小提示:按 Ctrl+Enter 可快速提交反馈' + placeholder: '请在这里输入您的反馈、建议或问题...\n\n💡 小提示:\n• 按 Ctrl+Enter 可快速提交反馈\n• 按 Ctrl+V 可直接贴上剪贴板图片' }, command: { title: '⚡ 命令执行', @@ -169,7 +173,7 @@ class I18nManager { title: '🖼️ 图片附件(可选)', status: '已选择 {count} 张图片', statusWithSize: '已选择 {count} 张图片 (总计 {size})', - dragHint: '🎯 拖拽图片到这里 (PNG、JPG、JPEG、GIF、BMP、WebP)', + dragHint: '🎯 拖拽图片到这里 或 按 Ctrl+V 贴上剪贴板图片 (PNG、JPG、JPEG、GIF、BMP、WebP)', deleteConfirm: '确定要移除图片 "{filename}" 吗?', deleteTitle: '确认删除' }, @@ -189,6 +193,8 @@ class I18nManager { commandFinished: '命令执行完成', pasteSuccess: '已从剪贴板粘贴图片', pasteFailed: '无法从剪贴板获取图片', + paste_no_image: '剪贴板中没有图片可粘贴', + paste_image_from_textarea: '已将图片从文字框智能贴到图片区域', invalidFileType: '不支持的文件类型', fileTooLarge: '文件过大(最大 1MB)' }, @@ -361,6 +367,8 @@ class I18nManager { 'command_finished': 'status.commandFinished', 'paste_success': 'status.pasteSuccess', 'paste_failed': 'status.pasteFailed', + 'paste_no_image': 'status.paste_no_image', + 'paste_image_from_textarea': 'status.paste_image_from_textarea', 'invalid_file_type': 'status.invalidFileType', 'file_too_large': 'status.fileTooLarge' }; diff --git a/src/mcp_feedback_enhanced/templates/feedback.html b/src/mcp_feedback_enhanced/templates/feedback.html index 4826793..0434dc9 100644 --- a/src/mcp_feedback_enhanced/templates/feedback.html +++ b/src/mcp_feedback_enhanced/templates/feedback.html @@ -656,7 +656,7 @@ @@ -669,7 +669,7 @@