i$dZddlmZmZmZmZmZmZmZddl m Z m Z ddl m Z mZddlmZddlmZddlmZGdd eZd S) z\ Real-time Log Monitor Window - PyQt6 Shows job execution log in real-time with auto-scroll )QDialog QVBoxLayout QTextEditQLabel QPushButton QHBoxLayout QMessageBox)QTimerQt)QFont QTextCursor)Path)Optional)SchedulerDatabasecjeZdZdZddedeffd ZdZdZdZ d Z d Z d Z d e fd ZdZdZxZS)LogMonitorWindowz3Window that displays job execution log in real-timeN execution_iddbct|||_||_d|_d|_d|_d|_|| | dS)NrT) super__init__rr log_file_pathlog_file last_position is_monitoring _setup_ui_load_execution_info_start_monitoring)selfrrparent __class__s )C:\PYTHON\Frank\gui\log_monitor_window.pyrzLogMonitorWindow.__init__s    (-1 !  !!###      c|d|j|ddt|}t d|_|jd||jt d|_|jd||jt|_ |j d|j tj jtd d }|std d }|j ||j d ||j t%}t'd |_|jd|jd|jj|j||jt'd|_|jj|j||j|t'd|_|jj|j||j||tA||_!|j!j"|j#|j!$ddS)z Setup the UIzJob Monitor - Execution #iiXz Loading...z QLabel { background-color: #2c3e50; color: white; padding: 10px; font-weight: bold; font-size: 12pt; } zStatus: Initializing...z QLabel { background-color: #34495e; color: #ecf0f1; padding: 5px; } TConsolas z Courier Newz QTextEdit { background-color: #1e1e1e; color: #d4d4d4; border: 1px solid #3e3e3e; } zAuto-scroll: ONz Refresh NowClosedN)%setWindowTitlersetMinimumSizerr header_label setStyleSheet addWidget status_labelrlog_text setReadOnlysetLineWrapMode LineWrapModeNoWrapr exactMatchsetFontrrauto_scroll_btn setCheckable setCheckedclickedconnect_toggle_auto_scroll refresh_btn_manual_refresh addStretch close_btnclose addLayoutr update_timertimeout _update_log setInterval)rlayoutfont button_layouts r"rzLogMonitorWindow._setup_uis  K8IKKLLL C%%%T""#<00 '')     *+++##<== '')     *+++"   !!$''' %%i&<&CDDDZ##   +**D d### ##%     '''$ *+<== ))$/// ''--- $,,T-EFFF 4555&}55  (()=>>> 0111  """$W-- &&tz222///'''#4LL !))$*:;;; %%c*****r#c|j|j}|s5tj|dd|jd|dS|j|d}|r|dn d|d}|d||j d |d |jt|d |_ |d }d ddddd}| |d}|j d|d|dd|j j|j d|ddS)z(Load execution information from databaseErrorz Execution ID z not foundNjob_idnamezJob ID zJob Monitor - zJob: z | Execution ID: rstatusz#3498dbz#27ae60z#e74c3cz#e67e22z#95a5a6)running completedfailedrCpendingzStatus: z | Started: start_timez | Log: z8 QLabel { background-color: zw; color: white; padding: 5px; font-weight: bold; } )r get_executionrr criticalr@get_jobr)r+setTextrrgetr.upperrLr,)r executionjobjob_namerM status_colorscolors r"rz%LogMonitorWindow._load_execution_infolsG))$*;<<    w M0A M M M O O O JJLLL Fgooi122"%J3v;;+JYx5H+J+J 7X77888 !!"X("X"XTEV"X"XYYY")J"7888$ "    !!&)44 !! .v||~~ . .!,/ . .&+ . .   '') #() ) )      r#cZ|jr|js6|jdt jd|jdS t|jddd|_|j }|r.|j || |j |_ |jdS#t $r)}|jd|d Yd}~dSd}~wwxYw) zStart monitoring the log filez&Waiting for log file to be created... Nrzutf-8replace)encodingerrorsz ERROR opening log file:  )rexistsr/appendr singleShot_check_log_file_existsopenrread setPlainText_scroll_to_bottomtellrrBstart Exception)rcontentes r"rz"LogMonitorWindow._start_monitoringsF! );)B)B)D)D  M !J K K K  dD$? @ @ @ F E !3S7S\]]]DMm((**G ) **7333&&(((!%!3!3!5!5D    # # % % % % % E E E M !Ca!C!C!C D D D D D D D D D EsBC77 D*D%%D*c|jr/|jr|dStjd|jdS)z.Check if log file exists (called periodically)r_N)rrerr rgrhrs r"rhz'LogMonitorWindow._check_log_file_existss[   A$"4";";"="= A  " " $ $ $ $ $  dD$? @ @ @ @ @r#c^|jr|jsdS |j|j}|ddvr|j|j|j}|r.|j || |j d|_| |d}|d}|d}ddd}|d |dz }|d |d |d d z }|ddz }|j || dS|j|j|j}|rN|j ||j|_| dSdS#t $rB}|j d|d|j Yd}~dSd}~wwxYw)zUpdate log content from fileNrM)rOrPrCF exit_codeduration_secondsrdzP================================================================================zJOB FINISHED - Status: z Exit Code: z | Duration: z.1fzs z ERROR reading log: )rrrrSrseekrrjr/rfrlrBstoprrXrmro) rrY remainingrMrudurationcompletion_msg new_contentrqs r"rDzLogMonitorWindow._update_logsn} D$6  F+ %--d.?@@I"&HHH ""4#5666 M..00 -M((333**,,,!&&(((%*"))+++#8,%k2 $%78!0f"NFLLNN"N"N"NN"Y "Y"Y"Y"Y"Y"YYV---/ $$^444&&((( M  t1 2 2 2-,,..K ) $$[111%)]%7%7%9%9"&&((((( ) )  % % % M !>!>!>!> ? ? ?   " " $ $ $ $ $ $ $ $ $ %sEG BG H,*7H''H,c|jrY|j}|t jj|j|dSdS)z*Scroll to bottom if auto-scroll is enabledN) r6 isCheckedr/ textCursor movePositionr MoveOperationEnd setTextCursor)rcursors r"rlz"LogMonitorWindow._scroll_to_bottomsl   ) ) + + 0]--//F    9 = > > > M ' ' / / / / / 0 0r#checkedcx|jd|rdnd|r|dSdS)zToggle auto-scrollz Auto-scroll: ONOFFN)r6rVrl)rrs r"r;z$LogMonitorWindow._toggle_auto_scrollsU $$%QW5OTT%%Q%QRRR  %  " " $ $ $ $ $ % %r#c.|dS)zManually refresh log contentN)rDrss r"r=z LogMonitorWindow._manual_refreshs r#c|j|jr|tj|ddtjjtjjz}|tjjkr/|j| dS|j r|j | dS)zClean up when window closesz Close MonitorzMJob is still running. Close monitor window? (Job will continue in background)N) rBrxrr questionStandardButtonYesNornignorerr@accept)reventreplys r" closeEventzLogMonitorWindow.closeEvents      (`*.1K1NN E 2555!'')))  = " M   ! ! ! r#)N)__name__ __module__ __qualname____doc__intrrrrrrhrDrlboolr;r=r __classcell__)r!s@r"rrs== ! !S !.? ! ! ! ! ! !K+K+K+Z, , , \EEE4AAA0%0%0%d000%4%%%% r#rN)rPyQt6.QtWidgetsrrrrrrr PyQt6.QtCorer r PyQt6.QtGuir r pathlibrtypingr core.databaserrr#r"rsEEEEEEEEEEEEEEEEEE########********++++++EEEEEwEEEEEr#