Files
VisionFlowAutomator/__pycache__/main.cpython-313.pyc
T

667 lines
125 KiB
Plaintext
Raw Normal View History

2025-07-31 12:52:28 +02:00
ó
Jh$^ã
óxSSKrSSKrSSKrSSKrSSKrSSKrSSKrSSKrSSKrSSK r SSK
J r SSK J
r
JrJr SSKrSSKrSSKrSSKrSSKJr SSKrSSKJrJrJr S\lS\lS\l Sr!\RDRG\!5(d\RH"\!5 \RJ"\RLS \RN"\RDRQ\!S
5S S 9\RR"5/S
9 \RT"S5r+\+RY\RZ5 \RT"\.5r/Sr0\RDRG\05(d\RH"\05 "SS5r1\1"5r2"SS5r3Sr4"SS\
Rj5r6"SS\
Rn5r8"SS\
Rn5r9"SS\
Rn5r:\.S:XaT\
Rv"\Rx5r=\6"5r>\>R5 \R€"\=Rƒ55 gg)éN)Ú lru_cache)Ú QtWidgetsÚQtGuiÚQtCore)Úkeyboard)Ú ImageGrabÚImageÚImageTkFç{®Gáz„?Úlogsz([%(asctime)s] %(levelname)s: %(message)szscenario_automation.logzutf-8)Úencoding)ÚlevelÚformatÚhandlersÚ performanceÚ scenarioscó8\rSrSrSrS SjrS
SjrSrSrSr g) Ú
TemplateCacheé3z•
Cache for template images to avoid reloading them repeatedly.
Uses weak references to allow garbage collection when templates are no longer needed.
có,0UlXl0Ulg©N)Ú_cacheÚ _max_sizeÚ
_access_times)ÚselfÚmax_sizes Úmain.pyÚ__init__ÚTemplateCache.__init__8s؈Œ ØØˆÕócóŒU(dXR;a~[UR5URaUR5 [R
"U5nUb0X0RU'[ R "5URU'U$[ R "5URU'URU$)z)Get template image from cache or load it.)rÚlenrÚ_cleanup_old_entriesÚcv2ÚimreadÚtimer)rÚpathÚ force_reloadÚtemplates rÚ get_templateÚTemplateCache.get_template=sæ ˜4§{¡{Ó4—; 4§>¡>Ó×—zz 'ˆÑ#Ø$,— ˜!Ü+/¯9ª9«;×" ˆOä'+§y¢y£{ˆD× Ñ ˜ —;‘;˜tÑ $r cóUR(dg[URR5SS9n[U5S-nUSUH=up4URR US5 URR US5 M? g)z#Remove least recently used entries.Ncó US$)©)Úxs rÚ<lambda>Ú4TemplateCache._cleanup_old_entries.<locals>.<lambda>RsÈ!ÈAÊ$r )Úkeyé)rÚsortedÚitemsr"rÚpop)rÚsorted_entriesÚentries_to_remover'Ú_s rr#Ú"TemplateCache._cleanup_old_entriesLsxà×!× ô  × 2Ñ 2× 8Ñ 8Ó :ÁÑÜ Ó/°1Ñà%Ð&8Ð'8Ó9‰Gˆ K‰KO‰O˜D  × Ñ × " Ö :r có–URR5 URR5 [R"5 g)zClear all cached templates.N)rÚclearrÚgcÚcollect©rs rr=ÚTemplateCache.clearYs-à ×ÑÔØ ×Ñ× Ñ Ô
Š
r )rrrN)é2©F)
Ú__name__Ú
__module__Ú __qualname__Ú__firstlineno__Ú__doc__rr*r#r=Ú__static_attributes__r/r rrr3sñô ô
 r rcód\rSrSrSrS SjrSr\S5rSr Sr
\S 5r \S
5r S r
g)
ÚScenarioébzy
Represents a scenario, which consists of a name and a list of steps.
Handles saving/loading scenario data to/from disk.
Ncó0XlU=(d /Ulg)z7
Initialize a Scenario with a name and optional steps.
ÚnameÚsteps)rrOrPs rrÚScenario.__init__gsðŒ Ø—[˜bˆ
r có4URURS.$)z5
Return a dictionary representation of the scenario.
rNrNr@s rÚto_dictÚScenario.to_dictns🠙 ¨D¯J©JÑ7r có@[USURS/55$)z-
Create a Scenario object from a dictionary.
rOrP)rKÚget)Údatas rÚ from_dictÚScenario.from_dictts ô
˜˜V™  d§h¡h¨w¸Ó&;Ó<r có^[RR[UR5$)z6
Return the directory path for this scenario's files.
)Úosr'ÚjoinÚ
CONFIG_DIRrOr@s rÚget_scenario_dirÚScenario.get_scenario_dir{sôw‰w|‰|œJ¨¯ © Ó2r có(UR5n[RRU5(d[R"U5 [ [RR
US5S5n[R"UR5USS9 SSS5 [RSURS35 g!,(df  N2=f![a/n[RSURS U35 SnAgSnAff=f)
z+
Save the scenario to disk as a JSON file.
ú
scenario.jsonÚ)ÚindentNú
Scenario 'z' saved.zFailed to save scenario 'ú': )r^r[r'ÚexistsÚmakedirsÚopenr\ÚjsonÚdumprSÚloggerÚinforOÚ ExceptionÚerror)rÚ scenario_dirÚes rÚsaveÚ
Scenario.saveð HØ×2ˆ—77—>> ,× ˜”b—g‘g—l‘l <°ÓAÀ3ÔGÈ1Ü— ’ ˜$Ÿ,™,›.¨!°AÒHä K‰K˜* T§Y¡Y K¨xÐ HÕGûôó HÜ L‰LÐ4°T·Y±Y°K¸sÀ1À#Ð Gûð Hús0A4CÁ6%CÂ+CÃ
CÃCÃ
DÃ"%D Ä DcóÀ[RR[U5n[ [RRUS5S5n[
R
[R"U55nSSS5 [RSUS35 W$!,(df  N)=f![a%n[RSUSU35 SnAgSnAff=f)z$
Load a scenario from disk by name.
raÚrNrez ' loaded.zFailed to load scenario 'rf)
r[r'r\r]rirKrXrjÚloadrlrmrnro)rOrprqÚscenariorrs rrwÚ
Scenario.loadð
 ÜŸ7™7Ÿ<™<¬
°DÓ9ˆ”b—gg—ll ÓAÀ3ÔGÈ1Ü#×-¬d¯iªi¸«lÓ;÷Hä K‰K˜* T F¨)Ð ˆO÷HÕGûôó Ü L‰LÐ4°T°F¸#¸a¸SÐ ûð ús0AB.Á*BÁ:"B.Â
B+Â'B.Â.
CÂ8CÃCc óò[R"[5Vs/sHMn[RR [RR [U55(dMKUPMO sn$s snf)z
List all scenario directories.
)r[Úlistdirr]r'Úisdirr\)Úds rÚlist_allÚScenario.list_allŸsGô
Ÿ:š:¤jÔ1a´R·W±W·]±]Ä2Ç7Á7Ç<Á<ÔPZÐ\]ÓC^×5_—Ñ`ùÒ`s A
A4Á+A4rNr)rDrErFrGrHrrSÚ staticmethodrXr^rsrwr~rIr/r rrKrKbsZñô ñð 
Hðñ óð ðñaóóar rKcóŽ^^^^^ ^
^ ^ [R"5m T RSS5 T RSS5 T RSS5 T RT 5 T R SS5 T R S5 [R "T SSS 9mTRS
SS 9 S mS m S m S m
TRT R5S
-SSSSS9mUUUU U 4SjnUUU U 4SjnU U
U U 4SjnU U
4SjmU4SjnTRSU5 TRSU5 TRSU5 T RST5 T RSU5 T R5 T R5 T R5 T R#5 T
$![a$n[R!SU35 S m
S nAN<S nAff=f![a#n[R%SU35 S nAT
$S nAff=f!T R#5 f![a"n[R%SU35 S nAfS nAff=f=f)
Use Tkinter to let the user select a region of the screen for a screenshot.
Optimized for better performance and memory usage.
Returns a dict with x, y, width, height, or None.
z-alphaç333333Ó?z -fullscreenTz-topmostFÚcrossr)ÚcursorÚhighlightthicknessÚboth)ÚfillÚexpandNrcrBz3Click and drag to select area. Press ESC to cancel.Úwhite)ÚArialé)Útextr‡Úfontc ó€>URmURmTRT5 TRTTTTSSS9mg)redrc)ÚoutlineÚwidth)r0ÚdeleteÚcreate_rectangle)ÚeventÚcanvasÚinstruction_textÚrectÚstart_xÚstart_ys €€€€€rÚon_button_pressÚ5take_screenshot_with_tkinter.<locals>.on_button_pressÅsAø€à—''ˆØ—''ˆà
Ð×& ¸À'ÐSXÐ`aÐb‰r có|>T(a4Tb0Tb,URURp!TRTTTX5 ggggr)r0rÚcoords)r•Úcur_xÚcur_yrr˜r™s €€€€rÚ
on_mouse_dragÚ3take_screenshot_with_tkinter.<locals>.on_mouse_dragÍs<ø€æ '¨GÑ,?Ø Ÿ7™7 E§G¡G M‰M˜$ ¨°%Õ -@Ð'ˆ4r cóø>T bfT bcURURp![T U5n[T U5n[T U5n[T U5nXS-
nXd-
nUS:”a US:”aX4XxS.m
OSm
T R 5 g)
)r0rrÚheight)r0rÚminÚmaxÚquit)
r•Úend_xÚend_yÚx1Úy1Úx2Úy2rÚrootÚselection_rectr™s
€€€€rÚon_button_releaseÚ7take_screenshot_with_tkinter.<locals>.on_button_releaseÓsø€à Ñ  7Ñ#6Ø Ÿ7™7 E§G¡GW˜eÓ$ˆW˜$ˆBÜW˜eÓ$ˆBÜW˜eÓ$ˆBà‘GˆEØ‘Wˆrz˜f rkØ')¸UÑ!Uà!%à r có*>SmTR5 gr))r•s €€rÚ on_escapeÚ/take_screenshot_with_tkinter.<locals>.on_escapeèsø€àˆØ r có8>URS:Xa T"U5 gg)Escape)Úkeysym)r•r´s €rÚ on_key_pressÚ2take_screenshot_with_tkinter.<locals>.on_key_pressísø€Ø <‰<˜  ð $r z<ButtonPress-1>z <B1-Motion>z<ButtonRelease-1>z<Escape>z
<KeyPress>zError in screenshot selection: z!Error destroying tkinter window: )ÚtkÚTkÚ
attributesÚwait_visibilityÚ resizableÚoverrideredirectÚCanvasÚpackÚ create_textÚwinfo_screenwidthÚbindÚ focus_setÚ focus_forceÚmainlooprnrlroÚdestroyÚwarning)
rrrrr—r´r˜r™s
@@@@@@@@rÚtake_screenshot_with_tkinterr˦sÿ€ô 5Š57€D؇OOH˜‡OOM ‡OOÔ×јÔð ‡NN5˜%Ô Ø×ј$Ôä
YŠYt Ñ
B€FØ
‡KKV D€KÑ €DØ€GØ€GØ€Nð× ×ÑÓ  AÑ% rØ
˜=ðÐ÷ cñc÷@ð@÷ ðö*õ
ð
 ‡K! 
‡KK
˜
‡K#Ð%6Ô‡IIˆj˜‡IIˆl˜LÔ ‡NØ×ÑÔð DØ
Œð
 DØ L‰LŒNð Ðøô óÜ Ð6°q°cÐûðûô ó DÜ N‰NÐ>¸q¸ Ðûð Dûð DØ L‰LNøÜó DÜ N‰NÐ>¸q¸B× Cûð DýslÅ>F!ÆGÆ!
GÆ+G
ÇHÇ
GÇHÇ
G?ÇG:Ç:G?ÈIÈHÈIÈ
IÈH<È7IÈ<IÉIcó†^\rSrSrSrSrSrSrSrSr Sr
S r S
r S r
S rS
rSrSrU4SjrSrSrSrSrSrSrSrSrSrSrSrSrSrSr Sr!S r"S!r#S"r$S#r%S$r&S%r'S&r(S'r)S(r*S)r+S*r,S+r-S,r.S-r/S.r0S/r1S0r2S1r3S2r4S3r5S4r6S5r7S6r8S7r9S8r:S9r;S>S:jr<S;r=S<r>S=r?U=r@$)?Ú
MainWindowi zo
Main application window for Scenario Image Automation.
Handles UI, scenario management, and automation logic.
cóz[RS5 Sn[R"5nUR(G[R"5nUS-S:XaUR S5 UR 5nUc[R "S5 MlUupVnSn[R"5n [URR5up«U RSS U
35n XÀR;aXRU -
S
:aM@URXµXg5n
URX½5(dMjS UlUR S U 35 [RS
U 35 URX½5nU(aXRU 'S nSUl O [R"5U-
nUR!U5 US-
nUS-S:XaUR#5 U(d[%SSU-
5OSn[R "U5 UR(aGSUlUR S5 [RS5 g![&a"n[R)SU35 SnANUSnAff=f!SUlUR S5 [RS5 f=f)zP
Optimized automation loop with memory management and performance improvements.
zAutomation loop started.rúLooking for matchesNçš™™™™™¹?FrOÚstep_çð?TzPerforming step: zExecuting step: r.édçš™™™™™©?gš™™™™™É?zAutomation loop error: ÚPausedzAutomation loop ended.)rlrmr&ÚrunningÚ set_stateÚ_get_optimized_screenshotÚsleepÚ enumerateÚcurrent_scenariorPrVÚ_step_cooldownÚ_process_step_imagesÚ_check_step_triggerÚ_processing_stepÚ_execute_step_actionsÚ_update_performance_statsÚ_periodic_cleanupr§rnro)rÚ frame_countÚ last_gc_timeÚloop_start_timeÚ screen_dataÚ screen_npÚoffset_xÚoffset_yÚ
step_executedÚ current_timeÚstep_idxÚstepÚ step_nameÚ
detectionsÚsuccessÚ loop_timeÚ
sleep_timerrs rÚautomation_loopÚMainWindow.automation_loopsbô  Ј Ü—y’y“{ˆ ð@—,—,,Ü"&§)¢)£+ð Ñ# —NNÐ#8Ô#×> ØÑ—JJ˜s”OÙà0;Ñ-  !&
Ü#Ÿyšy{ ä&/°×0EÑ0E×0KÑ0KÖ&LNHà $§¡¨°5¸¸
Ð1CÓ D ×$7Ñ$7Ó'×*=Ñ*=¸iÑ*HÑHÈ3Ó"&×!:Ñ!:¸4ÈHÓ!_××AØ04˜ÔŸÐ):¸9¸+Ð'FÔŸ Ð&6°y°kÐ$BÔ#'×"<Ñ"<¸TÓ"N˜æ"Ø=I×/° Ñ:Ø,0˜Mà05˜Ôñ1'Mô6!ŸIšIK¨/Ñ9 Ø×.¨yÔ˜qÑ Ø ÑÓ×@MœS  s¨Y¡Ô7ÐRU
Ü
˜&ðq—,—,,ðz%*ˆ N‰N˜8Ô K‰KÐ 1øô ó L‰LÐ2°1°#Ð6× 7ûð 8ûð%*ˆDÔ N‰N˜ K‰KÐ 1ús1®D
IÄ?C,IÉ
JÉ&JÉ>J ÊJÊJ Ê /J:cóø[R"5nURb9UR(d(XR-
UR:a UR$UR
R
5nUS:Xa[R"5nSupEOêSn[R"5HnURU:XdMUn O UURS:”URS:”a|URURURUR4up‰p«USa+U Sa%U
S:”aU S:”a[R"X‰X«4S9nX‰pTO3[R"5nSupEO[R"5nSupE[ R""[$R&"U5[ R(5n XÄU4n
XÐlXlAU
$![*a"n[,R/SU35 SnAgSnAff=f)z:
Get screenshot with caching to reduce memory allocation.
Entire Screen©rrr)ÚregionzError capturing screenshot: )r&Ú_last_screenshotrßÚ_last_screenshot_timeÚ_screenshot_cache_durationÚ window_comboÚ currentTextÚ pyautoguiÚ
screenshotÚgwÚ
getAllWindowsÚtitlerÚleftÚtopr$ÚcvtColorÚnpÚarrayÚ
COLOR_RGB2BGRrnrlro)rÚselected_windowÚscreenrèÚwinrbr0rÚw_Úh_rçrrs rÚ$MainWindow._get_optimized_screenshotXs¸ô—y’y“{ˆ ð
× × × ×8WÑ8WÓ × ) Ø"×/×=ˆ "×/Ø%)Ñ"˜Ü×+—w‘w /Õ˜Ùñ
‘? s§y¡y°1£}¸¿¹Àa»Ø#&§8¡8¨S¯W©W°c·i±iÀÇÁÐ#KLA˜˜A“v ! q£&¨R°!«V¸¸Ü!*×!5Ò!5¸aÀB¸^Ñ!L˜Ø-.¡(ä!*×!5Ò!5Ó!7˜Ø-1Ñ*˜ &×3FØ)-Ñ&Ÿ š ¤R§X¢X¨fÓ%5´s×7HÑ7HÓIˆÐ9ˆKØ$/Ô !Ø)5Ô àÐ øäó Ü L‰LаsÐ ûð ús ÁA"G
ÃD G
Ç
G9ÇG4Ç4G9c ó&0nURS/5n[RUS5nUc[R SUS35 M<[
R "X'[
R5n[
R"U5upšp¼URSS5n
X­:”a#U SU-U SU-4nXçRU
4XVS 'A U$![a6n[RS
URS S 5S U35 SnASnAff=f)
z,
Process step images with template caching.
Úimagesr'NzCould not load template image: Ú sensitivityçÍÌÌÌÌÌì?rr.rOzError in image detection for Úunknownú: ) rVÚtemplate_cacher*rlr$Ú
matchTemplateÚTM_CCOEFF_NORMEDÚ minMaxLocÚshapernro)rÚimgr)ÚresÚmin_valÚmax_valÚmin_locÚmax_locrÚabs_locrrs rÚMainWindow._process_step_imagessðˆ
à—8‘8˜H bÖ)ˆCð
`ä6°s¸6±{ÓCØÑ—N‘NÐ%DÀSÈÁ[ÀMÐ#RÔô×'¨ ¼S×=QÑ=QÓRÜ58·]²]À3Ó5GÑ2 !Ÿg™g m°SÓ9 ØÓ& q™z¨HÑ4°g¸a±jÀ8Ñ6KÐLGØ/6¿¹ÈÐ.PJ 6™{Ññ'*ð0Ðøôó
`Ü Ð<¸S¿W¹WÀVÈYÓ=WÐ<XÐXZÐ[\ÐZ]Ð^×_ûð
`ús™6CÁA9CÃ
DÃ+D Ä Dcó
URS/5nU(dgUVs/sHoDRS5U;dMUPM nnURSS5nUS:Xa[U5[U5:H$[U5S:„$s snf)z8
Check if step should be triggered based on detections.
rFrOÚ conditionÚORÚANDr)rVr")rÚ step_imagesrÚfoundr#s rÚMainWindow._check_step_trigger¯s{ð—h‘h˜x¨Ó ÞØá +Ó ˜¯w©w°v«À*Ñ/L—¡ ˆÐ—H‘H˜[¨$Ó/ˆ à ˜Ó Üu“:¤ [Ó!1Ñ u“:  !ùò
Ns
ŸB»Bcó˜URS/5Vs/sHo3RS5U;dMUPM nnU(aUUSnURURS5S5upgnURS/5Hn URXU5 M gg s snf![a"n
[R SU
35 Sn
A
g Sn
A
ff=f)
z+
Execute step actions with error handling.
rrOr))rrrrÚactionsTzError executing step actions: NF)rVÚ_perform_step_actionrnrlro) rrÚ found_imagesÚref_imgÚlocrÚ
confidenceÚactionrrs rÚ MainWindow._execute_step_actions¿ð
?Ø+/¯8©8°H¸bÔ+AÓcÒ+A CÇWÁWÈVÃ_ÐXbÑEbŸCÑ+Aˆà& q™/Ø)3¯©¸¿ ¹ ÀFÓ8KÐMcÓ)dÑ&˜"Ÿh™h y°"Ö5×-¨f¸ððùòdøôó L‰LÐ9¸!¸Ð=× ûð ?ús-BB²B¸ABÂBÂ
C Â'CÃC cóNURRU5 [UR5UR:”aURR S5 [ UR5[UR5- nUS:”a[ RSUSS35 gg)z/
Update performance statistics for monitoring.
rçà?z(Performance warning: Average loop time: ú.3fÚsN)Ú _loop_timesÚappendr"Ú_max_loop_time_samplesr7Úsumrl)rÚavg_times rÚ$MainWindow._update_performance_statsÔð
×Ñ×Ñ  Ô ˆt×ÑÓ  4×#>Ñ#>Ó × Ñ × Ñ  Ô t×(¬3¨t×/?Ñ/?Ó+@Ñ@ˆØ c N‰NÐEÀhÈsÀ^ÐSTÐ  r cóSUl[R"5nURR5VVs/sHup#X-
S:”dMUPM nnnUHnURU M [R
"5 gs snnf)z3
Perform periodic cleanup to prevent memory leaks.
Né,)r&r6r>r?)rrOÚ timestampÚ
old_cooldownss rÚMainWindow._periodic_cleanupászð
!%ˆÔô—yy“{ˆ Ø59×5HÑ5H×5NÑ5NÔ5Pô;Ò5P¡/ 3°cÑÑ5Pˆ
ñ!ˆDØ×# 
Š
ùó
;s ºBÁ Bc
ó¼USnUSn[RSUSUSUSU35 US:XURSS 5nUS :XaUS
US S --nUS US
S --nOkUS
:Xa1US
URSS
5-nUS URSS
5-nO4US:Xa%URSS
5nURSS
5nO US
US p‡URSS5n [RSUSUSU 35 [R
"XxU S9 g(US:XaAURSS5n
[RSU
35 [R "U
5 g(US:Xa}URSS
5n URSS5n [RS U S!U 35 U S:Xa[R"U 5 g([R"[U 5*5 g(US":XaBURS#S 5n
[RS$U
S%35 [R"U
5 g(g(![a%n[RS&US'U35 S(nAg(S(nAff=f))zQ
Perform a single step action (click, key, scroll, delay) at the given location.
ÚtypeÚparamsúPerforming step action: ú , params=ú, loc=ú, shape=ÚclickÚpos_typeÚcenterrr.rcÚrelativeÚrel_xÚrel_yÚabsoluteÚabs_xÚabs_yÚbuttonrú
Clicking at (ú, ú) with button ©rQr3ÚenterúPressing key: ÚscrollÚamountÚ directionÚupú Scrolling: ú direction: ÚdelayÚdurationú
Delay for ú secondsúError performing step action r
rlÚdebugrVrmrHÚpressrXÚabsr&rnro©rr0r.rÚact_typerCrIr0rrQr3rYrZr_rrs rr+ÚMainWindow._perform_step_actionòóSð˜&‘>ˆØ˜ÑÜ Ð¨z¸À6À(È&ÐQTÐPUÐU]Ð^cÐ]dÐ" Jؘ!Ÿ:™: j°(Ó;ؘ˜A™  q¡¨Q¡Ñ.˜A™  q¡¨Q¡Ñ.‘AØ Ó˜A™ §¡¨G°QÓ!7Ñ7˜A™ §¡¨G°QÓ!7Ñ7‘AØ ÓŸ
 7¨AÓ.Ÿ
 7¨AÓ.˜q™6 3 q¡6Ÿ H¨fÓ5Ü ˜m¨A¨3¨b°°°>À&ÀР¨VÓ˜UÓ—j‘j ¨Ó0Ü ˜n¨S¨EР՘XÓŸ H¨aÓ0Ø"ŸJ™J {°DÓ9 Ü ˜k¨&¨°¸i¸[РÓ×$ VÕ×$¤c¨&£k ˜!Ÿ:™: j°!Ó4Ü ˜j¨¨
°(Ð
˜8Õ%øôó JÜ L‰Lи
À"ÀQÀCÐH× Iûð Júó3­C+H,ÄAH,Å A!H,Ç H,Ç#AH,È,
IÈ6IÉIcóLXlURRSU35 g)z#
Update the state label in the UI.
zState: N)Ú
state_textÚ state_labelÚsetText)rs rr×ÚMainWindow.set_states$ðŒØ ×Ñ× Ñ  7¨4¨&Ð!1Õ2r có$UR(aUR5 g[R"5nXR-
S:a7[R S5 [ RRUSS5 gUR5 g)z„
Toggle the automation state (start/stop). A debounce delay is added only
when changing from stop to start, not from start to stop.
éz9Start toggle ignored: pressed too quickly after stopping.ÚWaitz5Please wait at least 5 seconds before starting again.N)
Ústop_automationr&Úlast_toggle_timerlrmrÚ QMessageBoxÚ informationÚstart_automation)rÚnows rÚtoggle_automationÚMainWindow.toggle_automation#shð
< × Ñ Õ —)’)“+ˆCØ×*¨QÓ Ð×1°$¸Ð@wÔØ × #r cóx[RS5 UR(aUR(a[R S5 gSUlUR R5 [R"5 URR5 SUlURS5 URRSURR5S35 [ R""UR$SS9UlUR&R)5 [*R,"URUR.05UlUR0R)5 [RS
5 g![2a"n[R5S U35 SnAN=SnAff=f) zF
Start the automation process and worker thread with resource checks.
zStarting automation.z:Start Automation: No scenario selected or already running.NTrÏzStop (Ú))ÚtargetÚdaemonz!Failed to setup hotkey listener: z Automation started successfully.)rlrmr=r>r?r6r×Úbtn_start_stoproÚhotkeyÚupperÚ threadingÚThreadróÚworkerÚstartrÚ
GlobalHotKeysrtÚlistenerrnro©rrrs rrxÚMainWindow.start_automation2sGô  Ðׯ ¯ Ü N‰NÐ ð!%ˆÔØ ×Ñ×
Š
Œ ð
×Ñ×ÑÔ ðˆŒ Ø Ð ×Ñ×# f¨T¯[©[×->Ñ->Ó-@Ð,AÀÐ$CÔ ×&¨d×.BÑ.BÈ4ÑŒ Ø ×ÑÔð BÜ2°D·K±KÀ×AUÑAUÐ3VÓWˆDŒMØ M‰M× Ñ Ô
 Ð7øô ó BÜ L‰LÐ<¸Q¸@× Aûð BúsÄ,A F
Æ
F9ÆF4Æ4F9cóXSSKnUR5nUR5nURS- S- URS- S- UR 5S.$![ aE [[R5[US5(a[UR5OSS.s$f=f)z6
Get current memory usage information for monitoring.
rNi)ÚrssÚvmsÚpercentrÜ)Útemplate_cache_sizeÚcooldown_entries) ÚpsutilÚProcessÚ memory_inforŒrÚmemory_percentÚ ImportErrorr"rrÚhasattrrÜ)rrÚprocessr“s rÚget_memory_usageÚMainWindow.get_memory_usageVð Û Ø—n&ˆ!×/ˆ"—¨ÑÑ"—¨ÑÑð
øô
ó ô(+¬>×+@Ñ+@Ó'AÜ@GÈÐN^×@_Ñ@_¤C¨×(;Ñ(;Ô$<Ðefñò
ð úsAAÁA B)Â(B)có[RS5 SUl[R"5UlUR S5 UR RSURR5S35 UR(a"URR5 SUl
UR(atURR5(aUURR!SS 9 URR5(a[RS
5 SUlSUlSUlUR&R)5 [*R,"5 [RS 5 g![a#n[RSU35 SnAGNSnAff=f!SUl
f=f![a"n[RS U35 SnAN½SnAff=f!SUlf=f)
zD
Stop the automation process and worker thread with proper cleanup.
zStopping automation.FrÕúStart (r}z Error stopping hotkey listener: Ng@)Útimeoutz)Worker thread did not stop within timeoutzError joining worker thread: z,Automation stopped and resources cleaned up.)rlrmr&rur×r€rorrrˆÚstoprnr…Úis_aliver\r=r>r?r‰s rrtÚMainWindow.stop_automationjs‡ô  ЈŒ Ü $§ ¢ £ ˆÔØ  Ø ×Ñ×# g¨d¯k©k×.?Ñ.?Ó.AÐ-BÀ!Ð$DÔ =

×!%
ð ;;˜4Ÿ;™;×/×
 × Ñ ¨Ð Ñ—;;×'×—NNÐ#NÔ# ð!&ˆÔØ $ˆÔØ ×Ñ×
Š
Œ ä ÐCøô1ó
GÜÐ!AÀ!ÀÐFûð
Gûð!%
ûôó
DÜÐ!>¸q¸Cûð
Dûð# úsUÂF
Ã#A
GÆ
F7ÆF2Æ,F:Æ2F7Æ7F:Æ: GÇ
G2ÇG-Ç(G5Ç-G2Ç2G5Ç5 G>cóÆ>[TU]5 URS5 SnSnURX5 UR SSX5 SUlSUlSUlSUlSUl SUl
SUl SUl SUl
SUlSUl0Ul/UlS UlUR'5 UR)5 UR+[,R.R0R25 [,R4"5UlUR6R8R;UR<5 UR6R?S
5 g) z5
Initialize the main window, UI, and load scenarios.
zScenario Image Automationi€Fz<f9>Nré') ÚsuperrÚsetWindowTitleÚsetMinimumSizeÚ setGeometryrÖrrˆr…Úselected_step_idxrur6r8Úinit_uiÚload_scenariosÚ setAttributerÚQtÚWidgetAttributeÚWA_DeleteOnCloseÚQTimerÚ
monitor_timerrœÚconnectÚ_monitor_performancer†)rÚ min_widthÚ
min_heightÚ __class__s €rrÚMainWindow.__init__s2ø€ô ÑÔØ ×ÑЈ ؈
Ø ×јIÔ ×ј˜c 9ÔˆŒ ؈Œ ؈Œ
؈Œ Ø $ˆÔØ!%ˆÔØ !ˆÔð!%ˆÔØ%&ˆÔ"Ø*.ˆÔ'Ø %ˆÔØ ˆÔðˆÔØ&(ˆÔ ŒØ ×ÑÔð
×Ñœ&Ÿ)™)×3×$Ÿ]š]›_ˆÔØ ×Ñ×"×*¨4×+DÑ+DÔ ×Ñ× Ñ  Õ'r cóàUR(dgUR5n[US5(aUR(ay[ UR5[ UR5- nUS:”a[ RSUSS35 SU;a'USS:”a[ RS USS
35 ggggg![a"n[ RS U35 SnAgSnAff=f) z3
Monitor application performance and memory usage.
Nr6z%Performance issue: Average loop time r4r5rézTemplate cache has z entrieszPerformance monitoring error: ) r˜rr6r9r"rlrmrnrd)rr“Ú
avg_loop_timerrs rÚMainWindow._monitor_performance»ð| ð×1ˆKôt˜]××0@×0@Ü # D×$4Ñ$4Ó 5¼¸D×<LÑ<LÓ8MÑ M
ð! —NNÐ%JÈ=ÐY\ÐJ]Ð]^Ð#_Ô)¨KÓ7¸KÐH]Ñ<^ÐacÓ<cÜ—KKÐ"5°kÐBWÑ6XÐ5YÐYaÐ bÕ=dÐ1AÐ+øôó L‰LÐ9¸!¸Ð=× >ûð ?ús”B(CÃ
C-à C(Ã(C-có€[US5(a-UR(aURR5 ggg)z"Stop performance monitoring timer.r®N)rrr@s rÚstop_monitoringÚMainWindow.stop_monitoringÔs2ä 4˜× )¨d×.@×.@Ø × Ñ × /AÐ )r cóDUR5 UR5 g)z3Handle application close event with proper cleanup.N)Úcleanup_resourcesÚaccept©rr•s rÚ
closeEventÚMainWindow.closeEventÙsà ×ÑÔ Ø
r cóœUR(aUR5 UR5 [R 5 SUl[
US5(aURR 5 [
US5(aURR 5 [R"5 [RS5 g)z+Clean up resources to prevent memory leaks.Nr6z!Resources cleaned up successfully)
rtrr=rr6r>r?rlrmr@s rÚMainWindow.cleanup_resourcesÞs”à < × Ñ Ô 
×ÑÔô ×ÑÔð!%ˆÔô 4˜× × Ñ × )× × Ñ × 
Š
Œ ä Ð8r cóî[R"5nURS5 URU5 SnUR U5 [
R "S5nUR[
RRR[
RRR5 [
R"5n[
R"5UlURRS5 URR R#UR$5 UR'UR5 [
R"5UlUR(RS5 [
R "S5nUR[
RRR[
RRR5 [
R*"5nUR(RS5 UR(R R#UR,5 [
R."S5UlUR0R3S5 UR0R4R#UR65 UR'UR(5 UR'UR05 UR9U5 UR;5 [
R."S5UlUR<R3S 5 UR<R4R#UR>5 [
R."S
5Ul UR@R3S 5 UR@R4R#URB5 [
R."S 5Ul"URDR3S
5 URDR4R#URF5 [
R."S5Ul$URHR3S5 URHR4R#URJ5 [
R."S5Ul&URLR3S5 URLR4R#URN5 [
R*"5nURQS5 URSSSSS5 UR'UR<5 UR'UR@5 UR'URD5 UR'URH5 UR'URL5 URUU5 UR9U5 [
R "S5n[
R"5n [
RV"5Ul,URXR[S5 URXR\R#UR^5 U R'URX5 [
R."S5Ul0UR`R3S5 UR`R4R#URb5 [
R."S5Ul2URdR3S5 URdR4R#URf5 [
R."S5Ul4URhR3S5 URhR4R#URj5 [
R."S5Ul6URlR3S5 URlR4R#URn5 [
R."S5Ul8URpR3S5 URpR4R#URr5 [
R."S5Ul:URtR3S5 URtR4R#URv5 [
R*"5n
U
RQS5 U
RSSSSS5 U
R'UR`5 U
R'URd5 U
R'URh5 U
R'URl5 U
R'URp5 U
R'URt5 U RUU
5 UR9U 5 [
R."SURxR{5S 35Ul>UR|RS!5 UR|R4R#UR~5 [
R€"S"5UlAURR S#5 URR…[†Rˆ[†Rˆ-5 [
R"5n U R“S$5 U R•S5 U RSS%S%S%S%5 U R'US&S&S'S(5 U R—S&S&5 U R'US'S&S'S(5 U R'US)S&S*S(5 [
R "5n U R™S+5 U R[
RRR[
RRR5 [
R*"5n
U
RQS$5 U
R'UR|5 U
R'UR5 U
RS'5 U R9U
5 U R'U S(S&S'S(5 U R—S(S&5 [
"5nUR9U 5 UU5 g,)-zw
Initializes the main UI components and layouts.
Sets up scenario and window dropdowns, step list, and action buttons.
é aN
QPushButton, QComboBox, QListWidget, QLabel {
font-size: 9pt;
min-height: 20px;
padding: 2px 6px;
}
QComboBox { min-width: 90px; }
QPushButton { min-width: 70px; }
QListWidget { min-width: 200px; min-height: 120px; }
rKéZz
Target WindowÚRefreshzRefresh open windows listÚNewzCreate new scenarioÚImportzImport scenarioÚExportzExport scenarioÚRenamezRename scenarioÚDeletezDelete current scenarior4z3Steps (Up = Higher Priority, Down = Lower Priority)éxÚAddzAdd stepÚEditz Edit stepz Delete stepz Rename stepúMove UpzMove step up (higher priority)ú Move DownzMove step down (lower priority)rr}éPz
State: Pausedz3font-weight: bold; font-size: 11pt; color: #0055aa;éérr.rrrcéÚN)PrÚQFontÚ setPointSizeÚsetFontÚ
setStyleSheetrÚ QGroupBoxÚ
setSizePolicyÚ QSizePolicyÚPolicyÚ PreferredÚFixedÚ QVBoxLayoutÚ QComboBoxÚcomboÚsetMinimumWidthÚcurrentIndexChangedr¯Ú_log_combo_scenarioÚ addWidgetrüÚ QHBoxLayoutÚ_log_combo_windowÚ QPushButtonÚbtn_refresh_windowsÚ
setToolTipÚclickedÚ_log_btn_refresh_windowsÚ setLayoutÚrefresh_window_listÚbtn_newÚ _log_btn_newÚ
btn_importÚ_log_btn_importÚ
btn_exportÚ_log_btn_exportÚbtn_rename_scenarioÚ_log_btn_rename_scenarioÚbtn_delete_scenarioÚ_log_btn_delete_scenarioÚ
setSpacingÚsetContentsMarginsÚ addLayoutÚ QListWidgetÚ
steps_listÚsetMinimumHeightÚcurrentRowChangedÚ_log_steps_listÚ btn_add_stepÚ_log_btn_add_stepÚ
btn_edit_stepÚ_log_btn_edit_stepÚ btn_del_stepÚ_log_btn_del_stepÚbtn_rename_stepÚ_log_btn_rename_stepÚbtn_move_up_stepÚ_log_btn_move_up_stepÚbtn_move_down_stepÚ_log_btn_move_down_steprrr€Ú_log_btn_start_stopÚQLabelrnÚ setAlignmentrÚ
AlignmentFlagÚ AlignLeftÚ AlignVCenterÚ QGridLayoutÚsetHorizontalSpacingÚsetVerticalSpacingÚ
setRowStretchÚsetTitleÚ
addStretchÚQWidgetÚsetCentralWidget)rrÚstyleÚscenario_group_boxÚscenario_group_layoutÚwindow_group_boxÚwindow_group_layoutÚscenario_btn_group_layoutÚsteps_group_boxÚsteps_group_layoutÚstep_btn_group_layoutÚlayoutÚstart_state_groupÚstart_state_layoutÚcentrals rÚMainWindow.init_ui÷ss ô {Š{‹}ˆØ ×ј!ÔØ ð  ˆð
×ј'×ÓØ××)>Ñ)>×)EÑ)E×)OÑ)OÔQZ×QfÑQf×QmÑQm×QsÑQsÔtÜ )× 5Ò 5Ó 7ÐÜ׌
Ø
×" 
×&×.¨t×/GÑ/GÔׯ
©
ÔÔØ ×Ñ×)¨"Ô$×ÓØ×&¤y×'<Ñ'<×'CÑ'C×'MÑ'MÌy×OdÑOd×OkÑOk×OqÑOqÔ'ר ×Ñ×)¨"Ô ×Ñ×-×5°d×6LÑ6LÔMÜ#,×#8Ò#8¸Ó#CˆÔ Ø × Ñ ×+Ð,GÔ × Ñ ××1NÑ1NÔ×% d×&7Ñ&7Ô×% d×&>Ñ&>Ô×"Ð#6Ô × Ñ Ô ×,¨UÓŒ Ø ×ÑÐ 5Ô ×Ñ×$ T×%6Ñ%6ÔÓŒØ ×"Ð#4Ô ×Ñ××(<Ñ(<Ô#×Ó9ˆŒØ ×"Ð#4Ô ×Ñ××(<Ñ(<Ô=Ü#,×#8Ò#8¸Ó#BˆÔ Ø × Ñ ×+Ð,=Ô × Ñ ×(××1NÑ1NÔOÜ#,×#8Ò#8¸Ó#BˆÔ Ø × Ñ ×+Ð,EÔ × Ñ ×(××1NÑ1NÔOÜ$-×$9Ò$9Ó$;Ð!×,¨QÔ4°Q¸¸1¸aÔ+¨D¯L©LÔ!×+¨D¯O©OÔ!×+¨D¯O©OÔ!×+¨D×,DÑ,DÔ!×+¨D×,DÑ,DÔ×'Ð(AÔ×$Ð%:Ô$×-Ð.cÓdˆÜ&×ÜŒØ ×Ô ×1°$×2FÑ2FÔ×$ T§_¡_Ô1°%ÓÔØ ×Ñ×$ ZÔ ×Ñ×)¨$×*@Ñ*@Ô&×2°6ÓÔØ ×Ñ×% kÔ ×Ñ×"×*¨4×+BÑ+BÔ1°(ÓÔØ ×Ñ×$ ]Ô ×Ñ×)¨$×*@Ñ*@Ô(×4°XÓ>ˆÔØ ×Ñ×
Ô ×Ñ×,¨T×-FÑ-FÔGÜ )× 5Ò 5°iÓ @ˆÔØ ×Ñ×(Ð)IÔ ×Ñ×%×-¨d×.HÑ.HÔIÜ"+×"7Ò"7¸ Ó"DˆÔØ ×Ñ×*Ð+LÔ ×Ñ×'××0LÑ0LÔMÜ )× 5Ò 5Ó 7ÐØ×Ô×°A°q¸××(9Ñ(9Ô××(:Ñ(:Ô××(9Ñ(9Ô××(<Ñ(<Ô××(=Ñ(=Ô××(?Ñ(?Ô×$Ð%:Ô×!Ð"4Ô(×3°g¸d¿k¹k×>OÑ>OÓ>QÐ=RÐRSÐ4TÓUˆÔØ ×Ñ×+¨BÔ ×Ñ×+¨D×,DÑ,DÔ%×+¨OÓ<ˆÔØ ×Ñ×&Ð'\Ô ×Ñ×%¤f§i¡i×&=Ñ&=×&GÑ&GÌ&Ï)É)×JaÑJa×JnÑJnÑ&nÔ×(ˆØ×# ×! ×! ! Q¨¨1Ô ×ÑÐ+¨Q°°1°aÔ×јQ Ô×ÑÐ)¨1¨a°°AÔ×ј¨!¨Q°°1Ô&ר×" ××(=Ñ(=×(DÑ(D×(NÑ(NÔPY×PeÑPe×PlÑPl×PrÑPrÔ&ר×% aÔ×$ T×%8Ñ%8Ô×$ T×%5Ñ%5Ô×% ×#Ð$6Ô×ÑÐ*¨A¨q°!°QÔ×јQ Ô×%ˆØ×ј&Ô ×ј&r cóN[RS5 UR5 g)Nz"UI: Refresh Windows button pressed)rlrmr@s rÚ#MainWindow._log_btn_refresh_windowsŽsÜ Ð × Ñ Õ"r cóŒ[RSUSURR5S35 UR 5 g)z9
Log scenario combo box change and call select_scenario.
z$UI: Scenario combo changed to index ú (r}N)rlrmÚselect_scenario©rÚidxs rÚMainWindow._log_combo_scenarios;ô  Ð:¸3¸%¸rÀ$Ç*Á*×BXÑBXÓBZÐA[Ð[\Ð ×ÑÕr cóŒ[RSUSURR5S35 UR 5 g)z<
Log window combo box change and call save_selected_window.
z"UI: Window combo changed to index r.r}N)rlrmÚsave_selected_windowr0s rÚMainWindow._log_combo_window™s=ô  Ð8¸¸¸RÀ×@QÑ@Q×@]Ñ@]Ó@_Ð?`Ð`aÐ ×#r cóN[RS5 UR5 g)z9
Log New Scenario button press and call create_scenario.
zUI: New Scenario button pressedN)rlrmÚcreate_scenarior@s rÚMainWindow._log_btn_new sô  Ð ×ÑÕr cóN[RS5 UR5 g)z<
Log Import Scenario button press and call import_scenario.
z"UI: Import Scenario button pressedN)rlrmÚimport_scenarior@s rÚMainWindow._log_btn_import§óô  Ð ×ÑÕr cóN[RS5 UR5 g)z<
Log Export Scenario button press and call export_scenario.
z"UI: Export Scenario button pressedN)rlrmÚexport_scenarior@s rÚMainWindow._log_btn_export®r<r cóN[RS5 UR5 g)z<
Log Rename Scenario button press and call rename_scenario.
z"UI: Rename Scenario button pressedN)rlrmÚrename_scenarior@s rÚ#MainWindow._log_btn_rename_scenarioµr<r cóN[RS5 UR5 g)z<
Log Delete Scenario button press and call delete_scenario.
z"UI: Delete Scenario button pressedN)rlrmÚdelete_scenarior@s rÚ#MainWindow._log_btn_delete_scenario¼r<r có4UR(dgURRn[RR USSUS3[RR
R [RR
R-5nU[RR
R :Xa…URR5n[RRU5(a[R"U5 [RSU35 SUlUR!5 gg!["aIn[R%SUSU35 [RR'USS U35 SnAgSnAff=f)
z1
Delete the current scenario after confirmation.
NzDelete Scenarioz.Are you sure you want to delete the scenario 'z'? This cannot be undone.zDeleted scenario: zFailed to delete scenario 'rfz Delete ErrorzFailed to delete scenario.
)rOrrvÚquestionÚStandardButtonÚYesÚNor^r[r'rgÚshutilÚrmtreerlrmrnroÚcritical)rrOÚreplyrprrs rrDÚMainWindow.delete_scenarioÃsKð× Ø×Ü× Ø Ø<¸T¸FÐB[Ð × !× 0× 4´y×7LÑ7L×7[Ñ7[×7^Ñ7^Ñ 
ˆð ”I×)×8× 
iØG Ü—77—>> ,×—MM ,Ô Ð°Ð8Ø(,Ô× =øôó
iÜ Ð:¸4¸&ÀÀAÀ3Ð×%×.¨t°^ÐGcÐdeÐcfÐEg×hûð
iúsÂ?BEÅ
FÅ?FÆFcóV[RSU35 URU5 g)z1
Log steps list row change and call select_step.
zUI: Steps list row changed to N)rlrmÚ select_stepr0s rrÚMainWindow._log_steps_listÜs&ô  Ð4°S°EÐ ×јÕr cóN[RS5 UR5 g)z.
Log Add Step button press and call add_step.
zUI: Add Step button pressedN)rlrmÚadd_stepr@s rrÚMainWindow._log_btn_add_stepãsô  Ð
r cóN[RS5 UR5 g)z0
Log Edit Step button press and call edit_step.
zUI: Edit Step button pressedN)rlrmÚ edit_stepr@s rrÚMainWindow._log_btn_edit_stepêsô  Ð Õr cóN[RS5 UR5 g)z4
Log Delete Step button press and call delete_step.
zUI: Delete Step button pressedN)rlrmÚ delete_stepr@s rrÚMainWindow._log_btn_del_stepñóô  Ð ×ÑÕr cóN[RS5 UR5 g)z4
Log Rename Step button press and call rename_step.
zUI: Rename Step button pressedN)rlrmÚ rename_stepr@s rr
ÚMainWindow._log_btn_rename_stepør\r cóN[RS5 UR5 g)z9
Log Start/Stop button press and call toggle_automation.
zUI: Start/Stop button pressedN)rlrmrzr@s rrÚMainWindow._log_btn_start_stopÿsô  Ð ×ÑÕ r cóN[RS5 UR5 g)z6
Log Move Up Step button press and call move_up_step.
zUI: Move Up Step button pressedN)rlrmÚ move_up_stepr@s rr Ú MainWindow._log_btn_move_up_stepsô  Ð ×ÑÕr cóN[RS5 UR5 g)z:
Log Move Down Step button press and call move_down_step.
z!UI: Move Down Step button pressedN)rlrmÚmove_down_stepr@s rrÚ"MainWindow._log_btn_move_down_step
sô  Ð ×ÑÕr cóURnUR(UUS:”U[URR5:URRUURRUS-
sURRUS-
'URRU'URR 5 UR 5 UR RUS-
5 US-
Ulggggg)z@
Move the selected step up in the steps list (higher priority).
Nrr.©r"rPrsÚ
refresh_listsrÿÚ
setCurrentRowr0s rrcÚMainWindow.move_up_stepð×à × Øa“Ø”c˜$××+¨CÑ×+¨C°!©GÑ
SˆD× !× ¨a©Ñ 0°$×2GÑ2G×2MÑ2MÈcÑ2Rð
× !× × Ñ Ô Ø O‰O× )¨#°©'Ô 2Ø%(¨1¡Wˆ ð ð
"r cóURnUR(UUSU[URR5S-
:URRUURRUS-sURRUS-'URRU'URR 5 UR 5 UR RUS-5 US-Ulggggg)zA
Move the selected step down in the steps list (lower priority).
Nrr.rir0s rrfÚMainWindow.move_down_step(ð×à × Øq“Ø”c˜$×Ñ×+¨CÑ×+¨C°!©GÑ
SˆD× !× ¨a©Ñ 0°$×2GÑ2G×2MÑ2MÈcÑ2Rð
× !× × Ñ Ô Ø O‰O× )¨#°©'Ô 2Ø%(¨1¡Wˆ ð ð
"r cóXlg)z(
Set the selected step index in the UI.
N)r0s rrQÚMainWindow.select_step<s
ð"%Õr có¶[U5UlURRRUR5 URR 5 g)z<
Open the dialog to add a new step to the current scenario.
N)Ú
StepDialogÚ _step_dialogÚacceptedr¯Ú_on_add_step_acceptedÚshowr@s rrTÚMainWindow.add_stepBsCô' ,ˆÔØ ×Ñ×"×*¨4×+EÑ+EÔ ×Ñ×ÑÕ r cóHURR5nURRR U5 URR 5 UR
5 [RSU35 URR5 SUlg)Nz Added step: )
rsÚget_steprÛrPr7rsrjrlrmÚ deleteLater)rs rruÚ MainWindow._on_add_step_acceptedJs{Ø× Ñ ×Ø ×Ñ×*¨4Ô ×Ñ× ×ÑÔÜ l 4 &Ð ×Ñ× ˆÕr cóV^^TRmTb)TS:d#T[TRR5agTRRTn[ TU5TlTR
R RUU4Sj5 TR
R5 g)zD
Open the dialog to edit the selected step in the current scenario.
Nrcó&>TRT5$r)Ú_on_edit_step_accepted)r1rs€€rr1Ú&MainWindow.edit_step.<locals>.<lambda>\sø€°4×3NÑ3NÈsÔ3Sr ) r¦r"rPrrrsrtrv)rr1s` @rrWÚMainWindow.edit_stepSsˆù€ðר ‰;˜# ' S¬C°×0EÑ0E×0KÑ0KÓ,LÓ%LØ Ø×$×*¨3Ñ/ˆÜ& t¨TÓ2ˆÔØ ×Ñ×"×*Õ+SÔ ×Ñ×ÑÕ r có,URR5URRU'URR 5 UR 5 [ RSU35 URR5 SUlg)NzEdited step at idx ) rsryrPrsrjrlrmrzr0s rr~Ú!MainWindow._on_edit_step_accepted_ssØ+/×+<Ñ+<×+EÑ+EÓ+Gˆ×Ñ×# CÑ ×Ñ× ×ÑÔÜ Ð)¨#¨Ð ×Ñ× ˆÕr có(URnUb)US:d#U[URR5agURRU URR 5 UR 5 [ RSU35 g)z5
Delete the selected step from the current scenario.
NrzDeleted step at idx )r"rPrsrjrlrmr0s rrZÚMainWindow.delete_stepgs{ð×$ˆØ ‰;˜# ' S¬C°×0EÑ0E×0KÑ0KÓ,LÓ%LØ Ø × !× Ð  ×Ñ× ×ÑÔÜ Ð*¨3¨%Ð1r có[[RR[S5S5nUR U5 SSS5 g!,(df  g=f![ a"n[RSU35 SnAgSnAff=f)z6
Save the name of the last selected scenario to disk.
úlast_scenario.txtrbNzCould not save last scenario: ) rir[r'r\r]Úwriternrlro)rrOrqrrs rÚsave_last_scenarioÚMainWindow.save_last_scenariossað”b—gg—l‘l¤:Ð/BÓCÀSÔIÈQؘ
÷J×Iûäó L‰LÐ9¸!¸Ð=× >ûð ?ús4.A°A ÁAÁ
AÁAÁAÁ
BÁ&BÂBcó~[RR[S5n[RR U5(dg[ US5nUR
5R5sSSS5 $!,(df  g=f![a"n[RSU35 SnAgSnAff=f)z8
Read the name of the last selected scenario from disk.
r†NrvzCould not read last scenario: ) r[r'r\r]rgriÚreadÚstriprnrlro)rr'rqrrs rÚread_last_scenarioÚMainWindow.read_last_scenario}s}ð Ü—77—<
Ð,?Ó@ˆ—77—>> $×Üd˜C” —vv“x—~‘~Ó!—ûäó Ü L‰LÐ9¸!¸Ð ûð ús<ABÁ BÁA?Á5 BÁ?
B
 BÂ
BÂ
B<ÂB7Â7B<cóú[RS5 URR5 [R 5nUHnURR
U5 M UR5 U(G[R"U5nURS5 URS5 URS[RRR5nURS[RRR5nUR!U5 UR#5 UR%5nXd:X[R&R)USS5up'U(aqU(aj[R+SU35 [ U5nUR-5 URR
U5 URR/U5 g
UR15 g
Xe:XaUR35 g
UR15 g
UR55n U (a!X;aURR/U 5 g
URR7S 5 g
) z9
Load all scenarios and populate the scenario combo box.
zLoading scenarios...zNo Scenarios FoundzJNo scenarios found. Would you like to create a new scenario or import one?z
Create NewrÉú New Scenarioz%Enter a name for your first scenario:úCreating new scenario: rN)rlrdr=rKr~ÚaddItemrðrrvroÚ addButtonÚ
ButtonRoleÚ
AcceptRoleÚ
ActionRoleÚsetDefaultButtonÚexecÚ
clickedButtonÚ QInputDialogÚgetTextrmrsÚsetCurrentTextrjr:rÚsetCurrentIndex)
rrrOÚ
choice_dialogÚ
create_btnÚ
import_btnríÚokr5Úlast_scenario_names
rÚMainWindow.load_scenariosô  Ð
×ÑÔÜ×'ˆ Ûˆ J‰J× Ñ ˜tÖ ð
× Ñ ÔÜ1°$Ó7ˆ × (Ð)=Ô × !Ð"nÔ &×¼y×?TÑ?T×?_Ñ?_×?jÑ?jÓkˆ&×¼9×;PÑ;P×;[Ñ;[×;fÑ;fÓgˆ × *¨:Ô × Ñ Ô Ø3ˆGØÓ9¸$ÀÐPwÓx‘Þž$Ü—KKÐ"9¸$¸Ð @Ô  —F‘F”HØ—JJ×& —JJ×-¨dÕ×Ó××$à!%×!8Ñ!8Ó!:Ð Þ!Ð&8Ó&EØ
×)Ð*<Õ
×*¨1Õ-r cóURR5n[RSU35 U(aL[R U5UlURU5 UR5 UR5 gg)z/
Load the selected scenario and update the UI.
zScenario selected: N)
rlrmrKrwrˆrjÚ load_selected_window_from_config)rrOs rr/ÚMainWindow.select_scenarioµsiðz‰z×Ü Ð)¨$¨Ð Ü$,§M¡M°$Ó$7ˆ × # DÔ × Ñ Ô Ø × r có&[RRUSS5upU(agU(a_[R SU35 [ U5nUR
5 UR5 URRU5 ggg)z)
Open a dialog to create a new scenario.
rzEnter scenario name:rN)
rrrlrmrKrs)rrOr5s rr7ÚMainWindow.create_scenarioÁsqô×1°$¸ÐH^Ó_‰ˆÞ
–$Ü K‰KÐ1°$°Ð ˜ˆAØ
F‰FŒHØ × Ñ Ô J‰J× %  ˆ2r có¤UR(dgURRn[RR USSUS9up#U(Ga+U(Ga"X!:wGa[
R R[U5n[
R R[U5n[
R RU5(d[SUS35e[
R RU5(a[SUS35e[
R"XE5 X RlURR%5 UR'5 UR(R+U5 gggg![aFn[RS U35 [R R#US
S U35 SnAgSnAff=f) z/
Open a dialog to rename the current scenario.
NzRename Scenarioú New name:©zScenario directory 'z' does not exist.zA scenario named 'z' already exists.z#Error renaming scenario directory: ÚErrorz%Could not rename scenario directory.
)rOrrr[r'r\r]rgÚFileNotFoundErrorÚFileExistsErrorÚrenameÚOSErrorrlrorvrMrs)rÚold_nameÚnew_namer¡Úold_dirÚnew_dirrrs rrAÚMainWindow.rename_scenarioÍsmð× à×Ü ×-×5°dÐ<MÈ{ÐaiÐj‰ ˆç
—(˜
ÜŸ'™'Ÿ,™,¤z°8Ó<ÜŸ'™'Ÿ,™,¤z°8Ó<Ü—ww—~~ g×+Ð.BÀ7À)ÐK\Ð,]Ó—77—>> '×)Ð,>¸x¸jÐHYÐ*ZÓ ˜*2× × !× 
× Ñ Ô J‰J× % hÕ /ð+ 4(ˆ2øôó
Ü ÐBÀ1À#Ð×%×.¨t°WÐ@fÐghÐfiÐ>jÔûð
úsÁ"CE?Å?
GÆ <G
Ç
GcóxUR(a
URcgURRURnURSS5n[R
R
USSUS9up4U(a=U(a5X2:wa/X1S'URR5 UR5 gggg)z,
Open a dialog to rename the selected step.
NrOú Unnamed Stepz Rename Steprª) rÛrPrVrrrsrj)rs rr^ÚMainWindow.rename_stepîð×$××(>Ñ(>Ñ(FØ à×$×*¨4×+AÑ+AÑØ—8‘8˜F NÓÜ ×5°d¸MÈ;Ð]eÐf‰ ˆæ
–(˜xÓ#‰LØ × !× × Ñ Õ ð 4(ˆ2r c
ó([RRUSSS5upU(G[R"US5n[
R R[S5n[
R RU5(a[R"U5 URU5 [
R"U5Vs/sHHn[
R R[
R RXE55(dMFUPMJ nnU(d [S5eUSn[
R RXG5n[
R R[U5n [
R RU 5(a[R"U 5 [R "X‰5 [R"U5 SSS5 ["R%S U35 UR'5 UR(R+W5 ggs snf!,(df  NX=f![aFn
["R-S
U
35 [R.R1US S U
35 Sn
A
gSn
A
ff=f)
z:
Open a file dialog to import a scenario from a zip file.
zImport ScenariorÖúZIP Files (*.zip)rvÚ _temp_importz,No scenario directory found in the zip file.rNzImported scenario from zFailed to import scenario: z Import ErrorzFailed to import scenario.
)rÚ QFileDialogÚgetOpenFileNameÚzipfileÚZipFiler[r'r\r]rgrKrLÚ
extractallr{r|rnÚmoverlrmrorvrM) rr'r:Úzip_refÚtemp_dirr}Úextracted_dirsÚ
scenario_nameÚsrc_pathÚ dest_pathrrs rr:ÚMainWindow.import_scenarioþô×'×7¸Ð>OÐQSÐUhÓi‰ˆß ð
iÜ—__ T¨3Ô/°7ä!Ÿw™wŸ|™|¬J¸ÓG—w‘w—~‘~ hן
š
 ×& 24·²¸HÔ1EÓ%rÒ1E¨AÌÏÉÏÉÔWY×W^ÑW^×WcÑWcÐdlÓWp×Iq§aÑ1ENÐ%rÞ'Ð(VÓWØ$2°1Ñ$5 "Ÿw™wŸ|™|¨HÓDHÜ "§¡§ ¡ ¬Z¸Ó G—w‘w—~‘~ iן
š
 iÔ—K’K Ô—M’M (Ô+÷)0ô, Ð5°d°VÐ×
×)¨-Õ8ð5 ùò&s÷/ûô2ó
iÜ Ð:¸1¸#Ð×%×.¨t°^ÐGcÐdeÐcfÐEg×hûð
iúsK®IÁBH0Ã
AH+ÄH+ÄCH0ÇA IÈ+H0È0
H>È:IÉ
JÉ <J Ê Jcó^UR(d[RS5 gURR5n[R
R
USURRS3S5up#U([R"US[R5n[R"U5HcupSnUHWn[RRXW5n[RRU[ 5n UR#X‰5 MY Me SSS5 [R%SU35 gg!,(df  N(=f![&aFn
[R)SU
35 [R*R-US S
U
35 Sn
A
gSn
A
ff=f) zB
Open a file dialog to export the current scenario to a zip file.
z No scenario selected for export.NzExport Scenarioz.ziprºrbzExported scenario to zFailed to export scenario: z Export ErrorzFailed to export scenario.
)rlr^rÚgetSaveFileNamerOr¿Ú ZIP_DEFLATEDr[Úwalkr'r\Úrelpathr]r‡rmrnrorvrM) rrpr'r:Úzipfr¯ÚfilesÚfileÚ file_pathÚarcnamerrs rr>ÚMainWindow.export_scenario"sWð×$× N‰NÐ à×,×?ˆ Ü×'×7¸Ð>OÐTX×TiÑTi×TnÑTnÐSoÐosÐQtðwJóKˆæ ð
iÜ—_’_ T¨3´×0DÑ0DÔÜ*,¯'ª'°,Ö*?™˜ Û$)˜DÜ(*¯©¯ © °TÓ(@˜IÜ&(§g¡g§o¡o°iÄÓ&L˜ ŸJ™J %*ñ+@÷Fô  Ð3°D°6Ð çEûôó
iÜ Ð:¸1¸#Ð×%×.¨t°^ÐGcÐdeÐcfÐEg×hûð
iús1Â&EÂ+A>E Ä) EÅ
EÅEÅ
F,Å&<F'Æ'F,cóˆ[RS5 [XRR5nUR 5(axUR
5nURRRU5 URR5 UR5 [RSU35 gg)z2
Open the dialog to add a new action to the step.
z"Add Action: Opening action dialog.zAction added: N) rlrdÚ ActionDialogrÛrr˜Ú
get_actionr*r7rsrjrm)rÚdlgr0s rÚ
add_actionÚMainWindow.add_action;s“ð ô  И4×!6Ñ!6×!=Ñ!=Ó>ˆØ 8‰8:‰:Ø—^‘^Ó%ˆFØ × Ô × !× × Ñ Ô Ü K‰K˜.¨¨Ð r c óœ[RS5 URR5 UR(dgURR
nUR
SS5nUR
SS5nSRUR
S/5Vs/sH,nUR
SS 5S
UR
S S 5S
S3PM. sn5nSRUR
S/5Vs/sHofR
SS5PM sn5nURRUSUSUSU35 gs snfs snf)zA
Refresh the step list widget with the current scenario's steps.
zRefreshing steps list.NrOr#r$Ú,rrr.rrz.2fr}r*rBr0z [z] imgs: z
actions: ) rlrdrÿr=rPrVr\r)rrOÚcondrÚimgsÚactss rrjÚMainWindow.refresh_listsKs(ô  Ð ×ÑÔØ× Ø×/ˆDØ—8‘8˜F NÓ3ˆDØ—8‘8˜K¨Ó.ˆDØ—8‘8àŸ8™8 H¨bÔâ1—77˜6 *¨"¨S¯W©W°]ÀCÓ-HÈÐ,MÈQÓóˆDð—88¸d¿h¹hÀyÐRTÔ>UÓVÒ>U¸ŸU™U 6¨8Ö4Ñ>UÑWˆ O‰O× # t f¨B¨t¨f°H¸T¸FÀ*ÈTÈFÐ$SÖ 0ùòùòWs Â3E
Ã7E
có´URRS5 U(aURR5OSnURR5 URR S5 [
R "5nUH5nUR5(dMURR U5 M7 U(aCU(a<URRU5nUS:waURRU5 URRS5 g![a"n[RSU35 SnANSnAff=f)z
Populate the window selection dropdown with all open windows and 'Entire Screen'.
If keep_selection is True, try to keep the current selection.
TNrözError listing windows: éÿÿÿÿF)
Ú blockSignalsrýr=rrÚ getAllTitlesrŒrnrlroÚfindTextr)rÚkeep_selectionÚcurrentÚwindowsrrrr1s rÚMainWindow.refresh_window_list]sð
×Ñ×& ,Þ5C$×#×ˆØ ×Ñ×ÑÔ ×Ñ×! /Ô—o'ˆ Ø—;;—=“=Ø×-¨eÖ
žgØ×,¨WÓ5ˆCØb‹yØ×1°#Ô ×Ñ×& -øô
ó L‰LÐ2°1°#Ð6× 7ûð 8úsÁ5-D+Â&D+Ä+
EÄ5EÅEcó®UR(a„URR5nURR5n[R
R
US5n[US5n[R"SU0U5 SSS5 gg!,(df  g=f![a"n[RSU35 SnAgSnAff=f)zC
Save the currently selected window to the scenario's config file.
úwindow_config.jsonrbr Nz!Failed to save window selection: )
r^r[r'r\rirjrkrnrlro)rr rpÚ config_pathrqrrs rr4ÚMainWindow.save_selected_windowsð × × Ø/×=ˆ×0×CˆŸ'™'Ÿ,™, |Ð5IÓJˆ
Fܘ+ sÔ+¨qÜ—I’IÐ0°/ÐBÀAÔ
+ûäó
FÜ ÐÀÐEûð
Fús6Á' B(Á3BÂ
B(Â
B%Â!B(Â%B(Â(
CÂ2CÃCcó6^^TR(TRR5n[RR US5nSm[RR U5(a>[
US5n[R"U5nURSS5mSSS5 UU4Sjn[RRSU5 gg!,(df  N7=f![a"n[RSU35 SnANaSnAff=f) zS
Load the selected window from the scenario's config file and update the dropdown.
rvr Nz!Failed to load window selection: có:>TR5 TRRT5nUS:wa5TRRU5 [R STS35 gTRRS5 [R
STS35 g)NrâzUI: Set window to 'z' from config.rzUI: Saved window 'z+' not found. Defaulting to 'Entire Screen'.)rrlrm)r1rÚwin_names €€rÚ
set_windowÚ?MainWindow.load_selected_window_from_config.<locals>.set_window•sø€Ø××'×Ó:ؘ"“9Ø×%×5°cÔ—KKÐ"5°h°Z¸~Ð NÕ×5°aÔ—NNÐ%7¸°zÐAlÐ#mÕnr )r^r[r'r\rgrirjrwrVrnrlrorr­Ú
singleShot)rrprqrWrrs` @rÚ+MainWindow.load_selected_window_from_configù€ð × × Ø×CˆŸ'™'Ÿ,™, |Ð5IÓJˆ'ˆw‰w~‰~˜k×Jܘk¨3Ô/°1Ü#Ÿyšy¨|˜Ø#'§8¡8Ð,=¸Ó#O˜÷
oô
M‰M× $ S¨*Õ 5ð5 /ûôJÜ—L‘LÐ#DÀQÀCÐ!H×IûðJús6Á5 C,Â)CÂ*C,Ã
C)Ã%C,Ã)C,Ã,
DÃ6DÄD)"rùr6r8rsrrrr
r r r€rrurˆrnrmrÿr…rC)ArDrErFrGrHr+r×rzrxr˜rtrrDrrrrr
rr rrcrfrQrTrurWr~rZrˆrr/r7rAr^r:r>rjr4rIÚ
__classcell__©s@r sDø†ñòH2òT5ònò@ò* Wòò")JòT
"8òHò(&DõP'(òR?ò2
ò
9ò2U'ònòòòòòòiò2òòòòòòò-ò(-ò( 

 ò(.òT

0òB!ò "iòHiò2Uô$.ò, F÷6r có¢^\rSrSrSrSU4SjjrSrSr"SS\R5r
Sr S r S
r
S rS rS
rSrSrSrSrSrU=r$)rrzk
Dialog for creating or editing a step in a scenario.
Allows editing images, actions, and step properties.
có`>[TU]U5 URS5 URSS5 Uc/OUR S/5UlUc/OUR S/5Ul[R"U(a SU;aUSOS5Ul [R"5Ul URRS S