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"상표권명: {result['title']}
\n" \ f"등록상태: {result['application_status']}
\n" \ f"카테고리: {result['classification_code']}
\n" \ f"권리자: {result['applicant_name']}
\n" \ f"출원일자 {result['application_date']}
\n" \ f"공고일자 {result['publication_date']}
\n" \ f"등록일자 {result['registration_date']}\n" \ f"전문 {result['full_text']}
\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"상표권명: {result['title']}
\n" \ f"등록상태: {result['application_status']}
\n" \ f"카테고리: {result['product_category']}
\n" \ f"권리자: {result['applicant_name']}
\n" \ f" {result['publication_date']}
\n" \ f" {result['registration_date']}" 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