DeliveryFeeCalc/src/result_widget.py

219 lines
11 KiB
Python

import sys
from PyQt5.QtWidgets import QSizePolicy, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QGridLayout
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import Qt
# from PyQt5.Qt import QDesktopServices
import webbrowser
import requests
from PIL import Image
from io import BytesIO
import asyncio, aiofiles, aiohttp
import logging
# 로거 인스턴스 가져오기
logger = logging.getLogger('default_logger')
class ResultWidget(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
def show_results(self, results, searchType, elapsed_time, currentURL=''):
searchType = searchType
elapsed_time = elapsed_time
currentURL = currentURL
logger.debug(f"show_results - searchType : {searchType}")
logger.debug(f"show_results - elapsed_time : {elapsed_time}")
# try:
# 결과 위젯 생성
self.results_widget = QWidget()
layout = QVBoxLayout()
self.results_widget.setLayout(layout)
# 결과 갯수 확인 및 레이아웃 동적 생성
total_count = int(results['total_count'])
set_count = min(total_count, 10)
grid_layout = QGridLayout()
layout.addLayout(grid_layout)
grid_index = 0
grid_columns = 5
logger.debug(f"show_results - set_count : {set_count}")
for i in range(1, set_count + 1):
result_key = f"result_{i}"
if result_key in results:
result = results[result_key]
logger.debug(f"show_results - result_key : {result_key}")
# 테두리 설정
border_style = ''
if result['application_status'] == '등록':
border_style = 'border: 4px solid red;'
elif result['application_status'] == '공고':
border_style = 'border: 3px solid black;'
# 각 결과에 대한 레이아웃 생성
item_layout = QVBoxLayout()
item_widget = QWidget() # 위젯 생성
# item_layout의 크기 정책 설정
item_widget.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.MinimumExpanding)
# 이미지 처리
image_label = QLabel()
image_label.setFixedSize(150, 150)
image_data = self.fetch_image_data(result['drawing_url'])
pixmap = QPixmap()
pixmap.loadFromData(image_data)
# QLabel의 크기에 맞게 이미지 크기 조정
scaled_pixmap = pixmap.scaled(image_label.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
image_label.setPixmap(scaled_pixmap)
# QLabel의 가로 세로 중앙에 이미지 표시
image_label.setAlignment(Qt.AlignCenter)
# 이미지 표시 위젯의 크기 조정 정책 설정
image_label.setScaledContents(True)
#이미지 중앙배치를 위해
horizontal_layout = QHBoxLayout()
horizontal_layout.addWidget(image_label)
horizontal_layout.setAlignment(Qt.AlignCenter)
item_layout.addLayout(horizontal_layout)
# item_layout.addWidget(image_label)
if searchType =='api':
# API 정보 텍스트
# info_text = f"상표권명: {result['title']}\n등록상태: {result['admin_status']}\nCategory: {result['product_category']}\nApplicant: {result['applicant']}\nPublication Date: {result['publication_date']}\nRegistration Date: {result['registration_date']}"
info_text = f"<span style='font-size: 11pt; font-weight: bold; text-decoration: underline;'>상표권명: {result['title']}</span><br>\n" \
f"<span style='font-size: 11pt; font-weight: bold; text-decoration: underline;'>등록상태: {result['application_status']}</span><br>\n" \
f"<span style='font-size: 9pt;'>카테고리: {result['classification_code']}</span><br>\n" \
f"<span style='font-size: 9pt;'>권리자: {result['applicant_name']}</span><br>\n" \
f"<span style='font-size: 9pt;'>출원일자 {result['application_date']}</span><br>\n" \
f"<span style='font-size: 9pt;'>공고일자 {result['publication_date']}</span><br>\n" \
f"<span style='font-size: 9pt;'>등록일자 {result['registration_date']}</span>\n" \
f"<span style='font-size: 9pt;'>전문 {result['full_text']}</span><br>\n"
elif searchType =='web':
# WEB 정보 텍스트
# info_text = f"상표권명: {result['title']}\n등록상태: {result['admin_status']}\nCategory: {result['product_category']}\nApplicant: {result['applicant']}\nPublication Date: {result['publication_date']}\nRegistration Date: {result['registration_date']}"
info_text = f"<span style='font-size: 11pt; font-weight: bold; text-decoration: underline;'>상표권명: {result['title']}</span><br>\n" \
f"<span style='font-size: 11pt; font-weight: bold; text-decoration: underline;'>등록상태: {result['application_status']}</span><br>\n" \
f"<span style='font-size: 9pt;'>카테고리: {result['product_category']}</span><br>\n" \
f"<span style='font-size: 9pt;'>권리자: {result['applicant_name']}</span><br>\n" \
f"<span style='font-size: 9pt;'> {result['publication_date']}</span><br>\n" \
f"<span style='font-size: 9pt;'> {result['registration_date']}</span>"
info_label = QLabel(info_text)
if searchType =='web':
currentURL_btn = QPushButton("웹 열기")
# currentURL_btn.clicked.connect(self.openCurrentPage(currentURL))
info_label.setToolTip(self.wrap_text(result['category_description'], 50))
image_label.setToolTip(self.wrap_text(result['category_description'], 50))
item_layout.addWidget(info_label)
image_label.setStyleSheet(border_style)
info_label.setStyleSheet(border_style)
# 레이아웃에 위젯 추가
row = grid_index // grid_columns
col = grid_index % grid_columns
grid_layout.addLayout(item_layout, row, col)
grid_index += 1
# 결과 위젯에 닫기 버튼 추가
close_button = QPushButton("Close")
close_button.clicked.connect(self.close_results_widget)
layout.addWidget(close_button)
# e
elapsed_time_Label = QLabel(f"Elapsed Time : {elapsed_time}")
layout.addWidget(elapsed_time_Label)
# 결과 위젯을 메인 윈도우에 추가
self.results_widget.setGeometry(300, 300, 600, 300) # 위치와 크기 설정
self.results_widget.setWindowTitle('Search Results') # 타이틀 설정
self.results_widget.show()
# except Exception as e:
# logger.debug(f"Error displaying results: {e}")
def close_results_widget(self):
# 결과 위젯닫기 함수를 호출할 때 사용하는 메서드
self.results_widget.close()
def openCurrentPage(self, currentURL):
logger.debug(f"open the page : {currentURL}")
webbrowser.open('currentURL')
pass
# QDesktopServices.openUrl(self.currentURL)
def wrap_text(self, text, width=40):
"""주어진 너비에 맞게 텍스트를 줄바꿈합니다."""
words = text.split()
wrapped_text = ''
line_length = 0
for word in words:
if line_length + len(word) + 1 > width:
wrapped_text += '\n'
line_length = 0
wrapped_text += word + ' '
line_length += len(word) + 1
return wrapped_text.strip()
async def fetch_image_data_async(self, url):
"""주어진 URL로부터 이미지 데이터를 비동기적으로 가져와 반환합니다."""
async with aiohttp.ClientSession() as session:
# logger.debug(f"download_image session Start!!")
async with session.get(url) as response:
logger.debug(f"download_image url : {url}")
if response.status == 200:
# logger.debug(f"response : {response}")
content_type = response.headers.get('Content-Type', '') # await 제거
logger.debug(f"content_type : {content_type}")
if 'image' in content_type or 'octet-stream' in content_type:
# logger.debug(f"image content type or octet-stream : {content_type}")
return await response.read()
else:
try:
# Content-Type이 이미지가 아니면, 데이터를 이미지로 변환
data = await response.read()
# logger.debug(f"Content-Type이 이미지가 아님 : {data}")
image = Image.open(BytesIO(data))
with BytesIO() as buffer:
image.save(buffer, 'JPEG')
logger.debug(f"image 를 JPEG로 저장")
return buffer.getvalue()
except Exception as e:
logger.debug(f"이미지 변환 실패: {e}")
return None
else:
logger.debug(f"이미지 다운로드 실패: HTTP {response.status}")
return None
def fetch_image_data(self, url):
"""주어진 URL로부터 이미지 데이터를 가져와 반환합니다."""
response = requests.get(url)
if response.status_code == 200:
# 서버 응답 헤더에서 Content-Type 확인
content_type = response.headers.get('Content-Type', '')
if 'image' in content_type:
return response.content
else:
# Content-Type이 이미지가 아니면, 데이터를 이미지로 변환
try:
image = Image.open(BytesIO(response.content))
with BytesIO() as buffer:
image.save(buffer, 'JPEG') # 예시로 JPEG 포맷을 사용
return buffer.getvalue()
except Exception as e:
logger.debug(f"이미지 변환 실패: {e}")
return None
else:
logger.debug(f"이미지 다운로드 실패: HTTP {response.status_code}")
return None