NaverCatCodeGen/gui.py

519 lines
26 KiB
Python

import sys
import json
from PyQt5.QtWidgets import QDialog, QMainWindow, QApplication, QVBoxLayout, QWidget, QLineEdit, QComboBox, QPushButton, QLabel, QGridLayout, QMessageBox, QListWidget
from PyQt5.QtCore import Qt, QUrl
from PyQt5.QtGui import QClipboard, QDesktopServices
# import webbrowser
class SearchResultDialog(QDialog):
def __init__(self, results, mainWindow, parent=None):
super().__init__(parent)
self.mainWindow = mainWindow # 메인 윈도우 참조 저장
self.setWindowTitle('Search Results')
self.setGeometry(100, 100, 800, 300) # Dialog 크기 설정
layout = QVBoxLayout(self)
self.listWidget = QListWidget()
for result in results:
self.listWidget.addItem(result)
layout.addWidget(self.listWidget)
closeBtn = QPushButton('Close')
closeBtn.clicked.connect(self.close)
layout.addWidget(closeBtn)
self.listWidget.itemDoubleClicked.connect(self.itemDoubleClicked)
def itemDoubleClicked(self, item):
self.mainWindow.updateSelectionFromSearch(item.text())
self.accept()
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
# JSON 데이터와 카테고리 초기화
self.json_data = []
self.categories = {"category1Name": {}, "category2Name": {}, "category3Name": {}, "category4Name": {}}
self.setWindowTitle("내차타냐 코드검색기")
self.setGeometry(100, 100, 400, 300)
self.initUI() # UI 초기화
self.loadJsonData() # JSON 데이터 로딩
self.loadCategories() # 카테고리 로딩 및 콤보 박스 초기화
self.cat1 = ""
self.cat2 = ""
self.cat3 = ""
self.cat4 = ""
self.cat_code = ""
self.naver_code = ""
def loadJsonData(self):
self.json_data = [] # 데이터를 저장할 리스트 초기화
try:
with open("Percenty_SS_Code.json", "r", encoding='utf-8') as file:
for line in file:
item = json.loads(line)
# 'category3Name'과 'category4Name'의 '$numberDouble':"NaN"을 처리
if isinstance(item.get("category3Name"), dict) and "$numberDouble" in item["category3Name"]:
item["category3Name"] = "" # 또는 None 사용
if isinstance(item.get("category4Name"), dict) and "$numberDouble" in item["category4Name"]:
item["category4Name"] = "" # 또는 None 사용
self.json_data.append(item)
except FileNotFoundError:
QMessageBox.critical(self, "Error", "Percenty_SS_Code.json 파일을 찾을 수 없습니다.")
self.json_data = [] # 파일이 없을 경우 빈 리스트 할당
def initUI(self):
# Main widget and layout
self.mainWidget = QWidget()
self.setCentralWidget(self.mainWidget)
self.layout = QGridLayout()
self.mainWidget.setLayout(self.layout)
# Widgets
self.searchButton = QPushButton("Search")
self.inputField = QLineEdit()
self.inputField.setPlaceholderText("Search categories...")
self.inputSSField = QLineEdit()
self.inputSSField.setPlaceholderText("검색어 입력")
self.category1ComboBox = QComboBox()
self.category2ComboBox = QComboBox()
self.category3ComboBox = QComboBox()
self.category4ComboBox = QComboBox()
self.naverCodeLabel = QLabel("Naver Code: ")
self.catCodeLabel = QLabel("Cat Code: ")
self.catCodeButton = QPushButton("카테고리 코드 복사")
self.naverCodeButton = QPushButton("카테+검색어로 링크 열기")
# Adding widgets to layout
self.layout.addWidget(QLabel("카테고리 코드 검색"), 0, 0)
self.layout.addWidget(QLabel("Search:"), 1, 0)
self.layout.addWidget(self.inputField, 1, 1, 1, 2)
self.layout.addWidget(self.searchButton, 1, 3)
self.layout.addWidget(QLabel("Category 1:"), 2, 0)
self.layout.addWidget(self.category1ComboBox, 2, 1)
self.layout.addWidget(QLabel("Category 2:"), 3, 0)
self.layout.addWidget(self.category2ComboBox, 3, 1)
self.layout.addWidget(QLabel("Category 3:"), 4, 0)
self.layout.addWidget(self.category3ComboBox, 4, 1)
self.layout.addWidget(QLabel("Category 4:"), 5, 0)
self.layout.addWidget(self.category4ComboBox, 5, 1)
self.layout.addWidget(self.catCodeLabel, 6, 0)
self.layout.addWidget(self.catCodeButton, 6, 1)
self.layout.addWidget(self.naverCodeLabel, 7, 0)
self.layout.addWidget(self.naverCodeButton, 7, 1, 1, 1)
self.layout.addWidget(self.inputSSField, 7, 2, 1, 2)
self.layout.addWidget(QLabel("Made by 내차는언제타냐"), 8, 1)
# Event connections
self.category1ComboBox.currentIndexChanged.connect(self.updateCodeLabels)
self.category2ComboBox.currentIndexChanged.connect(self.updateCodeLabels)
self.category3ComboBox.currentIndexChanged.connect(self.updateCodeLabels)
self.category4ComboBox.currentIndexChanged.connect(self.updateCodeLabels)
# Event connections
# self.inputField.textChanged.connect(self.onSearchTextChanged)
self.category1ComboBox.currentIndexChanged.connect(lambda: self.onCategoryChanged(1))
self.category2ComboBox.currentIndexChanged.connect(lambda: self.onCategoryChanged(2))
self.category3ComboBox.currentIndexChanged.connect(lambda: self.onCategoryChanged(3))
self.category4ComboBox.currentIndexChanged.connect(lambda: self.onCategoryChanged(4))
# self.catCodeButton.clicked.connect(lambda: self.copyToClipboard(self.catCodeButton))
# self.naverCodeButton.clicked.connect(lambda: self.copyToClipboard(self.naverCodeButton))
self.catCodeButton.clicked.connect(lambda: self.copyToClipboard("cat_code"))
self.naverCodeButton.clicked.connect(self.on_naver_code_button_clicked)
self.searchButton.clicked.connect(self.showSearchResults)
self.inputField.returnPressed.connect(self.showSearchResults)
self.inputSSField.returnPressed.connect(self.on_naver_code_button_clicked)
self.updateCodeButtons()
def loadCategories(self):
# self.categories = {"category1Name": {}, "category2Name": {}, "category3Name": {}, "category4Name": {}}
try:
for item in self.json_data:
cat1 = item.get("category1Name")
cat2 = item.get("category2Name")
cat3 = item.get("category3Name", None)
cat4 = item.get("category4Name", None)
# category3Name과 category4Name 처리
cat3 = item.get("category3Name", None)
cat4 = item.get("category4Name", None)
if isinstance(cat3, dict) and "$numberDouble" in cat3:
cat3 = None # "$numberDouble":"NaN"일 경우 None으로 처리
if isinstance(cat4, dict) and "$numberDouble" in cat4:
cat4 = None # "$numberDouble":"NaN"일 경우 None으로 처리
# 계층 구조 구축
if cat1 not in self.categories["category1Name"]:
self.categories["category1Name"][cat1] = {"category2Name": {}}
if cat2 and cat2 not in self.categories["category1Name"][cat1]["category2Name"]:
self.categories["category1Name"][cat1]["category2Name"][cat2] = {"category3Name": {}}
if cat3 and cat3 not in self.categories["category1Name"][cat1]["category2Name"][cat2]["category3Name"]:
self.categories["category1Name"][cat1]["category2Name"][cat2]["category3Name"][cat3] = {"category4Name": {}}
if cat4:
self.categories["category1Name"][cat1]["category2Name"][cat2]["category3Name"][cat3]["category4Name"][cat4] = True
except Exception as e:
QMessageBox.critical(self, "Error", f"카테고리 로딩 에러.{e}")
return
# 첫 번째 콤보 박스를 대분류 카테고리로 초기화
self.category1ComboBox.addItems(sorted(self.categories["category1Name"].keys()))
def showSearchResults(self):
searchText = self.inputField.text()
if searchText.strip():
results = self.performSearch(searchText)
if results:
dialog = SearchResultDialog(results, self, self)
if dialog.exec_(): # Dialog 실행
# Dialog가 accept 되었을 때의 처리를 여기에 작성
pass
else:
QMessageBox.information(self, "No Results", "검색결과가 없습니다.")
else:
QMessageBox.warning(self, "Empty Search", "검색어를 입력하세요")
def performSearch(self, searchText):
results = []
for item in self.json_data:
cat1 = item["category1Name"]
cat2 = item["category2Name"]
cat3 = item.get("category3Name", 'N/A')
cat4 = item.get("category4Name", 'N/A')
cat_code = item.get("cat_code", 'N/A')
naver_code = item.get("Naver_code", 'N/A')
# cat3와 cat4가 문자열이 아니면 빈 문자열로 처리
cat3_str = f"-{cat3}" if cat3 and cat3 != 'N/A' else ''
cat4_str = f"-{cat4}" if cat4 and cat4 != 'N/A' else ''
if searchText.lower() in cat1.lower() or \
searchText.lower() in cat2.lower() or \
searchText.lower() in cat3_str.lower() or \
searchText.lower() in cat4_str.lower():
# 조건에 맞는 결과 문자열 생성
result_text = f"{cat_code} {cat1}-{cat2}{cat3_str}{cat4_str} - Naver Code: {naver_code}"
results.append(result_text)
print(f"performSearch result_text : {result_text}")
return results
def updateSelectionFromSearch(self, selectionText):
# 선택된 검색 결과에서 cat_code와 Naver_code를 추출
cat_code_part, naver_code_part = selectionText.split(" - ")
naver_code = naver_code_part.replace("Naver Code: ", "").strip()
self.naver_code = naver_code
print(f"선택된 naver_code : {naver_code}")
cat_code = cat_code_part.split(' ')[0]
self.cat_code = cat_code
print(f"선택된 cat_code : {cat_code}")
# 카테고리 경로 추출
categories_part = cat_code_part.split(" ")[1]
categories = categories_part.split("-")
# categories 리스트에서 '', 'N/A' 값을 제외한 실제 카테고리만 필터링
filtered_categories = [cat for cat in categories if cat and cat != 'N/A']
# 단계별로 카테고리 출력
if len(filtered_categories) - 0:
cat1 = filtered_categories[0]
print(f"Category 1: {cat1}")
if len(filtered_categories) - 1:
cat2 = filtered_categories[1]
print(f"Category 2: {cat2}")
if len(filtered_categories) - 2:
cat3 = filtered_categories[2]
print(f"Category 3: {cat3}")
if len(filtered_categories) - 3:
cat4 = filtered_categories[3]
print(f"Category 4: {cat4}")
# 콤보박스 업데이트
if filtered_categories:
if len(filtered_categories) - 0:
self.category1ComboBox.setCurrentText(filtered_categories[0])
if len(filtered_categories) - 1:
self.category2ComboBox.setCurrentText(filtered_categories[1])
if len(filtered_categories) - 2:
self.category3ComboBox.setCurrentText(filtered_categories[2])
if len(filtered_categories) - 3:
self.category4ComboBox.setCurrentText(filtered_categories[3])
# 레이블 업데이트
self.catCodeLabel.setText(f"Cat Code: {cat_code}")
self.naverCodeLabel.setText(f"Naver Code: {naver_code}")
# 각 단계의 콤보박스를 업데이트할 때 필요한 로직을 추가
self.updateComboBoxesAfterSelection(categories)
# # 해당 콤보박스 값이 변경됐을 때 연관된 하위 콤보박스 내용도 업데이트 되도록 강제로 변경 이벤트를 호출
# self.onCategoryChanged(1)
# self.onCategoryChanged(2)
# self.onCategoryChanged(3)
# self.onCategoryChanged(4)
def updateComboBoxesAfterSelection(self, selectedCategories):
# selectedCategories: 선택된 카테고리 목록 [cat1, cat2, cat3, cat4] (있을 경우)
# 첫 번째 카테고리 설정
if selectedCategories:
self.updateCategory1ComboBox(selectedCategories[0])
if len(selectedCategories) - 1:
self.updateCategory2ComboBox(selectedCategories[1])
if len(selectedCategories) - 2:
self.updateCategory3ComboBox(selectedCategories[2])
if len(selectedCategories) - 3:
self.updateCategory4ComboBox(selectedCategories[3])
def updateCategory1ComboBox(self, selectedCategory1):
self.category1ComboBox.setCurrentText(selectedCategory1)
self.updateCategory2ComboBox()
def updateCategory2ComboBox(self, selectedCategory2=None):
cat1 = self.category1ComboBox.currentText()
self.category2ComboBox.clear()
if cat1 in self.categories["category1Name"]:
cat2Names = sorted(self.categories["category1Name"][cat1]["category2Name"].keys())
self.category2ComboBox.addItems(cat2Names)
if selectedCategory2:
self.category2ComboBox.setCurrentText(selectedCategory2)
self.updateCategory3ComboBox()
def updateCategory3ComboBox(self, selectedCategory3=None):
cat1 = self.category1ComboBox.currentText()
cat2 = self.category2ComboBox.currentText()
self.category3ComboBox.clear()
if cat2 in self.categories["category1Name"].get(cat1, {}).get("category2Name", {}):
cat3Names = sorted(self.categories["category1Name"][cat1]["category2Name"][cat2].get("category3Name", {}).keys())
self.category3ComboBox.addItems(cat3Names)
if selectedCategory3:
self.category3ComboBox.setCurrentText(selectedCategory3)
self.updateCategory4ComboBox()
def updateCategory4ComboBox(self, selectedCategory4=None):
cat1 = self.category1ComboBox.currentText()
cat2 = self.category2ComboBox.currentText()
cat3 = self.category3ComboBox.currentText()
self.category4ComboBox.clear()
if cat3 in self.categories["category1Name"].get(cat1, {}).get("category2Name", {}).get(cat2, {}).get("category3Name", {}):
cat4Names = sorted(self.categories["category1Name"][cat1]["category2Name"][cat2]["category3Name"][cat3].get("category4Name", {}).keys())
self.category4ComboBox.addItems(cat4Names)
if selectedCategory4:
self.category4ComboBox.setCurrentText(selectedCategory4)
def processCategories(self, data):
# Process and structure the category data
for item in data:
cat1 = item.get('category1Name')
cat2 = item.get('category2Name')
cat3 = item.get('category3Name')
cat4 = item.get('category4Name')
if cat1 not in self.categories:
self.categories[cat1] = {}
if cat2 and cat2 not in self.categories[cat1]:
self.categories[cat1][cat2] = {}
if cat3 and cat3 not in self.categories[cat1][cat2]:
self.categories[cat1][cat2][cat3] = {}
if cat4:
self.categories[cat1][cat2][cat3][cat4] = item # Store the full item for leaf nodes
def onCategoryChanged(self, level):
if level == 1:
# category2ComboBox를 업데이트하는 로직
self.category2ComboBox.clear()
cat1 = self.category1ComboBox.currentText()
if cat1 in self.categories["category1Name"]:
cat2Names = sorted(self.categories["category1Name"][cat1]["category2Name"].keys())
self.category2ComboBox.addItems(cat2Names)
self.onCategoryChanged(2) # category3ComboBox를 초기화하기 위해 호출
elif level == 2:
# category3ComboBox를 업데이트하는 로직
self.category3ComboBox.clear()
cat1 = self.category1ComboBox.currentText()
cat2 = self.category2ComboBox.currentText()
if cat2 in self.categories["category1Name"].get(cat1, {}).get("category2Name", {}):
cat3Names = sorted(self.categories["category1Name"][cat1]["category2Name"][cat2].get("category3Name", {}).keys())
if cat3Names: # cat3Names가 있으면 추가
self.category3ComboBox.addItems(cat3Names)
self.onCategoryChanged(3) # category4ComboBox를 초기화하기 위해 호출
elif level == 3:
# category4ComboBox를 업데이트하는 로직
self.category4ComboBox.clear()
cat1 = self.category1ComboBox.currentText()
cat2 = self.category2ComboBox.currentText()
cat3 = self.category3ComboBox.currentText()
if cat3 in self.categories["category1Name"].get(cat1, {}).get("category2Name", {}).get(cat2, {}).get("category3Name", {}):
cat4Names = sorted(self.categories["category1Name"][cat1]["category2Name"][cat2].get("category3Name", {}).get(cat3, {}).get("category4Name", {}).keys())
if cat4Names: # cat4Names가 있으면 추가
self.category4ComboBox.addItems(cat4Names)
def copyToClipboard(self, buttonRole):
clipboard = QApplication.clipboard()
# 카테고리 값이 유효한지 확인하고 유효한 값만 연결하여 문자열을 생성합니다.
categories = [self.cat1, self.cat2]
if self.cat3: # cat3가 빈 문자열이 아니면 추가
categories.append(self.cat3)
if self.cat4: # cat4가 빈 문자열이 아니면 추가
categories.append(self.cat4)
# 유효한 카테고리만 '-'로 연결하여 최종 문자열을 생성합니다.
category_text = "-".join(categories)
print(f"현재 카테고리 출력: {category_text}")
if buttonRole == "cat_code":
text = f'{self.cat_code} {category_text}'
elif buttonRole == "naver_code":
text = str(self.naver_code)
print(f"선택된 naver_code: {text}")
else:
text = ""
clipboard.setText(text)
QMessageBox.information(self, "클립보드 복사", f"'{text}'가 복사되었습니다.")
def on_naver_code_button_clicked(self):
naver_search = self.inputSSField.text()
base_url = "https://search.shopping.naver.com/search/all?query="
urlEnd = f"&cat_id={self.naver_code}&frm=NVSHATC&pagingIndex=1&pagingSize=40&productSet=total&sort=rel&timestamp=&viewType=list"
full_url = f"{base_url}{naver_search}{urlEnd}"
print(f"full_url \n {full_url}")
# URL을 엽니다.
QDesktopServices.openUrl(QUrl(full_url))
# webbrowser.open(full_url)
def filterCategories(self, text):
filtered = {"category1Name": {}, "category2Name": {}, "category3Name": {}, "category4Name": {}}
for cat1, cat1_data in self.categories["category1Name"].items():
if text.lower() in cat1.lower():
filtered["category1Name"][cat1] = cat1_data
for cat2, cat2_data in cat1_data["category2Name"].items():
if text.lower() in cat2.lower():
if cat1 not in filtered["category1Name"]:
filtered["category1Name"][cat1] = {"category2Name": {}}
filtered["category1Name"][cat1]["category2Name"][cat2] = cat2_data
for cat3, cat3_data in cat2_data["category3Name"].items():
# cat3가 문자열인 경우에만 lower() 메소드를 호출
if isinstance(cat3, str) and text.lower() in cat3.lower():
if cat1 not in filtered["category1Name"]:
filtered["category1Name"][cat1] = {"category2Name": {}}
if cat2 not in filtered["category1Name"][cat1]["category2Name"]:
filtered["category1Name"][cat1]["category2Name"][cat2] = {"category3Name": {}}
filtered["category1Name"][cat1]["category2Name"][cat2]["category3Name"][cat3] = {"category4Name": {}}
for cat4 in cat3_data.get("category4Name", {}):
# cat4가 문자열인 경우에만 lower() 메소드를 호출
if isinstance(cat4, str) and text.lower() in cat4.lower():
if cat1 not in filtered["category1Name"]:
filtered["category1Name"][cat1] = {"category2Name": {}}
if cat2 not in filtered["category1Name"][cat1]["category2Name"]:
filtered["category1Name"][cat1]["category2Name"][cat2] = {"category3Name": {}}
if cat3 not in filtered["category1Name"][cat1]["category2Name"][cat2]["category3Name"]:
filtered["category1Name"][cat1]["category2Name"][cat2]["category3Name"][cat3] = {"category4Name": {}}
filtered["category1Name"][cat1]["category2Name"][cat2]["category3Name"][cat3]["category4Name"][cat4] = True
return filtered
def updateComboBoxesWithFilteredResults(self, filtered):
if not filtered["category1Name"]:
QMessageBox.warning(self, "No Results", "No categories match your search.")
self.resetComboBoxes() # Resets combo boxes to their initial state
# 이 메서드는 콤보박스 선택이 변경될 때마다 호출됩니다.
def updateCodeLabels(self):
cat1 = self.category1ComboBox.currentText()
self.cat1 = cat1
cat2 = self.category2ComboBox.currentText()
self.cat2 = cat2
cat3 = self.category3ComboBox.currentText()
self.cat3 = cat3
cat4 = self.category4ComboBox.currentText()
self.cat4 = cat4
for item in self.json_data:
if item.get("category1Name") == cat1 and item.get("category2Name") == cat2 and item.get("category3Name", 'N/A') == cat3 and item.get("category4Name", 'N/A') == cat4:
self.naverCodeLabel.setText(f"Naver Code: {item['Naver_code']}")
self.naver_code = item['Naver_code']
self.catCodeLabel.setText(f"Cat Code: {item['cat_code']}")
self.cat_code = item['cat_code']
return
self.naverCodeLabel.setText("Naver Code: Not Found")
self.catCodeLabel.setText("Cat Code: Not Found")
def updateCodeButtons(self):
# 선택된 카테고리를 기반으로 JSON 데이터에서 cat_code와 Naver_code를 찾습니다.
self.cat1 = self.category1ComboBox.currentText()
self.cat2 = self.category2ComboBox.currentText()
self.cat3 = self.category3ComboBox.currentText() or "" # 'None'이나 빈 문자열일 경우 ""으로 처리
self.cat4 = self.category4ComboBox.currentText() or "" # 'None'이나 빈 문자열일 경우 ""으로 처리
found = False
for item in self.json_data:
# item에서 'category3Name'과 'category4Name'이 None이나 빈 문자열일 경우 ""으로 처리
item_cat3 = item.get("category3Name", "")
item_cat4 = item.get("category4Name", "")
if item["category1Name"] == self.cat1 and item["category2Name"] == self.cat2 and item_cat3 == self.cat3 and item_cat4 == self.cat4:
self.cat_code = item['cat_code']
self.naver_code = item['Naver_code']
self.catCodeLabel.setText(f"Cat Code: {self.cat_code}")
self.naverCodeLabel.setText(f"Naver Code: {self.naver_code}")
found = True
break
if not found:
self.catCodeLabel.setText("Cat Code: Invalid Selection")
self.naverCodeLabel.setText("Naver Code: Invalid Selection")
def validateSelection(self):
# 예시: 모든 콤보 박스에서 유효한 항목이 선택되었는지 확인
if self.category1ComboBox.currentIndex() != -1 and self.category2ComboBox.currentIndex() != -1 and self.category3ComboBox.currentIndex() != -1 and self.category4ComboBox.currentIndex() != -1:
# 여기에 추가 로직을 구현하여 선택이 유효한지 확인할 수 있습니다.
return True
else:
return False
def resetComboBoxes(self):
self.category1ComboBox.clear()
self.category2ComboBox.clear()
self.category3ComboBox.clear()
self.category4ComboBox.clear()
# 첫 번째 콤보 박스를 다시 초기화합니다.
self.category1ComboBox.addItems(sorted(self.categories["category1Name"].keys()))
def getCodeFromSelection(self):
cat1 = self.category1ComboBox.currentText()
cat2 = self.category2ComboBox.currentText()
cat3 = self.category3ComboBox.currentText()
cat4 = self.category4ComboBox.currentText()
for line in open("Percenty_SS_Code.json", "r", encoding='utf-8'):
entry = json.loads(line)
if entry["category1Name"] == cat1 and entry["category2Name"] == cat2 and \
entry.get("category3Name") == cat3 and entry.get("category4Name") == cat4:
return entry["cat_code"], entry["Naver_code"]
return None, None
# Running the application
def main():
app = QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()