BookMakerAdder/test/t5.py

459 lines
20 KiB
Python

import sys
import asyncio
from PySide6 import QtWidgets, QtCore, QtGui, QtWebEngineWidgets
from PySide6.QtCore import QUrl, QTimer
from PySide6.QtGui import QIcon, QAction
from PySide6.QtWidgets import QToolBar, QLineEdit, QMessageBox, QHBoxLayout, QWidget, QDialog, QFormLayout, QDialogButtonBox
from playwright.async_api import async_playwright
# chrome_sync 모듈 import (플레이스홀더)
import chrome_sync
# Playwright 자동화 작업을 위한 QThread 클래스
class PlaywrightThread(QtCore.QThread):
result_signal = QtCore.Signal(str)
def run(self):
asyncio.run(self.run_playwright())
async def run_playwright(self):
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False)
page = await browser.new_page()
await page.goto("https://example.com")
screenshot_path = "screenshot.png"
await page.screenshot(path=screenshot_path)
await browser.close()
self.result_signal.emit(f"Playwright 자동화 완료: 스크린샷 저장 - {screenshot_path}")
# 각 브라우저 탭에 들어갈 위젯 클래스 (QWebEngineView 포함)
class BrowserTab(QtWidgets.QWidget):
def __init__(self, url, parent=None):
super().__init__(parent)
layout = QtWidgets.QVBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
self.web_view = QtWebEngineWidgets.QWebEngineView()
layout.addWidget(self.web_view)
self.web_view.setUrl(QUrl(url))
# 북마크 수정/추가 다이얼로그
class BookmarkEditDialog(QDialog):
def __init__(self, bookmark=None, parent=None):
super().__init__(parent)
self.setWindowTitle("북마크 수정" if bookmark else "새 북마크 추가")
layout = QFormLayout(self)
self.name_edit = QLineEdit()
self.url_edit = QLineEdit()
self.folder_edit = QLineEdit()
if bookmark:
self.name_edit.setText(bookmark["name"])
self.url_edit.setText(bookmark["url"])
self.folder_edit.setText(bookmark.get("folder", ""))
layout.addRow("이름:", self.name_edit)
layout.addRow("주소:", self.url_edit)
layout.addRow("폴더 경로:", self.folder_edit)
button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
button_box.accepted.connect(self.accept)
button_box.rejected.connect(self.reject)
layout.addWidget(button_box)
def getData(self):
return {
"name": self.name_edit.text().strip(),
"url": self.url_edit.text().strip(),
"folder": self.folder_edit.text().strip()
}
# 북마크 버튼 (QToolButton 확장) - 우클릭 시 수정 메뉴 제공
class BookmarkButton(QtWidgets.QToolButton):
def __init__(self, bookmark, edit_callback, parent=None):
super().__init__(parent)
self.bookmark = bookmark
self.edit_callback = edit_callback
self.setText(bookmark["name"])
self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.show_context_menu)
def show_context_menu(self, pos):
menu = QtWidgets.QMenu(self)
edit_action = menu.addAction("북마크 수정")
action = menu.exec(self.mapToGlobal(pos))
if action == edit_action:
self.edit_callback(self)
# 도구 패널(QTabWidget) - 세로 탭
class ToolPanel(QtWidgets.QTabWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setTabPosition(QtWidgets.QTabWidget.West)
self.setMinimumWidth(250)
self.auto_hide = False
self.hide_timer = QTimer(self)
self.hide_timer.setInterval(500)
self.hide_timer.setSingleShot(True)
self.hide_timer.timeout.connect(self.hide_panel)
self.installEventFilter(self)
def eventFilter(self, obj, event):
if self.auto_hide:
if event.type() == QtCore.QEvent.Leave:
self.hide_timer.start()
elif event.type() == QtCore.QEvent.Enter:
self.hide_timer.stop()
return super().eventFilter(obj, event)
def hide_panel(self):
self.hide()
def show_panel(self):
self.show()
# 문자전송 탭의 간단한 예제 위젯
class MessageTab(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(QtWidgets.QLabel("문자전송 기능"))
self.message_input = QtWidgets.QLineEdit()
self.message_input.setPlaceholderText("보낼 메시지를 입력하세요")
self.send_button = QtWidgets.QPushButton("전송")
self.send_button.clicked.connect(self.send_message)
layout.addWidget(self.message_input)
layout.addWidget(self.send_button)
self.status_label = QtWidgets.QLabel("")
layout.addWidget(self.status_label)
def send_message(self):
message = self.message_input.text()
# 실제 문자 전송 API 호출 구현 필요
self.status_label.setText(f"전송됨: {message}")
# 메인 윈도우 클래스
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("크롬과 유사한 커스텀 브라우저")
self.resize(1920, 1080)
# 북마크 리스트 (각 항목은 dict: name, url, folder)
self.bookmarks = []
# 메인 레이아웃: 브라우저 영역과 도구 패널 (세로 탭)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
self.main_layout = QtWidgets.QHBoxLayout(central_widget)
self.main_layout.setContentsMargins(0, 0, 0, 0)
# 브라우저 영역 (네비게이션 바, 북마크 바, 브라우저 탭)
self.browser_area = QtWidgets.QWidget()
self.init_browser_area()
self.main_layout.addWidget(self.browser_area, 8)
# 도구 패널
self.tool_panel = ToolPanel()
self.init_tool_panel()
self.main_layout.addWidget(self.tool_panel, 2)
def init_browser_area(self):
layout = QtWidgets.QVBoxLayout(self.browser_area)
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)
# 1. 네비게이션 바 (아이콘 버튼 + 주소창 등)
self.nav_toolbar = QToolBar()
self.nav_toolbar.setIconSize(QtCore.QSize(24, 24))
self.nav_toolbar.setMovable(False)
layout.addWidget(self.nav_toolbar)
# 뒤로가기
back_icon = self.style().standardIcon(QtWidgets.QStyle.SP_ArrowBack)
back_action = QAction(back_icon, "", self)
back_action.triggered.connect(self.navigate_back)
self.nav_toolbar.addAction(back_action)
# 앞으로가기
forward_icon = self.style().standardIcon(QtWidgets.QStyle.SP_ArrowForward)
forward_action = QAction(forward_icon, "", self)
forward_action.triggered.connect(self.navigate_forward)
self.nav_toolbar.addAction(forward_action)
# 새로고침
refresh_icon = self.style().standardIcon(QtWidgets.QStyle.SP_BrowserReload)
refresh_action = QAction(refresh_icon, "", self)
refresh_action.triggered.connect(self.refresh_page)
self.nav_toolbar.addAction(refresh_action)
# 주소창
self.url_bar = QLineEdit()
self.url_bar.returnPressed.connect(self.load_url_from_bar)
self.url_bar.setMinimumWidth(400)
self.nav_toolbar.addWidget(self.url_bar)
self.nav_toolbar.addSeparator()
# 북마크 추가 (아이콘)
bookmark_icon = self.style().standardIcon(QtWidgets.QStyle.SP_DialogYesButton)
bookmark_action = QAction(bookmark_icon, "", self)
bookmark_action.triggered.connect(self.new_bookmark)
self.nav_toolbar.addAction(bookmark_action)
# 확장 프로그램 (아이콘)
ext_icon = self.style().standardIcon(QtWidgets.QStyle.SP_DirIcon)
ext_action = QAction(ext_icon, "", self)
ext_action.triggered.connect(self.show_extensions)
self.nav_toolbar.addAction(ext_action)
# 2. 북마크 바 (주소창 바로 아래) - 오른쪽 끝에 도구 패널 토글 버튼 포함
self.bookmark_bar_widget = QWidget()
bookmark_layout = QHBoxLayout(self.bookmark_bar_widget)
bookmark_layout.setContentsMargins(2, 2, 2, 2)
self.bookmark_toolbar = QToolBar()
self.bookmark_toolbar.setMovable(False)
self.bookmark_toolbar.setIconSize(QtCore.QSize(20, 20))
bookmark_layout.addWidget(self.bookmark_toolbar)
bookmark_layout.addStretch()
self.tool_toggle_button = QtWidgets.QToolButton()
toggle_icon = self.style().standardIcon(QtWidgets.QStyle.SP_ComputerIcon)
self.tool_toggle_button.setIcon(toggle_icon)
self.tool_toggle_button.setCheckable(True)
self.tool_toggle_button.setChecked(True)
self.tool_toggle_button.clicked.connect(self.toggle_tool_panel)
self.tool_toggle_button.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.tool_toggle_button.customContextMenuRequested.connect(self.show_toggle_menu)
bookmark_layout.addWidget(self.tool_toggle_button)
layout.addWidget(self.bookmark_bar_widget)
self.load_sync_bookmarks()
# 3. 브라우저 탭 영역
self.browser_tabs = QtWidgets.QTabWidget()
self.browser_tabs.setTabsClosable(True)
self.browser_tabs.tabCloseRequested.connect(self.close_current_tab)
self.browser_tabs.currentChanged.connect(self.update_url_bar)
layout.addWidget(self.browser_tabs)
# 첫 탭 추가
self.add_new_tab("https://www.google.com", "Google")
def init_tool_panel(self):
# 도구 패널 탭 추가 (세로 탭)
# 배송비 계산기 탭
self.shipping_tab = QtWidgets.QWidget()
self.init_shipping_tab()
self.tool_panel.addTab(self.shipping_tab, "배송비")
# 금지어 관리 탭
self.prohibited_tab = QtWidgets.QWidget()
self.init_prohibited_tab()
self.tool_panel.addTab(self.prohibited_tab, "금지어")
# 카테고리 관리 탭
self.category_tab = QtWidgets.QWidget()
self.init_category_tab()
self.tool_panel.addTab(self.category_tab, "카테고리")
# Playwright 매크로 탭
self.playwright_tab = QtWidgets.QWidget()
self.init_playwright_tab()
self.tool_panel.addTab(self.playwright_tab, "Playwright")
# 문자전송 탭
self.message_tab = MessageTab()
self.tool_panel.addTab(self.message_tab, "문자전송")
def add_new_tab(self, url="https://www.google.com", label="New Tab"):
new_tab = BrowserTab(url)
index = self.browser_tabs.addTab(new_tab, label)
self.browser_tabs.setCurrentIndex(index)
new_tab.web_view.urlChanged.connect(lambda qurl, tab=new_tab: self.update_tab_title(tab, qurl))
new_tab.web_view.loadFinished.connect(lambda ok, tab=new_tab: self.update_url_bar())
def close_current_tab(self, index):
if self.browser_tabs.count() > 1:
self.browser_tabs.removeTab(index)
def update_tab_title(self, tab, qurl):
title = tab.web_view.title() or qurl.toString()
index = self.browser_tabs.indexOf(tab)
self.browser_tabs.setTabText(index, title)
if self.browser_tabs.currentWidget() == tab:
self.url_bar.setText(qurl.toString())
def update_url_bar(self):
current_tab = self.browser_tabs.currentWidget()
if current_tab:
url = current_tab.web_view.url().toString()
self.url_bar.setText(url)
def load_url_from_bar(self):
url_text = self.url_bar.text().strip()
if url_text and not url_text.startswith("http"):
url_text = "http://" + url_text
current_tab = self.browser_tabs.currentWidget()
if current_tab:
current_tab.web_view.setUrl(QUrl(url_text))
def navigate_back(self):
current_tab = self.browser_tabs.currentWidget()
if current_tab:
current_tab.web_view.back()
def navigate_forward(self):
current_tab = self.browser_tabs.currentWidget()
if current_tab:
current_tab.web_view.forward()
def refresh_page(self):
current_tab = self.browser_tabs.currentWidget()
if current_tab:
current_tab.web_view.reload()
# 북마크 추가 버튼 클릭 시: 새 북마크 다이얼로그 띄움
def new_bookmark(self):
dialog = BookmarkEditDialog(parent=self)
if dialog.exec() == QDialog.Accepted:
data = dialog.getData()
self.bookmarks.append(data)
self.add_bookmark_button(data)
# 북마크 바에 버튼 추가
def add_bookmark_button(self, bookmark):
btn = BookmarkButton(bookmark, edit_callback=self.edit_bookmark)
btn.clicked.connect(lambda checked, url=bookmark["url"]: self.open_bookmark(url))
self.bookmark_toolbar.addWidget(btn)
# 우클릭으로 북마크 수정 호출
def edit_bookmark(self, btn: BookmarkButton):
dialog = BookmarkEditDialog(bookmark=btn.bookmark, parent=self)
if dialog.exec() == QDialog.Accepted:
data = dialog.getData()
btn.bookmark = data
btn.setText(data["name"])
# 업데이트된 데이터를 bookmarks 리스트에도 반영
for bm in self.bookmarks:
if bm["url"] == btn.bookmark["url"]:
bm.update(data)
break
def open_bookmark(self, url):
current_tab = self.browser_tabs.currentWidget()
if current_tab:
current_tab.web_view.setUrl(QUrl(url))
def load_sync_bookmarks(self):
# chrome_sync 모듈을 통해 동기화된 북마크 가져오기 (플레이스홀더)
sync_bookmarks = chrome_sync.get_chrome_bookmarks()
for bm in sync_bookmarks:
if bm not in self.bookmarks:
self.bookmarks.append(bm)
self.add_bookmark_button(bm)
def show_extensions(self):
# chrome_sync 모듈을 통해 확장 프로그램 가져오기 (플레이스홀더)
ext_list = chrome_sync.get_chrome_extensions()
msg = "\n".join(ext_list)
QMessageBox.information(self, "확장 프로그램", f"사용 가능한 확장 프로그램:\n{msg}")
def init_shipping_tab(self):
layout = QtWidgets.QVBoxLayout(self.shipping_tab)
layout.addWidget(QtWidgets.QLabel("배송비 계산기"))
self.weight_input = QtWidgets.QLineEdit()
self.weight_input.setPlaceholderText("무게 입력")
self.size_input = QtWidgets.QLineEdit()
self.size_input.setPlaceholderText("크기 입력")
self.calculate_button = QtWidgets.QPushButton("계산")
self.calculate_result = QtWidgets.QLabel("결과:")
self.calculate_button.clicked.connect(self.calculate_shipping)
layout.addWidget(self.weight_input)
layout.addWidget(self.size_input)
layout.addWidget(self.calculate_button)
layout.addWidget(self.calculate_result)
def calculate_shipping(self):
try:
shipping_cost = float(self.weight_input.text()) * 0.5 + float(self.size_input.text()) * 0.3
self.calculate_result.setText(f"결과: {shipping_cost:.2f}")
except ValueError:
self.calculate_result.setText("올바른 숫자를 입력하세요.")
def init_prohibited_tab(self):
layout = QtWidgets.QVBoxLayout(self.prohibited_tab)
layout.addWidget(QtWidgets.QLabel("금지어 관리"))
self.prohibited_table = QtWidgets.QTableWidget(0, 3)
self.prohibited_table.setHorizontalHeaderLabels(["단어", "등급", "비고"])
layout.addWidget(self.prohibited_table)
btn_layout = QtWidgets.QHBoxLayout()
self.add_word_button = QtWidgets.QPushButton("추가")
self.remove_word_button = QtWidgets.QPushButton("삭제")
btn_layout.addWidget(self.add_word_button)
btn_layout.addWidget(self.remove_word_button)
layout.addLayout(btn_layout)
self.add_word_button.clicked.connect(self.add_prohibited_word)
self.remove_word_button.clicked.connect(self.remove_prohibited_word)
def add_prohibited_word(self):
row = self.prohibited_table.rowCount()
self.prohibited_table.insertRow(row)
self.prohibited_table.setItem(row, 0, QtWidgets.QTableWidgetItem("dummy_word"))
self.prohibited_table.setItem(row, 1, QtWidgets.QTableWidgetItem("1"))
self.prohibited_table.setItem(row, 2, QtWidgets.QTableWidgetItem("추가됨"))
def remove_prohibited_word(self):
row = self.prohibited_table.currentRow()
if row >= 0:
self.prohibited_table.removeRow(row)
def init_category_tab(self):
layout = QtWidgets.QVBoxLayout(self.category_tab)
layout.addWidget(QtWidgets.QLabel("카테고리 관리"))
self.category_table = QtWidgets.QTableWidget(0, 4)
self.category_table.setHorizontalHeaderLabels(["카테고리", "필터링", "금지여부", "추가배송비"])
layout.addWidget(self.category_table)
for cat in ["전자제품", "의류", "식품"]:
row = self.category_table.rowCount()
self.category_table.insertRow(row)
self.category_table.setItem(row, 0, QtWidgets.QTableWidgetItem(cat))
self.category_table.setItem(row, 1, QtWidgets.QTableWidgetItem("필터링"))
self.category_table.setItem(row, 2, QtWidgets.QTableWidgetItem("미금지"))
self.category_table.setItem(row, 3, QtWidgets.QTableWidgetItem("0"))
def init_playwright_tab(self):
layout = QtWidgets.QVBoxLayout(self.playwright_tab)
layout.addWidget(QtWidgets.QLabel("Playwright 매크로"))
self.playwright_run_button = QtWidgets.QPushButton("실행")
self.playwright_output = QtWidgets.QTextEdit()
self.playwright_output.setReadOnly(True)
layout.addWidget(self.playwright_run_button)
layout.addWidget(self.playwright_output)
self.playwright_run_button.clicked.connect(self.run_playwright_macro)
def run_playwright_macro(self):
self.playwright_run_button.setEnabled(False)
self.playwright_output.append("Playwright 실행 중...")
self.thread = PlaywrightThread()
self.thread.result_signal.connect(self.handle_playwright_result)
self.thread.finished.connect(lambda: self.playwright_run_button.setEnabled(True))
self.thread.start()
def handle_playwright_result(self, result):
self.playwright_output.append(result)
def toggle_tool_panel(self):
if self.tool_toggle_button.isChecked():
self.tool_panel.show_panel()
else:
self.tool_panel.hide()
def show_toggle_menu(self, pos):
menu = QtWidgets.QMenu()
action = QtWidgets.QAction("자동 숨김 모드", self)
action.setCheckable(True)
action.setChecked(self.tool_panel.auto_hide)
action.triggered.connect(self.toggle_auto_hide)
menu.addAction(action)
menu.exec(self.tool_toggle_button.mapToGlobal(pos))
def toggle_auto_hide(self, checked):
self.tool_panel.auto_hide = checked
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())