383 lines
15 KiB
Python
383 lines
15 KiB
Python
from PySide6.QtWidgets import (QWidget, QVBoxLayout, QTabWidget, QPushButton,
|
|
QLabel, QLineEdit, QListWidget, QTextEdit)
|
|
from PySide6.QtCore import Qt, Signal, Slot
|
|
from modules.xlsFilter.xls_filter_dialog import XlsFilterDialog
|
|
|
|
# Fluent Widgets 추가
|
|
from qfluentwidgets import (ScrollArea, ExpandLayout, SimpleCardWidget, SettingCardGroup,
|
|
SwitchSettingCard, ComboBoxSettingCard, ToolButton, FluentIcon,
|
|
PrimaryPushButton, InfoBar, InfoBarPosition, SpinBox, LineEdit,
|
|
TextEdit, ListWidget, PushButton, TabWidget, SmoothScrollArea)
|
|
|
|
class ToolsWidget(ScrollArea):
|
|
# 시그널 정의
|
|
status_changed = Signal(str)
|
|
|
|
def __init__(self, parent=None, thread_pool=None, logger=None, forbidden_words=None, category_manager=None):
|
|
super().__init__(parent)
|
|
self.parent = parent
|
|
self.thread_pool = thread_pool
|
|
self.logger = logger
|
|
self.forbidden_words = forbidden_words
|
|
self.category_manager = category_manager
|
|
|
|
if self.logger:
|
|
self.logger.info("도구 위젯 초기화 시작")
|
|
|
|
self.setup_ui()
|
|
|
|
if self.logger:
|
|
self.logger.info("도구 위젯 초기화 완료")
|
|
|
|
def setup_ui(self):
|
|
# 스크롤 영역 설정
|
|
self.setWidgetResizable(True)
|
|
|
|
# 메인 위젯 및 레이아웃
|
|
self.main_widget = QWidget()
|
|
self.expand_layout = ExpandLayout(self.main_widget)
|
|
|
|
# 탭 위젯 생성
|
|
self.tab_widget = TabWidget(self.main_widget)
|
|
|
|
# 배송비 계산기 탭
|
|
self.shipping_calc_tab = QWidget()
|
|
self.setup_shipping_calc_tab()
|
|
self.tab_widget.addTab(self.shipping_calc_tab, "배송비 계산기")
|
|
|
|
# 금지어 관리 탭
|
|
self.forbidden_words_tab = QWidget()
|
|
self.setup_forbidden_words_tab()
|
|
self.tab_widget.addTab(self.forbidden_words_tab, "금지어 관리")
|
|
|
|
# 카테고리 관리 탭
|
|
self.category_tab = QWidget()
|
|
self.setup_category_tab()
|
|
self.tab_widget.addTab(self.category_tab, "카테고리 관리")
|
|
|
|
# 로그 관리 탭
|
|
self.log_tab = QWidget()
|
|
self.setup_log_tab()
|
|
self.tab_widget.addTab(self.log_tab, "로그 관리")
|
|
|
|
# 엑셀 필터링 탭
|
|
self.xls_filter_tab = QWidget()
|
|
self.setup_xls_filter_tab()
|
|
self.tab_widget.addTab(self.xls_filter_tab, "엑셀 필터링")
|
|
|
|
# 카드 그룹 추가
|
|
card_group = SettingCardGroup("도구 모음", self.main_widget)
|
|
card_text = "다양한 도구를 탭을 통해 사용할 수 있습니다."
|
|
|
|
# 도구 카드 추가
|
|
self.tools_card = SimpleCardWidget(FluentIcon.SETTING, "도구 모음", card_text, self.main_widget)
|
|
self.tools_card.setFixedHeight(120)
|
|
self.tools_card.setFixedWidth(self.width())
|
|
|
|
# 레이아웃에 위젯 추가
|
|
self.expand_layout.addWidget(self.tools_card)
|
|
self.expand_layout.addWidget(card_group)
|
|
self.expand_layout.addWidget(self.tab_widget)
|
|
|
|
# 위젯 설정
|
|
self.setWidget(self.main_widget)
|
|
|
|
def setup_shipping_calc_tab(self):
|
|
layout = QVBoxLayout(self.shipping_calc_tab)
|
|
|
|
# 설정 카드 그룹
|
|
card_group = SettingCardGroup("배송비 계산", self.shipping_calc_tab)
|
|
|
|
# 무게 입력
|
|
self.weight_input = SpinBox(self.shipping_calc_tab)
|
|
self.weight_input.setRange(0, 100)
|
|
self.weight_input.setSuffix(" kg")
|
|
self.weight_input.setToolTip("배송 상품의 무게를 입력하세요")
|
|
weight_card = ComboBoxSettingCard(
|
|
FluentIcon.WEIGHT,
|
|
"무게",
|
|
"배송 상품의 무게를 입력하세요",
|
|
customWidget=self.weight_input,
|
|
parent=card_group
|
|
)
|
|
|
|
# 지역 선택
|
|
self.region_input = LineEdit(self.shipping_calc_tab)
|
|
self.region_input.setPlaceholderText("배송 지역")
|
|
region_card = ComboBoxSettingCard(
|
|
FluentIcon.GLOBE,
|
|
"지역",
|
|
"배송 지역을 입력하세요",
|
|
customWidget=self.region_input,
|
|
parent=card_group
|
|
)
|
|
|
|
# 카드 그룹에 추가
|
|
card_group.addSettingCard(weight_card)
|
|
card_group.addSettingCard(region_card)
|
|
|
|
# 계산 버튼
|
|
self.calc_button = PrimaryPushButton("계산하기")
|
|
self.calc_button.clicked.connect(self.calculate_shipping)
|
|
|
|
# 결과 표시
|
|
self.result_label = QLabel("배송비: ")
|
|
|
|
# 레이아웃에 위젯 추가
|
|
layout.addWidget(card_group)
|
|
layout.addWidget(self.calc_button)
|
|
layout.addWidget(self.result_label)
|
|
layout.addStretch()
|
|
|
|
def setup_forbidden_words_tab(self):
|
|
layout = QVBoxLayout(self.forbidden_words_tab)
|
|
|
|
# 설정 카드 그룹
|
|
card_group = SettingCardGroup("금지어 관리", self.forbidden_words_tab)
|
|
|
|
# 금지어 입력
|
|
self.word_input = LineEdit(self.forbidden_words_tab)
|
|
self.word_input.setPlaceholderText("금지어 입력")
|
|
word_card = ComboBoxSettingCard(
|
|
FluentIcon.REMOVE,
|
|
"금지어",
|
|
"추가할 금지어를 입력하세요. 콤마 또는 공백으로 구분하여 여러 개 입력 가능합니다.",
|
|
customWidget=self.word_input,
|
|
parent=card_group
|
|
)
|
|
card_group.addSettingCard(word_card)
|
|
|
|
# 추가 버튼
|
|
self.add_button = PrimaryPushButton("추가")
|
|
self.add_button.clicked.connect(self.add_forbidden_word)
|
|
|
|
# 금지어 목록
|
|
self.word_list = ListWidget(self.forbidden_words_tab)
|
|
|
|
# 삭제 버튼
|
|
self.delete_button = PushButton("선택 삭제")
|
|
self.delete_button.setIcon(FluentIcon.DELETE)
|
|
self.delete_button.clicked.connect(self.delete_forbidden_word)
|
|
|
|
# 금지어 목록 로드
|
|
if self.forbidden_words:
|
|
self.load_forbidden_words()
|
|
|
|
# 레이아웃에 위젯 추가
|
|
layout.addWidget(card_group)
|
|
layout.addWidget(self.add_button)
|
|
layout.addWidget(self.word_list)
|
|
layout.addWidget(self.delete_button)
|
|
|
|
def setup_category_tab(self):
|
|
layout = QVBoxLayout(self.category_tab)
|
|
|
|
# 설정 카드 그룹
|
|
card_group = SettingCardGroup("카테고리 관리", self.category_tab)
|
|
|
|
# 카테고리 입력
|
|
self.category_input = LineEdit(self.category_tab)
|
|
self.category_input.setPlaceholderText("카테고리 입력")
|
|
category_card = ComboBoxSettingCard(
|
|
FluentIcon.FOLDER,
|
|
"카테고리",
|
|
"추가할 카테고리를 입력하세요",
|
|
customWidget=self.category_input,
|
|
parent=card_group
|
|
)
|
|
card_group.addSettingCard(category_card)
|
|
|
|
# 추가 버튼
|
|
self.add_cat_button = PrimaryPushButton("추가")
|
|
self.add_cat_button.clicked.connect(self.add_category)
|
|
|
|
# 카테고리 목록
|
|
self.category_list = ListWidget(self.category_tab)
|
|
|
|
# 삭제 버튼
|
|
self.delete_cat_button = PushButton("선택 삭제")
|
|
self.delete_cat_button.setIcon(FluentIcon.DELETE)
|
|
self.delete_cat_button.clicked.connect(self.delete_category)
|
|
|
|
# 카테고리 목록 로드
|
|
if self.category_manager:
|
|
self.load_categories()
|
|
|
|
# 레이아웃에 위젯 추가
|
|
layout.addWidget(card_group)
|
|
layout.addWidget(self.add_cat_button)
|
|
layout.addWidget(self.category_list)
|
|
layout.addWidget(self.delete_cat_button)
|
|
|
|
def setup_log_tab(self):
|
|
layout = QVBoxLayout(self.log_tab)
|
|
|
|
# 설정 카드 그룹
|
|
card_group = SettingCardGroup("로그 관리", self.log_tab)
|
|
card_group.addSettingCard(SwitchSettingCard(
|
|
FluentIcon.HISTORY,
|
|
"자동 저장",
|
|
"로그를 자동으로 파일에 저장합니다",
|
|
True,
|
|
parent=card_group
|
|
))
|
|
|
|
# 로그 표시 영역
|
|
self.log_text = TextEdit(self.log_tab)
|
|
self.log_text.setReadOnly(True)
|
|
|
|
# 로그 정리 버튼
|
|
self.clear_button = PushButton("로그 정리")
|
|
self.clear_button.setIcon(FluentIcon.CLEAR)
|
|
self.clear_button.clicked.connect(self.clear_logs)
|
|
|
|
# 레이아웃에 위젯 추가
|
|
layout.addWidget(card_group)
|
|
layout.addWidget(self.log_text)
|
|
layout.addWidget(self.clear_button)
|
|
|
|
def setup_xls_filter_tab(self):
|
|
layout = QVBoxLayout(self.xls_filter_tab)
|
|
|
|
# 설정 카드 그룹
|
|
card_group = SettingCardGroup("엑셀 필터링", self.xls_filter_tab)
|
|
card_text = "엑셀 파일에서 상품 정보를 추출하고 금지어/카테고리를 필터링합니다."
|
|
|
|
info_card = SimpleCardWidget(FluentIcon.FILTER, "엑셀 필터링", card_text, self.xls_filter_tab)
|
|
info_card.setFixedHeight(120)
|
|
|
|
# 엑셀 필터링 버튼
|
|
self.filter_button = PrimaryPushButton("엑셀 필터링 실행")
|
|
self.filter_button.setIcon(FluentIcon.FILTER)
|
|
self.filter_button.clicked.connect(self.run_xls_filter)
|
|
|
|
# 레이아웃에 위젯 추가
|
|
layout.addWidget(card_group)
|
|
layout.addWidget(info_card)
|
|
layout.addWidget(self.filter_button)
|
|
layout.addStretch()
|
|
|
|
def calculate_shipping(self):
|
|
weight = self.weight_input.value()
|
|
region = self.region_input.text()
|
|
|
|
if not region:
|
|
self.show_info_bar("경고", "지역을 입력해주세요", InfoBarPosition.TOP, True)
|
|
self.status_changed.emit("무게와 지역을 입력해주세요.")
|
|
return
|
|
|
|
try:
|
|
# 여기에서 실제 배송비 계산 로직을 구현
|
|
shipping_cost = weight * 2500 # 예시 계산 로직
|
|
self.result_label.setText(f"배송비: {shipping_cost:,} 원")
|
|
self.status_changed.emit(f"배송비 계산 완료: {shipping_cost:,} 원")
|
|
self.show_info_bar("완료", f"배송비 계산 완료: {shipping_cost:,} 원", InfoBarPosition.BOTTOM_RIGHT)
|
|
except ValueError:
|
|
self.show_info_bar("오류", "무게는 숫자로 입력해주세요.", InfoBarPosition.TOP, True)
|
|
self.status_changed.emit("무게는 숫자로 입력해주세요.")
|
|
|
|
def show_info_bar(self, title, content, position=InfoBarPosition.TOP, is_error=False):
|
|
"""정보 바 표시"""
|
|
if is_error:
|
|
InfoBar.error(
|
|
title=title,
|
|
content=content,
|
|
parent=self,
|
|
position=position,
|
|
duration=3000
|
|
)
|
|
else:
|
|
InfoBar.success(
|
|
title=title,
|
|
content=content,
|
|
parent=self,
|
|
position=position,
|
|
duration=3000
|
|
)
|
|
|
|
def load_forbidden_words(self):
|
|
"""금지어 목록 로드"""
|
|
if self.logger:
|
|
self.logger.debug("금지어 목록 로드 시작")
|
|
|
|
words = self.forbidden_words.get_all_words()
|
|
self.word_list.clear()
|
|
for word in words:
|
|
self.word_list.addItem(word)
|
|
|
|
if self.logger:
|
|
self.logger.debug(f"금지어 {len(words)}개 로드 완료")
|
|
|
|
def add_forbidden_word(self):
|
|
word = self.word_input.text()
|
|
if word:
|
|
if self.forbidden_words:
|
|
self.forbidden_words.add_word(word)
|
|
self.status_changed.emit(f"금지어 '{word}' 추가됨")
|
|
self.show_info_bar("추가 완료", f"금지어 '{word}' 추가됨", InfoBarPosition.BOTTOM_RIGHT)
|
|
self.word_list.addItem(word)
|
|
self.word_input.clear()
|
|
|
|
def delete_forbidden_word(self):
|
|
current_item = self.word_list.currentItem()
|
|
if current_item:
|
|
word = current_item.text()
|
|
if self.forbidden_words:
|
|
self.forbidden_words.remove_word(word)
|
|
self.status_changed.emit(f"금지어 '{word}' 삭제됨")
|
|
self.show_info_bar("삭제 완료", f"금지어 '{word}' 삭제됨", InfoBarPosition.BOTTOM_RIGHT)
|
|
self.word_list.takeItem(self.word_list.row(current_item))
|
|
|
|
def load_categories(self):
|
|
"""카테고리 목록 로드"""
|
|
if self.logger:
|
|
self.logger.debug("카테고리 목록 로드 시작")
|
|
|
|
categories = self.category_manager.get_all_categories()
|
|
self.category_list.clear()
|
|
for category in categories:
|
|
self.category_list.addItem(category)
|
|
|
|
if self.logger:
|
|
self.logger.debug(f"카테고리 {len(categories)}개 로드 완료")
|
|
|
|
def add_category(self):
|
|
category = self.category_input.text()
|
|
if category:
|
|
if self.category_manager:
|
|
self.category_manager.add_category(category)
|
|
self.status_changed.emit(f"카테고리 '{category}' 추가됨")
|
|
self.show_info_bar("추가 완료", f"카테고리 '{category}' 추가됨", InfoBarPosition.BOTTOM_RIGHT)
|
|
self.category_list.addItem(category)
|
|
self.category_input.clear()
|
|
|
|
def delete_category(self):
|
|
current_item = self.category_list.currentItem()
|
|
if current_item:
|
|
category = current_item.text()
|
|
if self.category_manager:
|
|
self.category_manager.remove_category(category)
|
|
self.status_changed.emit(f"카테고리 '{category}' 삭제됨")
|
|
self.show_info_bar("삭제 완료", f"카테고리 '{category}' 삭제됨", InfoBarPosition.BOTTOM_RIGHT)
|
|
self.category_list.takeItem(self.category_list.row(current_item))
|
|
|
|
def clear_logs(self):
|
|
self.log_text.clear()
|
|
self.status_changed.emit("로그가 정리되었습니다.")
|
|
self.show_info_bar("완료", "로그가 정리되었습니다", InfoBarPosition.BOTTOM_RIGHT)
|
|
|
|
def run_xls_filter(self):
|
|
if self.logger:
|
|
self.logger.info("엑셀 필터링 다이얼로그 실행")
|
|
|
|
# 다이얼로그에 필요한 관리자 객체 전달
|
|
dialog = XlsFilterDialog(
|
|
parent=self,
|
|
thread_pool=self.thread_pool,
|
|
logger=self.logger,
|
|
forbidden_words=self.forbidden_words,
|
|
category_manager=self.category_manager
|
|
)
|
|
|
|
dialog.status_changed.connect(self.status_changed.emit)
|
|
dialog.exec() |