194 lines
7.3 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
命令分頁組件
============
專門處理命令執行的分頁組件。
"""
from PySide6.QtWidgets import (
QWidget, QVBoxLayout, QHBoxLayout, QLabel,
QTextEdit, QLineEdit, QPushButton
)
from PySide6.QtCore import Signal
from PySide6.QtGui import QFont
from ..utils import apply_widget_styles
from ..window.command_executor import CommandExecutor
from ...i18n import t
class CommandTab(QWidget):
"""命令分頁組件"""
def __init__(self, project_dir: str, parent=None):
super().__init__(parent)
self.project_dir = project_dir
self.command_executor = CommandExecutor(project_dir, self)
self._setup_ui()
self._connect_signals()
def _setup_ui(self) -> None:
"""設置用戶介面"""
command_layout = QVBoxLayout(self)
command_layout.setSpacing(0) # 緊湊佈局
command_layout.setContentsMargins(0, 0, 0, 0)
# 命令說明區域(頂部,只保留說明文字)
header_widget = QWidget()
header_layout = QVBoxLayout(header_widget)
header_layout.setSpacing(6)
header_layout.setContentsMargins(12, 8, 12, 8)
self.command_description_label = QLabel(t('command.description'))
self.command_description_label.setStyleSheet("color: #9e9e9e; font-size: 11px; margin-bottom: 6px;")
self.command_description_label.setWordWrap(True)
header_layout.addWidget(self.command_description_label)
command_layout.addWidget(header_widget)
# 命令輸出區域(中間,佔大部分空間)
output_widget = QWidget()
output_layout = QVBoxLayout(output_widget)
output_layout.setSpacing(6)
output_layout.setContentsMargins(12, 4, 12, 8)
self.command_output = QTextEdit()
self.command_output.setReadOnly(True)
self.command_output.setFont(QFont("Consolas", 11))
self.command_output.setPlaceholderText(t('command.outputPlaceholder'))
# 終端機風格樣式
self.command_output.setStyleSheet("""
QTextEdit {
background-color: #1a1a1a;
border: 1px solid #333;
border-radius: 6px;
padding: 12px;
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
font-size: 11px;
color: #00ff00;
line-height: 1.4;
}
QScrollBar:vertical {
background-color: #2a2a2a;
width: 12px;
border-radius: 6px;
}
QScrollBar::handle:vertical {
background-color: #555;
border-radius: 6px;
min-height: 20px;
}
QScrollBar::handle:vertical:hover {
background-color: #666;
}
""")
output_layout.addWidget(self.command_output, 1) # 佔據剩餘空間
command_layout.addWidget(output_widget, 1) # 輸出區域佔大部分空間
# 命令輸入區域(底部,固定高度)
input_widget = QWidget()
input_widget.setFixedHeight(70) # 固定高度
input_layout = QVBoxLayout(input_widget)
input_layout.setSpacing(6)
input_layout.setContentsMargins(12, 8, 12, 12)
# 命令輸入和執行按鈕(水平布局)
input_row_layout = QHBoxLayout()
input_row_layout.setSpacing(8)
# 提示符號標籤
prompt_label = QLabel("$")
prompt_label.setStyleSheet("color: #00ff00; font-family: 'Consolas', 'Monaco', monospace; font-size: 14px; font-weight: bold;")
prompt_label.setFixedWidth(20)
input_row_layout.addWidget(prompt_label)
self.command_input = QLineEdit()
self.command_input.setPlaceholderText(t('command.placeholder'))
self.command_input.setMinimumHeight(36)
# 終端機風格輸入框
self.command_input.setStyleSheet("""
QLineEdit {
background-color: #1a1a1a;
border: 2px solid #333;
border-radius: 4px;
padding: 8px 12px;
color: #00ff00;
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
font-size: 12px;
}
QLineEdit:focus {
border-color: #007acc;
background-color: #1e1e1e;
}
""")
self.command_input.returnPressed.connect(self._run_command)
input_row_layout.addWidget(self.command_input, 1) # 佔據大部分空間
self.command_run_button = QPushButton(t('command.run'))
self.command_run_button.clicked.connect(self._run_command)
self.command_run_button.setFixedSize(80, 36)
apply_widget_styles(self.command_run_button, "primary_button")
input_row_layout.addWidget(self.command_run_button)
self.command_terminate_button = QPushButton(t('command.terminate'))
self.command_terminate_button.clicked.connect(self._terminate_command)
self.command_terminate_button.setFixedSize(80, 36)
apply_widget_styles(self.command_terminate_button, "danger_button")
input_row_layout.addWidget(self.command_terminate_button)
input_layout.addLayout(input_row_layout)
command_layout.addWidget(input_widget) # 輸入區域在底部
def _connect_signals(self) -> None:
"""連接信號"""
self.command_executor.output_received.connect(self._append_command_output)
def _run_command(self) -> None:
"""執行命令"""
command = self.command_input.text().strip()
if command:
self.command_executor.run_command(command)
self.command_input.clear()
def _terminate_command(self) -> None:
"""終止命令"""
self.command_executor.terminate_command()
def _append_command_output(self, text: str) -> None:
"""添加命令輸出並自動滾動到底部"""
# 移動光標到最後
cursor = self.command_output.textCursor()
cursor.movePosition(cursor.MoveOperation.End)
self.command_output.setTextCursor(cursor)
# 插入文本
self.command_output.insertPlainText(text)
# 確保滾動到最底部
scrollbar = self.command_output.verticalScrollBar()
scrollbar.setValue(scrollbar.maximum())
# 刷新界面
from PySide6.QtWidgets import QApplication
QApplication.processEvents()
def get_command_logs(self) -> str:
"""獲取命令日誌"""
return self.command_output.toPlainText().strip()
def update_texts(self) -> None:
"""更新界面文字(用於語言切換)"""
self.command_description_label.setText(t('command.description'))
self.command_input.setPlaceholderText(t('command.placeholder'))
self.command_output.setPlaceholderText(t('command.outputPlaceholder'))
self.command_run_button.setText(t('command.run'))
self.command_terminate_button.setText(t('command.terminate'))
def cleanup(self) -> None:
"""清理資源"""
if self.command_executor:
self.command_executor.cleanup()