SellFree_MultiTrans/main.py

230 lines
9.1 KiB
Python

import sys
import keyboard
import pyperclip
from PySide6.QtCore import QTimer, QEvent, Qt, QSettings
from PySide6.QtWidgets import (
QApplication, QMainWindow, QVBoxLayout, QCheckBox, QPushButton, QMessageBox, QWidget, QLabel, QLineEdit
)
from translatepy.translators.bing import BingTranslate
from translatepy.translators.deepl import DeeplTranslate
from translatepy.translators.google import GoogleTranslate
from translatepy.translators.libre import LibreTranslate
from translatepy.translators.mymemory import MyMemoryTranslate
from translatepy.translators.reverso import ReversoTranslate
from translatepy.translators.yandex import YandexTranslate
from translatepy.translators.microsoft import MicrosoftTranslate
class MultiTranslatorApp(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("다중 번역기 설정")
self.setGeometry(100, 100, 400, 600)
# QSettings 초기화
self.settings = QSettings("MultiTranslatorApp", "TranslatorSettings")
# 번역 요청 카운터
self.request_count = {
"Bing": 0,
"DeepL": 0,
"Google": 0,
"LibreTranslate": 0,
"MyMemory": 0,
"Reverso": 0,
"Yandex": 0,
"Microsoft": 0
}
# GUI 레이아웃
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
self.layout = QVBoxLayout(self.central_widget)
# 번역기 체크박스 및 API 키 필드 생성
self.translator_settings = {
"Bing": {"checkbox": QCheckBox("Bing Translate"), "api_key": QLineEdit()},
"DeepL": {"checkbox": QCheckBox("DeepL Translate"), "api_key": QLineEdit()},
"Google": {"checkbox": QCheckBox("Google Translate"), "api_key": None},
"LibreTranslate": {"checkbox": QCheckBox("LibreTranslate"), "api_key": None},
"MyMemory": {"checkbox": QCheckBox("MyMemory Translate"), "api_key": None},
"Reverso": {"checkbox": QCheckBox("Reverso Translate"), "api_key": None},
"Yandex": {"checkbox": QCheckBox("Yandex Translate"), "api_key": QLineEdit()},
"Microsoft": {"checkbox": QCheckBox("Microsoft Translate"), "api_key": QLineEdit()}
}
# 번역기 옵션 UI 구성
for name, widgets in self.translator_settings.items():
checkbox = widgets["checkbox"]
api_key_field = widgets["api_key"]
self.layout.addWidget(checkbox)
if api_key_field: # API 키 필드가 있는 경우
api_key_field.setPlaceholderText(f"{name} API 키 입력")
api_key_field.setVisible(False)
self.layout.addWidget(api_key_field)
checkbox.stateChanged.connect(lambda state, name=name: self.toggle_api_key_field(name, state))
# 자동 번역 토글
self.auto_translate_toggle = QCheckBox("클립보드 변경 시 자동 번역")
self.layout.addWidget(self.auto_translate_toggle)
self.auto_translate_toggle.stateChanged.connect(self.toggle_auto_translate)
# 적용 버튼
self.apply_button = QPushButton("설정 적용")
self.apply_button.clicked.connect(self.apply_settings)
self.layout.addWidget(self.apply_button)
# 번역기 초기화
self.selected_services = []
# 클립보드 감지 관련
self.auto_translate_enabled = False
self.last_clipboard_content = ""
self.clipboard_timer = QTimer(self)
self.clipboard_timer.timeout.connect(self.monitor_clipboard)
# 단축키 등록
keyboard.add_hotkey("ctrl+shift+t", lambda: self.run_translation_in_main_thread())
# ESC 키로 창 최소화
self.installEventFilter(self)
# 이전 설정 복원
self.load_settings()
def load_settings(self):
"""QSettings에서 체크박스 상태 및 API 키를 불러옵니다."""
for name, widgets in self.translator_settings.items():
checkbox = widgets["checkbox"]
api_key_field = widgets["api_key"]
# 체크박스 상태 복원
state = self.settings.value(f"{name}_checked", False, type=bool)
checkbox.setChecked(state)
# API 키 복원
if api_key_field:
api_key = self.settings.value(f"{name}_api_key", "", type=str)
api_key_field.setText(api_key)
def save_settings(self):
"""QSettings에 체크박스 상태 및 API 키를 저장합니다."""
for name, widgets in self.translator_settings.items():
checkbox = widgets["checkbox"]
api_key_field = widgets["api_key"]
# 체크박스 상태 저장
self.settings.setValue(f"{name}_checked", checkbox.isChecked())
# API 키 저장
if api_key_field:
self.settings.setValue(f"{name}_api_key", api_key_field.text())
def toggle_api_key_field(self, name, state):
"""API 키 입력 필드의 가시성을 토글합니다."""
api_key_field = self.translator_settings[name]["api_key"]
if api_key_field:
api_key_field.setVisible(state == Qt.Checked)
def apply_settings(self):
"""선택된 번역기를 업데이트하고 설정을 저장합니다."""
self.selected_services = []
for name, widgets in self.translator_settings.items():
checkbox = widgets["checkbox"]
api_key_field = widgets["api_key"]
if checkbox.isChecked():
# 필요한 번역기 추가
if name == "Bing":
self.selected_services.append(BingTranslate())
elif name == "DeepL":
self.selected_services.append(DeeplTranslate(api_key=api_key_field.text()))
elif name == "Google":
self.selected_services.append(GoogleTranslate())
elif name == "LibreTranslate":
self.selected_services.append(LibreTranslate())
elif name == "MyMemory":
self.selected_services.append(MyMemoryTranslate())
elif name == "Reverso":
self.selected_services.append(ReversoTranslate())
elif name == "Yandex":
self.selected_services.append(YandexTranslate(api_key=api_key_field.text()))
elif name == "Microsoft":
self.selected_services.append(MicrosoftTranslate(api_key=api_key_field.text()))
# 설정 저장
self.save_settings()
# 창 최소화
self.showMinimized()
def toggle_auto_translate(self):
if self.auto_translate_toggle.isChecked():
self.auto_translate_enabled = True
self.last_clipboard_content = pyperclip.paste()
self.clipboard_timer.start(500) # 0.5초마다 클립보드 감지
else:
self.auto_translate_enabled = False
self.clipboard_timer.stop()
def monitor_clipboard(self):
if not self.auto_translate_enabled:
return
clipboard_text = pyperclip.paste()
if clipboard_text != self.last_clipboard_content:
self.last_clipboard_content = clipboard_text
self.run_translation_in_main_thread()
def run_translation_in_main_thread(self):
"""메인 스레드에서 번역 실행."""
QTimer.singleShot(0, self.run_translation)
def run_translation(self):
# 클립보드 텍스트 가져오기
clipboard_text = pyperclip.paste()
if not clipboard_text.strip():
self.show_popup("클립보드에 텍스트가 없습니다.")
return
# 번역 결과 생성
results = []
for service in self.selected_services:
try:
result = service.translate(clipboard_text, "Korean")
service_name = service.__class__.__name__.replace("Translate", "")
# 요청 카운트 증가
if service_name in self.request_count:
self.request_count[service_name] += 1
# 번역 결과 추가
results.append(
f"[{service_name}]\n{result.result}\n\n(사용량: {self.request_count[service_name]}번 요청됨)"
)
except Exception as e:
service_name = service.__class__.__name__.replace("Translate", "")
results.append(f"[{service_name}] 번역 실패: {str(e)}")
# 결과 표시
self.show_popup("\n\n".join(results))
def show_popup(self, message):
popup = QMessageBox(self)
popup.setWindowTitle("번역 결과")
popup.setText(message)
popup.setStandardButtons(QMessageBox.Close)
popup.show()
def eventFilter(self, source, event):
if event.type() == QEvent.KeyPress and event.key() == Qt.Key_Escape:
self.showMinimized()
return super().eventFilter(source, event)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MultiTranslatorApp()
window.show()
sys.exit(app.exec())