iQdZddlmZmZmZmZmZmZmZm Z m Z m Z m Z m Z mZddlmZmZmZmZddlmZmZddlmZddlmZddlZddlmZdd lmZGd d eZGd d eZ dS)z@ Backup Widget for GUI - Manages backup profiles and operations ) QWidget QVBoxLayout QHBoxLayout QPushButton QTableWidgetQTableWidgetItemQLabel QMessageBox QGroupBox QTextEdit QHeaderViewQAbstractItemView QFileDialog)Qt pyqtSignalQThreadQTimer)QFontQColor)logger)datetimeN)Database)SchedulerConfigcDeZdZdZeeZdeffd ZdZ xZ S) BackupWorkerz5Worker thread for running backup without blocking GUI profile_idcdt||_||_dSN)super__init__rdb)selfrr! __class__s $C:\PYTHON\Frank\gui\backup_widget.pyr zBackupWorker.__init__s+ $cddlm}||j}||j}|j|dS)Nr) BackupModule)modules.backup.backup_moduler'r!execute_backuprfinishedemit)r"r'moduleresults r$runzBackupWorker.runsV======dg&&&&t77 6"""""r%) __name__ __module__ __qualname____doc__rdictr*intr r. __classcell__r#s@r$rrsh??z$H3 #######r%rceZdZdZeZdedeffd ZdZ dZ dZ dZ d Z d Zd Zd Zd ZdefdZdZdZdZdZdZdZxZS) BackupWidgetz2Widget for managing backup profiles and operationsr!configct||_||_||dSr)rr r!r9 _setup_uirefresh)r"r!r9r#s r$r zBackupWidget.__init__)sH    r%ct|}|dddd|dt}t d}t }|d|d||| || td|_ |j j |j| |j td|_|jj |j|jd| |jtd|_|jj |j|jd| |jtd |_|jj |j|jd| |jtd |_|jj |j|jd| |jtd |_|jj |j| |j||t9d }t|}t;|_|jd |j gd|j!"tFj$j%|j!&d|j'tPj)j*|j+tPj,j-|j.tPj/j0|jj1|j2|jj3|j4|j5dd|j5dd|j5dd|j5dd|j5dd|j5dd| |j| |dt9d}t|}t;|_6|j6d|j6 gd|j6!"tFj$j%|j6!&d|j6'tPj)j*|j6+tPj,j-|j6.tPj/j0|j6j1|j7|j65dd|j65dd|j65dd|j65dd|j65dd|j65dd|j65d d| |j6| |dd S)!zSetup backup UI componentsu💾 Backup ProfilesTu➕ New Profileu▶ Run BackupFu 📅 Scheduleu 🗑 Deleteu 🔄 Restoreu📋 View All BackupszBackup Profiles)IDNamez Backup RootSourceszRetention (days)Enabledr2xP)stretchzRecent Backup Operations)rAProfileTypeStatusz Start TimeDurationFilesdN)8rsetContentsMargins setSpacingrr r setPointSizesetBoldsetFont addWidget addStretchrnew_btnclickedconnect_create_profilerun_btn _run_backup setEnabled schedule_btn_schedule_backup delete_btn_delete_profile restore_btn_restore_backup view_all_btn_view_all_backups addLayoutr rprofiles_tablesetColumnCountsetHorizontalHeaderLabelshorizontalHeadersetSectionResizeModer ResizeMode InteractivesetStretchLastSectionsetSelectionBehaviorrSelectionBehavior SelectRowssetSelectionMode SelectionModeSingleSelectionsetEditTriggers EditTriggerNoEditTriggersitemSelectionChanged_on_profile_selected doubleClicked _edit_profilesetColumnWidthoperations_table_on_operation_selected) r"layout header_layout title_label title_fontprofiles_groupprofiles_layoutoperations_groupoperations_layouts r$r;zBackupWidget._setup_ui1sT""!!"b"b111"$ 344 WW ###4   J''' ,,,  """##455  $$T%9::: ---"#344  $$T%5666 &&& ---'88 !))$*?@@@ $$U+++ 1222%m44 ''(<=== ""5)))000&~66  (()=>>> ##E*** 0111'(?@@ !))$*@AAA 1222'''##455%n55*nn **1--- 557 7 7     ,,..CCKDZDfggg ,,..DDTJJJ 001B1T1_``` ,,->-L-\]]] ++,=,I,XYYY 0889RSSS )11$2DEEE **1b111 **1c222 **1c222 **1c222 **1c222 **1b111!!$"5666333%%?@@'(899 , ,,Q/// 779 9 9     ..00EEkF\Fhiii ..00FFtLLL 223D3V3abbb ../@/N/^___ --.?.K.Z[[[ 2::4;VWWW ,,Q333 ,,Q444 ,,Q444 ,,Q444 ,,Q444 ,,Q444 ,,Q444##D$9:::)155555r%cV||dS)zRefresh all dataN)_load_profiles_load_operations)r"s r$r<zBackupWidget.refreshs,  r%cd |jtj}|jt |t|D]\}}tt|d}| tj j |j|d|t|d}|j|d|t|d}|j|d|ddl} t!|d tr||d n|d }t |} n #d} YnxYwt| d } | tj j |j|d | tt|d } | tj j |j|d | |drdnd} t| } | tj j |dr#| t'dn"| t'd|j|d| dS#t($r;}t+jd|t/j|dd|Yd}~dSd}~wwxYw)z"Load backup profiles from database)hostnameidrnamerF backup_rootrHNsourcesz source(s)rJretention_daysrLenabledu✓ Yesu✗ NogreenredrNzError loading backup profiles: Errorz Failed to load backup profiles: )r!get_all_backup_profilessocket gethostnamero setRowCountlen enumeraterstrsetTextAlignmentr AlignmentFlag AlignCentersetItemjson isinstanceloads setForegroundr Exceptionrerrorr critical)r"profilesrowprofileid_item name_item root_itemrr sources_count sources_itemretention_item enabled_text enabled_itemes r$rzBackupWidget._load_profiless-/ Xw66@R@T@T6UUH   + +CMM : : : )( 3 3& B& B W*3wt}+=+=>>(()9)EFFF#++CG<<<-WV_== #++CI>>>-W]-CDD #++CI>>> &@J7S\K]_b@c@c{djj);<<.JKKK#++CLAAA"2#g>N6O2P2P!Q!Q//0@0LMMM#++CNCCC-4I,>LyyH / == --b.>.JKKK9%> ..vg???? ..ve}}===#++CLAAAAM& B& BP X X X L>1>> ? ? ?  w0VST0V0V W W W W W W W W W Xs2D0K*3A FK*FE#K** L/40L**L/c |jdtj}|jt |t|D]\}}tt|d}| tj j |j|d||j|d}|r|dn d|d}t|}|j|d|t|d }|j|d ||d } t| } | tj j |d d kr#| t#d n]|d dkr#| t#dn.|d dkr"| t#d|j|d| |d} | rQ t%j| } | d} n(#t | dkr | ddn| } YnxYwd} t| }|j|d||drq|dr\ t%j|d}t%j|d}||z }|dd}n#d}YnxYw|d dkrdnd}t|}| tj j |j|d||dd}|dd}|dkr|d |d!nd}t|}| tj j |j|d"|dS#t.$r"}t1jd#|Yd}~dSd}~wwxYw)$zLoad recent backup operationslimitrrrrrProfile rFoperation_typerHstatus completedrfailedrrunningorangerJ start_timez%Y-%m-%d %H:%M:%SNzN/ArLend_timez.1fsz Running...rN files_total files_linkedz (z links)r@z!Error loading backup operations: )r!get_recent_backup_operationsrrrrrrrrrrrrrget_backup_profilerrr fromisoformatstrftimeget total_secondsrrr)r" operationsroprr profile_name profile_item type_item status_text status_itemrdttime_str time_itemstartendduration duration_str duration_itemrr files_str files_itemrs r$rzBackupWidget._load_operationssI B==BQWQcQeQe=ffJ  ! - -c*oo > > >$Z00A BA BR*3r$x==99(()9)EFFF%--c1g>>>'44R 5EFF29\wv?\"\JZ?\?\ / == %--c1lCCC-R0@-ABB %--c1i@@@!l .{;; ,,R-=-IJJJh<;..--fWoo>>>>\X----fUmm<<<<\Y..--fX.>.>???%--c1kBBB - %[%3J??#%;;/B#C#C[69*oo6J6J:crc??PZ$H,X66 %--c1i@@@66*%% X"&&*>*> X- ( 6r,7G H H&4R ^DD$'%K#>#>#@#@*2'9'9'9'9 -', 35h<93L3L< > ..r/?/KLLL%--c1mDDD!ff]A66 !vvna88 GRUV{CClCCCC\a -i88 ++B,<,HIII%--c1jAAAACA BA BF B B B L@Q@@ A A A A A A A A A BsKI P= )I65P=6!JAP=4AMP=M  C1P== Q)Q$$Q)ct|jdk}|j||j||j|dS)zHandle profile selectionrN)rro selectedItemsrcrerfrh)r" has_selections r$rz!BackupWidget._on_profile_selectedslD/==??@@1D   ... $$]333 ""=11111r%c|j}|sdS|d}t|j|dS)zGet selected profile IDNr)rorrr4itemtext)r"selectedrs r$_get_selected_profile_idz%BackupWidget._get_selected_profile_id$sc&4466 4qkoo4&++C3388::;;;r%c ddlm}ddlm}|||j}||jjkrCtj d| |j dSdS)zCreate new backup profilerBackupProfileDialogQDialogzNew backup profile createdN) gui.backup_profile_dialogrPyQt6.QtWidgetsrr!exec DialogCodeAcceptedrinfor<profile_changedr+)r"rrdialogs r$rbzBackupWidget._create_profile-sAAAAAA++++++$$T4733 ;;==G.7 7 7 K4 5 5 5 LLNNN  % % ' ' ' ' ' 8 7r%cpddlm}ddlm}|}|st j|dddS|||j|}||j j krGtj d|d| |jdSdS) zEdit selected backup profilerrr No SelectionzPlease select a profile to editNzBackup profile z updated)rrrrrr warningr!rrrrrr<rr+)r"rrrrs r$rzBackupWidget._edit_profile8sAAAAAA++++++2244    n6W X X X F$$T47J?? ;;==G.7 7 7 K>*>>> ? ? ? LLNNN  % % ' ' ' ' ' 8 7r%c|}|sdStj|dd|dtjjtjjz}|tjjkr|jd|jdt||j |_ |j j |j|j dSdS)zRun backup for selected profileNz Run Backupz#Start backup operation for profile ?Fu⏳ Running...)rr questionStandardButtonYesNorcresetTextrr!_backup_workerr*ra_on_backup_finishedr)r"rreplys r$rdzBackupWidget._run_backupHs2244   F$   ?* ? ? ?  & *[-G-J J    K.2 2 2 L # #E * * * L !1 2 2 2".z47"C"CD    ( 0 01I J J J   % % ' ' ' ' ' 3 2r%r-c F|jd|jdtjd|j|j|dru|di}d|ddd |d dd |d d}tj |d |dS|dd}tj |dd|dS)z*Called when backup worker thread completesTu ▶ Run Nowi,successstatsz.Backup completed successfully. Files copied: files_copiedrz Files linked: rz Total files: rzBackup Completerz Unknown errorz Backup FailedzBackup failed: N) rcrerr singleShotr<rr+rr informationr)r"r-rmsgrs r$rz BackupWidget._on_backup_finished]s9 %%% ]+++#t|,,, !!### ::i TJJw++E@!&>3!?!?@@!&>3!?!?@@!& - = =@@   #D*;S A A A A AJJw88E  8R58R8R S S S S Sr%ct|}|sdS ddlm}ddlm}|j|}|stj|dd|ddS|||j|j }|j dt|j D]<}|j ||kr|j |n=|jd |d ||jjkr9t-jd |tj|d d |d ddSdS#t2$r;}t-jd|tj|dd|Yd}~dSd}~wwxYw)z0Open schedule dialog for selected backup profileNr)ScheduleEditorDialogrrr not foundTzScheduled Backup: rz$Created schedule for backup profile zSchedule Createdz#Schedule created successfully for 'z2'. Check the Schedules tab to view and manage it.zError scheduling backup: z Failed to open schedule dialog: )rgui.schedule_editor_dialogr rrr!rr rr9 backup_radio setCheckedrange backup_combocountitemDatasetCurrentIndex name_inputrrrrrrr rrr)r"rr rrrirs r$rgzBackupWidget._schedule_backuprs:2244   F$ X G G G G G G / / / / / /g00<XYYYYYr%c|j}|sdS|d}t|j|d} |jdtj }|D]}|d|kr|cSn.#t$r!}tj d|Yd}~nd}~wwxYwdS)z%Get selected backup operation detailsNrrWrrz!Error getting operation details: ) rrrr4rrr!rrrrrr)r"rrop_idrrrs r$_get_selected_operationz$BackupWidget._get_selected_operations(6688 4qkooD)..sA66;;==>> B==CRXRdRfRf=ggJ   d8u$$III%  B B B L@Q@@ A A A A A A A A Bts3AB64B66 C!CC!c Rddlm}|}|stj|dddS|d}|stj|dddS|j|d }|s"tj|dd |d d dS |||d || }| dS#t$rH}tj d|tj|ddt|Yd}~dSd}~wwxYw)z5Restore selected backup with selective restore dialogr)BackupRestoreDialogrz+Please select a completed backup to restoreN backup_namerz%Selected operation has no backup namerrrr)rzError opening restore dialog: zRestore FailedzFailed to open restore dialog: )gui.backup_restore_dialogr!rr rrr!rrrrrrr)r"r! operationr"rrrs r$rkzBackupWidget._restore_backupsAAAAAA0022    n6c d d d FmmM22    g/V W W W F',,Y|-DEE   w0^9\;R0^0^0^ _ _ _ F ((w}/E{\cdddF KKMMMMM    L=!== > > >   ;3q66;;          s))C D&=D!!D&c  ddlm}|||j}|dS#t$rH}t jd|tj|ddt|Yd}~dSd}~wwxYw)z)Open dialog showing all backup operationsr)AllBackupsDialogz"Error opening all backups dialog: rz#Failed to open all backups dialog: N) gui.all_backups_dialogr&r!rrrrr rr)r"r&rrs r$rmzBackupWidget._view_all_backupss  ? ? ? ? ? ?%%dDG44F KKMMMMM    LAaAA B B B  ?s1vv??          s+/ B=A<<B)r/r0r1r2rrrrr r;r<rrrrrbrrdr3rrgrirrrkrmr5r6s@r$r8r8$sw<< jllO8_e6e6e6N   1X1X1XfKBKBKBZ222<<< ( ( (((( (((*T$TTTT**X*X*XXVVV2 Z Z Z(Br%r8)!r2rrrrrrrr r r r r rr PyQt6.QtCorerrrr PyQt6.QtGuirrlogururrr core.databaser core.configrrr8r%r$r.s 988888888888%%%%%%%% """"""'''''' # # # # #7 # # # ddddd7dddddr%