PaIRS-UniNa 0.2.10__cp313-cp313-macosx_11_0_universal2.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (333) hide show
  1. PaIRS_UniNa/Calibration_Tab.py +347 -0
  2. PaIRS_UniNa/Changes.txt +174 -0
  3. PaIRS_UniNa/Custom_Top.py +303 -0
  4. PaIRS_UniNa/Explorer.py +3322 -0
  5. PaIRS_UniNa/FolderLoop.py +562 -0
  6. PaIRS_UniNa/Input_Tab.py +829 -0
  7. PaIRS_UniNa/Input_Tab_CalVi.py +787 -0
  8. PaIRS_UniNa/Input_Tab_tools.py +3026 -0
  9. PaIRS_UniNa/Log_Tab.py +110 -0
  10. PaIRS_UniNa/Output_Tab.py +922 -0
  11. PaIRS_UniNa/PaIRS.py +18 -0
  12. PaIRS_UniNa/PaIRS_PIV.py +873 -0
  13. PaIRS_UniNa/PaIRS_pypacks.py +1374 -0
  14. PaIRS_UniNa/Process_Tab.py +1761 -0
  15. PaIRS_UniNa/Process_Tab_CalVi.py +313 -0
  16. PaIRS_UniNa/Process_Tab_Disp.py +170 -0
  17. PaIRS_UniNa/Process_Tab_Min.py +120 -0
  18. PaIRS_UniNa/ResizePopup.py +55 -0
  19. PaIRS_UniNa/SPIVCalHelp.py +155 -0
  20. PaIRS_UniNa/Saving_tools.py +298 -0
  21. PaIRS_UniNa/TabTools.py +1413 -0
  22. PaIRS_UniNa/Vis_Tab.py +2176 -0
  23. PaIRS_UniNa/Vis_Tab_CalVi.py +982 -0
  24. PaIRS_UniNa/Whatsnew.py +130 -0
  25. PaIRS_UniNa/_PaIRS_PIV.so +0 -0
  26. PaIRS_UniNa/__init__.py +6 -0
  27. PaIRS_UniNa/__main__.py +45 -0
  28. PaIRS_UniNa/addwidgets_ps.py +1633 -0
  29. PaIRS_UniNa/calib.py +1488 -0
  30. PaIRS_UniNa/calibView.py +833 -0
  31. PaIRS_UniNa/gPaIRS.py +3957 -0
  32. PaIRS_UniNa/gPalette.py +189 -0
  33. PaIRS_UniNa/icons/abort.png +0 -0
  34. PaIRS_UniNa/icons/about.png +0 -0
  35. PaIRS_UniNa/icons/align_all.png +0 -0
  36. PaIRS_UniNa/icons/announcement.png +0 -0
  37. PaIRS_UniNa/icons/automatic_levels_off.png +0 -0
  38. PaIRS_UniNa/icons/automatic_levels_on.png +0 -0
  39. PaIRS_UniNa/icons/automatic_off.png +0 -0
  40. PaIRS_UniNa/icons/automatic_on.png +0 -0
  41. PaIRS_UniNa/icons/automatic_size_off.png +0 -0
  42. PaIRS_UniNa/icons/automatic_size_on.png +0 -0
  43. PaIRS_UniNa/icons/axes.png +0 -0
  44. PaIRS_UniNa/icons/background.png +0 -0
  45. PaIRS_UniNa/icons/background_vectors.png +0 -0
  46. PaIRS_UniNa/icons/bin_off.png +0 -0
  47. PaIRS_UniNa/icons/bin_on.png +0 -0
  48. PaIRS_UniNa/icons/browse_file_c.png +0 -0
  49. PaIRS_UniNa/icons/browse_folder_c.png +0 -0
  50. PaIRS_UniNa/icons/brush_cursor.png +0 -0
  51. PaIRS_UniNa/icons/bugfix.png +0 -0
  52. PaIRS_UniNa/icons/cal_proc.png +0 -0
  53. PaIRS_UniNa/icons/cal_proc_off.png +0 -0
  54. PaIRS_UniNa/icons/cal_step.png +0 -0
  55. PaIRS_UniNa/icons/cal_step_off.png +0 -0
  56. PaIRS_UniNa/icons/calibrate.png +0 -0
  57. PaIRS_UniNa/icons/calibration_logo.png +0 -0
  58. PaIRS_UniNa/icons/change_folder.png +0 -0
  59. PaIRS_UniNa/icons/change_folder_off.png +0 -0
  60. PaIRS_UniNa/icons/checklist.png +0 -0
  61. PaIRS_UniNa/icons/clean.png +0 -0
  62. PaIRS_UniNa/icons/clean_run.png +0 -0
  63. PaIRS_UniNa/icons/close.png +0 -0
  64. PaIRS_UniNa/icons/close_all.png +0 -0
  65. PaIRS_UniNa/icons/close_project.png +0 -0
  66. PaIRS_UniNa/icons/close_workspace.png +0 -0
  67. PaIRS_UniNa/icons/colormap.png +0 -0
  68. PaIRS_UniNa/icons/colormaps/Accent.png +0 -0
  69. PaIRS_UniNa/icons/colormaps/BrBG.png +0 -0
  70. PaIRS_UniNa/icons/colormaps/Dark2.png +0 -0
  71. PaIRS_UniNa/icons/colormaps/PRGn.png +0 -0
  72. PaIRS_UniNa/icons/colormaps/Paired.png +0 -0
  73. PaIRS_UniNa/icons/colormaps/Pastel1.png +0 -0
  74. PaIRS_UniNa/icons/colormaps/Pastel2.png +0 -0
  75. PaIRS_UniNa/icons/colormaps/PiYG.png +0 -0
  76. PaIRS_UniNa/icons/colormaps/PuOr.png +0 -0
  77. PaIRS_UniNa/icons/colormaps/RdBu.png +0 -0
  78. PaIRS_UniNa/icons/colormaps/RdGy.png +0 -0
  79. PaIRS_UniNa/icons/colormaps/RdYlBu.png +0 -0
  80. PaIRS_UniNa/icons/colormaps/RdYlGn.png +0 -0
  81. PaIRS_UniNa/icons/colormaps/Set1.png +0 -0
  82. PaIRS_UniNa/icons/colormaps/Set2.png +0 -0
  83. PaIRS_UniNa/icons/colormaps/Set3.png +0 -0
  84. PaIRS_UniNa/icons/colormaps/Spectral.png +0 -0
  85. PaIRS_UniNa/icons/colormaps/Wistia.png +0 -0
  86. PaIRS_UniNa/icons/colormaps/afmhot.png +0 -0
  87. PaIRS_UniNa/icons/colormaps/autumn.png +0 -0
  88. PaIRS_UniNa/icons/colormaps/binary.png +0 -0
  89. PaIRS_UniNa/icons/colormaps/blackVector.png +0 -0
  90. PaIRS_UniNa/icons/colormaps/blueVector.png +0 -0
  91. PaIRS_UniNa/icons/colormaps/bone.png +0 -0
  92. PaIRS_UniNa/icons/colormaps/brg.png +0 -0
  93. PaIRS_UniNa/icons/colormaps/bwr.png +0 -0
  94. PaIRS_UniNa/icons/colormaps/cividis.png +0 -0
  95. PaIRS_UniNa/icons/colormaps/cool.png +0 -0
  96. PaIRS_UniNa/icons/colormaps/coolwarm.png +0 -0
  97. PaIRS_UniNa/icons/colormaps/copper.png +0 -0
  98. PaIRS_UniNa/icons/colormaps/cubehelix.png +0 -0
  99. PaIRS_UniNa/icons/colormaps/cyanVector.png +0 -0
  100. PaIRS_UniNa/icons/colormaps/flag.png +0 -0
  101. PaIRS_UniNa/icons/colormaps/gist_heat.png +0 -0
  102. PaIRS_UniNa/icons/colormaps/gray.png +0 -0
  103. PaIRS_UniNa/icons/colormaps/greenVector.png +0 -0
  104. PaIRS_UniNa/icons/colormaps/hot.png +0 -0
  105. PaIRS_UniNa/icons/colormaps/hsv.png +0 -0
  106. PaIRS_UniNa/icons/colormaps/inferno.png +0 -0
  107. PaIRS_UniNa/icons/colormaps/jet.png +0 -0
  108. PaIRS_UniNa/icons/colormaps/magentaVector.png +0 -0
  109. PaIRS_UniNa/icons/colormaps/magma.png +0 -0
  110. PaIRS_UniNa/icons/colormaps/ocean.png +0 -0
  111. PaIRS_UniNa/icons/colormaps/pink.png +0 -0
  112. PaIRS_UniNa/icons/colormaps/plasma.png +0 -0
  113. PaIRS_UniNa/icons/colormaps/prism.png +0 -0
  114. PaIRS_UniNa/icons/colormaps/rainbow.png +0 -0
  115. PaIRS_UniNa/icons/colormaps/redVector.png +0 -0
  116. PaIRS_UniNa/icons/colormaps/seismic.png +0 -0
  117. PaIRS_UniNa/icons/colormaps/spring.png +0 -0
  118. PaIRS_UniNa/icons/colormaps/summer.png +0 -0
  119. PaIRS_UniNa/icons/colormaps/tab10.png +0 -0
  120. PaIRS_UniNa/icons/colormaps/tab20.png +0 -0
  121. PaIRS_UniNa/icons/colormaps/tab20b.png +0 -0
  122. PaIRS_UniNa/icons/colormaps/tab20c.png +0 -0
  123. PaIRS_UniNa/icons/colormaps/terrain.png +0 -0
  124. PaIRS_UniNa/icons/colormaps/twilight.png +0 -0
  125. PaIRS_UniNa/icons/colormaps/viridis.png +0 -0
  126. PaIRS_UniNa/icons/colormaps/whiteVector.png +0 -0
  127. PaIRS_UniNa/icons/colormaps/winter.png +0 -0
  128. PaIRS_UniNa/icons/colormaps/yellowVector.png +0 -0
  129. PaIRS_UniNa/icons/common_region.png +0 -0
  130. PaIRS_UniNa/icons/common_region_off.png +0 -0
  131. PaIRS_UniNa/icons/completed.png +0 -0
  132. PaIRS_UniNa/icons/contourf_off.png +0 -0
  133. PaIRS_UniNa/icons/contourf_on.png +0 -0
  134. PaIRS_UniNa/icons/copy.png +0 -0
  135. PaIRS_UniNa/icons/copy_process.png +0 -0
  136. PaIRS_UniNa/icons/copy_process_off.png +0 -0
  137. PaIRS_UniNa/icons/copygrid.png +0 -0
  138. PaIRS_UniNa/icons/cursor_lamp.png +0 -0
  139. PaIRS_UniNa/icons/cut.png +0 -0
  140. PaIRS_UniNa/icons/cut_warnings.png +0 -0
  141. PaIRS_UniNa/icons/darkmode.png +0 -0
  142. PaIRS_UniNa/icons/debug_run.png +0 -0
  143. PaIRS_UniNa/icons/delete.png +0 -0
  144. PaIRS_UniNa/icons/deleteErr.png +0 -0
  145. PaIRS_UniNa/icons/disp_step.png +0 -0
  146. PaIRS_UniNa/icons/disp_step_off.png +0 -0
  147. PaIRS_UniNa/icons/down.png +0 -0
  148. PaIRS_UniNa/icons/edit_list.png +0 -0
  149. PaIRS_UniNa/icons/editing.png +0 -0
  150. PaIRS_UniNa/icons/example_list.png +0 -0
  151. PaIRS_UniNa/icons/find_all_planes.png +0 -0
  152. PaIRS_UniNa/icons/find_plane.png +0 -0
  153. PaIRS_UniNa/icons/flaticon_PaIRS.png +0 -0
  154. PaIRS_UniNa/icons/flaticon_PaIRS_beta.png +0 -0
  155. PaIRS_UniNa/icons/flaticon_PaIRS_download.png +0 -0
  156. PaIRS_UniNa/icons/flaticon_PaIRS_download_warning.png +0 -0
  157. PaIRS_UniNa/icons/flip_y_off.png +0 -0
  158. PaIRS_UniNa/icons/flip_y_on.png +0 -0
  159. PaIRS_UniNa/icons/focusErrr.png +0 -0
  160. PaIRS_UniNa/icons/folder_loop_cleanup.png +0 -0
  161. PaIRS_UniNa/icons/folder_loop_cleanup_off.png +0 -0
  162. PaIRS_UniNa/icons/gear.gif +0 -0
  163. PaIRS_UniNa/icons/gear.png +0 -0
  164. PaIRS_UniNa/icons/ger.png +0 -0
  165. PaIRS_UniNa/icons/greenv.png +0 -0
  166. PaIRS_UniNa/icons/guide.png +0 -0
  167. PaIRS_UniNa/icons/icon_CalVi.png +0 -0
  168. PaIRS_UniNa/icons/icon_PaIRS.png +0 -0
  169. PaIRS_UniNa/icons/import.png +0 -0
  170. PaIRS_UniNa/icons/import_set.png +0 -0
  171. PaIRS_UniNa/icons/information.png +0 -0
  172. PaIRS_UniNa/icons/information2.png +0 -0
  173. PaIRS_UniNa/icons/input_logo.png +0 -0
  174. PaIRS_UniNa/icons/issue.png +0 -0
  175. PaIRS_UniNa/icons/laser_NTR.png +0 -0
  176. PaIRS_UniNa/icons/laser_TR_double.png +0 -0
  177. PaIRS_UniNa/icons/laser_TR_single.png +0 -0
  178. PaIRS_UniNa/icons/link.png +0 -0
  179. PaIRS_UniNa/icons/linked.png +0 -0
  180. PaIRS_UniNa/icons/loaded.png +0 -0
  181. PaIRS_UniNa/icons/loading_2.gif +0 -0
  182. PaIRS_UniNa/icons/log_logo.png +0 -0
  183. PaIRS_UniNa/icons/logo_CalVi.png +0 -0
  184. PaIRS_UniNa/icons/logo_CalVi_completo.png +0 -0
  185. PaIRS_UniNa/icons/logo_CalVi_party.png +0 -0
  186. PaIRS_UniNa/icons/logo_PaIRS.png +0 -0
  187. PaIRS_UniNa/icons/logo_PaIRS_completo.png +0 -0
  188. PaIRS_UniNa/icons/logo_PaIRS_download.png +0 -0
  189. PaIRS_UniNa/icons/logo_PaIRS_party_rect.png +0 -0
  190. PaIRS_UniNa/icons/logo_PaIRS_rect.png +0 -0
  191. PaIRS_UniNa/icons/logo_opaco.png +0 -0
  192. PaIRS_UniNa/icons/mask.png +0 -0
  193. PaIRS_UniNa/icons/measure.png +0 -0
  194. PaIRS_UniNa/icons/measure_off.png +0 -0
  195. PaIRS_UniNa/icons/min_proc.png +0 -0
  196. PaIRS_UniNa/icons/min_proc_off.png +0 -0
  197. PaIRS_UniNa/icons/min_step.png +0 -0
  198. PaIRS_UniNa/icons/min_step_off.png +0 -0
  199. PaIRS_UniNa/icons/minus.png +0 -0
  200. PaIRS_UniNa/icons/mirror_u.png +0 -0
  201. PaIRS_UniNa/icons/mirror_v.png +0 -0
  202. PaIRS_UniNa/icons/mirror_x.png +0 -0
  203. PaIRS_UniNa/icons/mirror_y.png +0 -0
  204. PaIRS_UniNa/icons/mtplt.png +0 -0
  205. PaIRS_UniNa/icons/new.png +0 -0
  206. PaIRS_UniNa/icons/new_workspace.png +0 -0
  207. PaIRS_UniNa/icons/news.png +0 -0
  208. PaIRS_UniNa/icons/normal_run.png +0 -0
  209. PaIRS_UniNa/icons/open.png +0 -0
  210. PaIRS_UniNa/icons/open_image.png +0 -0
  211. PaIRS_UniNa/icons/open_new_window.png +0 -0
  212. PaIRS_UniNa/icons/open_result.png +0 -0
  213. PaIRS_UniNa/icons/open_workspace.png +0 -0
  214. PaIRS_UniNa/icons/output_logo.png +0 -0
  215. PaIRS_UniNa/icons/paste_above.png +0 -0
  216. PaIRS_UniNa/icons/paste_below.png +0 -0
  217. PaIRS_UniNa/icons/pause.png +0 -0
  218. PaIRS_UniNa/icons/paused.png +0 -0
  219. PaIRS_UniNa/icons/pencil_bw.png +0 -0
  220. PaIRS_UniNa/icons/piv_proc.png +0 -0
  221. PaIRS_UniNa/icons/piv_proc_off.png +0 -0
  222. PaIRS_UniNa/icons/piv_step.png +0 -0
  223. PaIRS_UniNa/icons/piv_step_off.png +0 -0
  224. PaIRS_UniNa/icons/plane.png +0 -0
  225. PaIRS_UniNa/icons/play.png +0 -0
  226. PaIRS_UniNa/icons/plus.png +0 -0
  227. PaIRS_UniNa/icons/process_logo.png +0 -0
  228. PaIRS_UniNa/icons/process_loop.png +0 -0
  229. PaIRS_UniNa/icons/project.png +0 -0
  230. PaIRS_UniNa/icons/pylog.png +0 -0
  231. PaIRS_UniNa/icons/python_warning.png +0 -0
  232. PaIRS_UniNa/icons/queue.png +0 -0
  233. PaIRS_UniNa/icons/quit.png +0 -0
  234. PaIRS_UniNa/icons/read.png +0 -0
  235. PaIRS_UniNa/icons/read_list.png +0 -0
  236. PaIRS_UniNa/icons/redo.png +0 -0
  237. PaIRS_UniNa/icons/redx.png +0 -0
  238. PaIRS_UniNa/icons/reset.png +0 -0
  239. PaIRS_UniNa/icons/reset_levels.png +0 -0
  240. PaIRS_UniNa/icons/resize_icon.png +0 -0
  241. PaIRS_UniNa/icons/restore.png +0 -0
  242. PaIRS_UniNa/icons/restore_undo.png +0 -0
  243. PaIRS_UniNa/icons/rotate_clock.png +0 -0
  244. PaIRS_UniNa/icons/rotate_counter.png +0 -0
  245. PaIRS_UniNa/icons/rotate_v_clock.png +0 -0
  246. PaIRS_UniNa/icons/rotate_v_counter.png +0 -0
  247. PaIRS_UniNa/icons/running.gif +0 -0
  248. PaIRS_UniNa/icons/running.png +0 -0
  249. PaIRS_UniNa/icons/running_warn.png +0 -0
  250. PaIRS_UniNa/icons/sandglass.png +0 -0
  251. PaIRS_UniNa/icons/save.png +0 -0
  252. PaIRS_UniNa/icons/save_and_stop.png +0 -0
  253. PaIRS_UniNa/icons/save_cfg.png +0 -0
  254. PaIRS_UniNa/icons/saveas.png +0 -0
  255. PaIRS_UniNa/icons/saveas_workspace.png +0 -0
  256. PaIRS_UniNa/icons/scale_all.png +0 -0
  257. PaIRS_UniNa/icons/scale_down.png +0 -0
  258. PaIRS_UniNa/icons/scale_up.png +0 -0
  259. PaIRS_UniNa/icons/scan_list.png +0 -0
  260. PaIRS_UniNa/icons/scan_path.png +0 -0
  261. PaIRS_UniNa/icons/scan_path_loop.png +0 -0
  262. PaIRS_UniNa/icons/scan_path_loop_off.png +0 -0
  263. PaIRS_UniNa/icons/search.png +0 -0
  264. PaIRS_UniNa/icons/showIW_off.png +0 -0
  265. PaIRS_UniNa/icons/showIW_on.png +0 -0
  266. PaIRS_UniNa/icons/show_all.png +0 -0
  267. PaIRS_UniNa/icons/sort.png +0 -0
  268. PaIRS_UniNa/icons/sort_reversed.png +0 -0
  269. PaIRS_UniNa/icons/spiv_proc.png +0 -0
  270. PaIRS_UniNa/icons/spiv_proc_off.png +0 -0
  271. PaIRS_UniNa/icons/spiv_setup_no.png +0 -0
  272. PaIRS_UniNa/icons/spiv_setup_ok.png +0 -0
  273. PaIRS_UniNa/icons/star.png +0 -0
  274. PaIRS_UniNa/icons/step_inheritance.png +0 -0
  275. PaIRS_UniNa/icons/subMIN_off.png +0 -0
  276. PaIRS_UniNa/icons/subMIN_on.png +0 -0
  277. PaIRS_UniNa/icons/tom.png +0 -0
  278. PaIRS_UniNa/icons/trash.png +0 -0
  279. PaIRS_UniNa/icons/undo.png +0 -0
  280. PaIRS_UniNa/icons/unedited.png +0 -0
  281. PaIRS_UniNa/icons/unina_dii.png +0 -0
  282. PaIRS_UniNa/icons/uninitialized.png +0 -0
  283. PaIRS_UniNa/icons/unlink.png +0 -0
  284. PaIRS_UniNa/icons/unwrap_items.png +0 -0
  285. PaIRS_UniNa/icons/up.png +0 -0
  286. PaIRS_UniNa/icons/updating_import.gif +0 -0
  287. PaIRS_UniNa/icons/updating_pairs.gif +0 -0
  288. PaIRS_UniNa/icons/vectorColor.png +0 -0
  289. PaIRS_UniNa/icons/vettore.png +0 -0
  290. PaIRS_UniNa/icons/view.png +0 -0
  291. PaIRS_UniNa/icons/view_off.png +0 -0
  292. PaIRS_UniNa/icons/vis_logo.png +0 -0
  293. PaIRS_UniNa/icons/waiting_circle.png +0 -0
  294. PaIRS_UniNa/icons/warning.png +0 -0
  295. PaIRS_UniNa/icons/warning_circle.png +0 -0
  296. PaIRS_UniNa/icons/window.png +0 -0
  297. PaIRS_UniNa/icons/workspace.png +0 -0
  298. PaIRS_UniNa/icons/wrap_items.png +0 -0
  299. PaIRS_UniNa/icons/write_list.png +0 -0
  300. PaIRS_UniNa/listLib.py +303 -0
  301. PaIRS_UniNa/mtfPIV.py +256 -0
  302. PaIRS_UniNa/parForMulti.py +435 -0
  303. PaIRS_UniNa/parForWorkers.py +593 -0
  304. PaIRS_UniNa/pivParFor.py +235 -0
  305. PaIRS_UniNa/plt_util.py +141 -0
  306. PaIRS_UniNa/preProcParFor.py +155 -0
  307. PaIRS_UniNa/procTools.py +1439 -0
  308. PaIRS_UniNa/readcfg.py +52 -0
  309. PaIRS_UniNa/rqrdpckgs.txt +9 -0
  310. PaIRS_UniNa/stereoPivParFor.py +227 -0
  311. PaIRS_UniNa/tAVarie.py +215 -0
  312. PaIRS_UniNa/tabSplitter.py +612 -0
  313. PaIRS_UniNa/ui_Calibration_Tab.py +578 -0
  314. PaIRS_UniNa/ui_Custom_Top.py +296 -0
  315. PaIRS_UniNa/ui_Input_Tab.py +1101 -0
  316. PaIRS_UniNa/ui_Input_Tab_CalVi.py +1283 -0
  317. PaIRS_UniNa/ui_Log_Tab.py +263 -0
  318. PaIRS_UniNa/ui_Output_Tab.py +2362 -0
  319. PaIRS_UniNa/ui_Process_Tab.py +3810 -0
  320. PaIRS_UniNa/ui_Process_Tab_CalVi.py +1549 -0
  321. PaIRS_UniNa/ui_Process_Tab_Disp.py +1141 -0
  322. PaIRS_UniNa/ui_Process_Tab_Min.py +437 -0
  323. PaIRS_UniNa/ui_ResizePopup.py +204 -0
  324. PaIRS_UniNa/ui_Vis_Tab.py +1628 -0
  325. PaIRS_UniNa/ui_Vis_Tab_CalVi.py +1251 -0
  326. PaIRS_UniNa/ui_Whatsnew.py +132 -0
  327. PaIRS_UniNa/ui_gPairs.py +877 -0
  328. PaIRS_UniNa/ui_infoPaIRS.py +551 -0
  329. PaIRS_UniNa/whatsnew.txt +4 -0
  330. pairs_unina-0.2.10.dist-info/METADATA +159 -0
  331. pairs_unina-0.2.10.dist-info/RECORD +333 -0
  332. pairs_unina-0.2.10.dist-info/WHEEL +5 -0
  333. pairs_unina-0.2.10.dist-info/top_level.txt +2 -0
@@ -0,0 +1,1633 @@
1
+ from __future__ import annotations
2
+ from .PaIRS_pypacks import *
3
+ #from ui_Tree_Tab import Ui_TreeTab
4
+
5
+ QLocale.setDefault(QLocale.Language.English)
6
+ curr_locale = QLocale()
7
+
8
+ InitCheck=True #False=Collap closed, True=opened
9
+ #fonts
10
+ font_italic=True
11
+ font_weight=QFont.DemiBold
12
+ backgroundcolor_none=" background-color: none;"
13
+ backgroundcolor_changing=" background-color: rgb(255,230,230);"
14
+ backgroundcolor_hover=" background-color: rgba(0, 116, 255, 0.1);"
15
+ border_hover = " " #"border: 1px solid gray; "
16
+ color_changing="color: rgb(33,33,255); "+backgroundcolor_changing
17
+
18
+ #********************************************* Operating Widgets
19
+ def setSS(b,style):
20
+ ss=f"{b.metaObject().className()}{'{'+style+'}'}\\nQToolTip{'{'+b.initialStyle+'}'}"
21
+ return ss
22
+
23
+ class MyTabLabel(QLabel):
24
+ def __init__(self,parent):
25
+ super().__init__(parent)
26
+ #self.setCursor(QCursor(QtCore.Qt.PointingHandCursor))
27
+ self.addfuncclick={}
28
+
29
+ def mousePressEvent(self, event):
30
+ for f in self.addfuncclick:
31
+ self.addfuncclick[f]()
32
+ return super().mousePressEvent(event)
33
+
34
+ def setCustomCursor(self):
35
+ if self.addfuncclick:
36
+ self.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
37
+ else:
38
+ self.setCursor(QCursor(Qt.CursorShape.ArrowCursor))
39
+
40
+ #MyQLineEdit=QtWidgets.QLineEdit
41
+ class MyQLineEdit(QtWidgets.QLineEdit):
42
+ def __init__(self,parent):
43
+ super().__init__(parent)
44
+ self.addlab=QtWidgets.QLabel()
45
+ self.addwid=[]
46
+ self.initFlag=False
47
+ self.initFlag2=False
48
+ self.styleFlag=False
49
+ self.addfuncin={}
50
+ self.addfuncout={}
51
+ self.addfuncreturn={}
52
+ self.FlagCompleter=False
53
+ self.FunSetCompleterList=lambda: None
54
+
55
+ def setup(self):
56
+ if not self.initFlag:
57
+ self.initFlag=True
58
+ self.FlagFocusIn=False
59
+ self.oldFont=None
60
+ self.oldStyle=None
61
+ font_changing = QtGui.QFont(self.font())
62
+ font_changing.setItalic(font_italic)
63
+ font_changing.setWeight(font_weight)
64
+ children=self.parent().children()
65
+ self.bros=children+self.addwid
66
+ for b in self.bros:
67
+ hasStyleFlag=hasattr(b,'styleFlag')
68
+ if hasattr(b,'setStyleSheet'):
69
+ if hasStyleFlag:
70
+ if b.styleFlag: continue
71
+ b.initialStyle=b.styleSheet()+" "+backgroundcolor_none
72
+ b.setEnabled(False)
73
+ b.disabledStyle=b.styleSheet()
74
+ b.setEnabled(True)
75
+ b.setStyleSheet(setSS(b,b.initialStyle))
76
+ if hasattr(b,'setFont'):
77
+ b.initialFont=b.font()
78
+ b.font_changing=font_changing
79
+ if hasStyleFlag: b.styleFlag=True
80
+ self.CElabs=[w for w in self.bros if isinstance(w, ClickableEditLabel)]
81
+ self.CElabs_styles=[w.styleSheet() for w in self.CElabs]
82
+
83
+ def setup2(self):
84
+ if not self.initFlag2:
85
+ self.initFlag2=True
86
+ for b in self.bros:
87
+ if hasattr(b,'bros'):
88
+ for c in b.bros:
89
+ if c not in self.bros:
90
+ self.bros.append(c)
91
+
92
+ def setCompleterList(self):
93
+ if not self.FlagCompleter:
94
+ self.FunSetCompleterList()
95
+ self.FlagCompleter=True
96
+ self.showCompleter()
97
+
98
+ def mouseReleaseEvent(self, event):
99
+ super().mouseReleaseEvent(event) #to preserve classical behaviour before adding the below
100
+ self.setCompleterList()
101
+
102
+ def enterEvent(self, event):
103
+ if not self.hasFocus() and self.isEnabled():
104
+ self.oldFont=self.font()
105
+ self.oldStyle=self.styleSheet()
106
+ self.setFont(self.font_changing)
107
+ self.setStyleSheet(setSS(self,self.initialStyle+" "+backgroundcolor_hover))
108
+ for k,w in enumerate(self.CElabs):
109
+ self.CElabs_styles[k]=w.styleSheet()
110
+ w.setStyleSheet(w.styleSheet()+" "+f"""
111
+ ClickableEditLabel {{
112
+ {backgroundcolor_hover};
113
+ }}
114
+ """)
115
+ w.repaint()
116
+ super().enterEvent(event)
117
+
118
+ def leaveEvent(self, event):
119
+ if not self.hasFocus() and self.oldFont is not None:
120
+ self.setFont(self.oldFont)
121
+ self.setStyleSheet(self.oldStyle)
122
+ for k,w in enumerate(self.CElabs):
123
+ w.setStyleSheet(self.CElabs_styles[k])
124
+ w.repaint()
125
+ self.oldFont=None
126
+ self.oldStyle=None
127
+ super().leaveEvent(event)
128
+
129
+ def focusInEvent(self, event):
130
+ super().focusInEvent(event)
131
+ for f in self.addfuncin:
132
+ self.addfuncin[f]()
133
+ self.focusInFun()
134
+
135
+ def setFocus(self):
136
+ super().setFocus()
137
+ self.focusInFun()
138
+
139
+ def focusInFun(self):
140
+ self.setStyleFont(color_changing,self.font_changing)
141
+
142
+ def setStyleFont(self,color_changing,font):
143
+ for b in self.bros:
144
+ if hasattr(b,'setInitalStyle') and hasattr(b,'FlagFocusIn') and b.FlagFocusIn:
145
+ b.setInitalStyle()
146
+ break
147
+ if not self.FlagFocusIn:
148
+ self.FlagFocusIn=True
149
+ self.setFont(font)
150
+ for b in self.bros:
151
+ if hasattr(b,'initialStyle'):
152
+ b.setStyleSheet(setSS(b,b.initialStyle+" "+color_changing))
153
+
154
+ def focusOutEvent(self, event):
155
+ super().focusOutEvent(event) #to preserve classical behaviour before adding the below
156
+ for f in self.addfuncout:
157
+ self.addfuncout[f]()
158
+ self.setInitalStyle()
159
+
160
+ def clearFocus(self):
161
+ super().clearFocus()
162
+ self.setInitalStyle()
163
+
164
+ def setInitalStyle(self):
165
+ if self.FlagFocusIn:
166
+ self.FlagFocusIn=False
167
+ for b in self.bros:
168
+ if hasattr(b,'default_stylesheet'):
169
+ b.setStyleSheet(b.default_stylesheet)
170
+ elif hasattr(b,'initialStyle'):
171
+ b.setStyleSheet(b.initialStyle)
172
+ if hasattr(b,'initialFont'):
173
+ b.setFont(b.initialFont)
174
+ for k,w in enumerate(self.CElabs):
175
+ self.CElabs_styles[k]=w.default_stylesheet
176
+ w.setStyleSheet(self.CElabs_styles[k])
177
+ w.repaint()
178
+ self.oldFont=None
179
+ self.oldStyle=None
180
+ #self.addlab.clear()
181
+
182
+ def showCompleter(self):
183
+ if self.completer():
184
+ self.completer().complete()
185
+
186
+ class MyQLineEditNumber(MyQLineEdit):
187
+ def __init__(self,parent):
188
+ super().__init__(parent)
189
+ self.addfuncreturn={}
190
+
191
+ def keyPressEvent(self, event):
192
+ #infoPrint.white(event.key())
193
+ if event.key() in (Qt.Key.Key_Space, #space
194
+ Qt.Key.Key_Comma, #comma
195
+ Qt.Key.Key_Delete, Qt.Key.Key_Backspace, #del, backspace
196
+ Qt.Key.Key_Left,Qt.Key.Key_Right, #left, right
197
+ Qt.Key.Key_Return, Qt.Key.Key_Enter #return
198
+ ) \
199
+ or (event.key()>=Qt.Key.Key_0 and event.key()<=Qt.Key.Key_9):
200
+ super().keyPressEvent(event)
201
+ if event.key()==16777220:
202
+ for f in self.addfuncreturn:
203
+ self.addfuncreturn[f]()
204
+
205
+ class MyQCombo(QtWidgets.QComboBox):
206
+ def wheelEvent(self, event):
207
+ event.ignore()
208
+
209
+ #MyQSpin=QtWidgets.QSpinBox
210
+ class MyQSpin(QtWidgets.QSpinBox):
211
+ def __init__(self,parent):
212
+ super().__init__(parent)
213
+ self.addwid=[]
214
+ self.initFlag=False
215
+ self.styleFlag=False
216
+ self.addfuncin={}
217
+ self.addfuncout={}
218
+ self.addfuncreturn={}
219
+
220
+ self.setAccelerated(True)
221
+ self.setGroupSeparatorShown(True)
222
+
223
+ def setup(self):
224
+ if not self.initFlag:
225
+ self.initFlag=True
226
+ self.FlagFocusIn=False
227
+ self.oldFont=None
228
+ self.oldStyle=None
229
+ font_changing = QtGui.QFont(self.font())
230
+ font_changing.setItalic(font_italic)
231
+ font_changing.setWeight(font_weight)
232
+ self.bros=[self]+self.addwid
233
+ for b in self.bros:
234
+ if b.styleFlag: continue
235
+ b.initialStyle=b.styleSheet()+" "+backgroundcolor_none
236
+ b.initialFont=b.font()
237
+ b.font_changing=font_changing
238
+ b.styleFlag=True
239
+ #self.spinFontObj = self.findChildren(QtWidgets.QLineEdit)[0]
240
+ #self.spinFontObj.initialStyle=self.spinFontObj.styleSheet()+" "+backgroundcolor_none
241
+ #self.spinFontObj.font_changing=font_changing
242
+
243
+ def setFocus(self):
244
+ super().setFocus()
245
+ self.focusInFun()
246
+
247
+ def focusInEvent(self, event):
248
+ super().focusInEvent(event) #to preserve classical behaviour before adding the below
249
+ for f in self.addfuncin:
250
+ self.addfuncin[f]()
251
+ self.focusInFun()
252
+
253
+ def focusInFun(self):
254
+ if not self.FlagFocusIn:
255
+ self.FlagFocusIn=True
256
+ #self.spinFontObj.setStyleSheet(self.spinFontObj.initialStyle+" "+color_changing)
257
+ for b in self.bros:
258
+ b.setStyleSheet(setSS(b,b.initialStyle+" "+color_changing))
259
+ b.setFont(self.font_changing)
260
+
261
+ def clearFocus(self):
262
+ super().clearFocus()
263
+ self.setInitalStyle()
264
+
265
+ def focusOutEvent(self, event):
266
+ super().focusOutEvent(event) #to preserve classical behaviour before adding the below
267
+ for f in self.addfuncout:
268
+ self.addfuncout[f]()
269
+ self.setInitalStyle()
270
+
271
+ def setInitalStyle(self):
272
+ if self.FlagFocusIn:
273
+ self.FlagFocusIn=False
274
+ #self.spinFontObj.setStyleSheet(self.spinFontObj.initialStyle)
275
+ for b in self.bros:
276
+ b.setStyleSheet(setSS(b,b.initialStyle))
277
+ b.setFont(self.initialFont)
278
+ self.findChildren(QtWidgets.QLineEdit)[0].setFont(self.initialFont)
279
+ self.oldFont=None
280
+ self.oldStyle=None
281
+
282
+ def enterEvent(self, event):
283
+ super().enterEvent(event)
284
+ if not self.hasFocus() and self.isEnabled():
285
+ self.oldFont=self.font()
286
+ self.setFont(self.font_changing)
287
+ b=self #b=self.spinFontObj
288
+ self.oldStyle=b.styleSheet()
289
+ b.setStyleSheet(setSS(b,b.initialStyle+" "+backgroundcolor_hover+" "+border_hover))
290
+
291
+ def leaveEvent(self, event):
292
+ super().leaveEvent(event)
293
+ if not self.hasFocus() and self.oldFont is not None:
294
+ self.setFont(self.oldFont)
295
+ b=self #b=self.spinFontObj
296
+ b.setStyleSheet(self.oldStyle)
297
+ self.oldFont=None
298
+ self.oldStyle=None
299
+
300
+ def keyPressEvent(self, event):
301
+ super().keyPressEvent(event)
302
+ if event.key() in (Qt.Key.Key_Return,Qt.Key.Key_Enter) and self.hasFocus():
303
+ for f in self.addfuncreturn:
304
+ self.addfuncreturn[f]()
305
+
306
+ def wheelEvent(self, event):
307
+ event.ignore()
308
+
309
+ def textFromValue(self, value):
310
+ return formatNumber(self,value)
311
+
312
+ def formatNumber(self:QWidget,value):
313
+ if Flag_GROUPSEPARATOR:
314
+ text=self.locale().toString(float(value), 'd')
315
+ else:
316
+ text=f"{value:f}"
317
+ return (text).rstrip('0').rstrip(curr_locale.decimalPoint())
318
+ #return ('%f' % value).rstrip('0').rstrip('.')
319
+
320
+ class MyQSpinXW(MyQSpin):
321
+ def __init__(self,parent):
322
+ super().__init__(parent)
323
+ self.Win=-1
324
+
325
+ def focusInEvent(self, event):
326
+ super().focusInEvent(event) #to preserve classical behaviour before adding the below
327
+ if len(self.addwid)>0:
328
+ self.Win=self.addwid[0].value()
329
+
330
+ class MyToolButton(QtWidgets.QToolButton):
331
+ def __init__(self,parent):
332
+ super().__init__(parent)
333
+
334
+ class MyQDoubleSpin(QtWidgets.QDoubleSpinBox):
335
+ def __init__(self,parent):
336
+ super().__init__(parent)
337
+ self.addwid=[]
338
+ self.initFlag=False
339
+ self.styleFlag=False
340
+ self.addfuncin={}
341
+ self.addfuncout={}
342
+ self.addfuncreturn={}
343
+
344
+ self.setAccelerated(True)
345
+ self.setGroupSeparatorShown(True)
346
+
347
+ def setup(self):
348
+ if not self.initFlag:
349
+ self.initFlag=True
350
+ self.FlagFocusIn=False
351
+ self.oldFont=None
352
+ self.oldStyle=None
353
+ font_changing = QtGui.QFont(self.font())
354
+ font_changing.setItalic(font_italic)
355
+ font_changing.setWeight(font_weight)
356
+ self.bros=[self]+self.addwid
357
+ for b in self.bros:
358
+ if self.styleFlag: continue
359
+ b.initialStyle=b.styleSheet()+" "+backgroundcolor_none
360
+ b.initialFont=b.font()
361
+ b.font_changing=font_changing
362
+ b.styleFlag=True
363
+ #self.spinFontObj = self.findChildren(QtWidgets.QLineEdit)[0]
364
+ #self.spinFontObj.initialStyle=self.spinFontObj.styleSheet()+" "+backgroundcolor_none
365
+ #self.spinFontObj.font_changing=font_changing
366
+
367
+ def setFocus(self):
368
+ super().setFocus()
369
+ self.focusInFun()
370
+
371
+ def focusInEvent(self, event):
372
+ super().focusInEvent(event) #to preserve classical behaviour before adding the below
373
+ for f in self.addfuncin:
374
+ self.addfuncin[f]()
375
+ self.focusInFun()
376
+
377
+ def focusInFun(self):
378
+ if not self.FlagFocusIn:
379
+ self.FlagFocusIn=True
380
+ #self.spinFontObj.setStyleSheet(self.spinFontObj.initialStyle+" "+color_changing)
381
+ for b in self.bros:
382
+ b.setStyleSheet(setSS(b,b.initialStyle+" "+color_changing))
383
+ b.setFont(self.font_changing)
384
+
385
+ def clearFocus(self):
386
+ super().clearFocus()
387
+ self.setInitalStyle()
388
+
389
+ def focusOutEvent(self, event):
390
+ super().focusOutEvent(event) #to preserve classical behaviour before adding the below
391
+ for f in self.addfuncout:
392
+ self.addfuncout[f]()
393
+ self.setInitalStyle()
394
+
395
+ def setInitalStyle(self):
396
+ if self.FlagFocusIn:
397
+ self.FlagFocusIn=False
398
+ #self.spinFontObj.setStyleSheet(self.spinFontObj.initialStyle)
399
+ for b in self.bros:
400
+ b.setStyleSheet(setSS(b,b.initialStyle))
401
+ b.setFont(self.initialFont)
402
+ self.findChildren(QtWidgets.QLineEdit)[0].setFont(self.initialFont)
403
+ self.oldFont=None
404
+ self.oldStyle=None
405
+
406
+ def enterEvent(self, event):
407
+ super().enterEvent(event)
408
+ if not self.hasFocus() and self.isEnabled():
409
+ self.oldFont=self.font()
410
+ self.setFont(self.font_changing)
411
+ b=self #b=self.spinFontObj
412
+ self.oldStyle=b.styleSheet()
413
+ b.setStyleSheet(setSS(b,b.initialStyle+" "+backgroundcolor_hover+" "+border_hover))
414
+
415
+ def leaveEvent(self, event):
416
+ super().leaveEvent(event)
417
+ if not self.hasFocus() and self.oldFont is not None:
418
+ self.setFont(self.oldFont)
419
+ b=self #b=self.spinFontObj
420
+ b.setStyleSheet(self.oldStyle)
421
+ self.oldFont=None
422
+ self.oldStyle=None
423
+
424
+ def keyPressEvent(self, event):
425
+ super().keyPressEvent(event)
426
+ if event.key() in (Qt.Key.Key_Return,Qt.Key.Key_Enter) and self.hasFocus():
427
+ for f in self.addfuncreturn:
428
+ self.addfuncreturn[f]()
429
+
430
+ def wheelEvent(self, event):
431
+ event.ignore()
432
+
433
+ def textFromValue(self, value):
434
+ if Flag_GROUPSEPARATOR:
435
+ text=self.locale().toString(float(value), 'f', self.decimals())
436
+ else:
437
+ text=f"{value:f}"
438
+ return (text).rstrip('0').rstrip(curr_locale.decimalPoint())
439
+ #return ('%f' % value).rstrip('0').rstrip('.')
440
+
441
+ class CollapsibleBox(QtWidgets.QWidget):
442
+ def __init__(self, parent):
443
+ super().__init__(parent)
444
+ self.initFlag=False
445
+ self.FlagPush=False
446
+ self.dpix=5
447
+ self.toolMinimumWidth=400
448
+ self.toolHeight=20
449
+ self.content_area:QGroupBox=None
450
+ self.toggle_button:QPushButton=None
451
+ self.push_button:MyToolButton=None
452
+
453
+ def setup(self,*args):
454
+ if not self.initFlag:
455
+ if len(args):
456
+ self.ind=args[0]
457
+ self.stretch=args[1]
458
+ else:
459
+ self.ind=-1
460
+ self.stretch=0
461
+ self.initFlag=True
462
+
463
+ if self.content_area is None:
464
+ self.content_area=self.findChild(QtWidgets.QGroupBox)
465
+ self.content_area.setStyleSheet("QGroupBox{border: 1px solid gray; border-radius: 6px;}")
466
+
467
+ if self.toggle_button is None:
468
+ self.toggle_button=self.findChild(QtWidgets.QToolButton)
469
+ self.toggle_button.setObjectName("CollapsibleBox_toggle")
470
+ self.toggle_button.setChecked(InitCheck)
471
+ self.toggle_button.clicked.connect(self.on_click)
472
+ self.toggle_button.setCursor(QtCore.Qt.CursorShape.PointingHandCursor)
473
+ self.toggle_button.setMinimumWidth(self.toolMinimumWidth)
474
+
475
+ if self.push_button is None:
476
+ self.push_button=self.findChild(MyToolButton)
477
+
478
+ self.OpenStyle=\
479
+ "QToolButton { border: none; }\n"+\
480
+ "QToolButton::hover{color: rgba(0,0,255,200);}"+\
481
+ "QToolButton::focus{color: rgba(0,0,255,200);}"
482
+ #"QToolButton::hover{border: none; border-radius: 6px; background-color: rgba(0, 0,128,32); }"
483
+ self.ClosedStyle=\
484
+ "QToolButton { border: 1px solid lightgray; border-radius: 6px }\n"+\
485
+ "QToolButton::hover{ border: 1px solid rgba(0,0,255,200); border-radius: 6px; color: rgba(0,0,255,200);}"+\
486
+ "QToolButton::focus{ border: 1px solid rgba(0,0,255,200); border-radius: 6px; color: rgba(0,0,255,200);}" #background-color: rgba(0, 0,128,32); }"
487
+
488
+ self.heightToogle=self.toggle_button.minimumHeight()
489
+ self.heightOpened=self.minimumHeight()
490
+ self.heightArea=self.heightOpened-self.toolHeight
491
+
492
+ self.on_click()
493
+
494
+ #@QtCore.pyqtSlot()
495
+ def on_click(self):
496
+ checked = self.toggle_button.isChecked()
497
+ pri.Coding.yellow(f'>>>>> {self.objectName()} {"opening" if checked else "closing"}')
498
+ if self.objectName()=='CollapBox_ImSet' and checked:
499
+ pass
500
+ if self.FlagPush:
501
+ self.push_button.show()
502
+ else:
503
+ self.push_button.hide()
504
+ if checked:
505
+ self.content_area.show()
506
+ self.toggle_button.setArrowType(QtCore.Qt.ArrowType.DownArrow)
507
+
508
+ self.toggle_button.setMinimumHeight(self.heightToogle)
509
+ self.toggle_button.setMaximumHeight(self.heightToogle)
510
+ self.setMinimumHeight(self.heightOpened)
511
+ self.setMaximumHeight(int(self.heightOpened*1.5))
512
+ self.content_area.setMinimumHeight(self.heightArea)
513
+ self.content_area.setMaximumHeight(int(self.heightArea*1.5))
514
+
515
+ self.toggle_button.setSizePolicy(QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Preferred)
516
+ self.setSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Maximum)
517
+ self.content_area.setSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Expanding)
518
+
519
+ self.toggle_button.setStyleSheet(self.OpenStyle)
520
+ if self.ind>0:
521
+ self.parent().layout().setStretch(self.ind,self.stretch)
522
+ else:
523
+ self.content_area.hide()
524
+ self.toggle_button.setArrowType(QtCore.Qt.ArrowType.RightArrow)
525
+
526
+ self.toggle_button.setMinimumHeight(self.heightToogle+self.dpix)
527
+ self.toggle_button.setMaximumHeight(self.heightToogle+self.dpix)
528
+ self.setMinimumHeight(self.heightToogle+self.dpix*2)
529
+ self.setMaximumHeight(self.heightToogle+self.dpix*2)
530
+ self.content_area.setMinimumHeight(0)
531
+ self.content_area.setMaximumHeight(0)
532
+
533
+ self.toggle_button.setSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Preferred)
534
+ self.setSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Expanding)
535
+ self.content_area.setSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Minimum)
536
+
537
+ self.toggle_button.setStyleSheet(self.ClosedStyle)
538
+
539
+ if self.ind>0:
540
+ self.parent().layout().setStretch(self.ind,0)
541
+
542
+ # Forza l'aggiornamento dei layout
543
+ self.updateGeometry()
544
+ self.parentWidget().updateGeometry()
545
+ self.parentWidget().adjustSize()
546
+
547
+ def openBox(self):
548
+ self.toggle_button.setChecked(True)
549
+ self.on_click()
550
+
551
+ def closeBox(self):
552
+ self.toggle_button.setChecked(False)
553
+ self.on_click()
554
+
555
+ class myQTreeWidget(QTreeWidget):
556
+ def __init__(self,parent):
557
+ super().__init__(parent)
558
+ self.FlagArrowKeysNormal=False
559
+ self.addfuncin={}
560
+ self.addfuncout={}
561
+ self.addfuncreturn={}
562
+ self.addfuncshift_pressed={}
563
+ self.addfuncshift_released={}
564
+ self.addfuncdel_pressed={}
565
+ self.addfuncarrows_pressed={}
566
+ self.addfuncarrows_released={}
567
+ self.addfunckey_pressed={}
568
+ #self.ui:Ui_TreeTab=None
569
+ self.ui=None
570
+
571
+ def focusInEvent(self, event):
572
+ super().focusInEvent(event) #to preserve classical behaviour before adding the below
573
+ for f in self.addfuncin:
574
+ self.addfuncin[f]()
575
+
576
+ def focusOutEvent(self, event):
577
+ super().focusOutEvent(event) #to preserve classical behaviour before adding the below
578
+ for f in self.addfuncout:
579
+ self.addfuncout[f]()
580
+
581
+ def keyPressEvent(self, event):
582
+ if event.key() == Qt.Key.Key_Shift:
583
+ super().keyPressEvent(event)
584
+ for f in self.addfuncshift_pressed:
585
+ self.addfuncshift_pressed[f]()
586
+ elif event.key() == Qt.Key.Key_Delete or event.key() == Qt.Key.Key_Backspace:
587
+ super().keyPressEvent(event)
588
+ for f in self.addfuncdel_pressed:
589
+ self.addfuncdel_pressed[f]()
590
+ elif event.key() == Qt.Key.Key_Up or event.key() == Qt.Key.Key_Down:
591
+ if self.FlagArrowKeysNormal:
592
+ return super().keyPressEvent(event)
593
+ else:
594
+ Flag=True
595
+ for f in self.addfuncarrows_pressed:
596
+ Flag=Flag and self.addfuncarrows_pressed[f](event.key())
597
+ #if Flag: super().keyPressEvent(event)
598
+ else:
599
+ super().keyPressEvent(event)
600
+ for f in self.addfunckey_pressed:
601
+ self.addfunckey_pressed[f](event.key())
602
+
603
+ def keyReleaseEvent(self, event):
604
+ super().keyReleaseEvent(event)
605
+ if event.key() == QtCore.Qt.Key_Shift:
606
+ for f in self.addfuncshift_released:
607
+ self.addfuncshift_released[f]()
608
+ elif event.key() == QtCore.Qt.Key_Up or event.key() == QtCore.Qt.Key_Down:
609
+ if self.FlagArrowKeysNormal:
610
+ return super().keyReleaseEvent(event)
611
+ else:
612
+ Flag=True
613
+ for f in self.addfuncarrows_released:
614
+ Flag=Flag and self.addfuncarrows_released[f](event.key())
615
+ #if Flag: super().keyPressEvent(event)
616
+
617
+ class ToggleSplitterHandle(QtWidgets.QSplitterHandle):
618
+ def mousePressEvent(self, event):
619
+ super().mousePressEvent(event)
620
+ for f in self.parent().addfuncin:
621
+ self.parent().addfuncin[f]()
622
+
623
+ def mouseReleaseEvent(self, event):
624
+ super().mouseReleaseEvent(event)
625
+ for f in self.parent().addfuncout:
626
+ self.parent().addfuncout[f]()
627
+
628
+ class myQSplitter(QSplitter):
629
+ def __init__(self,parent):
630
+ super().__init__(parent)
631
+ self.OpWidth=0
632
+ self.OpMaxWidth=0
633
+ self.addfuncin={}
634
+ self.addfuncout={}
635
+ self.addfuncreturn={}
636
+
637
+ def createHandle(self):
638
+ return ToggleSplitterHandle(self.orientation(), self)
639
+
640
+ class RichTextPushButton(QPushButton):
641
+ margin=0
642
+ spacing=0
643
+
644
+ def __init__(self, parent=None, text=None):
645
+ if parent is not None:
646
+ super().__init__(parent)
647
+ else:
648
+ super().__init__()
649
+
650
+ self.__lyt = QHBoxLayout()
651
+ self.__lyt.setContentsMargins(self.margin, 0, self.margin, 0)
652
+ self.__lyt.setSpacing(self.spacing)
653
+ self.setLayout(self.__lyt)
654
+
655
+ self.__icon= QLabel(self)
656
+ self.__icon.setSizePolicy(
657
+ QSizePolicy.Preferred,
658
+ QSizePolicy.Expanding,
659
+ )
660
+ self.__icon.setAlignment(QtCore.Qt.AlignCenter | QtCore.Qt.AlignVCenter)
661
+
662
+ self.__lbl = QLabel(self)
663
+ if text is not None:
664
+ self.__lbl.setText(text)
665
+ else:
666
+ self.__lbl.hide()
667
+ self.__lbl.setAttribute(Qt.WA_TranslucentBackground)
668
+ self.__lbl.setAttribute(Qt.WA_TransparentForMouseEvents)
669
+ self.__lbl.setSizePolicy(
670
+ QSizePolicy.Preferred,
671
+ QSizePolicy.Expanding,
672
+ )
673
+ self.__lbl.setTextFormat(Qt.RichText)
674
+ self.__lbl.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
675
+
676
+ self.__lyt.addWidget(self.__icon)
677
+ self.__lyt.addWidget(self.__lbl)
678
+ self.__lyt.setStretch(0,1)
679
+ self.__lyt.setStretch(1,2)
680
+
681
+ self.lyt=self.__lyt
682
+ self.lbl=self.__lbl
683
+ self.icnWidget=self.__icon
684
+ self.icn=None
685
+ return
686
+
687
+ def setText(self, text):
688
+ if text:
689
+ self.__lbl.show()
690
+ self.__lbl.setText(text)
691
+ else: self.__lbl.hide()
692
+ self.updateGeometry()
693
+ return
694
+
695
+ def setIcon(self, icon):
696
+ h=int(self.size().height()/2)
697
+ pixmap = icon.pixmap(QSize(h,h))
698
+ self.__icon.setPixmap(pixmap)
699
+ self.icn=icon
700
+ self.updateGeometry()
701
+ return
702
+
703
+ def setIconSize(self, size:QSize):
704
+ if self.icn: self.__icon.setPixmap(self.icn.pixmap(size))
705
+ self.updateGeometry()
706
+ return
707
+
708
+ def sizeHint(self):
709
+ s = QPushButton.sizeHint(self)
710
+ w_lbl = self.__lbl.sizeHint()
711
+ w_icon = self.__icon.sizeHint()
712
+ s.setWidth(w_lbl.width()+w_icon.width()
713
+ +self.margin*2+self.spacing)
714
+ s.setHeight(w_lbl.height())
715
+ return s
716
+
717
+ class myQTableWidget(QtWidgets.QTableWidget):
718
+ def __init__(self,parent):
719
+ super().__init__(parent)
720
+ self.RowInfo=[]
721
+ self.InfoLabel:QLabel=None
722
+ self.DeleteButton:QPushButton=None
723
+ self.addwid=[]
724
+ self.addfuncreturn={}
725
+ self.addfuncout={}
726
+ #self.itemSelectionChanged.connect(self.resizeInfoLabel)
727
+
728
+ def keyPressEvent(self, event):
729
+ #infoPrint.white(event.key())
730
+ super().keyPressEvent(event)
731
+ if event.key() in (Qt.Key.Key_Return,Qt.Key.Key_Enter): #return
732
+ for f in self.addfuncreturn:
733
+ self.addfuncreturn[f]()
734
+
735
+ def focusInEvent(self, event):
736
+ super().focusInEvent(event)
737
+ #if self.DeleteButton: #and self.currentItem():
738
+ # self.DeleteButton.setEnabled(True)
739
+
740
+ def focusOutEvent(self, event):
741
+ super().focusOutEvent(event)
742
+ for f in self.addfuncout:
743
+ self.addfuncout[f]()
744
+ #if self.InfoLabel:
745
+ # self.InfoLabel.hide()
746
+ # self.InfoLabel.setText('')
747
+ #if self.DeleteButton:
748
+ # self.DeleteButton.setEnabled(False)
749
+
750
+ def resizeEvent(self, event):
751
+ super().resizeEvent(event)
752
+ self.resizeInfoLabel()
753
+
754
+ def resizeInfoLabel(self):
755
+ if self.InfoLabel and (True if not self.addwid else not self.addwid[0].hasFocus()):
756
+ item=self.currentItem()
757
+ if item:
758
+ self.InfoLabel.show()
759
+ if self.RowInfo: rowInfo=self.RowInfo[self.currentRow()]
760
+ else: rowInfo=''
761
+ tip=item.toolTip()
762
+ if not "<br>" in tip:
763
+ fw=lambda t: QtGui.QFontMetrics(self.InfoLabel.font()).size(QtCore.Qt.TextSingleLine,t).width()
764
+ if fw(tip)>self.InfoLabel.width():
765
+ k=0
766
+ while fw(tip[:k])<self.InfoLabel.width():
767
+ k+=1
768
+ tip="<br>".join([tip[:k-1], tip[k-1:2*k]])
769
+ if rowInfo: tip="<br>".join([tip,rowInfo])
770
+ self.InfoLabel.setText(tip)
771
+ else:
772
+ self.InfoLabel.hide()
773
+ self.InfoLabel.setText('')
774
+
775
+ def isfloat(num):
776
+ try:
777
+ float(num)
778
+ return True
779
+ except ValueError:
780
+ return False
781
+
782
+ class ClickableLabel(QLabel):
783
+ pixmap_size=25
784
+ def __init__(self, *args):
785
+ super().__init__(*args)
786
+
787
+ self.default_stylesheet = self.styleSheet()
788
+ self.highlight_stylesheet = "background-color: rgba(0, 116, 255, 0.1); border-radius: 3px;"
789
+
790
+ self.timer = QTimer(self)
791
+ self.timer.timeout.connect(self.resetHighlight)
792
+ self.timer.setSingleShot(True)
793
+
794
+ self.moviePixmap=None
795
+
796
+ def mousePressEvent(self, event):
797
+ if event.button() == Qt.LeftButton and self.toolTip():
798
+ self.highlight()
799
+ self.showMessageBox()
800
+ self.resetHighlight()
801
+
802
+ def showMessageBox(self):
803
+ if self.moviePixmap: pixmap=self.moviePixmap
804
+ else: pixmap=self.pixmap()
805
+ warningDialog(self.window(),Message=self.toolTip(),pixmap=pixmap,title='Info')
806
+
807
+ def highlight(self):
808
+ self.default_stylesheet = self.styleSheet() # <-- capture current style
809
+ self.setStyleSheet(self.highlight_stylesheet)
810
+ self.repaint()
811
+
812
+ def resetHighlight(self):
813
+ self.setStyleSheet(self.default_stylesheet)
814
+
815
+ def setToolTip(self,arg__1):
816
+ QLabel.setToolTip(self,arg__1)
817
+ QLabel.setStatusTip(self,arg__1)
818
+ if arg__1:
819
+ self.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
820
+ else:
821
+ self.setCursor(QCursor(Qt.CursorShape.ArrowCursor))
822
+
823
+ class ClickableEditLabel(ClickableLabel):
824
+ def setup(self):
825
+ le = QLineEdit()
826
+ bg = le.palette().color(QPalette.Base)
827
+ bg_rgba = f"rgba({bg.red()}, {bg.green()}, {bg.blue()}, {bg.alpha()})"
828
+
829
+ self.default_stylesheet = self.styleSheet() + f"""
830
+ ClickableEditLabel {{
831
+ background-color: {bg_rgba};
832
+ }}
833
+ """
834
+ self.setStyleSheet(self.default_stylesheet)
835
+ le.setParent(None)
836
+
837
+ class CustomLineEdit(QLineEdit):
838
+ cancelEditing = Signal()
839
+
840
+ def __init__(self, text, parent=None):
841
+ super().__init__(text, parent)
842
+ self.originalText = text
843
+
844
+ def focusOutEvent(self, event):
845
+ self.cancelEditing.emit()
846
+ super().focusOutEvent(event)
847
+
848
+ def keyPressEvent(self, event):
849
+ if event.key() == Qt.Key.Key_Escape:
850
+ self.cancelEditing.emit()
851
+ else:
852
+ super().keyPressEvent(event)
853
+
854
+ def keyReleaseEvent(self, event):
855
+ if event.key() == Qt.Key.Key_Escape:
856
+ self.cancelEditing.emit()
857
+ else:
858
+ super().keyReleaseEvent(event)
859
+
860
+ class ResizingLabel(QLabel):
861
+ def __init__(self,*args,**kwargs):
862
+ super().__init__(*args,**kwargs)
863
+ self.complete_text=self.text()
864
+
865
+ def setText(self,text):
866
+ self.complete_text=text
867
+ self.resizeText(text)
868
+ return
869
+
870
+ def resizeEvent(self, event: QResizeEvent) -> None:
871
+ super().resizeEvent(event)
872
+ self.resizeText(self.text())
873
+ return
874
+
875
+ def resizeText(self,text):
876
+ text=self.complete_text
877
+ metrics = QFontMetrics(self.font())
878
+ if self.alignment() & Qt.AlignmentFlag.AlignRight:
879
+ FlagRight=True
880
+ textElideMode=Qt.TextElideMode.ElideLeft
881
+ else:
882
+ FlagRight=False
883
+ textElideMode=Qt.TextElideMode.ElideRight
884
+ if "<span" in text:
885
+ match = re.search(r"<span(.*?)</span>", text)
886
+ html_part = "<span"+match.group(1)+"</span>"
887
+ index = match.start(1)-5
888
+ text_without_bullet=text.replace(html_part,'')
889
+ truncated_text=metrics.elidedText(text_without_bullet, textElideMode, self.width()-5)
890
+ if FlagRight:
891
+ index=len(truncated_text)-3*(int('...' in truncated_text))-len(text_without_bullet[index:])
892
+ if index>0:
893
+ truncated_text=truncated_text[:index]+html_part+truncated_text[index:]
894
+ elif index>len(truncated_text)-3:
895
+ truncated_text=truncated_text[:index]+html_part+truncated_text[index:]
896
+ else:
897
+ truncated_text = metrics.elidedText(text, textElideMode, self.width())
898
+ super().setText(truncated_text)
899
+
900
+ class EditableLabel(QWidget):
901
+ def __init__(self, parent=None):
902
+ super().__init__(parent)
903
+
904
+ self.main_layout = QVBoxLayout(self)
905
+ self.main_layout.setContentsMargins(0,0,0,0)
906
+ self.main_layout.setSpacing(0)
907
+
908
+ self.label = ResizingLabel(self)
909
+ self.label.setAlignment(Qt.AlignmentFlag.AlignLeft)
910
+ self.label.mouseDoubleClickEvent = self.enable_editing
911
+
912
+ self.edit = CustomLineEdit(self)
913
+ self.edit.setAlignment(Qt.AlignmentFlag.AlignLeft)
914
+ self.edit.hide()
915
+ self.edit.editingFinished.connect(self.disable_editing)
916
+ self.edit.cancelEditing.connect(self.disable_editing)
917
+ self.updateLabel=lambda: None
918
+ self.bullet=''
919
+
920
+ self.installEventFilter(self) # Installare il filtro eventi
921
+
922
+ self.main_layout.addWidget(self.label)
923
+ self.main_layout.addWidget(self.edit)
924
+
925
+ def setText(self,text):
926
+ self.label.setText(text)
927
+ self.edit.setText(text)
928
+
929
+ def setFont(self,font:QFont):
930
+ self.label.setFont(font)
931
+ self.edit.setFont(font)
932
+
933
+ def enable_editing(self, event):
934
+ self.label.hide()
935
+ self.edit.setGeometry(self.label.geometry()) # Assicurati che l'editor prenda la posizione della label
936
+ self.edit.setText(self.label.text().replace(self.bullet,'')) # Assicurati che il testo corrente venga impostato nell'editor
937
+ self.edit.selectAll()
938
+ self.edit.show()
939
+ self.window().setFocus()
940
+ self.edit.setFocus()
941
+
942
+ def disable_editing(self):
943
+ self.edit.hide()
944
+ self.label.setText(self.edit.text())
945
+ self.label.show()
946
+ self.updateLabel()
947
+
948
+ def setButtonHoverStyle(w:QWidget,FlagBorder=True,borderRadius=6,FlagCls=True):
949
+ if FlagCls:
950
+ cls = w.metaObject().className()
951
+ base = w.styleSheet() or ""
952
+ if cls not in base: base=f"{cls} {{" +f"{base}"+"}"
953
+ if base and not base.endswith("\n"):
954
+ base += "\n"
955
+ else: cls=base=''
956
+
957
+ """"
958
+ style = (
959
+ f"{cls}:hover {{"
960
+ "background: qlineargradient("
961
+ "x1:0, y1:0, x2:0, y2:1, "
962
+ "stop:0 rgba(0, 116, 255, 0.05), "
963
+ "stop:0.2 rgba(0, 116, 255, 0.15), "
964
+ "stop:0.8 rgba(0, 116, 255, 0.15), "
965
+ "stop:1 rgba(0, 116, 255, 0.05));"
966
+ f"border-radius: {borderRadius}px;"
967
+ f"{'border: 1px solid gray;' if FlagBorder else ''}"
968
+ "padding: 2px 2px;"
969
+ "}"
970
+ )
971
+ """
972
+
973
+ style = (
974
+ f"{cls}:hover {{"
975
+ f"border-radius: {borderRadius}px;"
976
+ f"background-color: none;"
977
+ f"{'border: 1px solid gray;' if FlagBorder else ''}"
978
+ "padding: 2px 2px;"
979
+ "}"
980
+ )
981
+
982
+ w.setStyleSheet(base + style)
983
+
984
+ def apply_hover_glow_label(
985
+ w: QLabel,
986
+ *,
987
+ color="#0051FF",
988
+ blur=18,
989
+ max_alpha=170,
990
+ duration_ms=160,
991
+ ):
992
+ if getattr(w, "_hoverGlowInstalled", False):
993
+ w._hoverGlowColor = QColor(color)
994
+ w._hoverGlowBlur = float(blur)
995
+ w._hoverGlowMaxAlpha = int(max_alpha)
996
+ w._hoverGlowDuration = int(duration_ms)
997
+ w._hoverGlowEffect.setBlurRadius(w._hoverGlowBlur)
998
+ return
999
+
1000
+ w._hoverGlowInstalled = True
1001
+ w._hoverGlowColor = QColor(color)
1002
+ w._hoverGlowBlur = float(blur)
1003
+ w._hoverGlowMaxAlpha = int(max_alpha)
1004
+ w._hoverGlowDuration = int(duration_ms)
1005
+
1006
+ eff = QGraphicsDropShadowEffect(w)
1007
+ eff.setOffset(0, 0)
1008
+ eff.setBlurRadius(w._hoverGlowBlur)
1009
+
1010
+ c = QColor(w._hoverGlowColor)
1011
+ c.setAlpha(0)
1012
+ eff.setColor(c)
1013
+
1014
+ w.setGraphicsEffect(eff)
1015
+ w._hoverGlowEffect = eff
1016
+
1017
+ def _set_alpha(val):
1018
+ col = QColor(w._hoverGlowColor)
1019
+ col.setAlpha(int(val))
1020
+ w._hoverGlowEffect.setColor(col)
1021
+
1022
+ # ✅ Animate a plain value (no Qt property needed)
1023
+ w._hoverGlowAnimAlpha = QVariantAnimation(w)
1024
+ w._hoverGlowAnimAlpha.setEasingCurve(QEasingCurve.OutCubic)
1025
+ w._hoverGlowAnimAlpha.valueChanged.connect(_set_alpha)
1026
+
1027
+ class _GlowFilter(QObject):
1028
+ def eventFilter(self, obj, ev):
1029
+ if obj is not w:
1030
+ return False
1031
+
1032
+ t = ev.type()
1033
+ if t in (QEvent.Enter, QEvent.HoverEnter):
1034
+ w._hoverGlowAnimAlpha.stop()
1035
+ w._hoverGlowAnimAlpha.setDuration(w._hoverGlowDuration)
1036
+ w._hoverGlowAnimAlpha.setStartValue(w._hoverGlowEffect.color().alpha())
1037
+ w._hoverGlowAnimAlpha.setEndValue(w._hoverGlowMaxAlpha)
1038
+ w._hoverGlowAnimAlpha.start()
1039
+
1040
+ elif t in (QEvent.Leave, QEvent.HoverLeave):
1041
+ w._hoverGlowAnimAlpha.stop()
1042
+ w._hoverGlowAnimAlpha.setDuration(w._hoverGlowDuration)
1043
+ w._hoverGlowAnimAlpha.setStartValue(w._hoverGlowEffect.color().alpha())
1044
+ w._hoverGlowAnimAlpha.setEndValue(0)
1045
+ w._hoverGlowAnimAlpha.start()
1046
+
1047
+ return False
1048
+
1049
+ w._hoverGlowFilter = _GlowFilter(w)
1050
+ w.installEventFilter(w._hoverGlowFilter)
1051
+
1052
+ w.setAttribute(Qt.WA_Hover, True)
1053
+ w.setMouseTracking(True)
1054
+
1055
+ def remove_hover_glow_label(w: QLabel):
1056
+ """Removes the hover glow behavior and restores a clean state."""
1057
+ if not getattr(w, "_hoverGlowInstalled", False):
1058
+ return
1059
+
1060
+ # Stop animation cleanly
1061
+ anim = getattr(w, "_hoverGlowAnimAlpha", None)
1062
+ if anim is not None:
1063
+ anim.stop()
1064
+
1065
+ # Remove event filter
1066
+ filt = getattr(w, "_hoverGlowFilter", None)
1067
+ if filt is not None:
1068
+ try:
1069
+ w.removeEventFilter(filt)
1070
+ except RuntimeError:
1071
+ pass
1072
+
1073
+ # Remove graphics effect
1074
+ w.setGraphicsEffect(None)
1075
+
1076
+ # Restore hover-related flags (safe defaults)
1077
+ w.setAttribute(Qt.WA_Hover, False)
1078
+ w.setMouseTracking(False)
1079
+
1080
+ # Cleanup attributes
1081
+ for attr in (
1082
+ "_hoverGlowInstalled",
1083
+ "_hoverGlowColor",
1084
+ "_hoverGlowBlur",
1085
+ "_hoverGlowMaxAlpha",
1086
+ "_hoverGlowDuration",
1087
+ "_hoverGlowEffect",
1088
+ "_hoverGlowAnimAlpha",
1089
+ "_hoverGlowFilter",
1090
+ ):
1091
+ if hasattr(w, attr):
1092
+ delattr(w, attr)
1093
+
1094
+ class SliderHandleCursorFilter(QObject):
1095
+ def eventFilter(self, obj, event):
1096
+ if isinstance(obj, QSlider) and event.type() == QEvent.MouseMove:
1097
+
1098
+ opt = QStyleOptionSlider()
1099
+ obj.initStyleOption(opt)
1100
+
1101
+ handle_rect = obj.style().subControlRect(
1102
+ QStyle.CC_Slider,
1103
+ opt,
1104
+ QStyle.SC_SliderHandle,
1105
+ obj
1106
+ )
1107
+
1108
+ if handle_rect.contains(event.position().toPoint()):
1109
+ obj.setCursor(QCursor(Qt.OpenHandCursor))
1110
+ else:
1111
+ obj.unsetCursor()
1112
+
1113
+ return False
1114
+
1115
+
1116
+ def changes(self,TabType,filename,title=" Changes"):
1117
+ FlagShow=False
1118
+ if self.logChanges:
1119
+ if self.logChanges.isVisible():
1120
+ FlagShow=True
1121
+ if FlagShow:
1122
+ self.logChanges.hide()
1123
+ self.logChanges.show()
1124
+ else:
1125
+ self.logChanges=TabType(self,True)
1126
+ self.logChanges.resize(720,720)
1127
+ self.logChanges.show()
1128
+ self.logChanges.ui.progress_Proc.hide()
1129
+ self.logChanges.ui.button_close_tab.hide()
1130
+ icon=QPixmap(''+ icons_path +'news.png')
1131
+ self.logChanges.ui.icon.setPixmap(icon)
1132
+ apply_hover_glow_label(self.logChanges.ui.icon)
1133
+ self.logChanges.setWindowIcon(self.windowIcon())
1134
+ self.logChanges.setWindowTitle(title)
1135
+ self.logChanges.ui.name_tab.setText(title)
1136
+
1137
+ self.logChanges.ui.log.setLineWrapColumnOrWidth(self.logChanges.ui.log.width()-20)
1138
+ base="""
1139
+ QTextEdit {
1140
+ border: 1px solid #2a2a2a;
1141
+ border-radius: 6px;
1142
+
1143
+ padding: 2px;
1144
+
1145
+ selection-background-color: #0051FF;
1146
+ selection-color: #FFFFFF;
1147
+ }
1148
+ """
1149
+ self.logChanges.ui.log.setStyleSheet(base+"\n"+gPaIRS_QMenu_style)
1150
+
1151
+ def setFontPixelSize(logChanges:type(self.logChanges),fPixSize):
1152
+ logfont=self.font()
1153
+ logfont.setFamily(fontName)
1154
+ logfont.setPixelSize(fPixSize+2)
1155
+ logChanges.ui.log.setFont(logfont)
1156
+ fPixSize_TabNames=min([fPixSize*2,30])
1157
+ lab=logChanges.ui.name_tab
1158
+ font=lab.font()
1159
+ font.setPixelSize(fPixSize_TabNames)
1160
+ lab.setFont(font)
1161
+ self.logChanges.setFontPixelSize=lambda fS: setFontPixelSize(self.logChanges,fS)
1162
+ self.logChanges.setFontPixelSize(self.TABpar.fontPixelSize)
1163
+ def logResizeEvent(logChanges:type(self.logChanges),e):
1164
+ super(type(logChanges),logChanges).resizeEvent(e)
1165
+ logChanges.ui.log.setLineWrapColumnOrWidth(logChanges.ui.log.width()-20)
1166
+ self.logChanges.ui.log.resizeEvent=lambda e: logResizeEvent(self.logChanges,e)
1167
+
1168
+ self.logChanges.ui.icon.addfuncclick['whatsnew']=self.whatsNew
1169
+ self.logChanges.ui.icon.setCustomCursor()
1170
+
1171
+ try:
1172
+ file = open(filename, "rb")
1173
+ content = file.read().decode("utf-8")
1174
+ self.logChanges.ui.log.setText(content)
1175
+ file.close()
1176
+ except Exception as inst:
1177
+ pri.Error.red(f'There was a problem while reading the file {filename}:\n{inst}')
1178
+ self.logChanges.ui.log.setText(f'No information about PaIRS-UniNa updates available!\n\nSorry for this, try to reinstall PaIRS-UniNa or alternatively contact the authors at {__mail__}.')
1179
+ return
1180
+
1181
+ #********************************************* Matplotlib
1182
+ import io
1183
+ import matplotlib as mpl
1184
+ mpl.use('Qt5Agg')
1185
+ import matplotlib.pyplot as pyplt
1186
+ import matplotlib.image as mplimage
1187
+ from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg, NavigationToolbar2QT as NavigationToolbar
1188
+ from matplotlib.figure import Figure as mplFigure
1189
+ from mpl_toolkits.axes_grid1 import make_axes_locatable
1190
+
1191
+ import matplotlib.style as mplstyle
1192
+ mplstyle.use('fast')
1193
+ #mplstyle.use(['dark_background', 'ggplot', 'fast'])
1194
+
1195
+ class MplCanvas(FigureCanvasQTAgg):
1196
+ def __init__(self, parent=None, width=8, height=8, dpi=100):
1197
+ self.inp_width=width
1198
+ self.inp_height=height
1199
+ self.inp_dpi=dpi
1200
+ self.fig = mplFigure(figsize=(width, height), dpi=dpi)
1201
+ self.fig2=[]
1202
+ self.axes = self.fig.gca() #self.fig.add_subplot(111)
1203
+ self.addfuncrelease={}
1204
+ mpl.rcParams["font.family"]=fontName
1205
+ #mpl.rcParams["font.size"]=12
1206
+ color_tuple=(0.95,0.95,0.95,0)
1207
+ #clrgb=[int(i*255) for i in color_tuple]
1208
+ self.fig.set_facecolor(color_tuple)
1209
+
1210
+ self.copyIcon=QIcon(icons_path+"copy.png")
1211
+ self.openNewWindowIcon=QIcon(icons_path+"open_new_window.png")
1212
+ self.scaleDownIcon=QIcon(icons_path+"scale_down.png")
1213
+ self.scaleUpIcon=QIcon(icons_path+"scale_up.png")
1214
+ self.scaleAllIcon=QIcon(icons_path+"scale_all.png")
1215
+ self.showAllIcon=QIcon(icons_path+"show_all.png")
1216
+ self.alignAllIcon=QIcon(icons_path+"align_all.png")
1217
+ self.closeAllIcon=QIcon(icons_path+"close_all.png")
1218
+ self.loadImageIcon=QIcon(icons_path+"open_image.png")
1219
+ self.loadResultIcon=QIcon(icons_path+"open_result.png")
1220
+
1221
+ super(MplCanvas, self).__init__(self.fig)
1222
+
1223
+ def mouseReleaseEvent(self, event):
1224
+ super().mouseReleaseEvent(event)
1225
+ if event.button() == Qt.LeftButton:
1226
+ for f in self.addfuncrelease:
1227
+ self.addfuncrelease[f]()
1228
+
1229
+ def copy2clipboard(self):
1230
+ with io.BytesIO() as buffer:
1231
+ self.fig.savefig(buffer)
1232
+ QApplication.clipboard().setImage(QImage.fromData(buffer.getvalue()))
1233
+ self.showTip(self,'Image copied to clipboard!')
1234
+
1235
+ def copy2newfig(self,text='Vis'):
1236
+ fig2=QMainWindow()
1237
+ fig2.setPalette(self.palette())
1238
+ fig2.setWindowTitle(text)
1239
+ fig2.setStyleSheet("background-color: white;")
1240
+
1241
+ wid=QWidget(fig2)
1242
+ fig2.setCentralWidget(wid)
1243
+ lay=QVBoxLayout(wid)
1244
+
1245
+ lbl=QLabel(fig2)
1246
+ lbl.setAlignment(QtCore.Qt.AlignCenter)
1247
+ with io.BytesIO() as buffer:
1248
+ self.fig.savefig(buffer)
1249
+ pixmap = QPixmap(QImage.fromData(buffer.getvalue()))
1250
+ lbl.setPixmap(pixmap)
1251
+ lbl.setScaledContents(False)
1252
+ lbl2=QLabel(text,fig2)
1253
+ lbl2.setWordWrap(True)
1254
+ lbl2.setStyleSheet("color: black;")
1255
+
1256
+ lay.setSpacing(0)
1257
+ lay.addWidget(lbl)
1258
+ lay.addWidget(lbl2)
1259
+
1260
+ self.fig2.append(fig2)
1261
+
1262
+ def closeFig2(event):
1263
+ type(fig2).closeEvent(fig2,event)
1264
+ self.fig2.pop(self.fig2.index(fig2))
1265
+ return
1266
+ fig2.closeEvent=lambda event: closeFig2(event)
1267
+
1268
+
1269
+ def fCopy2clipboard():
1270
+ QApplication.clipboard().setImage(lbl.pixmap().toImage())
1271
+ self.showTip(fig2,'Image copied to clipboard!')
1272
+ return
1273
+
1274
+ fig2.scaleFactor=1
1275
+ def resizeFig2(scale):
1276
+ fig2.scaleFactor=fig2.scaleFactor*scale
1277
+ fig2.scaleFactor=min([fig2.scaleFactor,1.5])
1278
+ fig2.scaleFactor=max([fig2.scaleFactor,0.5])
1279
+ fig2.setFixedSize(s0*fig2.scaleFactor)
1280
+ lbl.setPixmap(pixmap.scaled(pixmap.size()*fig2.scaleFactor,mode=Qt.TransformationMode.SmoothTransformation))
1281
+ return
1282
+ fig2.resizeFig2=resizeFig2
1283
+
1284
+ sc0=QGuiApplication.primaryScreen().geometry()
1285
+ def shiftFig2(dir):
1286
+ dpix=10
1287
+ geo=fig2.geometry()
1288
+ if dir=='u':
1289
+ geo.setY(max([geo.y()-dpix,sc0.y()]))
1290
+ elif dir=='d':
1291
+ geo.setY(min([geo.y()+dpix,sc0.y()+sc0.height()-fig2.height()]))
1292
+ elif dir=='l':
1293
+ geo.setX(max([geo.x()-dpix,sc0.x()]))
1294
+ elif dir=='r':
1295
+ geo.setX(min([geo.x()+dpix,sc0.x()+sc0.width()-fig2.width()]))
1296
+ fig2.setGeometry(geo)
1297
+ return
1298
+
1299
+ QS_down=QShortcut(QKeySequence('Down'), fig2)
1300
+ QS_down.activated.connect(lambda: shiftFig2('d'))
1301
+ QS_up=QShortcut(QKeySequence('Up'), fig2)
1302
+ QS_up.activated.connect(lambda: shiftFig2('u'))
1303
+ QS_right=QShortcut(QKeySequence('Right'), fig2)
1304
+ QS_right.activated.connect(lambda: shiftFig2('r'))
1305
+ QS_left=QShortcut(QKeySequence('Left'), fig2)
1306
+ QS_left.activated.connect(lambda: shiftFig2('l'))
1307
+
1308
+ QS_copy2clipboard=QShortcut(QKeySequence('Ctrl+C'), fig2)
1309
+ QS_copy2clipboard.activated.connect(fCopy2clipboard)
1310
+
1311
+ fScaleDown=lambda: resizeFig2(0.9)
1312
+ QS_scaleDown=QShortcut(QKeySequence('Ctrl+Down'), fig2)
1313
+ QS_scaleDown.activated.connect(fScaleDown)
1314
+ fScaleUp=lambda: resizeFig2(1.1)
1315
+ QS_scaleUp=QShortcut(QKeySequence('Ctrl+Up'), fig2)
1316
+ QS_scaleUp.activated.connect(fScaleUp)
1317
+ fScaleAll=lambda: self.scaleAll(fig2.scaleFactor)
1318
+ QS_scaleAll=QShortcut(QKeySequence('Ctrl+Return'), fig2)
1319
+ QS_scaleAll.activated.connect(fScaleAll)
1320
+
1321
+ QS_showAll=QShortcut(QKeySequence('Ctrl+S'), fig2)
1322
+ QS_showAll.activated.connect(self.showAll)
1323
+ QS_alignAll=QShortcut(QKeySequence('Ctrl+A'), fig2)
1324
+ QS_alignAll.activated.connect(self.alignAll)
1325
+ QS_closeAll=QShortcut(QKeySequence('Ctrl+X'), fig2)
1326
+ QS_closeAll.activated.connect(self.closeAll)
1327
+
1328
+ fig2.lbl:QLabel=lbl
1329
+ def contextMenuEventFig2(event):
1330
+ contextMenu = QMenu()
1331
+ contextMenu.setStyleSheet(self.parent().parent().gui.ui.menu.styleSheet())
1332
+ copy2clipboard = contextMenu.addAction("Copy to clipboard ("+QS_copy2clipboard.key().toString(QKeySequence.NativeText)+")")
1333
+ contextMenu.addSeparator()
1334
+ scaleDown = contextMenu.addAction("Scale down ("+QS_scaleDown.key().toString(QKeySequence.NativeText)+")")
1335
+ scaleUp = contextMenu.addAction("Scale up ("+QS_scaleUp.key().toString(QKeySequence.NativeText)+")")
1336
+ scaleAll = contextMenu.addAction("Scale all ("+QS_scaleAll.key().toString(QKeySequence.NativeText)+")")
1337
+ contextMenu.addSeparator()
1338
+ showAll = contextMenu.addAction("Show all ("+QS_showAll.key().toString(QKeySequence.NativeText)+")")
1339
+ alignAll = contextMenu.addAction("Align all ("+QS_alignAll.key().toString(QKeySequence.NativeText)+")")
1340
+ closeAll = contextMenu.addAction("Close all ("+QS_closeAll.key().toString(QKeySequence.NativeText)+")")
1341
+
1342
+ copy2clipboard.setIcon(self.copyIcon)
1343
+ scaleDown.setIcon(self.scaleDownIcon)
1344
+ scaleUp.setIcon(self.scaleUpIcon)
1345
+ scaleAll.setIcon(self.scaleAllIcon)
1346
+ showAll.setIcon(self.showAllIcon)
1347
+ alignAll.setIcon(self.alignAllIcon)
1348
+ closeAll.setIcon(self.closeAllIcon)
1349
+
1350
+ action = contextMenu.exec(fig2.mapToGlobal(event.pos()))
1351
+
1352
+ if action == copy2clipboard:
1353
+ fCopy2clipboard()
1354
+ elif action == scaleDown:
1355
+ fScaleDown()
1356
+ elif action == scaleUp:
1357
+ fScaleUp()
1358
+ elif action == scaleAll:
1359
+ self.scaleAll(fig2.scaleFactor)
1360
+ elif action == showAll:
1361
+ self.showAll()
1362
+ elif action == alignAll:
1363
+ self.alignAll()
1364
+ elif action == closeAll:
1365
+ self.closeAll()
1366
+
1367
+
1368
+ fig2.contextMenuEvent=lambda event: contextMenuEventFig2(event)
1369
+
1370
+ fig2.show()
1371
+ fig2.setFixedSize(fig2.width(), fig2.height())
1372
+ s0=fig2.size()
1373
+
1374
+ self.posWindow(len(self.fig2)-1)
1375
+ """
1376
+ fgeo = fig2.frameGeometry()
1377
+ centerPoint = QGuiApplication.primaryScreen().availableGeometry().center()
1378
+ fgeo.moveCenter(centerPoint)
1379
+ fig2.move(fgeo.topLeft())
1380
+ """
1381
+
1382
+ def showTip(self,obj,message):
1383
+ show_mouse_tooltip(obj,message)
1384
+
1385
+ def posWindow(self,ind):
1386
+ w=h=0
1387
+ for f in self.fig2:
1388
+ f:QMainWindow
1389
+ w=max([w,f.frameGeometry().width()])
1390
+ h=max([h,f.frameGeometry().height()])
1391
+ geoS=QGuiApplication.primaryScreen().availableGeometry()
1392
+ ncol=int(geoS.width()/w)
1393
+ nrow=int(geoS.height()/h)
1394
+ ntot=ncol*nrow
1395
+ if ind<0: ind=range(len(self.fig2))
1396
+ else: ind=[ind]
1397
+ for kk in ind:
1398
+ k=kk%ntot
1399
+ k=kk
1400
+ i=int(k/ncol)
1401
+ j=k-i*ncol
1402
+ f=self.fig2[kk]
1403
+ fg=f.frameGeometry()
1404
+ fg.moveTopLeft(QPoint(j*w,i*h))
1405
+ f.move(fg.topLeft())
1406
+
1407
+ def scaleAll(self,scale):
1408
+ for f in self.fig2:
1409
+ f:QMainWindow
1410
+ f.scaleFactor=scale
1411
+ f.resizeFig2(1.0)
1412
+
1413
+ def showAll(self):
1414
+ for f in self.fig2:
1415
+ f:QMainWindow
1416
+ f.hide()
1417
+ f.show()
1418
+
1419
+ def closeAll(self):
1420
+ for f in range(len(self.fig2)):
1421
+ f:QMainWindow
1422
+ f=self.fig2[0]
1423
+ f.close()
1424
+ self.fig2=[]
1425
+
1426
+ def alignAll(self):
1427
+ self.posWindow(-1)
1428
+ self.showAll()
1429
+
1430
+
1431
+ def setAppGuiPalette(self:QWidget,palette:QPalette=None):
1432
+ applic:QApplication
1433
+ if hasattr(self,'app'):
1434
+ applic=self.app
1435
+ else:
1436
+ return
1437
+ if palette==None:
1438
+ palette=applic.style().standardPalette()
1439
+ else:
1440
+ applic.setPalette(palette)
1441
+
1442
+ try:
1443
+ if self.focusWidget():
1444
+ self.focusWidget().clearFocus()
1445
+ widgets=[self]
1446
+ if hasattr(self,'FloatingTabs'): widgets+=self.FloatingTabs
1447
+ if hasattr(self,'FloatingWindows'): widgets+=self.FloatingWindows
1448
+ if hasattr(self,'aboutDialog'): widgets.append(self.aboutDialog)
1449
+ if hasattr(self,'logChanges'): widgets.append(self.logChanges)
1450
+ widgets+=self.findChildren(QDialog)
1451
+ for f in widgets:
1452
+ if f and isinstance(f, QWidget):
1453
+ f.setPalette(palette)
1454
+ for c in f.findChildren(QObject):
1455
+ if hasattr(c,'setPalette') and not isinstance(c, (MplCanvas, mplFigure, QStatusBar)):
1456
+ c.setPalette(palette)
1457
+ if hasattr(c,'initialStyle') and hasattr(c, 'setStyleSheet'):
1458
+ c.setStyleSheet(c.initialStyle)
1459
+ for c in f.findChildren(MyQLineEdit):
1460
+ c.initFlag=False
1461
+ c.styleFlag=False
1462
+ c.setup()
1463
+ for c in f.findChildren(ClickableEditLabel):
1464
+ c.setup()
1465
+ for c in f.findChildren(QObject):
1466
+ if hasattr(c,'setup2'):
1467
+ c.initFlag2=False
1468
+ c.setup2()
1469
+ if hasattr(self,'ResizePopup'):
1470
+ if self.ResizePopup is not None:
1471
+ self.ResizePopup=type(self.ResizePopup)(self.buttonSizeCallbacks) #non riesco a farlo come gli altri
1472
+ if hasattr(self,'w_Vis'): self.w_Vis.addPlotToolBar()
1473
+ except:
1474
+ pri.Error.red("***** Error while setting the application palette! *****")
1475
+
1476
+
1477
+ class Toast(QFrame):
1478
+ """
1479
+ Tooltip-like custom toast that appears at the current mouse cursor position.
1480
+ Non-native, does not steal focus. Auto-hides after timeout_ms.
1481
+ """
1482
+
1483
+ def __init__(
1484
+ self,
1485
+ parent: QWidget,
1486
+ msg: str,
1487
+ *,
1488
+ timeout_ms: int = 2500,
1489
+ offset: QPoint = QPoint(10, 15), # offset from cursor
1490
+ min_width: int = 0,
1491
+ max_width: int = 460,
1492
+ fade_in_ms: int = 80,
1493
+ fade_out_ms: int = 130,
1494
+ ):
1495
+ super().__init__(parent)
1496
+
1497
+ self.setObjectName("PaIRSToast")
1498
+ self.setWindowFlags(Qt.FramelessWindowHint | Qt.ToolTip)
1499
+ #self.setAttribute(Qt.WA_TranslucentBackground, True)
1500
+ self.setAttribute(Qt.WA_ShowWithoutActivating, True)
1501
+
1502
+ self._label = QLabel(msg, self)
1503
+ self._label.setObjectName("PaIRSToastLabel")
1504
+ self._label.setWordWrap(True)
1505
+
1506
+ lay = QHBoxLayout(self)
1507
+ lay.setContentsMargins(4,3,4,3)
1508
+ lay.addWidget(self._label)
1509
+
1510
+ # Classic tooltip-like styling
1511
+ self.setStyleSheet("""
1512
+ QFrame#PaIRSToast {
1513
+ background-color: #ffffdc; /* classic tooltip-ish */
1514
+ color: #000000;
1515
+ border: 1px solid rgba(0, 0, 0, 0.45);
1516
+ border-radius: 4px;
1517
+ }
1518
+ QLabel#PaIRSToastLabel {
1519
+ color: #000000;
1520
+ }
1521
+ """)
1522
+
1523
+ # Width clamp + nice wrapping
1524
+ # Reset any previous constraints (important if a previous tooltip was wider)
1525
+ self.setMinimumSize(min_width, 0)
1526
+ self.setMaximumSize(max_width, 16777215)
1527
+
1528
+ self._label.setMinimumSize(min_width, 0)
1529
+ self._label.setMaximumSize(max_width, 16777215)
1530
+
1531
+ # Make sure the label doesn't "expand"
1532
+ self._label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
1533
+
1534
+ font=self.window().font()
1535
+ self._label.setFont(font)
1536
+ self._apply_size(msg)
1537
+
1538
+ # Position at cursor (global)
1539
+ self._move_to_cursor(offset)
1540
+
1541
+ # Opacity animation
1542
+ self.setWindowOpacity(0.0)
1543
+ self._anim = QPropertyAnimation(self, b"windowOpacity", self)
1544
+ self._anim.setEasingCurve(QEasingCurve.OutCubic)
1545
+
1546
+ # Auto hide
1547
+ self._timer = QTimer(self)
1548
+ self._timer.setSingleShot(True)
1549
+ self._timer.timeout.connect(lambda: self.fade_out(duration_ms=fade_out_ms))
1550
+
1551
+ self.show()
1552
+ self.raise_()
1553
+ self.fade_in(duration_ms=fade_in_ms)
1554
+ self._timer.start(timeout_ms)
1555
+
1556
+ def _apply_size(self, msg: str):
1557
+ self._label.setText(msg)
1558
+
1559
+ # Let QLabel compute the correct wrapped size
1560
+ self._label.adjustSize()
1561
+ sh = self._label.sizeHint()
1562
+
1563
+ # Lock label to its real hint size
1564
+ self._label.setFixedSize(sh)
1565
+
1566
+ # Now shrink the frame to content + margins
1567
+ self.adjustSize()
1568
+
1569
+ # Lock the whole toaster too (prevents extra blank area)
1570
+ self.setFixedSize(self.sizeHint())
1571
+
1572
+ def _move_to_cursor(self, offset: QPoint):
1573
+ parent = self.parent()
1574
+ if hasattr(parent, "cursorRect"):
1575
+ rect = parent.cursorRect() # QRect in coordinate del widget
1576
+ p = parent.mapToGlobal(rect.bottomRight())
1577
+ else:
1578
+ p = QCursor.pos() + offset
1579
+
1580
+ # Keep inside the current screen geometry
1581
+ screen = self.screen()
1582
+ if screen is None:
1583
+ self.move(p)
1584
+ return
1585
+
1586
+ geo = screen.availableGeometry()
1587
+ self.adjustSize()
1588
+ w, h = self.width(), self.height()
1589
+
1590
+ x = p.x()
1591
+ y = p.y()
1592
+
1593
+ if x + w > geo.right():
1594
+ x = geo.right() - w
1595
+ if y + h > geo.bottom():
1596
+ y = geo.bottom() - h
1597
+ if x < geo.left():
1598
+ x = geo.left()
1599
+ if y < geo.top():
1600
+ y = geo.top()
1601
+
1602
+ self.move(QPoint(x, y))
1603
+
1604
+ def fade_in(self, *, duration_ms: int = 80):
1605
+ self._anim.stop()
1606
+ self._anim.setDuration(duration_ms)
1607
+ self._anim.setStartValue(self.windowOpacity())
1608
+ self._anim.setEndValue(1.0)
1609
+ self._anim.start()
1610
+
1611
+ def fade_out(self, *, duration_ms: int = 130):
1612
+ self._anim.stop()
1613
+ self._anim.setDuration(duration_ms)
1614
+ self._anim.setStartValue(self.windowOpacity())
1615
+ self._anim.setEndValue(0.0)
1616
+ self._anim.finished.connect(self.close)
1617
+ self._anim.start()
1618
+
1619
+ def show_mouse_tooltip(parent: QWidget, msg: str, *, timeout_ms: int = 2500):
1620
+ """
1621
+ Convenience function: show a tooltip-like toaster at the mouse cursor.
1622
+ Keeps a reference on parent to avoid garbage collection.
1623
+ """
1624
+ old = getattr(parent, "_pairs_mouse_toaster", None)
1625
+ if old is not None and old.isVisible():
1626
+ old.close()
1627
+
1628
+ if msg:
1629
+ t = Toast(parent, msg, timeout_ms=timeout_ms)
1630
+ else: t=None
1631
+ parent._pairs_mouse_toaster = t
1632
+ return t
1633
+