mirror of
https://github.com/Minidoracat/mcp-feedback-enhanced.git
synced 2025-07-27 10:42:25 +08:00
✨ 增強回饋分頁的界面設計,新增分割器位置保存功能,優化圖片上傳區域的顯示,並改善摘要分頁的內容處理邏輯。
This commit is contained in:
parent
48654d2c93
commit
aff61718cd
@ -7,11 +7,12 @@
|
||||
專門處理用戶回饋輸入的分頁組件。
|
||||
"""
|
||||
|
||||
from PySide6.QtWidgets import QWidget, QVBoxLayout, QLabel, QSplitter
|
||||
from PySide6.QtWidgets import QWidget, QVBoxLayout, QLabel, QSplitter, QSizePolicy
|
||||
from PySide6.QtCore import Qt, Signal
|
||||
|
||||
from ..widgets import SmartTextEdit, ImageUploadWidget
|
||||
from ...i18n import t
|
||||
from ..window.config_manager import ConfigManager
|
||||
|
||||
|
||||
class FeedbackTab(QWidget):
|
||||
@ -20,6 +21,7 @@ class FeedbackTab(QWidget):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.config_manager = ConfigManager()
|
||||
self._setup_ui()
|
||||
|
||||
def _setup_ui(self) -> None:
|
||||
@ -27,17 +29,56 @@ class FeedbackTab(QWidget):
|
||||
# 主布局
|
||||
tab_layout = QVBoxLayout(self)
|
||||
tab_layout.setSpacing(12)
|
||||
tab_layout.setContentsMargins(16, 16, 16, 16)
|
||||
tab_layout.setContentsMargins(0, 0, 0, 0) # 設置邊距為0,與合併分頁保持一致
|
||||
|
||||
# 說明文字容器
|
||||
description_wrapper = QWidget()
|
||||
description_layout = QVBoxLayout(description_wrapper)
|
||||
description_layout.setContentsMargins(16, 16, 16, 10) # 只對說明文字設置邊距
|
||||
description_layout.setSpacing(0)
|
||||
|
||||
# 說明文字
|
||||
self.feedback_description = QLabel(t('feedback.description'))
|
||||
self.feedback_description.setStyleSheet("color: #9e9e9e; font-size: 12px; margin-bottom: 10px;")
|
||||
self.feedback_description.setStyleSheet("color: #9e9e9e; font-size: 12px;")
|
||||
self.feedback_description.setWordWrap(True)
|
||||
tab_layout.addWidget(self.feedback_description)
|
||||
description_layout.addWidget(self.feedback_description)
|
||||
|
||||
tab_layout.addWidget(description_wrapper)
|
||||
|
||||
# 使用分割器來管理回饋輸入和圖片區域
|
||||
splitter_wrapper = QWidget() # 創建包裝容器
|
||||
splitter_wrapper_layout = QVBoxLayout(splitter_wrapper)
|
||||
splitter_wrapper_layout.setContentsMargins(16, 0, 16, 16) # 設置左右邊距
|
||||
splitter_wrapper_layout.setSpacing(0)
|
||||
|
||||
feedback_splitter = QSplitter(Qt.Vertical)
|
||||
feedback_splitter.setChildrenCollapsible(False)
|
||||
feedback_splitter.setHandleWidth(6)
|
||||
feedback_splitter.setContentsMargins(0, 0, 0, 0) # 設置分割器邊距為0
|
||||
feedback_splitter.setStyleSheet("""
|
||||
QSplitter {
|
||||
border: none;
|
||||
background: transparent;
|
||||
}
|
||||
QSplitter::handle:vertical {
|
||||
height: 8px;
|
||||
background-color: #3c3c3c;
|
||||
border: 1px solid #555555;
|
||||
border-radius: 4px;
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
margin-top: 2px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
QSplitter::handle:vertical:hover {
|
||||
background-color: #606060;
|
||||
border-color: #808080;
|
||||
}
|
||||
QSplitter::handle:vertical:pressed {
|
||||
background-color: #007acc;
|
||||
border-color: #005a9e;
|
||||
}
|
||||
""")
|
||||
|
||||
# 回饋輸入區域
|
||||
self.feedback_input = SmartTextEdit()
|
||||
@ -57,13 +98,13 @@ class FeedbackTab(QWidget):
|
||||
""")
|
||||
self.feedback_input.image_paste_requested.connect(self.image_paste_requested)
|
||||
|
||||
# 圖片上傳區域
|
||||
# 圖片上傳區域(確保固定高度和滾動支持)
|
||||
image_upload_widget = QWidget()
|
||||
image_upload_widget.setMinimumHeight(140)
|
||||
image_upload_widget.setMaximumHeight(250)
|
||||
image_upload_widget.setMinimumHeight(200) # 進一步增加最小高度
|
||||
image_upload_widget.setMaximumHeight(320) # 增加最大高度
|
||||
image_upload_layout = QVBoxLayout(image_upload_widget)
|
||||
image_upload_layout.setSpacing(8)
|
||||
image_upload_layout.setContentsMargins(0, 8, 0, 0)
|
||||
image_upload_layout.setContentsMargins(0, 8, 0, 0) # 與回饋輸入區域保持一致的邊距
|
||||
|
||||
self.image_upload = ImageUploadWidget()
|
||||
image_upload_layout.addWidget(self.image_upload, 1)
|
||||
@ -72,15 +113,37 @@ class FeedbackTab(QWidget):
|
||||
feedback_splitter.addWidget(self.feedback_input)
|
||||
feedback_splitter.addWidget(image_upload_widget)
|
||||
|
||||
# 設置分割器比例 (70% : 30%)
|
||||
feedback_splitter.setStretchFactor(0, 3) # 回饋輸入區域較大
|
||||
feedback_splitter.setStretchFactor(1, 1) # 圖片上傳區域較小
|
||||
feedback_splitter.setSizes([300, 140]) # 設置初始大小
|
||||
# 調整分割器比例和設置(確保圖片區域始終可見)
|
||||
feedback_splitter.setStretchFactor(0, 2) # 回饋輸入區域
|
||||
feedback_splitter.setStretchFactor(1, 1) # 圖片上傳區域
|
||||
|
||||
# 設置分割器的最小尺寸,防止子元件被過度壓縮
|
||||
feedback_splitter.setMinimumHeight(340) # 設置分割器最小高度
|
||||
# 從配置載入分割器位置,如果沒有則使用預設值
|
||||
saved_sizes = self.config_manager.get_splitter_sizes('feedback_splitter')
|
||||
if saved_sizes and len(saved_sizes) == 2:
|
||||
feedback_splitter.setSizes(saved_sizes)
|
||||
else:
|
||||
feedback_splitter.setSizes([220, 200]) # 預設大小
|
||||
|
||||
tab_layout.addWidget(feedback_splitter, 1)
|
||||
# 連接分割器位置變化信號,自動保存位置
|
||||
feedback_splitter.splitterMoved.connect(
|
||||
lambda pos, index: self._save_feedback_splitter_position(feedback_splitter)
|
||||
)
|
||||
|
||||
# 設置分割器的最小尺寸和處理策略
|
||||
feedback_splitter.setMinimumHeight(460) # 進一步增加分割器最小高度
|
||||
feedback_splitter.setMaximumHeight(2000) # 允許更大的高度以觸發滾動
|
||||
|
||||
# 確保子控件的最小尺寸(防止過度壓縮)
|
||||
self.feedback_input.setMinimumHeight(120)
|
||||
image_upload_widget.setMinimumHeight(200) # 確保圖片區域的最小高度
|
||||
|
||||
splitter_wrapper_layout.addWidget(feedback_splitter)
|
||||
|
||||
tab_layout.addWidget(splitter_wrapper, 1)
|
||||
|
||||
# 設置分頁的大小策略,確保能夠觸發父容器的滾動條
|
||||
self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
|
||||
self.setMinimumHeight(500) # 設置最小高度
|
||||
|
||||
def get_feedback_text(self) -> str:
|
||||
"""獲取回饋文字"""
|
||||
@ -102,3 +165,8 @@ class FeedbackTab(QWidget):
|
||||
def handle_image_paste_from_textarea(self) -> None:
|
||||
"""處理從文字框智能貼上圖片的功能"""
|
||||
self.image_upload.paste_from_clipboard()
|
||||
|
||||
def _save_feedback_splitter_position(self, splitter: QSplitter) -> None:
|
||||
"""保存分割器的位置"""
|
||||
sizes = splitter.sizes()
|
||||
self.config_manager.set_splitter_sizes('feedback_splitter', sizes)
|
@ -7,6 +7,7 @@
|
||||
專門顯示AI工作摘要的分頁組件。
|
||||
"""
|
||||
|
||||
import json
|
||||
from PySide6.QtWidgets import QWidget, QVBoxLayout, QLabel, QTextEdit
|
||||
|
||||
from ...i18n import t
|
||||
@ -17,14 +18,37 @@ class SummaryTab(QWidget):
|
||||
|
||||
def __init__(self, summary: str, parent=None):
|
||||
super().__init__(parent)
|
||||
self.summary = summary
|
||||
self.summary = self._process_summary(summary)
|
||||
self._setup_ui()
|
||||
|
||||
def _process_summary(self, summary: str) -> str:
|
||||
"""處理摘要內容,如果是JSON格式則提取實際內容"""
|
||||
try:
|
||||
# 嘗試解析JSON
|
||||
if summary.strip().startswith('{') and summary.strip().endswith('}'):
|
||||
json_data = json.loads(summary)
|
||||
# 如果是JSON格式,提取summary字段的內容
|
||||
if isinstance(json_data, dict) and 'summary' in json_data:
|
||||
return json_data['summary']
|
||||
# 如果JSON中沒有summary字段,返回原始內容
|
||||
return summary
|
||||
else:
|
||||
return summary
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
# 如果不是有效的JSON,返回原始內容
|
||||
return summary
|
||||
|
||||
def _setup_ui(self) -> None:
|
||||
"""設置用戶介面"""
|
||||
layout = QVBoxLayout(self)
|
||||
layout.setSpacing(12)
|
||||
layout.setContentsMargins(16, 16, 16, 16)
|
||||
layout.setContentsMargins(0, 16, 0, 0) # 只保留上邊距,移除左右和底部邊距
|
||||
|
||||
# 說明文字容器
|
||||
description_wrapper = QWidget()
|
||||
description_layout = QVBoxLayout(description_wrapper)
|
||||
description_layout.setContentsMargins(16, 0, 16, 0) # 只對說明文字設置左右邊距
|
||||
description_layout.setSpacing(0)
|
||||
|
||||
# 說明文字
|
||||
if self._is_test_summary():
|
||||
@ -34,7 +58,15 @@ class SummaryTab(QWidget):
|
||||
|
||||
self.summary_description_label.setStyleSheet("color: #9e9e9e; font-size: 12px; margin-bottom: 10px;")
|
||||
self.summary_description_label.setWordWrap(True)
|
||||
layout.addWidget(self.summary_description_label)
|
||||
description_layout.addWidget(self.summary_description_label)
|
||||
|
||||
layout.addWidget(description_wrapper)
|
||||
|
||||
# 摘要顯示區域容器
|
||||
summary_wrapper = QWidget()
|
||||
summary_layout = QVBoxLayout(summary_wrapper)
|
||||
summary_layout.setContentsMargins(16, 0, 16, 0) # 只對摘要區域設置左右邊距
|
||||
summary_layout.setSpacing(0)
|
||||
|
||||
# 摘要顯示區域
|
||||
self.summary_display = QTextEdit()
|
||||
@ -56,32 +88,37 @@ class SummaryTab(QWidget):
|
||||
line-height: 1.4;
|
||||
}
|
||||
""")
|
||||
layout.addWidget(self.summary_display, 1)
|
||||
summary_layout.addWidget(self.summary_display, 1)
|
||||
|
||||
layout.addWidget(summary_wrapper, 1)
|
||||
|
||||
def _is_test_summary(self) -> bool:
|
||||
"""檢查是否為測試摘要"""
|
||||
test_indicators = [
|
||||
# 繁體中文
|
||||
"圖片預覽和視窗調整測試",
|
||||
"圖片預覽和窗口調整測試",
|
||||
"這是一個測試會話",
|
||||
"功能測試項目",
|
||||
# 更精確的測試摘要檢測 - 必須包含特定的測試指標組合
|
||||
test_patterns = [
|
||||
# Qt GUI 測試特徵組合 - 必須同時包含多個特徵
|
||||
("圖片預覽和視窗調整測試", "功能測試項目", "🎯"),
|
||||
("圖片預覽和窗口調整測試", "功能測試項目", "🎯"),
|
||||
("图片预览和窗口调整测试", "功能测试项目", "🎯"),
|
||||
("Image Preview and Window Adjustment Test", "Test Items", "🎯"),
|
||||
|
||||
# 簡體中文
|
||||
"图片预览和窗口调整测试",
|
||||
"这是一个测试会话",
|
||||
"功能测试项目",
|
||||
# Web UI 測試特徵組合
|
||||
("測試 Web UI 功能", "🎯 **功能測試項目", "WebSocket 即時通訊"),
|
||||
("测试 Web UI 功能", "🎯 **功能测试项目", "WebSocket 即时通讯"),
|
||||
("Test Web UI Functionality", "🎯 **Test Items", "WebSocket real-time communication"),
|
||||
|
||||
# 英文
|
||||
"Image Preview and Window Adjustment Test",
|
||||
"This is a test session",
|
||||
"Test Items",
|
||||
|
||||
# 通用
|
||||
"測試", "测试", "test", "Test",
|
||||
"🎯", "✅", "📋" # 測試摘要特有的 emoji
|
||||
# 具體的測試步驟特徵
|
||||
("智能 Ctrl+V 圖片貼上功能", "📋 測試步驟", "請測試這些功能並提供回饋"),
|
||||
("智能 Ctrl+V 图片粘贴功能", "📋 测试步骤", "请测试这些功能并提供回馈"),
|
||||
("Smart Ctrl+V image paste", "📋 Test Steps", "Please test these features"),
|
||||
]
|
||||
return any(indicator in self.summary for indicator in test_indicators)
|
||||
|
||||
# 檢查是否匹配任何一個測試模式(必須同時包含模式中的所有關鍵詞)
|
||||
for pattern in test_patterns:
|
||||
if all(keyword in self.summary for keyword in pattern):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def update_texts(self) -> None:
|
||||
"""更新界面文字(用於語言切換)"""
|
||||
|
@ -19,6 +19,7 @@ from PySide6.QtWidgets import (
|
||||
)
|
||||
from PySide6.QtCore import Qt, Signal
|
||||
from PySide6.QtGui import QFont, QDragEnterEvent, QDropEvent
|
||||
from PySide6.QtWidgets import QSizePolicy
|
||||
|
||||
# 導入多語系支援
|
||||
from ...i18n import t
|
||||
@ -42,7 +43,7 @@ class ImageUploadWidget(QWidget):
|
||||
"""設置用戶介面"""
|
||||
layout = QVBoxLayout(self)
|
||||
layout.setSpacing(6)
|
||||
layout.setContentsMargins(12, 8, 12, 8)
|
||||
layout.setContentsMargins(0, 8, 0, 8) # 調整邊距使其與其他區域一致
|
||||
|
||||
# 標題
|
||||
self.title = QLabel(t('images.title'))
|
||||
@ -63,6 +64,9 @@ class ImageUploadWidget(QWidget):
|
||||
# 創建滾動區域
|
||||
self.preview_scroll = QScrollArea()
|
||||
self.preview_widget = QWidget()
|
||||
self.preview_widget.setMinimumHeight(140) # 設置預覽部件的最小高度
|
||||
# 設置尺寸策略,允許垂直擴展
|
||||
self.preview_widget.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
|
||||
self.preview_layout = QVBoxLayout(self.preview_widget)
|
||||
self.preview_layout.setSpacing(6)
|
||||
self.preview_layout.setContentsMargins(8, 8, 8, 8)
|
||||
@ -73,7 +77,8 @@ class ImageUploadWidget(QWidget):
|
||||
# 創建拖拽提示標籤(初始顯示)
|
||||
self.drop_hint_label = QLabel(t('images.dragHint'))
|
||||
self.drop_hint_label.setAlignment(Qt.AlignCenter)
|
||||
self.drop_hint_label.setMinimumHeight(60)
|
||||
self.drop_hint_label.setMinimumHeight(80) # 增加最小高度
|
||||
self.drop_hint_label.setMaximumHeight(120) # 設置最大高度
|
||||
self.drop_hint_label.setStyleSheet("""
|
||||
QLabel {
|
||||
border: 2px dashed #464647;
|
||||
@ -82,6 +87,7 @@ class ImageUploadWidget(QWidget):
|
||||
color: #9e9e9e;
|
||||
font-size: 11px;
|
||||
margin: 4px 0;
|
||||
padding: 16px 8px;
|
||||
}
|
||||
""")
|
||||
|
||||
@ -101,17 +107,61 @@ class ImageUploadWidget(QWidget):
|
||||
|
||||
# 設置滾動區域
|
||||
self.preview_scroll.setWidget(self.preview_widget)
|
||||
self.preview_scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
||||
self.preview_scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) # 改回按需顯示滾動條
|
||||
self.preview_scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
||||
self.preview_scroll.setMinimumHeight(120) # 增加最小高度以容納按鈕
|
||||
self.preview_scroll.setMaximumHeight(200) # 調整最大高度
|
||||
self.preview_scroll.setMinimumHeight(160) # 增加最小高度,確保有足夠空間
|
||||
self.preview_scroll.setMaximumHeight(300) # 增加最大高度
|
||||
self.preview_scroll.setWidgetResizable(True)
|
||||
|
||||
# 增強的滾動區域樣式,改善 macOS 兼容性
|
||||
self.preview_scroll.setStyleSheet("""
|
||||
QScrollArea {
|
||||
border: 1px solid #464647;
|
||||
border-radius: 4px;
|
||||
background-color: #1e1e1e;
|
||||
}
|
||||
QScrollArea QScrollBar:vertical {
|
||||
background-color: #2a2a2a;
|
||||
width: 14px;
|
||||
border-radius: 7px;
|
||||
margin: 0;
|
||||
}
|
||||
QScrollArea QScrollBar::handle:vertical {
|
||||
background-color: #555;
|
||||
border-radius: 7px;
|
||||
min-height: 30px;
|
||||
margin: 2px;
|
||||
}
|
||||
QScrollArea QScrollBar::handle:vertical:hover {
|
||||
background-color: #777;
|
||||
}
|
||||
QScrollArea QScrollBar::add-line:vertical,
|
||||
QScrollArea QScrollBar::sub-line:vertical {
|
||||
border: none;
|
||||
background: none;
|
||||
height: 0px;
|
||||
}
|
||||
QScrollArea QScrollBar:horizontal {
|
||||
background-color: #2a2a2a;
|
||||
height: 14px;
|
||||
border-radius: 7px;
|
||||
margin: 0;
|
||||
}
|
||||
QScrollArea QScrollBar::handle:horizontal {
|
||||
background-color: #555;
|
||||
border-radius: 7px;
|
||||
min-width: 30px;
|
||||
margin: 2px;
|
||||
}
|
||||
QScrollArea QScrollBar::handle:horizontal:hover {
|
||||
background-color: #777;
|
||||
}
|
||||
QScrollArea QScrollBar::add-line:horizontal,
|
||||
QScrollArea QScrollBar::sub-line:horizontal {
|
||||
border: none;
|
||||
background: none;
|
||||
width: 0px;
|
||||
}
|
||||
""")
|
||||
|
||||
layout.addWidget(self.preview_scroll)
|
||||
@ -359,6 +409,14 @@ class ImageUploadWidget(QWidget):
|
||||
col = i % 5
|
||||
self.images_grid_layout.addWidget(preview, row, col)
|
||||
|
||||
# 強制更新佈局和滾動區域
|
||||
self.preview_widget.updateGeometry()
|
||||
self.preview_scroll.updateGeometry()
|
||||
|
||||
# 確保滾動區域能正確計算內容大小
|
||||
from PySide6.QtWidgets import QApplication
|
||||
QApplication.processEvents()
|
||||
|
||||
def _remove_image(self, image_id: str) -> None:
|
||||
"""移除圖片"""
|
||||
if image_id in self.images:
|
||||
|
@ -77,3 +77,27 @@ class ConfigManager:
|
||||
"""設置語言"""
|
||||
self.set('language', language)
|
||||
debug_log(f"語言設置: {language}")
|
||||
|
||||
def get_splitter_sizes(self, splitter_name: str) -> list:
|
||||
"""獲取分割器尺寸"""
|
||||
sizes = self.get(f'splitter_sizes.{splitter_name}', [])
|
||||
if sizes:
|
||||
debug_log(f"載入分割器 {splitter_name} 尺寸: {sizes}")
|
||||
return sizes
|
||||
|
||||
def set_splitter_sizes(self, splitter_name: str, sizes: list) -> None:
|
||||
"""設置分割器尺寸"""
|
||||
self.set(f'splitter_sizes.{splitter_name}', sizes)
|
||||
debug_log(f"保存分割器 {splitter_name} 尺寸: {sizes}")
|
||||
|
||||
def get_window_geometry(self) -> dict:
|
||||
"""獲取窗口幾何信息"""
|
||||
geometry = self.get('window_geometry', {})
|
||||
if geometry:
|
||||
debug_log(f"載入窗口幾何信息: {geometry}")
|
||||
return geometry
|
||||
|
||||
def set_window_geometry(self, geometry: dict) -> None:
|
||||
"""設置窗口幾何信息"""
|
||||
self.set('window_geometry', geometry)
|
||||
debug_log(f"保存窗口幾何信息: {geometry}")
|
@ -9,7 +9,7 @@
|
||||
|
||||
from PySide6.QtWidgets import (
|
||||
QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QLabel,
|
||||
QTabWidget, QPushButton, QMessageBox
|
||||
QTabWidget, QPushButton, QMessageBox, QScrollArea, QSizePolicy
|
||||
)
|
||||
from PySide6.QtCore import Signal, Qt
|
||||
from PySide6.QtGui import QKeySequence, QShortcut
|
||||
@ -78,8 +78,69 @@ class FeedbackWindow(QMainWindow):
|
||||
|
||||
def _create_tab_area(self, layout: QVBoxLayout) -> None:
|
||||
"""創建分頁區域"""
|
||||
# 創建滾動區域來包裝整個分頁組件
|
||||
scroll_area = QScrollArea()
|
||||
scroll_area.setWidgetResizable(True)
|
||||
scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
||||
scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
||||
scroll_area.setMinimumHeight(500)
|
||||
scroll_area.setStyleSheet("""
|
||||
QScrollArea {
|
||||
border: 1px solid #464647;
|
||||
border-radius: 4px;
|
||||
background-color: #2b2b2b;
|
||||
}
|
||||
QScrollArea > QWidget > QWidget {
|
||||
background-color: #2b2b2b;
|
||||
}
|
||||
QScrollArea QScrollBar:vertical {
|
||||
background-color: #2a2a2a;
|
||||
width: 8px;
|
||||
border-radius: 4px;
|
||||
margin: 0;
|
||||
}
|
||||
QScrollArea QScrollBar::handle:vertical {
|
||||
background-color: #555;
|
||||
border-radius: 4px;
|
||||
min-height: 20px;
|
||||
margin: 1px;
|
||||
}
|
||||
QScrollArea QScrollBar::handle:vertical:hover {
|
||||
background-color: #777;
|
||||
}
|
||||
QScrollArea QScrollBar::add-line:vertical,
|
||||
QScrollArea QScrollBar::sub-line:vertical {
|
||||
border: none;
|
||||
background: none;
|
||||
height: 0px;
|
||||
}
|
||||
QScrollArea QScrollBar:horizontal {
|
||||
background-color: #2a2a2a;
|
||||
height: 8px;
|
||||
border-radius: 4px;
|
||||
margin: 0;
|
||||
}
|
||||
QScrollArea QScrollBar::handle:horizontal {
|
||||
background-color: #555;
|
||||
border-radius: 4px;
|
||||
min-width: 20px;
|
||||
margin: 1px;
|
||||
}
|
||||
QScrollArea QScrollBar::handle:horizontal:hover {
|
||||
background-color: #777;
|
||||
}
|
||||
QScrollArea QScrollBar::add-line:horizontal,
|
||||
QScrollArea QScrollBar::sub-line:horizontal {
|
||||
border: none;
|
||||
background: none;
|
||||
width: 0px;
|
||||
}
|
||||
""")
|
||||
|
||||
self.tab_widget = QTabWidget()
|
||||
self.tab_widget.setMinimumHeight(500)
|
||||
# 設置分頁組件的大小策略,確保能觸發滾動
|
||||
self.tab_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
||||
|
||||
# 初始化分頁管理器
|
||||
self.tab_manager = TabManager(
|
||||
@ -92,7 +153,10 @@ class FeedbackWindow(QMainWindow):
|
||||
# 創建分頁
|
||||
self.tab_manager.create_tabs()
|
||||
|
||||
layout.addWidget(self.tab_widget, 1)
|
||||
# 將分頁組件放入滾動區域
|
||||
scroll_area.setWidget(self.tab_widget)
|
||||
|
||||
layout.addWidget(scroll_area, 1)
|
||||
|
||||
def _create_action_buttons(self, layout: QVBoxLayout) -> None:
|
||||
"""創建操作按鈕"""
|
||||
@ -174,6 +238,7 @@ class FeedbackWindow(QMainWindow):
|
||||
QTabWidget::pane {
|
||||
border: 1px solid #464647;
|
||||
border-radius: 4px;
|
||||
background-color: #2b2b2b;
|
||||
}
|
||||
QTabBar::tab {
|
||||
background-color: #2d2d30;
|
||||
@ -185,6 +250,37 @@ class FeedbackWindow(QMainWindow):
|
||||
QTabBar::tab:selected {
|
||||
background-color: #007acc;
|
||||
}
|
||||
QSplitter {
|
||||
background-color: #2b2b2b;
|
||||
}
|
||||
QSplitter::handle {
|
||||
background-color: #3c3c3c;
|
||||
border: 1px solid #555555;
|
||||
border-radius: 3px;
|
||||
margin: 0px;
|
||||
}
|
||||
QSplitter::handle:horizontal {
|
||||
width: 6px;
|
||||
background-color: #3c3c3c;
|
||||
border: 1px solid #555555;
|
||||
border-radius: 3px;
|
||||
margin: 0px;
|
||||
}
|
||||
QSplitter::handle:vertical {
|
||||
height: 6px;
|
||||
background-color: #3c3c3c;
|
||||
border: 1px solid #555555;
|
||||
border-radius: 3px;
|
||||
margin: 0px;
|
||||
}
|
||||
QSplitter::handle:hover {
|
||||
background-color: #606060;
|
||||
border-color: #808080;
|
||||
}
|
||||
QSplitter::handle:pressed {
|
||||
background-color: #007acc;
|
||||
border-color: #005a9e;
|
||||
}
|
||||
""")
|
||||
|
||||
def _on_layout_mode_change_requested(self, combined_mode: bool) -> None:
|
||||
|
@ -8,13 +8,14 @@
|
||||
"""
|
||||
|
||||
from typing import Dict, Any
|
||||
from PySide6.QtWidgets import QTabWidget, QSplitter, QWidget, QVBoxLayout
|
||||
from PySide6.QtWidgets import QTabWidget, QSplitter, QWidget, QVBoxLayout, QScrollArea, QSizePolicy
|
||||
from PySide6.QtCore import Signal, Qt
|
||||
|
||||
from ..tabs import FeedbackTab, SummaryTab, CommandTab, SettingsTab
|
||||
from ..widgets import SmartTextEdit, ImageUploadWidget
|
||||
from ...i18n import t
|
||||
from ...debug import gui_debug_log as debug_log
|
||||
from .config_manager import ConfigManager
|
||||
|
||||
|
||||
class TabManager:
|
||||
@ -26,6 +27,9 @@ class TabManager:
|
||||
self.summary = summary
|
||||
self.combined_mode = combined_mode
|
||||
|
||||
# 配置管理器
|
||||
self.config_manager = ConfigManager()
|
||||
|
||||
# 分頁組件實例
|
||||
self.feedback_tab = None
|
||||
self.summary_tab = None
|
||||
@ -67,30 +71,99 @@ class TabManager:
|
||||
# 主布局
|
||||
tab_layout = QVBoxLayout(self.combined_feedback_tab)
|
||||
tab_layout.setSpacing(12)
|
||||
tab_layout.setContentsMargins(16, 16, 16, 16)
|
||||
tab_layout.setContentsMargins(0, 0, 0, 0) # 設置邊距為0
|
||||
|
||||
# 創建分割器包裝容器
|
||||
splitter_wrapper = QWidget()
|
||||
splitter_wrapper_layout = QVBoxLayout(splitter_wrapper)
|
||||
splitter_wrapper_layout.setContentsMargins(16, 16, 16, 0) # 恢復左右邊距設置
|
||||
splitter_wrapper_layout.setSpacing(0)
|
||||
|
||||
# 使用垂直分割器管理 AI摘要、回饋輸入和圖片區域
|
||||
main_splitter = QSplitter(Qt.Vertical)
|
||||
main_splitter.setChildrenCollapsible(False)
|
||||
main_splitter.setHandleWidth(6)
|
||||
main_splitter.setContentsMargins(0, 0, 0, 0) # 設置分割器邊距為0
|
||||
|
||||
# 設置分割器wrapper樣式,確保分割器延伸到邊緣
|
||||
splitter_wrapper.setStyleSheet("""
|
||||
QWidget {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
""")
|
||||
|
||||
main_splitter.setStyleSheet("""
|
||||
QSplitter {
|
||||
border: none;
|
||||
background: transparent;
|
||||
}
|
||||
QSplitter::handle:vertical {
|
||||
height: 8px;
|
||||
background-color: #3c3c3c;
|
||||
border: 1px solid #555555;
|
||||
border-radius: 4px;
|
||||
margin-left: 16px;
|
||||
margin-right: 16px;
|
||||
margin-top: 2px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
QSplitter::handle:vertical:hover {
|
||||
background-color: #606060;
|
||||
border-color: #808080;
|
||||
}
|
||||
QSplitter::handle:vertical:pressed {
|
||||
background-color: #007acc;
|
||||
border-color: #005a9e;
|
||||
}
|
||||
""")
|
||||
|
||||
# 創建AI摘要組件
|
||||
self.summary_tab = SummaryTab(self.summary)
|
||||
self.summary_tab.setMinimumHeight(150)
|
||||
self.summary_tab.setMaximumHeight(300)
|
||||
self.summary_tab.setMaximumHeight(1000) # 允許更大的拖拽範圍
|
||||
|
||||
# 創建回饋輸入組件
|
||||
self.feedback_tab = FeedbackTab()
|
||||
# 確保回饋分頁有足夠的最小高度來顯示圖片區域
|
||||
self.feedback_tab.setMinimumHeight(480)
|
||||
self.feedback_tab.setMaximumHeight(2000) # 允許更大的拖拽範圍
|
||||
|
||||
# 添加到主分割器
|
||||
main_splitter.addWidget(self.summary_tab)
|
||||
main_splitter.addWidget(self.feedback_tab)
|
||||
|
||||
# 設置分割器比例 (摘要:回饋 = 2:3)
|
||||
main_splitter.setStretchFactor(0, 2) # AI摘要區域
|
||||
main_splitter.setStretchFactor(1, 3) # 回饋輸入區域(包含圖片)
|
||||
main_splitter.setSizes([200, 400]) # 設置初始大小
|
||||
# 調整分割器比例和初始大小,確保圖片區域可見
|
||||
main_splitter.setStretchFactor(0, 1) # AI摘要區域
|
||||
main_splitter.setStretchFactor(1, 2) # 回饋輸入區域(包含圖片)- 給予更多空間
|
||||
|
||||
tab_layout.addWidget(main_splitter, 1)
|
||||
# 從配置載入分割器位置,如果沒有則使用預設值
|
||||
saved_sizes = self.config_manager.get_splitter_sizes('main_splitter')
|
||||
if saved_sizes and len(saved_sizes) == 2:
|
||||
main_splitter.setSizes(saved_sizes)
|
||||
else:
|
||||
main_splitter.setSizes([160, 480]) # 預設大小
|
||||
|
||||
# 連接分割器位置變化信號,自動保存位置
|
||||
main_splitter.splitterMoved.connect(
|
||||
lambda pos, index: self._save_main_splitter_position(main_splitter)
|
||||
)
|
||||
|
||||
# 設置主分割器的最小高度,確保圖片區域可見
|
||||
main_splitter.setMinimumHeight(660) # 進一步增加最小高度
|
||||
main_splitter.setMaximumHeight(3000) # 允許更大的高度以觸發滾動
|
||||
|
||||
splitter_wrapper_layout.addWidget(main_splitter)
|
||||
|
||||
# 添加底部空間以保持完整的邊距
|
||||
bottom_spacer = QWidget()
|
||||
bottom_spacer.setFixedHeight(16)
|
||||
tab_layout.addWidget(splitter_wrapper, 1)
|
||||
tab_layout.addWidget(bottom_spacer)
|
||||
|
||||
# 設置合併分頁的大小策略,確保能夠觸發父容器的滾動條
|
||||
self.combined_feedback_tab.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
|
||||
self.combined_feedback_tab.setMinimumHeight(700) # 設置最小高度
|
||||
|
||||
def update_tab_texts(self) -> None:
|
||||
"""更新分頁標籤文字"""
|
||||
@ -184,3 +257,9 @@ class TabManager:
|
||||
self.combined_mode = combined_mode
|
||||
if self.settings_tab:
|
||||
self.settings_tab.set_layout_mode(combined_mode)
|
||||
|
||||
def _save_main_splitter_position(self, splitter: QSplitter) -> None:
|
||||
"""保存分割器位置"""
|
||||
sizes = splitter.sizes()
|
||||
self.config_manager.set_splitter_sizes('main_splitter', sizes)
|
||||
debug_log(f"分割器位置保存成功,大小: {sizes}")
|
@ -28,13 +28,17 @@
|
||||
"description": "Please describe your thoughts, suggestions, or modifications needed for the AI's work.",
|
||||
"placeholder": "Please enter your feedback, suggestions, or questions here...\n\n💡 Tips:\n• Press Ctrl+Enter (numpad supported) to submit quickly\n• Press Ctrl+V to paste images from clipboard",
|
||||
"emptyTitle": "Feedback Content Empty",
|
||||
"emptyMessage": "Please enter feedback content before submitting. You can describe your thoughts, suggestions, or areas that need modification."
|
||||
"emptyMessage": "Please enter feedback content before submitting. You can describe your thoughts, suggestions, or areas that need modification.",
|
||||
"outputPlaceholder": "Command output will appear here..."
|
||||
},
|
||||
"command": {
|
||||
"title": "Command Execution",
|
||||
"description": "You can execute commands to verify results or gather more information.",
|
||||
"placeholder": "Enter command to execute...",
|
||||
"output": "Command Output"
|
||||
"output": "Command Output",
|
||||
"outputPlaceholder": "Command output will appear here...",
|
||||
"run": "▶️ Run",
|
||||
"terminate": "⏹️ Stop"
|
||||
},
|
||||
"images": {
|
||||
"title": "🖼️ Image Attachments (Optional)",
|
||||
|
@ -34,7 +34,10 @@
|
||||
"title": "命令执行",
|
||||
"description": "您可以执行命令来验证结果或收集更多信息。",
|
||||
"placeholder": "输入要执行的命令...",
|
||||
"output": "命令输出"
|
||||
"output": "命令输出",
|
||||
"outputPlaceholder": "命令输出将在这里显示...",
|
||||
"run": "▶️ 执行",
|
||||
"terminate": "⏹️ 停止"
|
||||
},
|
||||
"images": {
|
||||
"title": "🖼️ 图片附件(可选)",
|
||||
|
@ -43,8 +43,8 @@
|
||||
"placeholder": "輸入要執行的命令...",
|
||||
"output": "命令輸出",
|
||||
"outputPlaceholder": "命令輸出將顯示在這裡...",
|
||||
"run": "執行",
|
||||
"terminate": "終止"
|
||||
"run": "▶️ 執行",
|
||||
"terminate": "⏹️ 終止"
|
||||
},
|
||||
"images": {
|
||||
"title": "🖼️ 圖片附件(可選)",
|
||||
|
Loading…
x
Reference in New Issue
Block a user