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.
- PaIRS_UniNa/Calibration_Tab.py +347 -0
- PaIRS_UniNa/Changes.txt +174 -0
- PaIRS_UniNa/Custom_Top.py +303 -0
- PaIRS_UniNa/Explorer.py +3322 -0
- PaIRS_UniNa/FolderLoop.py +562 -0
- PaIRS_UniNa/Input_Tab.py +829 -0
- PaIRS_UniNa/Input_Tab_CalVi.py +787 -0
- PaIRS_UniNa/Input_Tab_tools.py +3026 -0
- PaIRS_UniNa/Log_Tab.py +110 -0
- PaIRS_UniNa/Output_Tab.py +922 -0
- PaIRS_UniNa/PaIRS.py +18 -0
- PaIRS_UniNa/PaIRS_PIV.py +873 -0
- PaIRS_UniNa/PaIRS_pypacks.py +1374 -0
- PaIRS_UniNa/Process_Tab.py +1761 -0
- PaIRS_UniNa/Process_Tab_CalVi.py +313 -0
- PaIRS_UniNa/Process_Tab_Disp.py +170 -0
- PaIRS_UniNa/Process_Tab_Min.py +120 -0
- PaIRS_UniNa/ResizePopup.py +55 -0
- PaIRS_UniNa/SPIVCalHelp.py +155 -0
- PaIRS_UniNa/Saving_tools.py +298 -0
- PaIRS_UniNa/TabTools.py +1413 -0
- PaIRS_UniNa/Vis_Tab.py +2176 -0
- PaIRS_UniNa/Vis_Tab_CalVi.py +982 -0
- PaIRS_UniNa/Whatsnew.py +130 -0
- PaIRS_UniNa/_PaIRS_PIV.so +0 -0
- PaIRS_UniNa/__init__.py +6 -0
- PaIRS_UniNa/__main__.py +45 -0
- PaIRS_UniNa/addwidgets_ps.py +1633 -0
- PaIRS_UniNa/calib.py +1488 -0
- PaIRS_UniNa/calibView.py +833 -0
- PaIRS_UniNa/gPaIRS.py +3957 -0
- PaIRS_UniNa/gPalette.py +189 -0
- PaIRS_UniNa/icons/abort.png +0 -0
- PaIRS_UniNa/icons/about.png +0 -0
- PaIRS_UniNa/icons/align_all.png +0 -0
- PaIRS_UniNa/icons/announcement.png +0 -0
- PaIRS_UniNa/icons/automatic_levels_off.png +0 -0
- PaIRS_UniNa/icons/automatic_levels_on.png +0 -0
- PaIRS_UniNa/icons/automatic_off.png +0 -0
- PaIRS_UniNa/icons/automatic_on.png +0 -0
- PaIRS_UniNa/icons/automatic_size_off.png +0 -0
- PaIRS_UniNa/icons/automatic_size_on.png +0 -0
- PaIRS_UniNa/icons/axes.png +0 -0
- PaIRS_UniNa/icons/background.png +0 -0
- PaIRS_UniNa/icons/background_vectors.png +0 -0
- PaIRS_UniNa/icons/bin_off.png +0 -0
- PaIRS_UniNa/icons/bin_on.png +0 -0
- PaIRS_UniNa/icons/browse_file_c.png +0 -0
- PaIRS_UniNa/icons/browse_folder_c.png +0 -0
- PaIRS_UniNa/icons/brush_cursor.png +0 -0
- PaIRS_UniNa/icons/bugfix.png +0 -0
- PaIRS_UniNa/icons/cal_proc.png +0 -0
- PaIRS_UniNa/icons/cal_proc_off.png +0 -0
- PaIRS_UniNa/icons/cal_step.png +0 -0
- PaIRS_UniNa/icons/cal_step_off.png +0 -0
- PaIRS_UniNa/icons/calibrate.png +0 -0
- PaIRS_UniNa/icons/calibration_logo.png +0 -0
- PaIRS_UniNa/icons/change_folder.png +0 -0
- PaIRS_UniNa/icons/change_folder_off.png +0 -0
- PaIRS_UniNa/icons/checklist.png +0 -0
- PaIRS_UniNa/icons/clean.png +0 -0
- PaIRS_UniNa/icons/clean_run.png +0 -0
- PaIRS_UniNa/icons/close.png +0 -0
- PaIRS_UniNa/icons/close_all.png +0 -0
- PaIRS_UniNa/icons/close_project.png +0 -0
- PaIRS_UniNa/icons/close_workspace.png +0 -0
- PaIRS_UniNa/icons/colormap.png +0 -0
- PaIRS_UniNa/icons/colormaps/Accent.png +0 -0
- PaIRS_UniNa/icons/colormaps/BrBG.png +0 -0
- PaIRS_UniNa/icons/colormaps/Dark2.png +0 -0
- PaIRS_UniNa/icons/colormaps/PRGn.png +0 -0
- PaIRS_UniNa/icons/colormaps/Paired.png +0 -0
- PaIRS_UniNa/icons/colormaps/Pastel1.png +0 -0
- PaIRS_UniNa/icons/colormaps/Pastel2.png +0 -0
- PaIRS_UniNa/icons/colormaps/PiYG.png +0 -0
- PaIRS_UniNa/icons/colormaps/PuOr.png +0 -0
- PaIRS_UniNa/icons/colormaps/RdBu.png +0 -0
- PaIRS_UniNa/icons/colormaps/RdGy.png +0 -0
- PaIRS_UniNa/icons/colormaps/RdYlBu.png +0 -0
- PaIRS_UniNa/icons/colormaps/RdYlGn.png +0 -0
- PaIRS_UniNa/icons/colormaps/Set1.png +0 -0
- PaIRS_UniNa/icons/colormaps/Set2.png +0 -0
- PaIRS_UniNa/icons/colormaps/Set3.png +0 -0
- PaIRS_UniNa/icons/colormaps/Spectral.png +0 -0
- PaIRS_UniNa/icons/colormaps/Wistia.png +0 -0
- PaIRS_UniNa/icons/colormaps/afmhot.png +0 -0
- PaIRS_UniNa/icons/colormaps/autumn.png +0 -0
- PaIRS_UniNa/icons/colormaps/binary.png +0 -0
- PaIRS_UniNa/icons/colormaps/blackVector.png +0 -0
- PaIRS_UniNa/icons/colormaps/blueVector.png +0 -0
- PaIRS_UniNa/icons/colormaps/bone.png +0 -0
- PaIRS_UniNa/icons/colormaps/brg.png +0 -0
- PaIRS_UniNa/icons/colormaps/bwr.png +0 -0
- PaIRS_UniNa/icons/colormaps/cividis.png +0 -0
- PaIRS_UniNa/icons/colormaps/cool.png +0 -0
- PaIRS_UniNa/icons/colormaps/coolwarm.png +0 -0
- PaIRS_UniNa/icons/colormaps/copper.png +0 -0
- PaIRS_UniNa/icons/colormaps/cubehelix.png +0 -0
- PaIRS_UniNa/icons/colormaps/cyanVector.png +0 -0
- PaIRS_UniNa/icons/colormaps/flag.png +0 -0
- PaIRS_UniNa/icons/colormaps/gist_heat.png +0 -0
- PaIRS_UniNa/icons/colormaps/gray.png +0 -0
- PaIRS_UniNa/icons/colormaps/greenVector.png +0 -0
- PaIRS_UniNa/icons/colormaps/hot.png +0 -0
- PaIRS_UniNa/icons/colormaps/hsv.png +0 -0
- PaIRS_UniNa/icons/colormaps/inferno.png +0 -0
- PaIRS_UniNa/icons/colormaps/jet.png +0 -0
- PaIRS_UniNa/icons/colormaps/magentaVector.png +0 -0
- PaIRS_UniNa/icons/colormaps/magma.png +0 -0
- PaIRS_UniNa/icons/colormaps/ocean.png +0 -0
- PaIRS_UniNa/icons/colormaps/pink.png +0 -0
- PaIRS_UniNa/icons/colormaps/plasma.png +0 -0
- PaIRS_UniNa/icons/colormaps/prism.png +0 -0
- PaIRS_UniNa/icons/colormaps/rainbow.png +0 -0
- PaIRS_UniNa/icons/colormaps/redVector.png +0 -0
- PaIRS_UniNa/icons/colormaps/seismic.png +0 -0
- PaIRS_UniNa/icons/colormaps/spring.png +0 -0
- PaIRS_UniNa/icons/colormaps/summer.png +0 -0
- PaIRS_UniNa/icons/colormaps/tab10.png +0 -0
- PaIRS_UniNa/icons/colormaps/tab20.png +0 -0
- PaIRS_UniNa/icons/colormaps/tab20b.png +0 -0
- PaIRS_UniNa/icons/colormaps/tab20c.png +0 -0
- PaIRS_UniNa/icons/colormaps/terrain.png +0 -0
- PaIRS_UniNa/icons/colormaps/twilight.png +0 -0
- PaIRS_UniNa/icons/colormaps/viridis.png +0 -0
- PaIRS_UniNa/icons/colormaps/whiteVector.png +0 -0
- PaIRS_UniNa/icons/colormaps/winter.png +0 -0
- PaIRS_UniNa/icons/colormaps/yellowVector.png +0 -0
- PaIRS_UniNa/icons/common_region.png +0 -0
- PaIRS_UniNa/icons/common_region_off.png +0 -0
- PaIRS_UniNa/icons/completed.png +0 -0
- PaIRS_UniNa/icons/contourf_off.png +0 -0
- PaIRS_UniNa/icons/contourf_on.png +0 -0
- PaIRS_UniNa/icons/copy.png +0 -0
- PaIRS_UniNa/icons/copy_process.png +0 -0
- PaIRS_UniNa/icons/copy_process_off.png +0 -0
- PaIRS_UniNa/icons/copygrid.png +0 -0
- PaIRS_UniNa/icons/cursor_lamp.png +0 -0
- PaIRS_UniNa/icons/cut.png +0 -0
- PaIRS_UniNa/icons/cut_warnings.png +0 -0
- PaIRS_UniNa/icons/darkmode.png +0 -0
- PaIRS_UniNa/icons/debug_run.png +0 -0
- PaIRS_UniNa/icons/delete.png +0 -0
- PaIRS_UniNa/icons/deleteErr.png +0 -0
- PaIRS_UniNa/icons/disp_step.png +0 -0
- PaIRS_UniNa/icons/disp_step_off.png +0 -0
- PaIRS_UniNa/icons/down.png +0 -0
- PaIRS_UniNa/icons/edit_list.png +0 -0
- PaIRS_UniNa/icons/editing.png +0 -0
- PaIRS_UniNa/icons/example_list.png +0 -0
- PaIRS_UniNa/icons/find_all_planes.png +0 -0
- PaIRS_UniNa/icons/find_plane.png +0 -0
- PaIRS_UniNa/icons/flaticon_PaIRS.png +0 -0
- PaIRS_UniNa/icons/flaticon_PaIRS_beta.png +0 -0
- PaIRS_UniNa/icons/flaticon_PaIRS_download.png +0 -0
- PaIRS_UniNa/icons/flaticon_PaIRS_download_warning.png +0 -0
- PaIRS_UniNa/icons/flip_y_off.png +0 -0
- PaIRS_UniNa/icons/flip_y_on.png +0 -0
- PaIRS_UniNa/icons/focusErrr.png +0 -0
- PaIRS_UniNa/icons/folder_loop_cleanup.png +0 -0
- PaIRS_UniNa/icons/folder_loop_cleanup_off.png +0 -0
- PaIRS_UniNa/icons/gear.gif +0 -0
- PaIRS_UniNa/icons/gear.png +0 -0
- PaIRS_UniNa/icons/ger.png +0 -0
- PaIRS_UniNa/icons/greenv.png +0 -0
- PaIRS_UniNa/icons/guide.png +0 -0
- PaIRS_UniNa/icons/icon_CalVi.png +0 -0
- PaIRS_UniNa/icons/icon_PaIRS.png +0 -0
- PaIRS_UniNa/icons/import.png +0 -0
- PaIRS_UniNa/icons/import_set.png +0 -0
- PaIRS_UniNa/icons/information.png +0 -0
- PaIRS_UniNa/icons/information2.png +0 -0
- PaIRS_UniNa/icons/input_logo.png +0 -0
- PaIRS_UniNa/icons/issue.png +0 -0
- PaIRS_UniNa/icons/laser_NTR.png +0 -0
- PaIRS_UniNa/icons/laser_TR_double.png +0 -0
- PaIRS_UniNa/icons/laser_TR_single.png +0 -0
- PaIRS_UniNa/icons/link.png +0 -0
- PaIRS_UniNa/icons/linked.png +0 -0
- PaIRS_UniNa/icons/loaded.png +0 -0
- PaIRS_UniNa/icons/loading_2.gif +0 -0
- PaIRS_UniNa/icons/log_logo.png +0 -0
- PaIRS_UniNa/icons/logo_CalVi.png +0 -0
- PaIRS_UniNa/icons/logo_CalVi_completo.png +0 -0
- PaIRS_UniNa/icons/logo_CalVi_party.png +0 -0
- PaIRS_UniNa/icons/logo_PaIRS.png +0 -0
- PaIRS_UniNa/icons/logo_PaIRS_completo.png +0 -0
- PaIRS_UniNa/icons/logo_PaIRS_download.png +0 -0
- PaIRS_UniNa/icons/logo_PaIRS_party_rect.png +0 -0
- PaIRS_UniNa/icons/logo_PaIRS_rect.png +0 -0
- PaIRS_UniNa/icons/logo_opaco.png +0 -0
- PaIRS_UniNa/icons/mask.png +0 -0
- PaIRS_UniNa/icons/measure.png +0 -0
- PaIRS_UniNa/icons/measure_off.png +0 -0
- PaIRS_UniNa/icons/min_proc.png +0 -0
- PaIRS_UniNa/icons/min_proc_off.png +0 -0
- PaIRS_UniNa/icons/min_step.png +0 -0
- PaIRS_UniNa/icons/min_step_off.png +0 -0
- PaIRS_UniNa/icons/minus.png +0 -0
- PaIRS_UniNa/icons/mirror_u.png +0 -0
- PaIRS_UniNa/icons/mirror_v.png +0 -0
- PaIRS_UniNa/icons/mirror_x.png +0 -0
- PaIRS_UniNa/icons/mirror_y.png +0 -0
- PaIRS_UniNa/icons/mtplt.png +0 -0
- PaIRS_UniNa/icons/new.png +0 -0
- PaIRS_UniNa/icons/new_workspace.png +0 -0
- PaIRS_UniNa/icons/news.png +0 -0
- PaIRS_UniNa/icons/normal_run.png +0 -0
- PaIRS_UniNa/icons/open.png +0 -0
- PaIRS_UniNa/icons/open_image.png +0 -0
- PaIRS_UniNa/icons/open_new_window.png +0 -0
- PaIRS_UniNa/icons/open_result.png +0 -0
- PaIRS_UniNa/icons/open_workspace.png +0 -0
- PaIRS_UniNa/icons/output_logo.png +0 -0
- PaIRS_UniNa/icons/paste_above.png +0 -0
- PaIRS_UniNa/icons/paste_below.png +0 -0
- PaIRS_UniNa/icons/pause.png +0 -0
- PaIRS_UniNa/icons/paused.png +0 -0
- PaIRS_UniNa/icons/pencil_bw.png +0 -0
- PaIRS_UniNa/icons/piv_proc.png +0 -0
- PaIRS_UniNa/icons/piv_proc_off.png +0 -0
- PaIRS_UniNa/icons/piv_step.png +0 -0
- PaIRS_UniNa/icons/piv_step_off.png +0 -0
- PaIRS_UniNa/icons/plane.png +0 -0
- PaIRS_UniNa/icons/play.png +0 -0
- PaIRS_UniNa/icons/plus.png +0 -0
- PaIRS_UniNa/icons/process_logo.png +0 -0
- PaIRS_UniNa/icons/process_loop.png +0 -0
- PaIRS_UniNa/icons/project.png +0 -0
- PaIRS_UniNa/icons/pylog.png +0 -0
- PaIRS_UniNa/icons/python_warning.png +0 -0
- PaIRS_UniNa/icons/queue.png +0 -0
- PaIRS_UniNa/icons/quit.png +0 -0
- PaIRS_UniNa/icons/read.png +0 -0
- PaIRS_UniNa/icons/read_list.png +0 -0
- PaIRS_UniNa/icons/redo.png +0 -0
- PaIRS_UniNa/icons/redx.png +0 -0
- PaIRS_UniNa/icons/reset.png +0 -0
- PaIRS_UniNa/icons/reset_levels.png +0 -0
- PaIRS_UniNa/icons/resize_icon.png +0 -0
- PaIRS_UniNa/icons/restore.png +0 -0
- PaIRS_UniNa/icons/restore_undo.png +0 -0
- PaIRS_UniNa/icons/rotate_clock.png +0 -0
- PaIRS_UniNa/icons/rotate_counter.png +0 -0
- PaIRS_UniNa/icons/rotate_v_clock.png +0 -0
- PaIRS_UniNa/icons/rotate_v_counter.png +0 -0
- PaIRS_UniNa/icons/running.gif +0 -0
- PaIRS_UniNa/icons/running.png +0 -0
- PaIRS_UniNa/icons/running_warn.png +0 -0
- PaIRS_UniNa/icons/sandglass.png +0 -0
- PaIRS_UniNa/icons/save.png +0 -0
- PaIRS_UniNa/icons/save_and_stop.png +0 -0
- PaIRS_UniNa/icons/save_cfg.png +0 -0
- PaIRS_UniNa/icons/saveas.png +0 -0
- PaIRS_UniNa/icons/saveas_workspace.png +0 -0
- PaIRS_UniNa/icons/scale_all.png +0 -0
- PaIRS_UniNa/icons/scale_down.png +0 -0
- PaIRS_UniNa/icons/scale_up.png +0 -0
- PaIRS_UniNa/icons/scan_list.png +0 -0
- PaIRS_UniNa/icons/scan_path.png +0 -0
- PaIRS_UniNa/icons/scan_path_loop.png +0 -0
- PaIRS_UniNa/icons/scan_path_loop_off.png +0 -0
- PaIRS_UniNa/icons/search.png +0 -0
- PaIRS_UniNa/icons/showIW_off.png +0 -0
- PaIRS_UniNa/icons/showIW_on.png +0 -0
- PaIRS_UniNa/icons/show_all.png +0 -0
- PaIRS_UniNa/icons/sort.png +0 -0
- PaIRS_UniNa/icons/sort_reversed.png +0 -0
- PaIRS_UniNa/icons/spiv_proc.png +0 -0
- PaIRS_UniNa/icons/spiv_proc_off.png +0 -0
- PaIRS_UniNa/icons/spiv_setup_no.png +0 -0
- PaIRS_UniNa/icons/spiv_setup_ok.png +0 -0
- PaIRS_UniNa/icons/star.png +0 -0
- PaIRS_UniNa/icons/step_inheritance.png +0 -0
- PaIRS_UniNa/icons/subMIN_off.png +0 -0
- PaIRS_UniNa/icons/subMIN_on.png +0 -0
- PaIRS_UniNa/icons/tom.png +0 -0
- PaIRS_UniNa/icons/trash.png +0 -0
- PaIRS_UniNa/icons/undo.png +0 -0
- PaIRS_UniNa/icons/unedited.png +0 -0
- PaIRS_UniNa/icons/unina_dii.png +0 -0
- PaIRS_UniNa/icons/uninitialized.png +0 -0
- PaIRS_UniNa/icons/unlink.png +0 -0
- PaIRS_UniNa/icons/unwrap_items.png +0 -0
- PaIRS_UniNa/icons/up.png +0 -0
- PaIRS_UniNa/icons/updating_import.gif +0 -0
- PaIRS_UniNa/icons/updating_pairs.gif +0 -0
- PaIRS_UniNa/icons/vectorColor.png +0 -0
- PaIRS_UniNa/icons/vettore.png +0 -0
- PaIRS_UniNa/icons/view.png +0 -0
- PaIRS_UniNa/icons/view_off.png +0 -0
- PaIRS_UniNa/icons/vis_logo.png +0 -0
- PaIRS_UniNa/icons/waiting_circle.png +0 -0
- PaIRS_UniNa/icons/warning.png +0 -0
- PaIRS_UniNa/icons/warning_circle.png +0 -0
- PaIRS_UniNa/icons/window.png +0 -0
- PaIRS_UniNa/icons/workspace.png +0 -0
- PaIRS_UniNa/icons/wrap_items.png +0 -0
- PaIRS_UniNa/icons/write_list.png +0 -0
- PaIRS_UniNa/listLib.py +303 -0
- PaIRS_UniNa/mtfPIV.py +256 -0
- PaIRS_UniNa/parForMulti.py +435 -0
- PaIRS_UniNa/parForWorkers.py +593 -0
- PaIRS_UniNa/pivParFor.py +235 -0
- PaIRS_UniNa/plt_util.py +141 -0
- PaIRS_UniNa/preProcParFor.py +155 -0
- PaIRS_UniNa/procTools.py +1439 -0
- PaIRS_UniNa/readcfg.py +52 -0
- PaIRS_UniNa/rqrdpckgs.txt +9 -0
- PaIRS_UniNa/stereoPivParFor.py +227 -0
- PaIRS_UniNa/tAVarie.py +215 -0
- PaIRS_UniNa/tabSplitter.py +612 -0
- PaIRS_UniNa/ui_Calibration_Tab.py +578 -0
- PaIRS_UniNa/ui_Custom_Top.py +296 -0
- PaIRS_UniNa/ui_Input_Tab.py +1101 -0
- PaIRS_UniNa/ui_Input_Tab_CalVi.py +1283 -0
- PaIRS_UniNa/ui_Log_Tab.py +263 -0
- PaIRS_UniNa/ui_Output_Tab.py +2362 -0
- PaIRS_UniNa/ui_Process_Tab.py +3810 -0
- PaIRS_UniNa/ui_Process_Tab_CalVi.py +1549 -0
- PaIRS_UniNa/ui_Process_Tab_Disp.py +1141 -0
- PaIRS_UniNa/ui_Process_Tab_Min.py +437 -0
- PaIRS_UniNa/ui_ResizePopup.py +204 -0
- PaIRS_UniNa/ui_Vis_Tab.py +1628 -0
- PaIRS_UniNa/ui_Vis_Tab_CalVi.py +1251 -0
- PaIRS_UniNa/ui_Whatsnew.py +132 -0
- PaIRS_UniNa/ui_gPairs.py +877 -0
- PaIRS_UniNa/ui_infoPaIRS.py +551 -0
- PaIRS_UniNa/whatsnew.txt +4 -0
- pairs_unina-0.2.10.dist-info/METADATA +159 -0
- pairs_unina-0.2.10.dist-info/RECORD +333 -0
- pairs_unina-0.2.10.dist-info/WHEEL +5 -0
- pairs_unina-0.2.10.dist-info/top_level.txt +2 -0
PaIRS_UniNa/TabTools.py
ADDED
|
@@ -0,0 +1,1413 @@
|
|
|
1
|
+
|
|
2
|
+
from .PaIRS_pypacks import *
|
|
3
|
+
from .addwidgets_ps import *
|
|
4
|
+
|
|
5
|
+
Num_Prevs_Max=100
|
|
6
|
+
Num_Prevs_back_forw=10
|
|
7
|
+
|
|
8
|
+
FlagAsyncCallbacks=True
|
|
9
|
+
FlagSimulateError=False
|
|
10
|
+
globExecutor = concurrent.futures.ThreadPoolExecutor(max_workers=10)
|
|
11
|
+
|
|
12
|
+
indParGlob=0
|
|
13
|
+
class TABpar:
|
|
14
|
+
#indParGlob=0
|
|
15
|
+
FlagSettingPar=False
|
|
16
|
+
FlagInit=False
|
|
17
|
+
|
|
18
|
+
def __init__(self,name=str(uuid.uuid4())[:8],surname=str(uuid.uuid4())[:8]):
|
|
19
|
+
self.uiFields=[f for f,_ in self.__dict__.items()]
|
|
20
|
+
|
|
21
|
+
self.name=name
|
|
22
|
+
self.surname=surname
|
|
23
|
+
self.ind=[0,0,0,0,0] #project, tree, item, subitem, do/undo
|
|
24
|
+
self.tip='...'
|
|
25
|
+
self.parentTab=None
|
|
26
|
+
self.FlagNone=False
|
|
27
|
+
self.flagRun=0 #0:not launched yet, 1:completed, -1:interrupted, -2:running
|
|
28
|
+
self.link=[]
|
|
29
|
+
|
|
30
|
+
self.parFields=[f for f,_ in self.__dict__.items() if f not in self.uiFields ]
|
|
31
|
+
self.uncopied_fields=['tip']
|
|
32
|
+
self.unchecked_fields=['name','surname','parentTab']+self.uncopied_fields
|
|
33
|
+
|
|
34
|
+
self.OptionDone=1
|
|
35
|
+
self.warningMessage=''
|
|
36
|
+
|
|
37
|
+
self.fields=[f for f,_ in self.__dict__.items()]
|
|
38
|
+
pass
|
|
39
|
+
|
|
40
|
+
def setNone(self):
|
|
41
|
+
for f in self.fields:
|
|
42
|
+
setattr(self,f,None)
|
|
43
|
+
|
|
44
|
+
def printPar(self,before='',after=''):
|
|
45
|
+
before=after=''
|
|
46
|
+
print(before+str(self.__dict__)+after)
|
|
47
|
+
|
|
48
|
+
def duplicate(self):
|
|
49
|
+
if hasattr(self,'Process') and hasattr(self,'Step'):
|
|
50
|
+
newist=type(self)(Process=self.Process,Step=self.Step)
|
|
51
|
+
else:
|
|
52
|
+
newist=type(self)()
|
|
53
|
+
for f in self.fields:
|
|
54
|
+
if f in self.uncopied_fields: continue
|
|
55
|
+
a=getattr(self,f)
|
|
56
|
+
if hasattr(a,'duplicate'): #type(a)==patternInfoList:
|
|
57
|
+
setattr(newist,f,a.duplicate())
|
|
58
|
+
else:
|
|
59
|
+
setattr(newist,f,copy.deepcopy(a))
|
|
60
|
+
return newist
|
|
61
|
+
|
|
62
|
+
def copyfromdiz(self,diz:dict):
|
|
63
|
+
for f,a in diz.items():
|
|
64
|
+
if hasattr(a,'duplicate'):
|
|
65
|
+
if hasattr(a,'isDifferentFrom') and hasattr(self,f):
|
|
66
|
+
b=getattr(self,f)
|
|
67
|
+
flag=a.isDifferentFrom(b,FlagPrint=False)
|
|
68
|
+
else: flag=True
|
|
69
|
+
if flag: setattr(self,f,a.duplicate())
|
|
70
|
+
else:
|
|
71
|
+
setattr(self,f,copy.deepcopy(a))
|
|
72
|
+
|
|
73
|
+
def copyfrom(self,newist,exceptions=None):
|
|
74
|
+
if newist is None:
|
|
75
|
+
self.FlagNone=True
|
|
76
|
+
else:
|
|
77
|
+
self.copyfromfields(newist,self.fields,exceptions)
|
|
78
|
+
|
|
79
|
+
def copyfromfields(self,newist,fields=None,exceptions=None):
|
|
80
|
+
"""
|
|
81
|
+
exceptions=[] --> no exceptions
|
|
82
|
+
"""
|
|
83
|
+
newist:TABpar
|
|
84
|
+
if exceptions is None:
|
|
85
|
+
exceptions=self.uncopied_fields
|
|
86
|
+
for f in fields:
|
|
87
|
+
if f in exceptions: continue
|
|
88
|
+
if not hasattr(self,f):
|
|
89
|
+
pri.Error.red(f'copyfromdiz: field <{f}> is missing in {self.name} par structure!')
|
|
90
|
+
continue
|
|
91
|
+
if not hasattr(newist,f):
|
|
92
|
+
pri.Error.red(f'copyfromdiz: field <{f}> is missing in {newist.name} par structure!')
|
|
93
|
+
continue
|
|
94
|
+
a=getattr(newist,f)
|
|
95
|
+
if hasattr(a,'duplicate'): #type(a)==patternInfoList:
|
|
96
|
+
if hasattr(a,'isDifferentFrom') and hasattr(self,f):
|
|
97
|
+
b=getattr(self,f)
|
|
98
|
+
flag=a.isDifferentFrom(b,FlagPrint=False)
|
|
99
|
+
else: flag=True
|
|
100
|
+
if flag: setattr(self,f,a.duplicate())
|
|
101
|
+
else:
|
|
102
|
+
setattr(self,f,copy.deepcopy(a))
|
|
103
|
+
|
|
104
|
+
def isDifferentFrom(self,v,exceptions:list=[],fields:list=[],FlagStrictDiff=False,FlagPrint=True):
|
|
105
|
+
if not FlagStrictDiff:
|
|
106
|
+
exceptions+=self.unchecked_fields
|
|
107
|
+
exceptions=list(set(exceptions))
|
|
108
|
+
if not fields:
|
|
109
|
+
fields=self.fields
|
|
110
|
+
else:
|
|
111
|
+
[exceptions.remove(f) for f in fields if f in exceptions]
|
|
112
|
+
|
|
113
|
+
Flag=False
|
|
114
|
+
for f in fields:
|
|
115
|
+
if f in exceptions: continue
|
|
116
|
+
else:
|
|
117
|
+
if not hasattr(self,f):
|
|
118
|
+
pri.Error.red(f'isDifferentFrom: field <{f}> is missing in {self.name} par structure!')
|
|
119
|
+
continue
|
|
120
|
+
if not hasattr(v,f):
|
|
121
|
+
pri.Error.red(f'isDifferentFrom: field <{f}> is missing in {v.name} par structure!')
|
|
122
|
+
continue
|
|
123
|
+
a=getattr(self,f)
|
|
124
|
+
b=getattr(v,f)
|
|
125
|
+
if f=='Vect':
|
|
126
|
+
Flag=not all([np.array_equal(a[i],b[i]) for i in range(4)])
|
|
127
|
+
if Flag:
|
|
128
|
+
break
|
|
129
|
+
else:
|
|
130
|
+
if hasattr(a,'isDifferentFrom'): #in ('Pinfo','pinfo'):
|
|
131
|
+
Flag=a.isDifferentFrom(b,exceptions,FlagStrictDiff=FlagStrictDiff)
|
|
132
|
+
if Flag: break
|
|
133
|
+
else:
|
|
134
|
+
if a!=b:
|
|
135
|
+
Flag=True
|
|
136
|
+
break
|
|
137
|
+
if FlagPrint:
|
|
138
|
+
if Flag:
|
|
139
|
+
pri.TABparDiff.red(f'{self.name} is different in {f}:\t {b} --> {a}')
|
|
140
|
+
else:
|
|
141
|
+
pri.TABparDiff.green(f'{self.name} is unchanged')
|
|
142
|
+
return Flag
|
|
143
|
+
|
|
144
|
+
def isEqualTo(self,v,exceptions=[],fields=[],FlagStrictDiff=False,FlagPrint=False):
|
|
145
|
+
Flag=bool(not self.isDifferentFrom(v,exceptions,fields,FlagStrictDiff,FlagPrint))
|
|
146
|
+
return Flag
|
|
147
|
+
|
|
148
|
+
def printDifferences(self,v,exceptions=[],fields=[],FlagStrictDiff=False):
|
|
149
|
+
if FlagStrictDiff: exceptions+=self.unchecked_fields
|
|
150
|
+
if not fields:
|
|
151
|
+
fields=self.fields
|
|
152
|
+
else:
|
|
153
|
+
[exceptions.remove(f) for f in fields if f in exceptions]
|
|
154
|
+
printing=''
|
|
155
|
+
df=[]
|
|
156
|
+
for f in fields:
|
|
157
|
+
if f in exceptions: continue
|
|
158
|
+
if not hasattr(self,f):
|
|
159
|
+
pri.Error.red(f'printDifferences: field <{f}> is missing in {self.name} par structure!')
|
|
160
|
+
continue
|
|
161
|
+
if not hasattr(v,f):
|
|
162
|
+
pri.Error.red(f'printDifferences: field <{f}> is missing in {v.name} par structure!')
|
|
163
|
+
continue
|
|
164
|
+
a=getattr(self,f)
|
|
165
|
+
b=getattr(v,f)
|
|
166
|
+
Flag=False
|
|
167
|
+
if f=='Vect':
|
|
168
|
+
Flag=not all([np.array_equal(a[i],b[i]) for i in range(4)])
|
|
169
|
+
else:
|
|
170
|
+
if hasattr(a,'isDifferentFrom'): #in ('Pinfo','pinfo'):
|
|
171
|
+
if hasattr(a,'fields'):
|
|
172
|
+
Flag=a.isDifferentFrom(b,[],a.fields,FlagStrictDiff,FlagPrint=False)
|
|
173
|
+
if Flag:
|
|
174
|
+
a.printDifferences(b,[],a.fields,FlagStrictDiff)
|
|
175
|
+
else:
|
|
176
|
+
Flag=a.isDifferentFrom(b,[],FlagPrint=False)
|
|
177
|
+
else:
|
|
178
|
+
if a!=b: Flag=True
|
|
179
|
+
if Flag:
|
|
180
|
+
df.append(f)
|
|
181
|
+
if not printing: printing=f'{self.name} differences in:'
|
|
182
|
+
printing=printing+f'\n*\t{f}:\t {str(a)[:100]} --> {str(b)[:100]}'
|
|
183
|
+
if not printing: printing=f'{self.name} no differences!'
|
|
184
|
+
pri.Info.magenta(printing)
|
|
185
|
+
return df
|
|
186
|
+
|
|
187
|
+
def hasIndexOf(self,d):
|
|
188
|
+
""" check if the indexes are the same """
|
|
189
|
+
return self.ind==d.ind
|
|
190
|
+
|
|
191
|
+
class gPaIRS_Tab(QWidget):
|
|
192
|
+
indGlob=(0,0,0,0)
|
|
193
|
+
FlagGlob=False
|
|
194
|
+
|
|
195
|
+
class Tab_Signals(QObject):
|
|
196
|
+
callback2_end=Signal(str,bool,bool)
|
|
197
|
+
|
|
198
|
+
def __init__(self, parent):
|
|
199
|
+
super().__init__(parent)
|
|
200
|
+
self.callback2_end.connect(parent.callback2_end)
|
|
201
|
+
|
|
202
|
+
def __init__(self,parent=None,UiClass=None,ParClass=TABpar):
|
|
203
|
+
super().__init__()
|
|
204
|
+
from .gPaIRS import gPaIRS
|
|
205
|
+
if parent is None:
|
|
206
|
+
self.gui=self.window()
|
|
207
|
+
else:
|
|
208
|
+
if hasattr(parent,'gui'):
|
|
209
|
+
self.gui:gPaIRS=parent.gui
|
|
210
|
+
else:
|
|
211
|
+
self.gui:gPaIRS=parent.window()
|
|
212
|
+
|
|
213
|
+
self.TABname='Tab'
|
|
214
|
+
self.signals=self.Tab_Signals(self)
|
|
215
|
+
self.father=parent
|
|
216
|
+
|
|
217
|
+
self.ParClass=ParClass
|
|
218
|
+
self.TABpar=self.ParClass() #current configuration
|
|
219
|
+
self.TABpar_old=self.ParClass() #last configuration in the current tab
|
|
220
|
+
self.TABpar_prev=[]
|
|
221
|
+
self.gen_TABpar(self.TABpar.ind,FlagEmptyPrev=True) #queue of previous configurations, alias undos/redos (indTree,indItem,ind)
|
|
222
|
+
self.Num_Prevs_Max=Num_Prevs_Max
|
|
223
|
+
|
|
224
|
+
self.FlagAddPrev=True #if False, no further par are added to the queue of undos/redos "prev"
|
|
225
|
+
self.FlagBridge=True #if False, no bridge is executed during setting of parameters
|
|
226
|
+
self.FlagPrevPropagation=False
|
|
227
|
+
|
|
228
|
+
#self.setTABpar_prev=lambda itree,iitem,i,flagBridge: None
|
|
229
|
+
self.TABsettings=[]
|
|
230
|
+
|
|
231
|
+
self.FlagSettingPar=False
|
|
232
|
+
self.FlagAsyncCallEvaluation=False
|
|
233
|
+
self.disableTab=lambda flag: None
|
|
234
|
+
|
|
235
|
+
self.adjustTABpar=lambda: None
|
|
236
|
+
self.setTABlayout=lambda: None
|
|
237
|
+
self.checkTABpar=lambda ind: None
|
|
238
|
+
self.setTABwarn=lambda ind: None
|
|
239
|
+
self.setTABpar_bridge=lambda fLagAdjustPar, flagCallback: None
|
|
240
|
+
self.add_TABpar_bridge=lambda tip, ind: None
|
|
241
|
+
|
|
242
|
+
self.buttonTab=None
|
|
243
|
+
|
|
244
|
+
#Controls
|
|
245
|
+
if UiClass!=None:
|
|
246
|
+
self.ui=UiClass()
|
|
247
|
+
if not hasattr(self,'ui'):
|
|
248
|
+
self.ui=self
|
|
249
|
+
if hasattr(self.ui,'setupUi'):
|
|
250
|
+
self.ui.setupUi(self)
|
|
251
|
+
if hasattr(self.ui,'name_tab'):
|
|
252
|
+
self.name_tab=self.ui.name_tab.text().replace(' ','')
|
|
253
|
+
else:
|
|
254
|
+
self.name_tab=''
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
#------------------------------------- Graphical interface: miscellanea
|
|
258
|
+
self.pixmap_warnc = QPixmap(u""+ icons_path +"warning_circle.png")
|
|
259
|
+
self.pixmap_done = QPixmap(u""+ icons_path +"completed.png")
|
|
260
|
+
|
|
261
|
+
self.undo_icon=QIcon()
|
|
262
|
+
self.undo_icon.addFile(u""+ icons_path +"undo.png", QSize(), QIcon.Normal, QIcon.Off)
|
|
263
|
+
self.redo_icon=QIcon()
|
|
264
|
+
self.redo_icon.addFile(u""+ icons_path +"redo.png", QSize(), QIcon.Normal, QIcon.Off)
|
|
265
|
+
if not hasattr(self.ui,'button_back'):
|
|
266
|
+
setattr(self.ui,'button_back',QPushButton(self))
|
|
267
|
+
else:
|
|
268
|
+
self.ui.button_back.contextMenuEvent=lambda e: self.bfContextMenu(-1,e)
|
|
269
|
+
if not hasattr(self.ui,'button_forward'):
|
|
270
|
+
setattr(self.ui,'button_forward',QPushButton(self))
|
|
271
|
+
else:
|
|
272
|
+
self.ui.button_forward.contextMenuEvent=lambda e: self.bfContextMenu(+1,e)
|
|
273
|
+
if not hasattr(self.ui,'button_restore_undo'):
|
|
274
|
+
setattr(self.ui,'button_restore_undo',QPushButton(self))
|
|
275
|
+
if not hasattr(self.ui,'label_number'):
|
|
276
|
+
setattr(self.ui,'label_number',QLabel(self))
|
|
277
|
+
if hasattr(self.ui,'button_close_tab'):
|
|
278
|
+
b:QPushButton=self.ui.button_close_tab
|
|
279
|
+
b.setCursor(Qt.CursorShape.PointingHandCursor)
|
|
280
|
+
self.onlyReadLabel:QLabel=None
|
|
281
|
+
self.button_reset_step:QPushButton=None
|
|
282
|
+
self.button_step_inherit:QPushButton=None
|
|
283
|
+
self.button_copy_step:QPushButton=None
|
|
284
|
+
self.button_link_step:QPushButton=None
|
|
285
|
+
|
|
286
|
+
self.FlagDisplayControls=True #if False, undo and redo buttons are hidden and so not usable
|
|
287
|
+
self.ui.button_forward.hide()
|
|
288
|
+
self.ui.button_back.hide()
|
|
289
|
+
self.ui.button_restore_undo.hide()
|
|
290
|
+
self.ui.button_back.clicked.connect(self.button_back_action)
|
|
291
|
+
self.ui.button_forward.clicked.connect(self.button_forward_action)
|
|
292
|
+
self.ui.label_number.setText('')
|
|
293
|
+
self.ui.label_number.hide()
|
|
294
|
+
|
|
295
|
+
if hasattr(self.ui,'spin_x'):
|
|
296
|
+
self.ui.spin_x.valueChanged.connect(self.spin_x_changing)
|
|
297
|
+
if hasattr(self.ui,'spin_y'):
|
|
298
|
+
self.ui.spin_y.valueChanged.connect(self.spin_y_changing)
|
|
299
|
+
|
|
300
|
+
self.spins_valueChanged=[]
|
|
301
|
+
|
|
302
|
+
self.nullCallback=lambda f='Null Callback': self.wrappedCallback(f,lambda: True)()
|
|
303
|
+
self.fullCallback=lambda f='Full Callback': self.wrappedCallback(f,lambda: None)()
|
|
304
|
+
|
|
305
|
+
#*************************************************** Widgets
|
|
306
|
+
def defineWidgets(self):
|
|
307
|
+
def wDict(types,signals):
|
|
308
|
+
l=[]
|
|
309
|
+
for t in types:
|
|
310
|
+
for c in self.findChildren(t): l.append(c) if c not in l else None
|
|
311
|
+
d={'widgets': l, 'signals': signals}
|
|
312
|
+
return d
|
|
313
|
+
|
|
314
|
+
widgets={
|
|
315
|
+
'spin': wDict([MyQSpin,MyQDoubleSpin],['addfuncout','addfuncreturn']),
|
|
316
|
+
'check': wDict([QCheckBox],['toggled']),
|
|
317
|
+
'radio': wDict([QRadioButton],['toggled']),
|
|
318
|
+
'line_edit': wDict([QLineEdit,MyQLineEdit,MyQLineEditNumber],['addfuncout','returnPressed']),
|
|
319
|
+
'button' : wDict([QPushButton,QToolButton,MyToolButton],['clicked']),
|
|
320
|
+
'combo' : wDict([QComboBox],['activated']),
|
|
321
|
+
}
|
|
322
|
+
self.widgetTypes=list(widgets)
|
|
323
|
+
self.widgets=[]
|
|
324
|
+
self.widgetSignals=[]
|
|
325
|
+
for w in self.widgetTypes:
|
|
326
|
+
self.widgets.append(widgets[w]['widgets'])
|
|
327
|
+
self.widgetSignals.append(widgets[w]['signals'])
|
|
328
|
+
self.widgetsOfType=lambda t: self.widgets[self.widgetTypes.index(t)]
|
|
329
|
+
|
|
330
|
+
for c in self.widgetsOfType('combo'):
|
|
331
|
+
c:QComboBox
|
|
332
|
+
nameCombo=c.objectName().split('combo_')[-1]
|
|
333
|
+
if hasattr(self,nameCombo+'_items'):
|
|
334
|
+
itemsCombo=getattr(self,nameCombo+'_items')
|
|
335
|
+
else: continue
|
|
336
|
+
if hasattr(self,nameCombo+'_order'):
|
|
337
|
+
orderCombo=getattr(self,nameCombo+'_order')
|
|
338
|
+
else: orderCombo=[i for i in range(len(itemsCombo))]
|
|
339
|
+
c.clear()
|
|
340
|
+
for i in orderCombo:
|
|
341
|
+
c.addItem(itemsCombo[i])
|
|
342
|
+
|
|
343
|
+
#*************************************************** Widget callbacks
|
|
344
|
+
def defaultCallback(self,wName,wtype):
|
|
345
|
+
widget=getattr(self.ui,wtype+'_'+wName)
|
|
346
|
+
if wName=='x_min':
|
|
347
|
+
pass
|
|
348
|
+
if wtype=='spin':
|
|
349
|
+
def callbackSpin(s:MyQSpin):
|
|
350
|
+
setattr(self.TABpar,wName,s.value())
|
|
351
|
+
default_callback=lambda: callbackSpin(widget)
|
|
352
|
+
elif (wtype=='check' or wtype=='radio') and hasattr(self.TABpar,'Flag'+wName):
|
|
353
|
+
def callbackCheck(c:QCheckBox):
|
|
354
|
+
setattr(self.TABpar,'Flag'+wName,c.isChecked())
|
|
355
|
+
default_callback=lambda: callbackCheck(widget)
|
|
356
|
+
elif wtype=='combo':
|
|
357
|
+
def callbackCombo(c:QComboBox):
|
|
358
|
+
if hasattr(self,wName+'_items'):
|
|
359
|
+
itemsCombo:list=getattr(self,wName+'_items')
|
|
360
|
+
else:
|
|
361
|
+
itemsCombo=[c.itemText(i) for i in range(c.count())]
|
|
362
|
+
if len(itemsCombo):
|
|
363
|
+
setattr(self.TABpar,wName,itemsCombo.index(c.currentText()))
|
|
364
|
+
else:
|
|
365
|
+
setattr(self.TABpar,wName,-1)
|
|
366
|
+
default_callback=lambda: callbackCombo(widget)
|
|
367
|
+
elif wtype=='line_edit':
|
|
368
|
+
def callbackLineEdit(l:MyQLineEdit):
|
|
369
|
+
setattr(self.TABpar,wName,l.text())
|
|
370
|
+
default_callback=lambda: callbackLineEdit(widget)
|
|
371
|
+
else:
|
|
372
|
+
default_callback=None
|
|
373
|
+
return default_callback
|
|
374
|
+
|
|
375
|
+
def defineCallbacks(self):
|
|
376
|
+
def buildCallback(wName,wtype,tip):
|
|
377
|
+
if not hasattr(self.ui,wtype+'_'+wName): return
|
|
378
|
+
callback01=callback02=callback03=callback1=callback2=None
|
|
379
|
+
|
|
380
|
+
#callback01: _preaction method in the class: particular callback that is fast and can be executed on the main thread instead of as concurrent future before the default callback
|
|
381
|
+
a=wtype+'_'+wName+'_preaction'
|
|
382
|
+
if hasattr(self,a): callback01=getattr(self,a)
|
|
383
|
+
|
|
384
|
+
#callback02: callback common to all widgets of the same type (avoid code repetition)
|
|
385
|
+
if hasattr(self.TABpar,wName) or ((wtype=='check' or wtype=='radio') and hasattr(self.TABpar,'Flag'+wName)):
|
|
386
|
+
callback02=self.defaultCallback(wName,wtype)
|
|
387
|
+
|
|
388
|
+
#callback03: _action method in the class: particular callback that is fast and can be executed on the main thread instead of as concurrent future after the default callback
|
|
389
|
+
a=wtype+'_'+wName+'_action'
|
|
390
|
+
if hasattr(self,a): callback03=getattr(self,a)
|
|
391
|
+
|
|
392
|
+
if callback01 or callback02 or callback03:
|
|
393
|
+
def callback1():
|
|
394
|
+
name=wName
|
|
395
|
+
flag=None
|
|
396
|
+
if callback01: callback01()
|
|
397
|
+
if callback02: callback02()
|
|
398
|
+
if callback03: flag=callback03()
|
|
399
|
+
return flag
|
|
400
|
+
else: callback1=None
|
|
401
|
+
|
|
402
|
+
#callback1: _action_future method in the class: particular callback that is fast and can be executed on the main thread instead of as concurrent future
|
|
403
|
+
a=wtype+'_'+wName+'_action_future'
|
|
404
|
+
if hasattr(self,a):
|
|
405
|
+
callback2=getattr(self,a)
|
|
406
|
+
|
|
407
|
+
if callback1 or callback2:
|
|
408
|
+
callback=self.wrappedCallback(tip,callback1,callback2)
|
|
409
|
+
setattr(self,wtype+'_'+wName+'_callback',callback)
|
|
410
|
+
else:
|
|
411
|
+
callback=None
|
|
412
|
+
return callback
|
|
413
|
+
|
|
414
|
+
self.widgetCallbacks=[]
|
|
415
|
+
for l,wtype in zip(self.widgets,self.widgetTypes):
|
|
416
|
+
missing_tips=[]
|
|
417
|
+
if hasattr(self,wtype+'_tips'):
|
|
418
|
+
d=getattr(self,wtype+'_tips')
|
|
419
|
+
else:
|
|
420
|
+
d=None
|
|
421
|
+
pri.Coding.red(f'*** [{self.TABname}] - {wtype}_tips - missing dictionary!')
|
|
422
|
+
widgetCallbacks=[]
|
|
423
|
+
for c in l:
|
|
424
|
+
c:QObject
|
|
425
|
+
if c.objectName() in ('button_back','button_forward','button_close_tab'):
|
|
426
|
+
callback=None
|
|
427
|
+
widgetCallbacks.append(callback)
|
|
428
|
+
continue
|
|
429
|
+
if '_' in c.objectName(): wName=c.objectName().split(wtype+'_')[-1]
|
|
430
|
+
else: wName=c.objectName()
|
|
431
|
+
if d!=None:
|
|
432
|
+
if wName in list(d): tip=d[wName]
|
|
433
|
+
else:
|
|
434
|
+
tip=f"{wtype} {wName}"
|
|
435
|
+
if wName and not (wtype=='line_edit' and wName in ('qt_spinbox_lineedit') ) and \
|
|
436
|
+
not (wtype=='button' and wName in ('back','forward','close_tab') ):
|
|
437
|
+
missing_tips.append(f"'{wName}'")
|
|
438
|
+
else: tip=f"{wtype} {wName}"
|
|
439
|
+
callback=buildCallback(wName,wtype,tip)
|
|
440
|
+
widgetCallbacks.append(callback)
|
|
441
|
+
if len(missing_tips):
|
|
442
|
+
pri.Coding.blue(f'*** [{self.TABname}] - {wtype}_tips - missing tips:\n\t'+"\n\t".join(missing_tips))
|
|
443
|
+
elif d:
|
|
444
|
+
pri.Coding.green(f'✔️ [{self.TABname}] - {wtype}_tips - complete dictionary!')
|
|
445
|
+
self.widgetCallbacks.append(widgetCallbacks)
|
|
446
|
+
|
|
447
|
+
def wrappedCallback(self,tip='',callback1=None,callback2=None):
|
|
448
|
+
def debugFun(fun,message=''):
|
|
449
|
+
try:
|
|
450
|
+
out=fun()
|
|
451
|
+
except Exception as inst:
|
|
452
|
+
out=None
|
|
453
|
+
pri.Error.red(f"{'!'*100}\n{message}:\n{traceback.format_exc()}\n{'!'*100}")
|
|
454
|
+
printException()
|
|
455
|
+
#if Flag_DEBUG: raise Exception("!!! Debug stop !!!")
|
|
456
|
+
return out
|
|
457
|
+
async def callback2_async(fun2):
|
|
458
|
+
if Flag_DEBUG: timesleep(time_callback2_async)
|
|
459
|
+
if fun2: debugFun(fun2,f'Asyncronus function error callback2 ({tip}): ')
|
|
460
|
+
return
|
|
461
|
+
def callback():
|
|
462
|
+
FlagSettingPar=self.FlagSettingPar or TABpar.FlagSettingPar
|
|
463
|
+
if FlagSettingPar:
|
|
464
|
+
return
|
|
465
|
+
else:
|
|
466
|
+
self.FlagSettingPar=True
|
|
467
|
+
try:
|
|
468
|
+
FlagPreventAddPrev=False
|
|
469
|
+
if callback1: FlagPreventAddPrev=debugFun(callback1,f'Error callback1 ({tip}): ')
|
|
470
|
+
if callback2:
|
|
471
|
+
self.FlagAsyncCallEvaluation=True
|
|
472
|
+
self.disableTab(True)
|
|
473
|
+
|
|
474
|
+
if FlagAsyncCallbacks:
|
|
475
|
+
f3=globExecutor.submit(asyncio.run,callback2_async(callback2))
|
|
476
|
+
def f3callback(_f3):
|
|
477
|
+
self.signals.callback2_end.emit(tip,FlagSettingPar,FlagPreventAddPrev)
|
|
478
|
+
f3.add_done_callback(f3callback)
|
|
479
|
+
else:
|
|
480
|
+
debugFun(callback2,f'Error callback2 ({tip}): ')
|
|
481
|
+
self.callback2_end(tip,FlagSettingPar,FlagPreventAddPrev)
|
|
482
|
+
else:
|
|
483
|
+
self.callback2_end(tip,FlagSettingPar,FlagPreventAddPrev)
|
|
484
|
+
except Exception as inst:
|
|
485
|
+
pri.Error.red(f"Error in wrapped callback ({tip}):\n{traceback.format_exc()}")
|
|
486
|
+
printException()
|
|
487
|
+
self.FlagSettingPar=FlagSettingPar
|
|
488
|
+
return
|
|
489
|
+
return callback
|
|
490
|
+
|
|
491
|
+
@Slot(str)
|
|
492
|
+
def callback2_end(self,tip,FlagSettingPar,FlagPreventAddPrev):
|
|
493
|
+
pri.Coding.green(f'{"*"*50}\nCallback <{self.TABname}>: {tip}')
|
|
494
|
+
if tip=='Null Callback':
|
|
495
|
+
pass
|
|
496
|
+
try:
|
|
497
|
+
if self.FlagAsyncCallEvaluation==True:
|
|
498
|
+
self.FlagAsyncCallEvaluation=False
|
|
499
|
+
self.disableTab(False)
|
|
500
|
+
try:
|
|
501
|
+
TABpar_ind=self.TABpar_at(self.TABpar.ind)
|
|
502
|
+
if TABpar_ind and self.TABpar.isEqualTo(TABpar_ind,FlagStrictDiff=True): return
|
|
503
|
+
FlagNewPar=self.isNewPar()
|
|
504
|
+
flagRun=self.TABpar_at(self.TABpar.ind).flagRun
|
|
505
|
+
if FlagNewPar and (flagRun!=0 or len(self.TABpar.link)>0):
|
|
506
|
+
#FlagNewPar=not self.FlagAddPrev
|
|
507
|
+
if len(self.TABpar.link)>0:
|
|
508
|
+
ITE0_master=self.gui.ui.Explorer.ITEsfromInd(self.TABpar.link)[0]
|
|
509
|
+
linkInfo=f'{ITE0_master.ind[2]+1}: {ITE0_master.name}'
|
|
510
|
+
Messagge=f'This process step is linked to process {linkInfo}. To modify it, you need to unlink the process step.'
|
|
511
|
+
if flagRun!=0 or ITE0_master.flagRun!=0:
|
|
512
|
+
Messagge+=' After unlinking the process will be reset!'
|
|
513
|
+
def unlink_pars_online():
|
|
514
|
+
TABpar_ind.copyfrom(self.TABpar)
|
|
515
|
+
self.gui.unlink_pars(self.TABpar.ind)
|
|
516
|
+
if self.TABpar.flagRun!=0 or ITE0_master.flagRun!=0:
|
|
517
|
+
self.gui.reset_step(self.TABpar.ind)
|
|
518
|
+
warningDialog(self.gui,Messagge,addButton={'Unlink step!': unlink_pars_online})
|
|
519
|
+
elif flagRun==-10:
|
|
520
|
+
Messagge='This process step is in the queue for process execution. To modify it, you need to stop processing and then reset it and all the subsequent steps.'
|
|
521
|
+
warningDialog(self.gui,Messagge)
|
|
522
|
+
elif flagRun==-2:
|
|
523
|
+
Messagge='This process step is currently in execution. To modify it, you need to stop processing and then reset it and all the subsequent steps.'
|
|
524
|
+
warningDialog(self.gui,Messagge)
|
|
525
|
+
elif flagRun!=0:
|
|
526
|
+
if self.gui.FlagRun:
|
|
527
|
+
Messagge='This process step has already been executed. To modify it, you need to stop processing and then reset it and all the subsequent steps.'
|
|
528
|
+
warningDialog(self.gui,Messagge)
|
|
529
|
+
else:
|
|
530
|
+
Messagge='This process step has already been executed. To modify it, you need to reset the current step and all the subsequent ones.'
|
|
531
|
+
def reset_step_online():
|
|
532
|
+
TABpar_ind.copyfrom(self.TABpar)
|
|
533
|
+
self.gui.reset_step(self.TABpar.ind)
|
|
534
|
+
return
|
|
535
|
+
warningDialog(self.gui,Messagge,addButton={'Reset step!': reset_step_online})
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
if flagRun!=0 or len(self.TABpar.link)>0:
|
|
539
|
+
self.TABpar.copyfrom(TABpar_ind)
|
|
540
|
+
originalStyleSheet=self.gui.styleSheet()
|
|
541
|
+
self.gui.setStyleSheet(f'background: {self.palette().color(QPalette.ColorRole.Text).name()} ;') #dcdcdc
|
|
542
|
+
self.repaint()
|
|
543
|
+
try:
|
|
544
|
+
self.setTABpar(FlagAdjustPar=False,FlagBridge=False,FlagCallback=False)
|
|
545
|
+
finally:
|
|
546
|
+
timesleep(.01)
|
|
547
|
+
self.gui.setStyleSheet(originalStyleSheet)
|
|
548
|
+
else:
|
|
549
|
+
return
|
|
550
|
+
else:
|
|
551
|
+
self.setTABpar(FlagAdjustPar=True,FlagBridge=self.FlagBridge,FlagCallback=True)
|
|
552
|
+
except:
|
|
553
|
+
pri.Error.red(f'Error in callback2_end ({tip}):\n |-> Error in setting the parameters')
|
|
554
|
+
pri.Error.red(f'{traceback.format_exc()}')
|
|
555
|
+
printException()
|
|
556
|
+
else:
|
|
557
|
+
try:
|
|
558
|
+
FlagNewPar=FlagNewPar and not FlagPreventAddPrev and self.TABpar.flagRun==0 and len(self.TABpar.link)==0
|
|
559
|
+
self.add_TABpar(tip,FlagNewPar)
|
|
560
|
+
except:
|
|
561
|
+
pri.Error.red(f'Error in callback2_end ({tip}):\n |-> Error in adding parameters to redos/undos {tip}')
|
|
562
|
+
printException()
|
|
563
|
+
except Exception as inst:
|
|
564
|
+
pri.Error.red(f"Error in callback2_end ({tip}):\n{traceback.format_exc()}")
|
|
565
|
+
printException()
|
|
566
|
+
finally:
|
|
567
|
+
self.FlagSettingPar=FlagSettingPar
|
|
568
|
+
pri.Coding.green(f'Callback <{self.TABname}>: {tip}\n{"*"*50}\n')
|
|
569
|
+
|
|
570
|
+
def connectCallbacks(self):
|
|
571
|
+
for W,S,CB in zip(self.widgets,self.widgetSignals,self.widgetCallbacks):
|
|
572
|
+
for w,cb in zip(W,CB):
|
|
573
|
+
if cb==None: continue
|
|
574
|
+
for s in S:
|
|
575
|
+
sig=getattr(w,s)
|
|
576
|
+
if hasattr(sig,'connect'):
|
|
577
|
+
sig.connect(cb)
|
|
578
|
+
elif s in ('addfuncout','addfuncreturn'):
|
|
579
|
+
if w in self.spins_valueChanged:
|
|
580
|
+
if s=='addfuncout': w.valueChanged.connect(cb)
|
|
581
|
+
else:
|
|
582
|
+
sig['callback']=cb
|
|
583
|
+
|
|
584
|
+
#*************************************************** Setting parameters to widgets
|
|
585
|
+
def defaultSetting(self,wName,wtype):
|
|
586
|
+
if not hasattr(self.ui,wtype+'_'+wName): return
|
|
587
|
+
widget=getattr(self.ui,wtype+'_'+wName)
|
|
588
|
+
if wtype=='spin':
|
|
589
|
+
def settingSpinValue(s:MyQSpin):
|
|
590
|
+
s.setValue(getattr(self.TABpar,wName))
|
|
591
|
+
default_setting=lambda: settingSpinValue(widget)
|
|
592
|
+
elif (wtype=='check' or wtype=='radio') and hasattr(self.TABpar,'Flag'+wName):
|
|
593
|
+
def settingChecked(c:QCheckBox):
|
|
594
|
+
try:
|
|
595
|
+
c.setChecked(getattr(self.TABpar,'Flag'+wName))
|
|
596
|
+
except:
|
|
597
|
+
pass
|
|
598
|
+
default_setting=lambda: settingChecked(widget)
|
|
599
|
+
elif wtype=='combo':
|
|
600
|
+
widget:QComboBox
|
|
601
|
+
def settingComboIndex(c:QComboBox):
|
|
602
|
+
items=[c.itemText(i) for i in range(c.count())]
|
|
603
|
+
if hasattr(self,wName+'_items'):
|
|
604
|
+
itemsCombo:list=getattr(self,wName+'_items')
|
|
605
|
+
else:
|
|
606
|
+
itemsCombo=items
|
|
607
|
+
ind=getattr(self.TABpar,wName)
|
|
608
|
+
if ind>-1: c.setCurrentIndex(items.index(itemsCombo[ind]))
|
|
609
|
+
default_setting=lambda: settingComboIndex(widget)
|
|
610
|
+
elif wtype=='line_edit':
|
|
611
|
+
def settingText(l:MyQLineEdit):
|
|
612
|
+
l.setText(getattr(self.TABpar,wName))
|
|
613
|
+
default_setting=lambda: settingText(widget)
|
|
614
|
+
else:
|
|
615
|
+
default_setting=None
|
|
616
|
+
return default_setting
|
|
617
|
+
|
|
618
|
+
def defineSettings(self):
|
|
619
|
+
def buildSetting(wName,wtype):
|
|
620
|
+
setting0=default_setting=setting2=None
|
|
621
|
+
#setting0: _preset method in the class: setting to be done before standard setting (0)
|
|
622
|
+
a=wtype+'_'+wName+'_preset'
|
|
623
|
+
if hasattr(self,a): setting0=getattr(self,a)
|
|
624
|
+
|
|
625
|
+
#setting1: setting common to all widgets of the same type (avoid code repetition)
|
|
626
|
+
if hasattr(self.TABpar,wName) or ((wtype=='check' or wtype=='radio') and hasattr(self.TABpar,'Flag'+wName)):
|
|
627
|
+
default_setting=self.defaultSetting(wName,wtype)
|
|
628
|
+
|
|
629
|
+
#callback2: _set method in the class: setting to be done before standard setting (1)
|
|
630
|
+
a=wtype+'_'+wName+'_set'
|
|
631
|
+
if hasattr(self,a): setting2=getattr(self,a)
|
|
632
|
+
|
|
633
|
+
def setting():
|
|
634
|
+
name=wName
|
|
635
|
+
if setting0: setting0()
|
|
636
|
+
if default_setting: default_setting()
|
|
637
|
+
if setting2: setting2()
|
|
638
|
+
return
|
|
639
|
+
setattr(self,wtype+'_'+wName+'_setting',setting)
|
|
640
|
+
self.TABsettings.append(setting)
|
|
641
|
+
return
|
|
642
|
+
|
|
643
|
+
self.TABsettings=[]
|
|
644
|
+
for l,wtype in zip(self.widgets,self.widgetTypes):
|
|
645
|
+
for c in l:
|
|
646
|
+
wName=c.objectName().split(wtype+'_')[-1]
|
|
647
|
+
buildSetting(wName,wtype)
|
|
648
|
+
if wtype=='line_edit':
|
|
649
|
+
if hasattr(c,'addfuncout'):
|
|
650
|
+
c.addfuncout['setting']=self.TABsettings[-1]
|
|
651
|
+
else:
|
|
652
|
+
def focusOutEvent(obj, event):
|
|
653
|
+
type(obj).focusOutEvent(obj,event) #to preserve classical behaviour before adding the below
|
|
654
|
+
self.TABsettings[-1]()
|
|
655
|
+
c.focusOutEvent=focusOutEvent
|
|
656
|
+
|
|
657
|
+
def setTABpar(self,FlagAdjustPar=True,FlagBridge=True,FlagCallback=False,FlagDisplayControls=None):
|
|
658
|
+
if self.TABpar.FlagNone and self.TABpar_at(self.TABpar.ind) is None: return
|
|
659
|
+
pri.Coding.magenta(f' --- setting {self.TABpar.name} {self.TABpar.ind}')
|
|
660
|
+
|
|
661
|
+
self.FlagSettingPar=True
|
|
662
|
+
FlagSettingPar=TABpar.FlagSettingPar
|
|
663
|
+
TABpar.FlagSettingPar=True
|
|
664
|
+
|
|
665
|
+
if FlagAdjustPar:
|
|
666
|
+
self.adjustTABpar()
|
|
667
|
+
|
|
668
|
+
self.setTABlayout()
|
|
669
|
+
for f in self.TABsettings:
|
|
670
|
+
f()
|
|
671
|
+
#self.TABpar_old.copyfrom(self.TABpar)
|
|
672
|
+
self.TABpar.FlagInit=True
|
|
673
|
+
|
|
674
|
+
if FlagBridge:
|
|
675
|
+
self.setTABpar_bridge(FlagAdjustPar,FlagCallback)
|
|
676
|
+
|
|
677
|
+
self.TABpar_old.copyfrom(self.TABpar)
|
|
678
|
+
|
|
679
|
+
if FlagDisplayControls is None: FlagDisplayControls=not FlagBridge
|
|
680
|
+
if FlagDisplayControls:
|
|
681
|
+
self.display_controls()
|
|
682
|
+
|
|
683
|
+
TABpar.FlagSettingPar=FlagSettingPar
|
|
684
|
+
self.FlagSettingPar=False
|
|
685
|
+
|
|
686
|
+
if not FlagCallback:
|
|
687
|
+
self.adjustTABparInd()
|
|
688
|
+
|
|
689
|
+
def setTABpar_at(self,ind,FlagAdjustPar=False,FlagBridge=False):
|
|
690
|
+
pri.Coding.green(f'{":"*50}\nSetting previous par <{self.TABname}>: {ind}')
|
|
691
|
+
TABpar_ind:TABpar=self.TABpar_at(ind)
|
|
692
|
+
if not TABpar_ind.FlagNone:
|
|
693
|
+
self.TABpar.copyfrom(TABpar_ind)
|
|
694
|
+
self.setTABpar(FlagAdjustPar,FlagBridge)
|
|
695
|
+
pri.Coding.green(f'Setting previous par <{self.TABname}>: {ind}\n{":"*50}\n')
|
|
696
|
+
|
|
697
|
+
def setupWid(self):
|
|
698
|
+
setupWid(self)
|
|
699
|
+
fPixSize_TabNames=30
|
|
700
|
+
qlabels=self.findChildren(QLabel)
|
|
701
|
+
labs=[l for l in qlabels if 'name_tab' in l.objectName()]
|
|
702
|
+
for lab in labs:
|
|
703
|
+
lab:QLabel #=self.ui.name_tab
|
|
704
|
+
font=lab.font()
|
|
705
|
+
font.setPixelSize(fPixSize_TabNames)
|
|
706
|
+
lab.setFont(font)
|
|
707
|
+
|
|
708
|
+
def setTABWarnLabel(self):
|
|
709
|
+
if hasattr(self.ui,'label_done'):
|
|
710
|
+
self.ui.name_tab.setFixedWidth(self.ui.name_tab.sizeHint().width())
|
|
711
|
+
self.ui.label_done.setPixmap(self.pixmap_done if self.TABpar.OptionDone==1 else self.pixmap_warnc)
|
|
712
|
+
self.ui.label_done.setToolTip(self.TABpar.warningMessage)
|
|
713
|
+
|
|
714
|
+
def syncPrevGlobalFields(self, ref_vals=None, include_bases=False, exceptions=[], FlagSync=True):
|
|
715
|
+
"""
|
|
716
|
+
Sync class-level fields (declared in class bodies, e.g. PROpar.mode = mode_init)
|
|
717
|
+
across all TABpar-like instances inside self.TABpar_prev (nested lists / None / TABpar).
|
|
718
|
+
|
|
719
|
+
Parameters
|
|
720
|
+
----------
|
|
721
|
+
ref : object | None
|
|
722
|
+
Reference TABpar instance whose values will be copied (default: self.TABpar).
|
|
723
|
+
include_bases : bool
|
|
724
|
+
If True, include class-level fields declared in base classes too.
|
|
725
|
+
If False, include ONLY fields declared in the concrete class (e.g., PROpar only).
|
|
726
|
+
"""
|
|
727
|
+
|
|
728
|
+
ref = getattr(self, "TABpar", None)
|
|
729
|
+
if ref is None:
|
|
730
|
+
return []
|
|
731
|
+
ref_cls = type(ref)
|
|
732
|
+
|
|
733
|
+
# Decide which class we consider as "TABpar-like"
|
|
734
|
+
# If your tabs store subclasses of a known ParClass, use that; otherwise fallback to TABpar.
|
|
735
|
+
par_base = getattr(self, "ParClass", None)
|
|
736
|
+
if par_base is None:
|
|
737
|
+
par_base = TABpar # assumes TABpar is in scope in TabTools.py
|
|
738
|
+
|
|
739
|
+
# Reference object
|
|
740
|
+
if ref_vals is None:
|
|
741
|
+
|
|
742
|
+
# Collect class-level fields declared in class bodies
|
|
743
|
+
def _class_fields(cls):
|
|
744
|
+
if include_bases:
|
|
745
|
+
classes = [C for C in cls.mro() if C not in (object,)]
|
|
746
|
+
else:
|
|
747
|
+
classes = [cls]
|
|
748
|
+
|
|
749
|
+
out = []
|
|
750
|
+
for C in classes:
|
|
751
|
+
for name, val in C.__dict__.items():
|
|
752
|
+
if name.startswith("__"):
|
|
753
|
+
continue
|
|
754
|
+
# Skip methods / descriptors
|
|
755
|
+
if callable(val) or isinstance(val, (staticmethod, classmethod, property)):
|
|
756
|
+
continue
|
|
757
|
+
out.append(name)
|
|
758
|
+
|
|
759
|
+
# Unique preserving order
|
|
760
|
+
seen = set()
|
|
761
|
+
fields = []
|
|
762
|
+
for n in out:
|
|
763
|
+
if n not in seen:
|
|
764
|
+
seen.add(n)
|
|
765
|
+
fields.append(n)
|
|
766
|
+
return fields
|
|
767
|
+
|
|
768
|
+
fields = _class_fields(ref_cls)
|
|
769
|
+
|
|
770
|
+
# Build reference values (prefer instance override, otherwise class default)
|
|
771
|
+
ref_vals = {}
|
|
772
|
+
#pri.Info.green(f'{self.TABname}:')
|
|
773
|
+
for f in fields:
|
|
774
|
+
try:
|
|
775
|
+
ref_vals[f] = getattr(ref, f)
|
|
776
|
+
#pri.Info.green(f'{f} = {ref_vals[f]}')
|
|
777
|
+
except Exception:
|
|
778
|
+
pass
|
|
779
|
+
#pri.Info.green('\n')
|
|
780
|
+
|
|
781
|
+
if not FlagSync: return ref_vals
|
|
782
|
+
|
|
783
|
+
# Exclude exception fields (if any)
|
|
784
|
+
if exceptions:
|
|
785
|
+
exc = set(exceptions)
|
|
786
|
+
ref_vals = {k: v for k, v in ref_vals.items() if k not in exc}
|
|
787
|
+
|
|
788
|
+
# Walk nested structure and patch instances
|
|
789
|
+
def _walk(node, ParBase=par_base): # <-- bind ParBase safely here
|
|
790
|
+
if node is None:
|
|
791
|
+
return
|
|
792
|
+
if isinstance(node, ParBase):
|
|
793
|
+
for f, v in ref_vals.items():
|
|
794
|
+
try:
|
|
795
|
+
setattr(node, f, v)
|
|
796
|
+
except Exception:
|
|
797
|
+
pass
|
|
798
|
+
return
|
|
799
|
+
if isinstance(node, (list, tuple)):
|
|
800
|
+
for it in node:
|
|
801
|
+
_walk(it, ParBase)
|
|
802
|
+
return
|
|
803
|
+
if isinstance(node, dict):
|
|
804
|
+
for it in node.values():
|
|
805
|
+
_walk(it, ParBase)
|
|
806
|
+
return
|
|
807
|
+
|
|
808
|
+
_walk(getattr(self, "TABpar_prev", None))
|
|
809
|
+
|
|
810
|
+
# Set class-level (global) fields ONCE
|
|
811
|
+
for C in (ref_cls, self.TABpar, self.TABpar_old):
|
|
812
|
+
if C is None:
|
|
813
|
+
continue
|
|
814
|
+
for f, v in ref_vals.items():
|
|
815
|
+
try:
|
|
816
|
+
setattr(C, f, v)
|
|
817
|
+
except Exception:
|
|
818
|
+
pass
|
|
819
|
+
return ref_vals
|
|
820
|
+
|
|
821
|
+
#*************************************************** Undo/redo
|
|
822
|
+
def adjustTABparInd(self):
|
|
823
|
+
TABpar_ind=self.TABpar_at(self.TABpar.ind)
|
|
824
|
+
if TABpar_ind:
|
|
825
|
+
TABpar_ind.copyfrom(self.TABpar)
|
|
826
|
+
|
|
827
|
+
def adjustFromTABparInd(self,ind=None):
|
|
828
|
+
if ind is None: ind=self.TABpar.ind
|
|
829
|
+
TABpar_ind=self.TABpar_at(ind)
|
|
830
|
+
if TABpar_ind:
|
|
831
|
+
self.TABpar.copyfrom(TABpar_ind)
|
|
832
|
+
|
|
833
|
+
def gen_TABpar(self,ind,FlagSet=True,FlagEmptyPrev=False,FlagNone=False,FlagInsert=-1,Process=None,Step=None):
|
|
834
|
+
Prev=prev=self.TABpar_prev if FlagSet else []
|
|
835
|
+
|
|
836
|
+
for i in range(len(ind)):
|
|
837
|
+
if i<len(ind)-1:
|
|
838
|
+
if i==FlagInsert:
|
|
839
|
+
prev.insert(ind[i],[])
|
|
840
|
+
else:
|
|
841
|
+
while ind[i]>len(prev)-1:
|
|
842
|
+
prev.append([])
|
|
843
|
+
prev=prev[ind[i]]
|
|
844
|
+
else:
|
|
845
|
+
if not FlagEmptyPrev:
|
|
846
|
+
if i==FlagInsert:
|
|
847
|
+
if ind[i]<len(prev):
|
|
848
|
+
if FlagNone:
|
|
849
|
+
prev[ind[i]]=None
|
|
850
|
+
else:
|
|
851
|
+
if Process is not None and Step is not None:
|
|
852
|
+
par=self.ParClass(Process=Process,Step=Step)
|
|
853
|
+
else:
|
|
854
|
+
par=self.ParClass()
|
|
855
|
+
par.ind=ind
|
|
856
|
+
prev[ind[i]]=par
|
|
857
|
+
pri.Coding.cyan(f'[gen_TABpar] {par.surname} {par.ind} ---> {self.TABpar_at(ind).ind}')
|
|
858
|
+
else:
|
|
859
|
+
if FlagNone:
|
|
860
|
+
prev.insert(ind[i],None)
|
|
861
|
+
else:
|
|
862
|
+
if Process is not None and Step is not None:
|
|
863
|
+
par=self.ParClass(Process=Process,Step=Step)
|
|
864
|
+
else:
|
|
865
|
+
par=self.ParClass()
|
|
866
|
+
par.ind=ind
|
|
867
|
+
prev.insert(ind[i],par)
|
|
868
|
+
pri.Coding.cyan(f'[gen_TABpar] {par.surname} {par.ind} ---> {self.TABpar_at(ind).ind}')
|
|
869
|
+
else:
|
|
870
|
+
while ind[i]>len(prev)-1:
|
|
871
|
+
if FlagNone:
|
|
872
|
+
prev.append(None)
|
|
873
|
+
else:
|
|
874
|
+
if Process is not None and Step is not None:
|
|
875
|
+
par=self.ParClass(Process=Process,Step=Step)
|
|
876
|
+
else:
|
|
877
|
+
par=self.ParClass()
|
|
878
|
+
par.ind=ind
|
|
879
|
+
prev.append(par)
|
|
880
|
+
pri.Coding.cyan(f'[gen_TABpar] {par.surname} {par.ind} ---> {self.TABpar_at(ind).ind}')
|
|
881
|
+
return Prev
|
|
882
|
+
|
|
883
|
+
def TABpar_at(self,ind):
|
|
884
|
+
if ind[0]<len(self.TABpar_prev):
|
|
885
|
+
p:TABpar=self.TABpar_prev[ind[0]]
|
|
886
|
+
else:
|
|
887
|
+
p=None
|
|
888
|
+
if p:
|
|
889
|
+
for i in range(1,len(ind)):
|
|
890
|
+
if ind[i]<len(p):
|
|
891
|
+
p=p[ind[i]]
|
|
892
|
+
else:
|
|
893
|
+
p=None
|
|
894
|
+
break
|
|
895
|
+
return p
|
|
896
|
+
|
|
897
|
+
def TABpar_prev_at(self,ind):
|
|
898
|
+
if len(self.TABpar_prev)-1<ind[0]:
|
|
899
|
+
return []
|
|
900
|
+
else:
|
|
901
|
+
p:TABpar=self.TABpar_prev[ind[0]]
|
|
902
|
+
for i in range(1,len(ind)-1):
|
|
903
|
+
if len(p)-1<ind[i]:
|
|
904
|
+
p=[]
|
|
905
|
+
break
|
|
906
|
+
else:
|
|
907
|
+
p=p[ind[i]]
|
|
908
|
+
return p
|
|
909
|
+
|
|
910
|
+
def isNewPar(self):
|
|
911
|
+
ind=self.TABpar.ind
|
|
912
|
+
TABpar_prev=self.TABpar_prev_at(ind)
|
|
913
|
+
if len(TABpar_prev)>0:
|
|
914
|
+
FlagNewPar=self.FlagAddPrev and self.TABpar.isDifferentFrom(TABpar_prev[-1],exceptions=self.TABpar.unchecked_fields+['ind']) #see below
|
|
915
|
+
self.TABpar.printDifferences(TABpar_prev[-1],exceptions=self.TABpar.unchecked_fields+['ind'])
|
|
916
|
+
else:
|
|
917
|
+
FlagNewPar=self.FlagAddPrev
|
|
918
|
+
return FlagNewPar
|
|
919
|
+
|
|
920
|
+
def add_TABpar(self,tip,FlagNewPar=True):
|
|
921
|
+
ind=self.TABpar.ind
|
|
922
|
+
TABpar_prev=self.TABpar_prev_at(ind)
|
|
923
|
+
if (FlagNewPar or len(TABpar_prev)==0) and self.FlagAddPrev: #something changed
|
|
924
|
+
if len(TABpar_prev): TABpar_prev[-1].printDifferences(self.TABpar,self.TABpar.unchecked_fields+['ind'])
|
|
925
|
+
self.add_TABpar_copy(tip,ind)
|
|
926
|
+
self.add_TABpar_bridge(tip,ind) #should create a copy of the other tabs' parameters (see gPaIRS)
|
|
927
|
+
ind[-1]=TABpar_prev[-1].ind[-1]
|
|
928
|
+
else:
|
|
929
|
+
self.adjustTABparInd()
|
|
930
|
+
|
|
931
|
+
if self.FlagPrevPropagation:
|
|
932
|
+
#pri.Time.blue('Propagation par init')
|
|
933
|
+
TABpar_prev=self.TABpar_prev_at(self.TABpar.ind)
|
|
934
|
+
for p in TABpar_prev:
|
|
935
|
+
p:TABpar
|
|
936
|
+
p.copyfrom(TABpar_prev[self.TABpar.ind[-1]],exceptions=['ind','tip'])
|
|
937
|
+
#pri.Time.blue('Propagation par end')
|
|
938
|
+
return ind
|
|
939
|
+
|
|
940
|
+
def add_TABpar_copy(self,name,ind):
|
|
941
|
+
TABpar_prev:list=self.TABpar_prev_at(ind)
|
|
942
|
+
if not self.TABpar.FlagNone:
|
|
943
|
+
TABpar_new=self.TABpar.duplicate()
|
|
944
|
+
if len(TABpar_prev)>self.Num_Prevs_Max:
|
|
945
|
+
TABpar_prev.pop(0)
|
|
946
|
+
for k,p in enumerate(TABpar_prev):
|
|
947
|
+
p.ind[-1]=k
|
|
948
|
+
else:
|
|
949
|
+
TABpar_new.ind[-1]=len(TABpar_prev)
|
|
950
|
+
TABpar_new.tip=name
|
|
951
|
+
self.TABpar.ind=copy.deepcopy(TABpar_new.ind) #in this way, we move to the last added par in the "prev"
|
|
952
|
+
pri.Coding.yellow(f' |-> +++ {self.TABpar.name}: new par {TABpar_new.ind} <{name}>')
|
|
953
|
+
else:
|
|
954
|
+
TABpar_new=None
|
|
955
|
+
TABpar_prev.append(TABpar_new)
|
|
956
|
+
self.display_controls()
|
|
957
|
+
ind_new=[i for i in ind]
|
|
958
|
+
ind_new[-1]=len(TABpar_prev)-1
|
|
959
|
+
return ind_new
|
|
960
|
+
|
|
961
|
+
def display_controls(self):
|
|
962
|
+
if not self.FlagDisplayControls: return
|
|
963
|
+
FlagVisible=self.TABpar.flagRun==0 and len(self.TABpar.link)==0
|
|
964
|
+
self.ui.button_restore_undo.setVisible(FlagVisible)
|
|
965
|
+
self.ui.button_back.setVisible(FlagVisible)
|
|
966
|
+
self.ui.button_forward.setVisible(FlagVisible)
|
|
967
|
+
lprev=len(self.TABpar_prev_at(self.TABpar.ind))
|
|
968
|
+
if self.onlyReadLabel:
|
|
969
|
+
if len(self.TABpar.link)==0:
|
|
970
|
+
if lprev:
|
|
971
|
+
ITE0=self.gui.ui.Explorer.ITEsfromInd(self.TABpar.ind)[0]
|
|
972
|
+
if ITE0.flagRun==0:
|
|
973
|
+
self.onlyReadLabel.setText('')
|
|
974
|
+
else:
|
|
975
|
+
self.onlyReadLabel.setText('read-only')
|
|
976
|
+
else:
|
|
977
|
+
self.onlyReadLabel.setText('')
|
|
978
|
+
self.button_link_step.setToolTip('Link current process step to another in the same project')
|
|
979
|
+
self.button_link_step.setIcon(self.icon_link)
|
|
980
|
+
self.gui.RCLbar.buttonData[3]['name']='Link step to...'
|
|
981
|
+
else:
|
|
982
|
+
if hasattr(self.gui,'ui') and hasattr(self.gui.ui,'Explorer'):
|
|
983
|
+
ITE0_master=self.gui.ui.Explorer.ITEsfromInd(self.TABpar.link)[0]
|
|
984
|
+
linkInfo=f'linked to {ITE0_master.ind[2]+1}: {ITE0_master.name}'
|
|
985
|
+
self.onlyReadLabel.setText(linkInfo)
|
|
986
|
+
else:
|
|
987
|
+
self.onlyReadLabel.setText('')
|
|
988
|
+
self.button_link_step.setToolTip('Unlink current process step')
|
|
989
|
+
self.button_link_step.setIcon(self.icon_unlink)
|
|
990
|
+
self.gui.RCLbar.buttonData[3]['name']='Unlink step'
|
|
991
|
+
self.button_link_step.setStatusTip(self.button_link_step.toolTip())
|
|
992
|
+
self.button_link_step.setChecked(len(self.TABpar.link)!=0)
|
|
993
|
+
|
|
994
|
+
if self.gui.ui.Explorer.TREpar.step is None:
|
|
995
|
+
FlagProcessTree=False
|
|
996
|
+
else:
|
|
997
|
+
FlagProcessTree=self.gui.ui.Explorer.currentTree==self.gui.ui.Explorer.processTree and self.gui.ui.Explorer.TREpar.step>0
|
|
998
|
+
FlagLabel=(self.TABpar.flagRun!=0 and len(self.TABpar.link)==0) or len(self.TABpar.link)>0
|
|
999
|
+
FlagReset=self.TABpar.flagRun!=0 and len(self.TABpar.link)==0
|
|
1000
|
+
FlagInherit=self.TABpar.flagRun==0 and len(self.TABpar.link)==0 and len(self.gui.IOVheritableSteps())>0
|
|
1001
|
+
FlagCopy=self.TABpar.flagRun==0 and len(self.TABpar.link)==0 and len(self.gui.linkableSteps(FlagExcludeLinked=True))>0
|
|
1002
|
+
FlagLink=(len(self.TABpar.link)==0 and self.TABpar.flagRun==0 and len(self.gui.linkableSteps(FlagExcludeLinked=True))>0) or len(self.TABpar.link)>0
|
|
1003
|
+
if FlagProcessTree and (FlagLabel or FlagReset or FlagInherit or FlagCopy or FlagLink):
|
|
1004
|
+
self.gui.w_RCL.setVisible(True)
|
|
1005
|
+
self.onlyReadLabel.setVisible(FlagLabel)
|
|
1006
|
+
self.button_reset_step.setVisible(FlagReset)
|
|
1007
|
+
self.button_step_inherit.setVisible(FlagInherit)
|
|
1008
|
+
self.button_copy_step.setVisible(FlagCopy)
|
|
1009
|
+
self.button_link_step.setVisible(FlagLink)
|
|
1010
|
+
else:
|
|
1011
|
+
self.gui.w_RCL.setVisible(False)
|
|
1012
|
+
FlagEnabled = not self.gui.FlagRun
|
|
1013
|
+
self.button_reset_step.setEnabled(FlagEnabled)
|
|
1014
|
+
self.button_step_inherit.setEnabled(FlagEnabled)
|
|
1015
|
+
self.button_copy_step.setEnabled(FlagEnabled)
|
|
1016
|
+
self.button_link_step.setEnabled(FlagEnabled)
|
|
1017
|
+
|
|
1018
|
+
if self.TABpar.flagRun or len(self.TABpar.link)>0: return
|
|
1019
|
+
|
|
1020
|
+
i=self.TABpar.ind[-1]
|
|
1021
|
+
self.ui.button_restore_undo.setVisible(lprev>1)
|
|
1022
|
+
self.ui.button_forward.setVisible(lprev>1)
|
|
1023
|
+
self.ui.button_back.setVisible(lprev>1)
|
|
1024
|
+
self.ui.button_restore_undo.setEnabled(not (i==lprev-1 or i==-1))
|
|
1025
|
+
self.ui.button_forward.setEnabled(not (i==lprev-1 or i==-1))
|
|
1026
|
+
self.ui.button_back.setEnabled(i!=0)
|
|
1027
|
+
if self.ui.label_number.isVisible():
|
|
1028
|
+
if i==lprev-1 or i==-1:
|
|
1029
|
+
self.ui.label_number.setText('')
|
|
1030
|
+
elif i>=0:
|
|
1031
|
+
self.ui.label_number.setText("(-"+str(lprev-1-i)+")")
|
|
1032
|
+
else:
|
|
1033
|
+
self.ui.label_number.setText("(-"+str(i+1)+")")
|
|
1034
|
+
|
|
1035
|
+
def button_back_action(self):
|
|
1036
|
+
ind=self.TABpar.ind
|
|
1037
|
+
ind[-1]-=1
|
|
1038
|
+
self.FlagSettingPar=True
|
|
1039
|
+
self.setFocus()
|
|
1040
|
+
self.FlagSettingPar=False
|
|
1041
|
+
self.setTABpar_at(ind,FlagAdjustPar=ind[-1]==0,FlagBridge=True) #True=with bridge
|
|
1042
|
+
return False
|
|
1043
|
+
|
|
1044
|
+
def button_forward_action(self):
|
|
1045
|
+
ind=self.TABpar.ind
|
|
1046
|
+
ind[-1]+=1
|
|
1047
|
+
self.FlagSettingPar=True
|
|
1048
|
+
self.setFocus()
|
|
1049
|
+
self.FlagSettingPar=False
|
|
1050
|
+
self.setTABpar_at(ind,FlagAdjustPar=ind[-1]==0,FlagBridge=True) #True=with bridge
|
|
1051
|
+
return False
|
|
1052
|
+
|
|
1053
|
+
def bfContextMenu(self,bf,event):
|
|
1054
|
+
i=self.TABpar.ind[-1]
|
|
1055
|
+
TABpar_prev=self.TABpar_prev_at(self.TABpar.ind)
|
|
1056
|
+
|
|
1057
|
+
if bf==-1:
|
|
1058
|
+
b=self.ui.button_back
|
|
1059
|
+
f=self.button_back_action
|
|
1060
|
+
kin=max([0,i-Num_Prevs_back_forw])
|
|
1061
|
+
krange=[k for k in range(i-1,kin,-1)]+[0]
|
|
1062
|
+
icon=self.undo_icon
|
|
1063
|
+
d=1
|
|
1064
|
+
elif bf==1:
|
|
1065
|
+
b=self.ui.button_forward
|
|
1066
|
+
f=self.button_forward_action
|
|
1067
|
+
kfin=min([len(TABpar_prev)-1,i+Num_Prevs_back_forw])
|
|
1068
|
+
krange=[k for k in range(i+1,kfin)]+[len(TABpar_prev)-1]
|
|
1069
|
+
icon=self.redo_icon
|
|
1070
|
+
d=0
|
|
1071
|
+
|
|
1072
|
+
menu=QMenu(b)
|
|
1073
|
+
menu.setStyleSheet(self.gui.ui.menu.styleSheet())
|
|
1074
|
+
act=[]
|
|
1075
|
+
nur=len(krange)
|
|
1076
|
+
flag=nur==Num_Prevs_back_forw
|
|
1077
|
+
for j,k in enumerate(krange):
|
|
1078
|
+
if j==nur-1:
|
|
1079
|
+
if flag: menu.addSeparator()
|
|
1080
|
+
if k==0: s=' (first)'
|
|
1081
|
+
else: s=' (current)'
|
|
1082
|
+
else:
|
|
1083
|
+
if j==nur-2 and flag:
|
|
1084
|
+
s=' (...)'
|
|
1085
|
+
else:
|
|
1086
|
+
s=''
|
|
1087
|
+
n=f"{k-i:+d}: "
|
|
1088
|
+
name=n+TABpar_prev[k+d].tip+s
|
|
1089
|
+
act.append(QAction(icon,name,b))
|
|
1090
|
+
menu.addAction(act[-1])
|
|
1091
|
+
|
|
1092
|
+
action = menu.exec_(b.mapToGlobal(event.pos()))
|
|
1093
|
+
for k,a in zip(krange,act):
|
|
1094
|
+
if a==action:
|
|
1095
|
+
self.TABpar.ind[-1]=k-bf
|
|
1096
|
+
f()
|
|
1097
|
+
|
|
1098
|
+
def cleanPrevs(self,ind,FlagAllPrev=False):
|
|
1099
|
+
TABpar_prev=self.TABpar_prev_at(ind)
|
|
1100
|
+
for _ in range(len(TABpar_prev)-1*int(not FlagAllPrev)):
|
|
1101
|
+
TABpar_prev.pop(0)
|
|
1102
|
+
if not FlagAllPrev:
|
|
1103
|
+
TABpar_prev[0].ind[-1]=0
|
|
1104
|
+
if self.TABpar.ind[:-1]==ind[:-1]:
|
|
1105
|
+
self.TABpar.ind[-1]=0
|
|
1106
|
+
|
|
1107
|
+
#*************************************************** Special spin boxes (x,y,w,h)
|
|
1108
|
+
def setMinMaxSpinxywh(self):
|
|
1109
|
+
self.ui.spin_x.setMinimum(0)
|
|
1110
|
+
self.ui.spin_x.setMaximum(self.TABpar.W-1)
|
|
1111
|
+
self.ui.spin_y.setMinimum(0)
|
|
1112
|
+
self.ui.spin_y.setMaximum(self.TABpar.H-1)
|
|
1113
|
+
self.ui.spin_w.setMinimum(1)
|
|
1114
|
+
self.ui.spin_w.setMaximum(self.TABpar.W)
|
|
1115
|
+
self.ui.spin_h.setMinimum(1)
|
|
1116
|
+
self.ui.spin_h.setMaximum(self.TABpar.H)
|
|
1117
|
+
for field in ('spin_x','spin_y','spin_w','spin_h'):
|
|
1118
|
+
s:MyQSpin=getattr(self.ui,field)
|
|
1119
|
+
tip=getattr(self,"tip_"+field)
|
|
1120
|
+
stringa=". Image size: "+str(self.TABpar.W)+"x"+str(self.TABpar.H)
|
|
1121
|
+
newtip=tip+stringa
|
|
1122
|
+
s.setToolTip(newtip)
|
|
1123
|
+
s.setStatusTip(newtip)
|
|
1124
|
+
self.check_resize()
|
|
1125
|
+
|
|
1126
|
+
def check_resize(self):
|
|
1127
|
+
if self.TABpar.W!=self.TABpar.w or \
|
|
1128
|
+
self.TABpar.H!=self.TABpar.h:
|
|
1129
|
+
self.ui.button_resize.show()
|
|
1130
|
+
else:
|
|
1131
|
+
self.ui.button_resize.hide()
|
|
1132
|
+
|
|
1133
|
+
def button_resize_action(self):
|
|
1134
|
+
self.TABpar.x=self.TABpar.y=0
|
|
1135
|
+
self.TABpar.w=self.TABpar.W
|
|
1136
|
+
self.TABpar.h=self.TABpar.H
|
|
1137
|
+
self.ui.spin_w.setMaximum(self.TABpar.W)
|
|
1138
|
+
self.ui.spin_h.setMaximum(self.TABpar.H)
|
|
1139
|
+
return
|
|
1140
|
+
|
|
1141
|
+
def spin_x_changing(self):
|
|
1142
|
+
wmax=self.TABpar.W-self.ui.spin_x.value()
|
|
1143
|
+
self.ui.spin_w.setMaximum(wmax)
|
|
1144
|
+
w=min([self.TABpar.w,wmax])
|
|
1145
|
+
self.ui.spin_w.setValue(w)
|
|
1146
|
+
|
|
1147
|
+
def spin_x_action(self):
|
|
1148
|
+
self.TABpar.w=self.ui.spin_w.value()
|
|
1149
|
+
|
|
1150
|
+
def spin_y_changing(self):
|
|
1151
|
+
hmax=self.TABpar.H-self.ui.spin_y.value()
|
|
1152
|
+
self.ui.spin_h.setMaximum(hmax)
|
|
1153
|
+
h=min([self.TABpar.h,hmax])
|
|
1154
|
+
self.ui.spin_h.setValue(h)
|
|
1155
|
+
|
|
1156
|
+
def spin_y_action(self):
|
|
1157
|
+
self.TABpar.h=self.ui.spin_h.value()
|
|
1158
|
+
|
|
1159
|
+
#*************************************************** Widget setup
|
|
1160
|
+
def newTip(self,field):
|
|
1161
|
+
s: MyQSpin
|
|
1162
|
+
if field=='spin_range_from': #INPpar
|
|
1163
|
+
s=self.ui.spin_range_from
|
|
1164
|
+
stringa=". Range: "+str(s.minimum())+'-'+str(s.maximum())
|
|
1165
|
+
newtip=self.tip_spin_range_from+stringa
|
|
1166
|
+
elif field=='spin_range_to': #INPpar
|
|
1167
|
+
s=self.ui.spin_range_to
|
|
1168
|
+
stringa=". Max.: "+str(s.maximum())
|
|
1169
|
+
newtip=self.tip_spin_range_to+stringa
|
|
1170
|
+
s.setToolTip(newtip)
|
|
1171
|
+
s.setStatusTip(newtip)
|
|
1172
|
+
|
|
1173
|
+
#*************************************************** Widget setup
|
|
1174
|
+
def setupWid(self:gPaIRS_Tab,FlagFontSize=True):
|
|
1175
|
+
if FlagFontSize: setFontPixelSize(self,fontPixelSize)
|
|
1176
|
+
|
|
1177
|
+
if hasattr(self,'widgets'): widgets=self.widgets
|
|
1178
|
+
else: widgets=self.findChildren(QWidget)
|
|
1179
|
+
if isinstance(widgets[0],list):
|
|
1180
|
+
widgets=[w for wi in widgets for w in wi]
|
|
1181
|
+
widgets+=self.findChildren(CollapsibleBox)
|
|
1182
|
+
widgets+=self.findChildren(QTextEdit)
|
|
1183
|
+
for w in widgets:
|
|
1184
|
+
w:QToolButton
|
|
1185
|
+
if hasattr(w,'toolTip'):
|
|
1186
|
+
tooltip=toPlainText(w.toolTip())
|
|
1187
|
+
if hasattr(w,'shortcut'):
|
|
1188
|
+
scut=w.shortcut().toString(QKeySequence.NativeText)
|
|
1189
|
+
if scut:
|
|
1190
|
+
scut=toPlainText('('+scut+')')
|
|
1191
|
+
if scut not in tooltip:
|
|
1192
|
+
tooltip+=' '+scut
|
|
1193
|
+
w.setToolTip(tooltip)
|
|
1194
|
+
#if hasattr(w,'statusTip'):
|
|
1195
|
+
w.setStatusTip(tooltip)
|
|
1196
|
+
|
|
1197
|
+
if hasattr(w,'setup'):
|
|
1198
|
+
w.setup()
|
|
1199
|
+
if hasattr(w,'setup2'):
|
|
1200
|
+
w.setup2()
|
|
1201
|
+
|
|
1202
|
+
if isinstance(w,QToolButton) or isinstance(w,QPushButton) or isinstance(w,QCheckBox) or isinstance(w,QRadioButton) or isinstance(w,QComboBox):
|
|
1203
|
+
if w.cursor().shape()==Qt.CursorShape.ArrowCursor:
|
|
1204
|
+
w.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
|
|
1205
|
+
if isinstance(w,QToolButton) or isinstance(w,QPushButton):
|
|
1206
|
+
if not w.icon().isNull():
|
|
1207
|
+
size = w.iconSize()
|
|
1208
|
+
new_size = QSize(
|
|
1209
|
+
max(1, size.width() ),
|
|
1210
|
+
max(1, size.height() )
|
|
1211
|
+
)
|
|
1212
|
+
w.setIconSize(new_size)
|
|
1213
|
+
if (isinstance(w,QToolButton) or isinstance(w,QPushButton) or isinstance(w,ClickableLabel) or w.objectName()=='logo') and w.metaObject().className() not in ('DraggableButton','RichTextPushButton') and w.objectName() not in ('binButton','CollapsibleBox_toggle','StartingPage_Button'):
|
|
1214
|
+
if w.objectName() in ('logo','title_icon','workspace_icon'):
|
|
1215
|
+
apply_hover_glow_label(w)
|
|
1216
|
+
w.default_stylesheet=w.styleSheet()
|
|
1217
|
+
else:
|
|
1218
|
+
setButtonHoverStyle(w)
|
|
1219
|
+
if w.metaObject().className() == "RichTextPushButton":
|
|
1220
|
+
w.icnWidget.setAttribute(Qt.WA_Hover, True)
|
|
1221
|
+
w.icnWidget.setMouseTracking(True)
|
|
1222
|
+
setButtonHoverStyle(w,FlagCls=False)
|
|
1223
|
+
setButtonHoverStyle(w.icnWidget,FlagCls=False,FlagBorder=False)
|
|
1224
|
+
if isinstance(w,QCheckBox) or isinstance(w,QRadioButton):
|
|
1225
|
+
style=f"{w.metaObject().className()}{'::hover{ background-color: rgba(0, 116, 255, 0.1); border-radius: 6px;}'}"
|
|
1226
|
+
w.setStyleSheet(style)
|
|
1227
|
+
if isinstance(w,QSlider):
|
|
1228
|
+
w.setMouseTracking(True)
|
|
1229
|
+
cursor_filter = SliderHandleCursorFilter(w)
|
|
1230
|
+
w.installEventFilter(cursor_filter)
|
|
1231
|
+
if w.objectName()=='log' and hasattr(self,'gui'):
|
|
1232
|
+
base="""
|
|
1233
|
+
QTextEdit {
|
|
1234
|
+
background-color: #000000;
|
|
1235
|
+
color: #FFFFFF;
|
|
1236
|
+
border: 1px solid #2a2a2a;
|
|
1237
|
+
border-radius: 6px;
|
|
1238
|
+
|
|
1239
|
+
padding: 2px;
|
|
1240
|
+
|
|
1241
|
+
selection-background-color: rgba(0, 116, 255, 0.8);
|
|
1242
|
+
selection-color: #FFFFFF;
|
|
1243
|
+
}
|
|
1244
|
+
"""
|
|
1245
|
+
w.setStyleSheet(base + "\n" + gPaIRS_QMenu_style)
|
|
1246
|
+
|
|
1247
|
+
|
|
1248
|
+
for sname in ('range_from','range_to','x','y','w','h'):
|
|
1249
|
+
if hasattr(self.ui,"spin_"+sname):
|
|
1250
|
+
sp=getattr(self.ui,"spin_"+sname)
|
|
1251
|
+
setattr(self,"tip_spin_"+sname,sp.toolTip())
|
|
1252
|
+
|
|
1253
|
+
def setFontPixelSize(self,fPixSize):
|
|
1254
|
+
font=self.font()
|
|
1255
|
+
font.setFamily(fontName)
|
|
1256
|
+
font.setPixelSize(fPixSize)
|
|
1257
|
+
self.setFont(font)
|
|
1258
|
+
c=self.findChildren(QWidget)
|
|
1259
|
+
for w in c:
|
|
1260
|
+
w:QWidget
|
|
1261
|
+
if w.objectName()=='title_project' and hasattr(self,'projectTree'):
|
|
1262
|
+
self.projectTree.titleFont(w,fPixSize)
|
|
1263
|
+
elif w.objectName()=='subtitle_project' and hasattr(self,'projectTree'):
|
|
1264
|
+
self.projectTree.subTitleFont(w,fPixSize)
|
|
1265
|
+
elif w.objectName()=='title_process' and hasattr(self,'processTree'):
|
|
1266
|
+
self.processTree.titleFont(w,fPixSize)
|
|
1267
|
+
elif w.objectName()=='subtitle_process' and hasattr(self,'processTree'):
|
|
1268
|
+
self.processTree.subTitleFont(w,fPixSize)
|
|
1269
|
+
elif w.objectName()=='title_step':
|
|
1270
|
+
w.parent().stepTitleFont(w,fPixSize)
|
|
1271
|
+
elif hasattr(w,'setFont'):
|
|
1272
|
+
font=w.font()
|
|
1273
|
+
font.setFamily(fontName)
|
|
1274
|
+
t=type(w)
|
|
1275
|
+
if issubclass(t,QLabel):
|
|
1276
|
+
setFontSizeText(w,[fPixSize-1])
|
|
1277
|
+
elif issubclass(t,QPushButton) or issubclass(t,QToolButton):
|
|
1278
|
+
font.setPixelSize(fPixSize+1)
|
|
1279
|
+
w.setFont(font)
|
|
1280
|
+
adjustFont(w)
|
|
1281
|
+
else:
|
|
1282
|
+
font.setPixelSize(fPixSize)
|
|
1283
|
+
w.setFont(font)
|
|
1284
|
+
adjustFont(w)
|
|
1285
|
+
c=self.findChildren(RichTextPushButton)
|
|
1286
|
+
for w in c:
|
|
1287
|
+
font=w.font()
|
|
1288
|
+
font.setFamily(fontName)
|
|
1289
|
+
font.setPixelSize(fPixSize+3)
|
|
1290
|
+
w.lbl.setFont(font)
|
|
1291
|
+
|
|
1292
|
+
def setFontSizeText(lab:QLabel,fPixSizes):
|
|
1293
|
+
text=lab.text()
|
|
1294
|
+
text=re.sub(r"font-size:\d+pt",f"font-size:{fPixSizes[0]}px",text)
|
|
1295
|
+
text=re.sub(r"font-size:\d+px",f"font-size:{fPixSizes[0]}px",text)
|
|
1296
|
+
if len(fPixSizes)>1:
|
|
1297
|
+
for k in range(len(fPixSizes)-1,0,-1):
|
|
1298
|
+
text=re.sub(r"font-size:\d+px",f"font-size:{fPixSizes[k]}px",text,k)
|
|
1299
|
+
lab.setText(text)
|
|
1300
|
+
font=lab.font()
|
|
1301
|
+
font.setPixelSize(fPixSizes[0])
|
|
1302
|
+
lab.setFont(font)
|
|
1303
|
+
adjustFont(lab)
|
|
1304
|
+
|
|
1305
|
+
def adjustFont(self:QLabel):
|
|
1306
|
+
if not hasattr(self,'geometry'): return
|
|
1307
|
+
if not hasattr(self,'text') and not hasattr(self,'currentText'): return
|
|
1308
|
+
flagParent=self.isVisible() and bool(self.parent())
|
|
1309
|
+
font = self.font()
|
|
1310
|
+
if hasattr(self,'text'):
|
|
1311
|
+
text = self.text()
|
|
1312
|
+
elif hasattr(self,'currentText'):
|
|
1313
|
+
text = self.currentText()
|
|
1314
|
+
else: return
|
|
1315
|
+
if 'Parallel' in text:
|
|
1316
|
+
pass
|
|
1317
|
+
|
|
1318
|
+
if hasattr(self,'text'):
|
|
1319
|
+
if 'Find' in self.text():
|
|
1320
|
+
pass
|
|
1321
|
+
|
|
1322
|
+
S=self.geometry()
|
|
1323
|
+
maxS = QRect(self.pos(),self.maximumSize())
|
|
1324
|
+
minS = QRect(self.pos(),self.minimumSize())
|
|
1325
|
+
if flagParent:
|
|
1326
|
+
r=self.parent().rect()
|
|
1327
|
+
S&= r
|
|
1328
|
+
maxS&= QRect(QPoint(r.x(),r.y()),self.parent().maximumSize())
|
|
1329
|
+
minS&= QRect(QPoint(r.x(),r.y()),self.parent().minimumSize())
|
|
1330
|
+
|
|
1331
|
+
textSize=QtGui.QFontMetrics(font).size(QtCore.Qt.TextSingleLine, text)
|
|
1332
|
+
if (textSize.height()<=S.height()) and (textSize.width()<=S.width()):
|
|
1333
|
+
return
|
|
1334
|
+
while True:
|
|
1335
|
+
if font.pixelSize()<=fontPixelSize_lim[0]:
|
|
1336
|
+
font.setPixelSize(fontPixelSize_lim[0])
|
|
1337
|
+
break
|
|
1338
|
+
if (textSize.height()<=S.height()):
|
|
1339
|
+
break
|
|
1340
|
+
font.setPixelSize(font.pixelSize()-1)
|
|
1341
|
+
textSize=QtGui.QFontMetrics(font).size(QtCore.Qt.TextSingleLine, text)
|
|
1342
|
+
|
|
1343
|
+
textWidth=min([textSize.width(),maxS.width()])
|
|
1344
|
+
textWidth=max([textWidth,minS.width()])
|
|
1345
|
+
if S.width()<textWidth:
|
|
1346
|
+
s=self.geometry()
|
|
1347
|
+
s.setWidth(textWidth)
|
|
1348
|
+
self.setGeometry(s)
|
|
1349
|
+
if flagParent:
|
|
1350
|
+
S=s&self.parent().rect()
|
|
1351
|
+
else:
|
|
1352
|
+
S=s
|
|
1353
|
+
while True:
|
|
1354
|
+
if font.pixelSize()<=fontPixelSize_lim[0]:
|
|
1355
|
+
font.setPixelSize(fontPixelSize_lim[0])
|
|
1356
|
+
break
|
|
1357
|
+
if (textSize.width()<=S.width()):
|
|
1358
|
+
break
|
|
1359
|
+
font.setPixelSize(font.pixelSize()-1)
|
|
1360
|
+
textSize=QtGui.QFontMetrics(font).size(QtCore.Qt.TextSingleLine, text)
|
|
1361
|
+
|
|
1362
|
+
self.setFont(font)
|
|
1363
|
+
|
|
1364
|
+
#*************************************************** Other
|
|
1365
|
+
def iterateList(l,value):
|
|
1366
|
+
if type(l)==list:
|
|
1367
|
+
if len(l):
|
|
1368
|
+
if type(l[0])==list:
|
|
1369
|
+
for m in l:
|
|
1370
|
+
iterateList(m,value)
|
|
1371
|
+
else:
|
|
1372
|
+
for k in range(len(l)):
|
|
1373
|
+
l[k]=value
|
|
1374
|
+
|
|
1375
|
+
def funexample():
|
|
1376
|
+
def fun2(i):
|
|
1377
|
+
if FlagSimulateError:
|
|
1378
|
+
raise Exception("funexample: the requested exception!")
|
|
1379
|
+
pri.Info.cyan('funexample: Hello, sir!')
|
|
1380
|
+
return [1,fun2]
|
|
1381
|
+
|
|
1382
|
+
if __name__ == "__main__":
|
|
1383
|
+
a=TABpar()
|
|
1384
|
+
b=TABpar()
|
|
1385
|
+
|
|
1386
|
+
a.printPar('a: ')
|
|
1387
|
+
c=a.duplicate()
|
|
1388
|
+
b.printPar('b: ')
|
|
1389
|
+
|
|
1390
|
+
a.copyfrom(b)
|
|
1391
|
+
a.printPar('a: ',' copied from b')
|
|
1392
|
+
c.printPar('c: ')
|
|
1393
|
+
c.copyfromfields(b,['surname'])
|
|
1394
|
+
c.printPar('c: ', ' surname copied from b')
|
|
1395
|
+
|
|
1396
|
+
print(f'Is a different from b? {a.isDifferentFrom(b)}')
|
|
1397
|
+
print(f'Is a equal to b? {a.isEqualTo(b)}')
|
|
1398
|
+
print(f'Is c different from b? {c.isDifferentFrom(b)}')
|
|
1399
|
+
print(f'Is c equal to b? {c.isEqualTo(b)}')
|
|
1400
|
+
print(f'Is c different from b except surname? {c.isDifferentFrom(b,["surname"])}')
|
|
1401
|
+
print(f'Is c equal to b except name? {c.isEqualTo(b,["name"])}')
|
|
1402
|
+
|
|
1403
|
+
"""
|
|
1404
|
+
app=QApplication.instance()
|
|
1405
|
+
if not app:app = QApplication(sys.argv)
|
|
1406
|
+
app.setStyle('Fusion')
|
|
1407
|
+
TAB = gPaIRS_Tab(None,QWidget)
|
|
1408
|
+
callbackfun=TAB.addParWrapper(funexample,'example')
|
|
1409
|
+
callbackfun()
|
|
1410
|
+
app.exec()
|
|
1411
|
+
app.quit()
|
|
1412
|
+
app=None
|
|
1413
|
+
"""
|