""" Clock-out Time Calculator 퇴근시간 계산 프로그램 - 메인 실행 파일 """ import sys import os # PyQt5 임포트 from PyQt5.QtWidgets import QApplication, QMessageBox from PyQt5.QtGui import QFont from PyQt5.QtCore import QLockFile, QDir from PyQt5.QtNetwork import QLocalServer, QLocalSocket # 프로젝트 루트를 경로에 추가 sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from ui.main_window import MainWindow from core.database import Database def check_requirements(): """필수 요구사항 확인""" try: import win32evtlog return True except ImportError: return False def main(): """메인 함수""" app = QApplication(sys.argv) # 애플리케이션 정보 app.setApplicationName("Clock-out Time Calculator") app.setOrganizationName("DevUtil") app.setApplicationVersion("1.0.0") # 중복 실행 방지 - 로컬 서버로 체크 server_name = "ClockOutCalculatorInstance" # 이미 실행 중인지 확인 socket = QLocalSocket() socket.connectToServer(server_name) if socket.waitForConnected(500): # 이미 실행 중 - 기존 인스턴스에 "show" 신호 전송 socket.write(b"show") socket.flush() socket.waitForBytesWritten(1000) socket.disconnectFromServer() return 0 # 새로운 인스턴스 - 서버 시작 server = QLocalServer() # 기존 서버가 남아있을 수 있으므로 제거 QLocalServer.removeServer(server_name) if not server.listen(server_name): QMessageBox.warning( None, "서버 오류", "프로그램 인스턴스 서버를 시작할 수 없습니다." ) return 1 # 폰트 설정 app.setFont(QFont("Segoe UI", 9)) # 필수 패키지 확인 if not check_requirements(): QMessageBox.critical( None, "요구사항 오류", "필수 패키지가 설치되지 않았습니다.\n\n" "다음 명령어를 실행하세요:\n" "pip install -r requirements.txt" ) return 1 # 데이터베이스 초기화 — db_path_override 설정 시 그 경로 사용 (클라우드 폴더 등) # 부트스트랩: 기본 DB로 한 번 열어 override 키 확인 from core.settings_keys import DB_PATH_OVERRIDE bootstrap = Database() override_path = bootstrap.get_setting(DB_PATH_OVERRIDE, '') or '' if override_path and os.path.exists(os.path.dirname(override_path) or '.'): db = Database(override_path) else: db = bootstrap # 1일 1회 자동 백업 (조용히 실패 — 백업 실패가 앱 실행을 막으면 안 됨) try: from utils.backup import backup_db_if_needed backup_db_if_needed(db) except Exception as e: from utils.debug_log import dlog dlog(f"backup failed: {e}") # 메인 윈도우 생성 및 표시 try: window = MainWindow() # 서버 연결 처리 - 다른 인스턴스에서 show 신호를 받으면 창을 보여줌 def on_new_connection(): client_socket = server.nextPendingConnection() if client_socket: client_socket.waitForReadyRead(1000) data = client_socket.readAll().data() if data == b"show": # 창 표시 window.show() window.raise_() window.activateWindow() client_socket.disconnectFromServer() server.newConnection.connect(on_new_connection) window.show() result = app.exec_() # 서버 종료 server.close() return result except Exception as e: QMessageBox.critical( None, "오류", f"프로그램 실행 중 오류가 발생했습니다:\n\n{str(e)}" ) server.close() return 1 if __name__ == "__main__": sys.exit(main())