setiastrosuitepro 1.6.0__py3-none-any.whl → 1.6.4.post1__py3-none-any.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.
Potentially problematic release.
This version of setiastrosuitepro might be problematic. Click here for more details.
- setiastro/data/SASP_data.fits +0 -0
- setiastro/data/catalogs/List_of_Galaxies_with_Distances_Gly.csv +488 -0
- setiastro/data/catalogs/astrobin_filters.csv +890 -0
- setiastro/data/catalogs/astrobin_filters_page1_local.csv +51 -0
- setiastro/data/catalogs/cali2.csv +63 -0
- setiastro/data/catalogs/cali2color.csv +65 -0
- setiastro/data/catalogs/celestial_catalog - original.csv +16471 -0
- setiastro/data/catalogs/celestial_catalog.csv +24031 -0
- setiastro/data/catalogs/detected_stars.csv +24784 -0
- setiastro/data/catalogs/fits_header_data.csv +46 -0
- setiastro/data/catalogs/test.csv +8 -0
- setiastro/data/catalogs/updated_celestial_catalog.csv +16471 -0
- setiastro/images/Astro_Spikes.png +0 -0
- setiastro/images/Background_startup.jpg +0 -0
- setiastro/images/HRDiagram.png +0 -0
- setiastro/images/LExtract.png +0 -0
- setiastro/images/LInsert.png +0 -0
- setiastro/images/Oxygenation-atm-2.svg.png +0 -0
- setiastro/images/RGB080604.png +0 -0
- setiastro/images/abeicon.png +0 -0
- setiastro/images/aberration.png +0 -0
- setiastro/images/andromedatry.png +0 -0
- setiastro/images/andromedatry_satellited.png +0 -0
- setiastro/images/annotated.png +0 -0
- setiastro/images/aperture.png +0 -0
- setiastro/images/astrosuite.ico +0 -0
- setiastro/images/astrosuite.png +0 -0
- setiastro/images/astrosuitepro.icns +0 -0
- setiastro/images/astrosuitepro.ico +0 -0
- setiastro/images/astrosuitepro.png +0 -0
- setiastro/images/background.png +0 -0
- setiastro/images/background2.png +0 -0
- setiastro/images/benchmark.png +0 -0
- setiastro/images/big_moon_stabilizer_timeline.png +0 -0
- setiastro/images/big_moon_stabilizer_timeline_clean.png +0 -0
- setiastro/images/blaster.png +0 -0
- setiastro/images/blink.png +0 -0
- setiastro/images/clahe.png +0 -0
- setiastro/images/collage.png +0 -0
- setiastro/images/colorwheel.png +0 -0
- setiastro/images/contsub.png +0 -0
- setiastro/images/convo.png +0 -0
- setiastro/images/copyslot.png +0 -0
- setiastro/images/cosmic.png +0 -0
- setiastro/images/cosmicsat.png +0 -0
- setiastro/images/crop1.png +0 -0
- setiastro/images/cropicon.png +0 -0
- setiastro/images/curves.png +0 -0
- setiastro/images/cvs.png +0 -0
- setiastro/images/debayer.png +0 -0
- setiastro/images/denoise_cnn_custom.png +0 -0
- setiastro/images/denoise_cnn_graph.png +0 -0
- setiastro/images/disk.png +0 -0
- setiastro/images/dse.png +0 -0
- setiastro/images/exoicon.png +0 -0
- setiastro/images/eye.png +0 -0
- setiastro/images/fliphorizontal.png +0 -0
- setiastro/images/flipvertical.png +0 -0
- setiastro/images/font.png +0 -0
- setiastro/images/freqsep.png +0 -0
- setiastro/images/functionbundle.png +0 -0
- setiastro/images/graxpert.png +0 -0
- setiastro/images/green.png +0 -0
- setiastro/images/gridicon.png +0 -0
- setiastro/images/halo.png +0 -0
- setiastro/images/hdr.png +0 -0
- setiastro/images/histogram.png +0 -0
- setiastro/images/hubble.png +0 -0
- setiastro/images/imagecombine.png +0 -0
- setiastro/images/invert.png +0 -0
- setiastro/images/isophote.png +0 -0
- setiastro/images/isophote_demo_figure.png +0 -0
- setiastro/images/isophote_demo_image.png +0 -0
- setiastro/images/isophote_demo_model.png +0 -0
- setiastro/images/isophote_demo_residual.png +0 -0
- setiastro/images/jwstpupil.png +0 -0
- setiastro/images/linearfit.png +0 -0
- setiastro/images/livestacking.png +0 -0
- setiastro/images/mask.png +0 -0
- setiastro/images/maskapply.png +0 -0
- setiastro/images/maskcreate.png +0 -0
- setiastro/images/maskremove.png +0 -0
- setiastro/images/morpho.png +0 -0
- setiastro/images/mosaic.png +0 -0
- setiastro/images/multiscale_decomp.png +0 -0
- setiastro/images/nbtorgb.png +0 -0
- setiastro/images/neutral.png +0 -0
- setiastro/images/nuke.png +0 -0
- setiastro/images/openfile.png +0 -0
- setiastro/images/pedestal.png +0 -0
- setiastro/images/pen.png +0 -0
- setiastro/images/pixelmath.png +0 -0
- setiastro/images/platesolve.png +0 -0
- setiastro/images/ppp.png +0 -0
- setiastro/images/pro.png +0 -0
- setiastro/images/project.png +0 -0
- setiastro/images/psf.png +0 -0
- setiastro/images/redo.png +0 -0
- setiastro/images/redoicon.png +0 -0
- setiastro/images/rescale.png +0 -0
- setiastro/images/rgbalign.png +0 -0
- setiastro/images/rgbcombo.png +0 -0
- setiastro/images/rgbextract.png +0 -0
- setiastro/images/rotate180.png +0 -0
- setiastro/images/rotatearbitrary.png +0 -0
- setiastro/images/rotateclockwise.png +0 -0
- setiastro/images/rotatecounterclockwise.png +0 -0
- setiastro/images/satellite.png +0 -0
- setiastro/images/script.png +0 -0
- setiastro/images/selectivecolor.png +0 -0
- setiastro/images/simbad.png +0 -0
- setiastro/images/slot0.png +0 -0
- setiastro/images/slot1.png +0 -0
- setiastro/images/slot2.png +0 -0
- setiastro/images/slot3.png +0 -0
- setiastro/images/slot4.png +0 -0
- setiastro/images/slot5.png +0 -0
- setiastro/images/slot6.png +0 -0
- setiastro/images/slot7.png +0 -0
- setiastro/images/slot8.png +0 -0
- setiastro/images/slot9.png +0 -0
- setiastro/images/spcc.png +0 -0
- setiastro/images/spin_precession_vs_lunar_distance.png +0 -0
- setiastro/images/spinner.gif +0 -0
- setiastro/images/stacking.png +0 -0
- setiastro/images/staradd.png +0 -0
- setiastro/images/staralign.png +0 -0
- setiastro/images/starnet.png +0 -0
- setiastro/images/starregistration.png +0 -0
- setiastro/images/starspike.png +0 -0
- setiastro/images/starstretch.png +0 -0
- setiastro/images/statstretch.png +0 -0
- setiastro/images/supernova.png +0 -0
- setiastro/images/uhs.png +0 -0
- setiastro/images/undoicon.png +0 -0
- setiastro/images/upscale.png +0 -0
- setiastro/images/viewbundle.png +0 -0
- setiastro/images/whitebalance.png +0 -0
- setiastro/images/wimi_icon_256x256.png +0 -0
- setiastro/images/wimilogo.png +0 -0
- setiastro/images/wims.png +0 -0
- setiastro/images/wrench_icon.png +0 -0
- setiastro/images/xisfliberator.png +0 -0
- setiastro/qml/ResourceMonitor.qml +126 -0
- setiastro/saspro/__main__.py +228 -67
- setiastro/saspro/_generated/build_info.py +2 -1
- setiastro/saspro/abe.py +76 -25
- setiastro/saspro/aberration_ai.py +14 -14
- setiastro/saspro/add_stars.py +15 -12
- setiastro/saspro/astrobin_exporter.py +61 -58
- setiastro/saspro/astrospike_python.py +3 -1
- setiastro/saspro/autostretch.py +4 -2
- setiastro/saspro/backgroundneutral.py +65 -14
- setiastro/saspro/batch_convert.py +8 -5
- setiastro/saspro/batch_renamer.py +39 -36
- setiastro/saspro/blemish_blaster.py +15 -12
- setiastro/saspro/blink_comparator_pro.py +605 -379
- setiastro/saspro/cheat_sheet.py +62 -17
- setiastro/saspro/clahe.py +34 -8
- setiastro/saspro/comet_stacking.py +103 -38
- setiastro/saspro/common_tr.py +107 -0
- setiastro/saspro/continuum_subtract.py +7 -7
- setiastro/saspro/convo.py +12 -9
- setiastro/saspro/copyastro.py +3 -0
- setiastro/saspro/cosmicclarity.py +77 -52
- setiastro/saspro/crop_dialog_pro.py +80 -45
- setiastro/saspro/curve_editor_pro.py +51 -33
- setiastro/saspro/debayer.py +6 -3
- setiastro/saspro/doc_manager.py +49 -19
- setiastro/saspro/exoplanet_detector.py +11 -11
- setiastro/saspro/fitsmodifier.py +48 -44
- setiastro/saspro/fix_bom.py +32 -0
- setiastro/saspro/frequency_separation.py +18 -12
- setiastro/saspro/function_bundle.py +18 -16
- setiastro/saspro/generate_translations.py +3092 -0
- setiastro/saspro/ghs_dialog_pro.py +19 -16
- setiastro/saspro/graxpert.py +3 -0
- setiastro/saspro/gui/main_window.py +471 -126
- setiastro/saspro/gui/mixins/dock_mixin.py +123 -11
- setiastro/saspro/gui/mixins/file_mixin.py +25 -20
- setiastro/saspro/gui/mixins/geometry_mixin.py +115 -15
- setiastro/saspro/gui/mixins/header_mixin.py +6 -6
- setiastro/saspro/gui/mixins/mask_mixin.py +8 -8
- setiastro/saspro/gui/mixins/menu_mixin.py +62 -33
- setiastro/saspro/gui/mixins/toolbar_mixin.py +382 -226
- setiastro/saspro/gui/mixins/update_mixin.py +26 -26
- setiastro/saspro/gui/statistics_dialog.py +47 -0
- setiastro/saspro/halobgon.py +29 -3
- setiastro/saspro/header_viewer.py +21 -18
- setiastro/saspro/histogram.py +29 -26
- setiastro/saspro/history_explorer.py +2 -0
- setiastro/saspro/i18n.py +168 -0
- setiastro/saspro/image_combine.py +3 -0
- setiastro/saspro/image_peeker_pro.py +52 -44
- setiastro/saspro/imageops/stretch.py +5 -13
- setiastro/saspro/isophote.py +3 -0
- setiastro/saspro/legacy/numba_utils.py +64 -47
- setiastro/saspro/linear_fit.py +3 -0
- setiastro/saspro/live_stacking.py +13 -2
- setiastro/saspro/mask_creation.py +180 -22
- setiastro/saspro/mfdeconv.py +5 -0
- setiastro/saspro/morphology.py +38 -13
- setiastro/saspro/multiscale_decomp.py +713 -256
- setiastro/saspro/nbtorgb_stars.py +12 -2
- setiastro/saspro/numba_utils.py +149 -48
- setiastro/saspro/ops/scripts.py +77 -17
- setiastro/saspro/ops/settings.py +177 -100
- setiastro/saspro/perfect_palette_picker.py +25 -7
- setiastro/saspro/pixelmath.py +114 -110
- setiastro/saspro/plate_solver.py +118 -108
- setiastro/saspro/remove_green.py +24 -7
- setiastro/saspro/remove_stars.py +136 -162
- setiastro/saspro/remove_stars_preset.py +55 -13
- setiastro/saspro/resources.py +46 -15
- setiastro/saspro/rgb_combination.py +19 -18
- setiastro/saspro/rgbalign.py +11 -11
- setiastro/saspro/save_options.py +5 -4
- setiastro/saspro/selective_color.py +84 -25
- setiastro/saspro/sfcc.py +119 -72
- setiastro/saspro/shortcuts.py +345 -36
- setiastro/saspro/signature_insert.py +4 -1
- setiastro/saspro/stacking_suite.py +2066 -1119
- setiastro/saspro/star_alignment.py +291 -331
- setiastro/saspro/star_spikes.py +137 -53
- setiastro/saspro/star_stretch.py +47 -10
- setiastro/saspro/stat_stretch.py +52 -16
- setiastro/saspro/status_log_dock.py +1 -1
- setiastro/saspro/subwindow.py +97 -36
- setiastro/saspro/supernovaasteroidhunter.py +68 -61
- setiastro/saspro/swap_manager.py +77 -42
- setiastro/saspro/translations/all_source_strings.json +4726 -0
- setiastro/saspro/translations/ar_translations.py +4096 -0
- setiastro/saspro/translations/de_translations.py +3728 -0
- setiastro/saspro/translations/es_translations.py +4169 -0
- setiastro/saspro/translations/fr_translations.py +4090 -0
- setiastro/saspro/translations/hi_translations.py +3803 -0
- setiastro/saspro/translations/integrate_translations.py +271 -0
- setiastro/saspro/translations/it_translations.py +4728 -0
- setiastro/saspro/translations/ja_translations.py +3834 -0
- setiastro/saspro/translations/pt_translations.py +3847 -0
- setiastro/saspro/translations/ru_translations.py +3082 -0
- setiastro/saspro/translations/saspro_ar.qm +0 -0
- setiastro/saspro/translations/saspro_ar.ts +16019 -0
- setiastro/saspro/translations/saspro_de.qm +0 -0
- setiastro/saspro/translations/saspro_de.ts +14548 -0
- setiastro/saspro/translations/saspro_es.qm +0 -0
- setiastro/saspro/translations/saspro_es.ts +16202 -0
- setiastro/saspro/translations/saspro_fr.qm +0 -0
- setiastro/saspro/translations/saspro_fr.ts +15870 -0
- setiastro/saspro/translations/saspro_hi.qm +0 -0
- setiastro/saspro/translations/saspro_hi.ts +14855 -0
- setiastro/saspro/translations/saspro_it.qm +0 -0
- setiastro/saspro/translations/saspro_it.ts +19046 -0
- setiastro/saspro/translations/saspro_ja.qm +0 -0
- setiastro/saspro/translations/saspro_ja.ts +14980 -0
- setiastro/saspro/translations/saspro_pt.qm +0 -0
- setiastro/saspro/translations/saspro_pt.ts +15024 -0
- setiastro/saspro/translations/saspro_ru.qm +0 -0
- setiastro/saspro/translations/saspro_ru.ts +11835 -0
- setiastro/saspro/translations/saspro_sw.qm +0 -0
- setiastro/saspro/translations/saspro_sw.ts +15237 -0
- setiastro/saspro/translations/saspro_uk.qm +0 -0
- setiastro/saspro/translations/saspro_uk.ts +15248 -0
- setiastro/saspro/translations/saspro_zh.qm +0 -0
- setiastro/saspro/translations/saspro_zh.ts +15289 -0
- setiastro/saspro/translations/sw_translations.py +3897 -0
- setiastro/saspro/translations/uk_translations.py +3929 -0
- setiastro/saspro/translations/zh_translations.py +3910 -0
- setiastro/saspro/versioning.py +77 -0
- setiastro/saspro/view_bundle.py +20 -17
- setiastro/saspro/wavescale_hdr.py +54 -33
- setiastro/saspro/wavescale_hdr_preset.py +6 -5
- setiastro/saspro/wavescalede.py +54 -31
- setiastro/saspro/wavescalede_preset.py +9 -7
- setiastro/saspro/whitebalance.py +58 -22
- setiastro/saspro/widgets/common_utilities.py +12 -11
- setiastro/saspro/widgets/minigame/game.js +991 -0
- setiastro/saspro/widgets/minigame/index.html +53 -0
- setiastro/saspro/widgets/minigame/style.css +241 -0
- setiastro/saspro/widgets/preview_dialogs.py +8 -8
- setiastro/saspro/widgets/resource_monitor.py +263 -0
- setiastro/saspro/widgets/spinboxes.py +18 -0
- setiastro/saspro/widgets/wavelet_utils.py +52 -20
- setiastro/saspro/wimi.py +7996 -0
- setiastro/saspro/wims.py +578 -0
- setiastro/saspro/window_shelf.py +2 -2
- {setiastrosuitepro-1.6.0.dist-info → setiastrosuitepro-1.6.4.post1.dist-info}/METADATA +15 -3
- setiastrosuitepro-1.6.4.post1.dist-info/RECORD +368 -0
- setiastrosuitepro-1.6.0.dist-info/RECORD +0 -174
- {setiastrosuitepro-1.6.0.dist-info → setiastrosuitepro-1.6.4.post1.dist-info}/WHEEL +0 -0
- {setiastrosuitepro-1.6.0.dist-info → setiastrosuitepro-1.6.4.post1.dist-info}/entry_points.txt +0 -0
- {setiastrosuitepro-1.6.0.dist-info → setiastrosuitepro-1.6.4.post1.dist-info}/licenses/LICENSE +0 -0
- {setiastrosuitepro-1.6.0.dist-info → setiastrosuitepro-1.6.4.post1.dist-info}/licenses/license.txt +0 -0
setiastro/saspro/pixelmath.py
CHANGED
|
@@ -59,9 +59,10 @@ class PixelImage:
|
|
|
59
59
|
a = np.asarray(a, dtype=np.float32)
|
|
60
60
|
b = np.asarray(b, dtype=np.float32)
|
|
61
61
|
if a.ndim == 3 and b.ndim == 2:
|
|
62
|
-
b
|
|
62
|
+
# Broadcast b to (H,W,1) virtual view; numpy ufuncs handle (H,W,3) vs (H,W,1) automatically
|
|
63
|
+
b = b[..., None]
|
|
63
64
|
elif a.ndim == 2 and b.ndim == 3:
|
|
64
|
-
a =
|
|
65
|
+
a = a[..., None]
|
|
65
66
|
return a, b
|
|
66
67
|
|
|
67
68
|
# ---- binary arithmetic helpers ----
|
|
@@ -755,7 +756,10 @@ class PixelMathDialogPro(QDialog):
|
|
|
755
756
|
"""
|
|
756
757
|
def __init__(self, parent, doc, icon: QIcon | None = None):
|
|
757
758
|
super().__init__(parent)
|
|
758
|
-
self.setWindowTitle("Pixel Math")
|
|
759
|
+
self.setWindowTitle(self.tr("Pixel Math"))
|
|
760
|
+
self.setWindowFlag(Qt.WindowType.Window, True)
|
|
761
|
+
self.setWindowModality(Qt.WindowModality.NonModal)
|
|
762
|
+
self.setModal(False)
|
|
759
763
|
if icon:
|
|
760
764
|
try:
|
|
761
765
|
self.setWindowIcon(icon)
|
|
@@ -805,7 +809,7 @@ class PixelMathDialogPro(QDialog):
|
|
|
805
809
|
# ──────────────────────────────────────────────────────────────────────────
|
|
806
810
|
# Variables mapping (raw title → identifier)
|
|
807
811
|
# ──────────────────────────────────────────────────────────────────────────
|
|
808
|
-
vars_grp = QGroupBox("Variables")
|
|
812
|
+
vars_grp = QGroupBox(self.tr("Variables"))
|
|
809
813
|
vars_layout = QVBoxLayout(vars_grp)
|
|
810
814
|
|
|
811
815
|
self.vars_list = QListWidget()
|
|
@@ -832,7 +836,7 @@ class PixelMathDialogPro(QDialog):
|
|
|
832
836
|
# First item = active view
|
|
833
837
|
active_item = QListWidgetItem("img (active)")
|
|
834
838
|
active_item.setData(Qt.ItemDataRole.UserRole, "img") # ← stash the real name
|
|
835
|
-
active_item.setToolTip("img (active)")
|
|
839
|
+
active_item.setToolTip(self.tr("img (active)"))
|
|
836
840
|
self.vars_list.addItem(active_item)
|
|
837
841
|
|
|
838
842
|
# Other open views
|
|
@@ -847,7 +851,7 @@ class PixelMathDialogPro(QDialog):
|
|
|
847
851
|
self.vars_list.setMinimumHeight(120)
|
|
848
852
|
self.vars_list.setMaximumHeight(180)
|
|
849
853
|
|
|
850
|
-
hint = QLabel("Tip: double-click to insert the identifier at the cursor")
|
|
854
|
+
hint = QLabel(self.tr("Tip: double-click to insert the identifier at the cursor"))
|
|
851
855
|
hint.setStyleSheet("color: gray; font-size: 11px;")
|
|
852
856
|
|
|
853
857
|
vars_layout.addWidget(self.vars_list)
|
|
@@ -873,10 +877,10 @@ class PixelMathDialogPro(QDialog):
|
|
|
873
877
|
# ──────────────────────────────────────────────────────────────────────────
|
|
874
878
|
# Output group
|
|
875
879
|
# ──────────────────────────────────────────────────────────────────────────
|
|
876
|
-
out_grp = QGroupBox("Output")
|
|
880
|
+
out_grp = QGroupBox(self.tr("Output"))
|
|
877
881
|
out_row = QHBoxLayout(out_grp)
|
|
878
|
-
self.rb_out_overwrite = QRadioButton("Overwrite active"); self.rb_out_overwrite.setChecked(True)
|
|
879
|
-
self.rb_out_new = QRadioButton("Create new view")
|
|
882
|
+
self.rb_out_overwrite = QRadioButton(self.tr("Overwrite active")); self.rb_out_overwrite.setChecked(True)
|
|
883
|
+
self.rb_out_new = QRadioButton(self.tr("Create new view"))
|
|
880
884
|
out_row.addWidget(self.rb_out_overwrite)
|
|
881
885
|
out_row.addWidget(self.rb_out_new)
|
|
882
886
|
out_row.addStretch(1)
|
|
@@ -886,8 +890,8 @@ class PixelMathDialogPro(QDialog):
|
|
|
886
890
|
# Mode (single expression vs per-channel)
|
|
887
891
|
# ──────────────────────────────────────────────────────────────────────────
|
|
888
892
|
mode_row = QHBoxLayout()
|
|
889
|
-
self.rb_single = QRadioButton("Single Expression"); self.rb_single.setChecked(True)
|
|
890
|
-
self.rb_sep = QRadioButton("Separate (R / G / B)")
|
|
893
|
+
self.rb_single = QRadioButton(self.tr("Single Expression")); self.rb_single.setChecked(True)
|
|
894
|
+
self.rb_sep = QRadioButton(self.tr("Separate (R / G / B)"))
|
|
891
895
|
mode_row.addWidget(self.rb_single)
|
|
892
896
|
mode_row.addWidget(self.rb_sep)
|
|
893
897
|
mode_row.addStretch(1)
|
|
@@ -900,48 +904,48 @@ class PixelMathDialogPro(QDialog):
|
|
|
900
904
|
|
|
901
905
|
# Editors
|
|
902
906
|
self.ed_single = QPlainTextEdit()
|
|
903
|
-
self.ed_single.setPlaceholderText("e.g. (img + otherView) / 2")
|
|
907
|
+
self.ed_single.setPlaceholderText(self.tr("e.g. (img + otherView) / 2"))
|
|
904
908
|
left_col.addWidget(self.ed_single)
|
|
905
909
|
|
|
906
910
|
self.tabs = QTabWidget(); self.tabs.setVisible(False)
|
|
907
911
|
self.ed_r, self.ed_g, self.ed_b = QPlainTextEdit(), QPlainTextEdit(), QPlainTextEdit()
|
|
908
|
-
for ed, name in ((self.ed_r, "Red"), (self.ed_g, "Green"), (self.ed_b, "Blue")):
|
|
912
|
+
for ed, name in ((self.ed_r, self.tr("Red")), (self.ed_g, self.tr("Green")), (self.ed_b, self.tr("Blue"))):
|
|
909
913
|
w = QWidget(); lay = QVBoxLayout(w); lay.addWidget(ed); self.tabs.addTab(w, name)
|
|
910
914
|
left_col.addWidget(self.tabs)
|
|
911
915
|
|
|
912
916
|
self.rb_single.toggled.connect(lambda on: self._mode(on))
|
|
913
917
|
|
|
914
|
-
glossary_btn = QPushButton("Glossary…")
|
|
918
|
+
glossary_btn = QPushButton(self.tr("Glossary…"))
|
|
915
919
|
glossary_btn.clicked.connect(self._open_glossary)
|
|
916
920
|
left_col.addWidget(glossary_btn)
|
|
917
921
|
|
|
918
922
|
# ──────────────────────────────────────────────────────────────────────────
|
|
919
923
|
# Preview (right side)
|
|
920
924
|
# ──────────────────────────────────────────────────────────────────────────
|
|
921
|
-
preview_grp = QGroupBox("Preview")
|
|
925
|
+
preview_grp = QGroupBox(self.tr("Preview"))
|
|
922
926
|
pv_lay = QVBoxLayout(preview_grp)
|
|
923
927
|
|
|
924
928
|
# Toolbar
|
|
925
929
|
tb = QHBoxLayout()
|
|
926
|
-
self.btn_preview = QPushButton("Preview")
|
|
927
|
-
self.btn_preview.setToolTip("Compute Pixel Math and show the result here without committing.")
|
|
930
|
+
self.btn_preview = QPushButton(self.tr("Preview"))
|
|
931
|
+
self.btn_preview.setToolTip(self.tr("Compute Pixel Math and show the result here without committing."))
|
|
928
932
|
|
|
929
933
|
# NEW: Auto-stretch toggle with a dropdown menu
|
|
930
934
|
self.btn_autostretch = QToolButton()
|
|
931
|
-
self.btn_autostretch.setText("Auto-stretch")
|
|
935
|
+
self.btn_autostretch.setText(self.tr("Auto-stretch"))
|
|
932
936
|
self.btn_autostretch.setCheckable(True)
|
|
933
937
|
self.btn_autostretch.setChecked(self._as_enabled)
|
|
934
938
|
self.btn_autostretch.setPopupMode(QToolButton.ToolButtonPopupMode.MenuButtonPopup)
|
|
935
939
|
|
|
936
940
|
as_menu = QMenu(self)
|
|
937
|
-
act_toggle = as_menu.addAction("Enable Auto-stretch")
|
|
941
|
+
act_toggle = as_menu.addAction(self.tr("Enable Auto-stretch"))
|
|
938
942
|
act_toggle.setCheckable(True); act_toggle.setChecked(self._as_enabled)
|
|
939
943
|
as_menu.addSeparator()
|
|
940
944
|
|
|
941
945
|
# Target presets
|
|
942
|
-
tgt_menu = as_menu.addMenu("Target median")
|
|
946
|
+
tgt_menu = as_menu.addMenu(self.tr("Target median"))
|
|
943
947
|
self._tgt_group = QActionGroup(self); self._tgt_group.setExclusive(True)
|
|
944
|
-
for label, val in (("0.18 (soft)", 0.18), ("0.25 (default)", 0.25), ("0.35 (brighter)", 0.35)):
|
|
948
|
+
for label, val in ((self.tr("0.18 (soft)"), 0.18), (self.tr("0.25 (default)"), 0.25), (self.tr("0.35 (brighter)"), 0.35)):
|
|
945
949
|
a = tgt_menu.addAction(label)
|
|
946
950
|
a.setCheckable(True)
|
|
947
951
|
a.setChecked(abs(self._as_target - val) < 1e-6)
|
|
@@ -949,9 +953,9 @@ class PixelMathDialogPro(QDialog):
|
|
|
949
953
|
a.triggered.connect(lambda _=False, v=val: self._set_as_target(v))
|
|
950
954
|
|
|
951
955
|
# Sigma presets
|
|
952
|
-
sig_menu = as_menu.addMenu("Black-point sigma")
|
|
956
|
+
sig_menu = as_menu.addMenu(self.tr("Black-point sigma"))
|
|
953
957
|
self._sig_group = QActionGroup(self); self._sig_group.setExclusive(True)
|
|
954
|
-
for label, val in (("σ=2.5", 2.5), ("σ=3 (default)", 3.0), ("σ=4 (deeper black)", 4.0)):
|
|
958
|
+
for label, val in ((self.tr("σ=2.5"), 2.5), (self.tr("σ=3 (default)"), 3.0), (self.tr("σ=4 (deeper black)"), 4.0)):
|
|
955
959
|
a = sig_menu.addAction(label)
|
|
956
960
|
a.setCheckable(True)
|
|
957
961
|
a.setChecked(abs(self._as_sigma - val) < 1e-6)
|
|
@@ -959,12 +963,12 @@ class PixelMathDialogPro(QDialog):
|
|
|
959
963
|
a.triggered.connect(lambda _=False, v=val: self._set_as_sigma(v))
|
|
960
964
|
|
|
961
965
|
# Linked channels
|
|
962
|
-
act_linked = as_menu.addAction("Linked channels (use luminance)")
|
|
966
|
+
act_linked = as_menu.addAction(self.tr("Linked channels (use luminance)"))
|
|
963
967
|
act_linked.setCheckable(True); act_linked.setChecked(self._as_linked)
|
|
964
968
|
as_menu.addSeparator()
|
|
965
969
|
|
|
966
970
|
# Output precision
|
|
967
|
-
act_16 = as_menu.addAction("Use 16-bit stats")
|
|
971
|
+
act_16 = as_menu.addAction(self.tr("Use 16-bit stats"))
|
|
968
972
|
act_16.setCheckable(True); act_16.setChecked(self._as_16bit)
|
|
969
973
|
|
|
970
974
|
self.btn_autostretch.setMenu(as_menu)
|
|
@@ -1021,10 +1025,10 @@ class PixelMathDialogPro(QDialog):
|
|
|
1021
1025
|
self._set_as_sigma = _set_sigma
|
|
1022
1026
|
|
|
1023
1027
|
# existing zoom buttons
|
|
1024
|
-
self.btn_zoom_in = themed_toolbtn("zoom-in", "Zoom In")
|
|
1025
|
-
self.btn_zoom_out = themed_toolbtn("zoom-out", "Zoom Out")
|
|
1026
|
-
self.btn_zoom_1_1 = themed_toolbtn("zoom-original", "1:1")
|
|
1027
|
-
self.btn_fit = themed_toolbtn("zoom-fit-best", "Fit to Preview")
|
|
1028
|
+
self.btn_zoom_in = themed_toolbtn("zoom-in", self.tr("Zoom In"))
|
|
1029
|
+
self.btn_zoom_out = themed_toolbtn("zoom-out", self.tr("Zoom Out"))
|
|
1030
|
+
self.btn_zoom_1_1 = themed_toolbtn("zoom-original", self.tr("1:1"))
|
|
1031
|
+
self.btn_fit = themed_toolbtn("zoom-fit-best", self.tr("Fit to Preview"))
|
|
1028
1032
|
|
|
1029
1033
|
tb.addWidget(self.btn_preview)
|
|
1030
1034
|
tb.addWidget(self.btn_autostretch) # ← NEW
|
|
@@ -1056,9 +1060,9 @@ class PixelMathDialogPro(QDialog):
|
|
|
1056
1060
|
# Examples (insertable templates)
|
|
1057
1061
|
# ──────────────────────────────────────────────────────────────────────────
|
|
1058
1062
|
ex_row = QHBoxLayout()
|
|
1059
|
-
ex_row.addWidget(QLabel("Examples:"))
|
|
1063
|
+
ex_row.addWidget(QLabel(self.tr("Examples:")))
|
|
1060
1064
|
self.cb_examples = QComboBox()
|
|
1061
|
-
self.cb_examples.addItem("Insert example…")
|
|
1065
|
+
self.cb_examples.addItem(self.tr("Insert example…"))
|
|
1062
1066
|
for title, kind, payload in self._examples_list():
|
|
1063
1067
|
self.cb_examples.addItem(title, (kind, payload))
|
|
1064
1068
|
self.cb_examples.currentIndexChanged.connect(self._apply_example_from_combo)
|
|
@@ -1069,12 +1073,12 @@ class PixelMathDialogPro(QDialog):
|
|
|
1069
1073
|
# Favorites
|
|
1070
1074
|
# ──────────────────────────────────────────────────────────────────────────
|
|
1071
1075
|
fav_row = QHBoxLayout()
|
|
1072
|
-
self.cb_fav = QComboBox(); self.cb_fav.addItem("Select a favorite expression")
|
|
1076
|
+
self.cb_fav = QComboBox(); self.cb_fav.addItem(self.tr("Select a favorite expression"))
|
|
1073
1077
|
self._load_favorites()
|
|
1074
1078
|
self.cb_fav.currentTextChanged.connect(self._pick_favorite)
|
|
1075
1079
|
|
|
1076
|
-
b_save = QPushButton("Save as Favorite")
|
|
1077
|
-
b_del = QPushButton("Delete Favorite")
|
|
1080
|
+
b_save = QPushButton(self.tr("Save as Favorite"))
|
|
1081
|
+
b_del = QPushButton(self.tr("Delete Favorite"))
|
|
1078
1082
|
|
|
1079
1083
|
b_save.clicked.connect(self._save_favorite)
|
|
1080
1084
|
b_del.clicked.connect(self._delete_favorite)
|
|
@@ -1088,7 +1092,7 @@ class PixelMathDialogPro(QDialog):
|
|
|
1088
1092
|
if self.cb_fav.currentIndex() <= 0:
|
|
1089
1093
|
return
|
|
1090
1094
|
menu = QMenu(self)
|
|
1091
|
-
act_del = menu.addAction("Delete this favorite")
|
|
1095
|
+
act_del = menu.addAction(self.tr("Delete this favorite"))
|
|
1092
1096
|
act = menu.exec(self.cb_fav.mapToGlobal(point))
|
|
1093
1097
|
if act == act_del:
|
|
1094
1098
|
self._delete_favorite()
|
|
@@ -1102,7 +1106,7 @@ class PixelMathDialogPro(QDialog):
|
|
|
1102
1106
|
btns = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel, parent=self)
|
|
1103
1107
|
btns.accepted.connect(self._apply)
|
|
1104
1108
|
btns.rejected.connect(self.reject)
|
|
1105
|
-
b_help = btns.addButton("Help", QDialogButtonBox.ButtonRole.HelpRole)
|
|
1109
|
+
b_help = btns.addButton(self.tr("Help"), QDialogButtonBox.ButtonRole.HelpRole)
|
|
1106
1110
|
b_help.clicked.connect(self._help)
|
|
1107
1111
|
left_col.addWidget(btns)
|
|
1108
1112
|
|
|
@@ -1184,8 +1188,8 @@ class PixelMathDialogPro(QDialog):
|
|
|
1184
1188
|
except Exception as e:
|
|
1185
1189
|
msg = str(e)
|
|
1186
1190
|
if "name '" in msg and "' is not defined" in msg:
|
|
1187
|
-
msg += "\n\nTip: use the identifier listed in Variables (or the raw title; it’s auto-mapped)."
|
|
1188
|
-
QMessageBox.critical(self, "Pixel Math Preview",
|
|
1191
|
+
msg += self.tr("\n\nTip: use the identifier listed in Variables (or the raw title; it’s auto-mapped).")
|
|
1192
|
+
QMessageBox.critical(self, self.tr("Pixel Math Preview"), self.tr("Failed:\n{0}").format(msg))
|
|
1189
1193
|
finally:
|
|
1190
1194
|
QApplication.restoreOverrideCursor()
|
|
1191
1195
|
|
|
@@ -1256,93 +1260,93 @@ class PixelMathDialogPro(QDialog):
|
|
|
1256
1260
|
|
|
1257
1261
|
return [
|
|
1258
1262
|
# --- existing basics ---
|
|
1259
|
-
("Average two views", "single", f"({a} + {b}) / 2"),
|
|
1260
|
-
("Difference (A - B)", "single", f"{a} - {b}"),
|
|
1261
|
-
("Invert active", "single", f"~{a}"),
|
|
1262
|
-
("Subtract median (bias remove)", "single", f"{a} - med({a})"),
|
|
1263
|
-
("Zero-center by mean", "single", f"{a} - mean({a})"),
|
|
1264
|
-
("Min + Max combine", "single", f"min({a}) + max({a})"),
|
|
1265
|
-
("Log transform", "single", f"log({a} + 1e-6)"),
|
|
1266
|
-
("Midtones transform m=0.25", "single", f"mtf({a}, 0.25)"),
|
|
1267
|
-
("If darker than median → 0 else 1", "single", f"iff({a} < med({a}), 0, 1)"),
|
|
1268
|
-
|
|
1269
|
-
("Per-channel: swap R↔B", "rgb", (f"{a}[2]", f"{a}[1]", f"{a}[0]")),
|
|
1270
|
-
("Per-channel: avg A & B", "rgb", (f"({a}[0]+{b}[0])/2", f"({a}[1]+{b}[1])/2", f"({a}[2]+{b}[2])/2")),
|
|
1271
|
-
("Per-channel: build RGB from A,B,C", "rgb", (f"{a}[0]", f"{b}[1]", f"{c}[2]")),
|
|
1263
|
+
(self.tr("Average two views"), "single", f"({a} + {b}) / 2"),
|
|
1264
|
+
(self.tr("Difference (A - B)"), "single", f"{a} - {b}"),
|
|
1265
|
+
(self.tr("Invert active"), "single", f"~{a}"),
|
|
1266
|
+
(self.tr("Subtract median (bias remove)"), "single", f"{a} - med({a})"),
|
|
1267
|
+
(self.tr("Zero-center by mean"), "single", f"{a} - mean({a})"),
|
|
1268
|
+
(self.tr("Min + Max combine"), "single", f"min({a}) + max({a})"),
|
|
1269
|
+
(self.tr("Log transform"), "single", f"log({a} + 1e-6)"),
|
|
1270
|
+
(self.tr("Midtones transform m=0.25"), "single", f"mtf({a}, 0.25)"),
|
|
1271
|
+
(self.tr("If darker than median → 0 else 1"), "single", f"iff({a} < med({a}), 0, 1)"),
|
|
1272
|
+
|
|
1273
|
+
(self.tr("Per-channel: swap R↔B"), "rgb", (f"{a}[2]", f"{a}[1]", f"{a}[0]")),
|
|
1274
|
+
(self.tr("Per-channel: avg A & B"), "rgb", (f"({a}[0]+{b}[0])/2", f"({a}[1]+{b}[1])/2", f"({a}[2]+{b}[2])/2")),
|
|
1275
|
+
(self.tr("Per-channel: build RGB from A,B,C"), "rgb", (f"{a}[0]", f"{b}[1]", f"{c}[2]")),
|
|
1272
1276
|
|
|
1273
1277
|
# --- new, single-expression tone/normalization ---
|
|
1274
|
-
("Normalize to 0–1 (per-channel)", "single", f"normalize01({a})"),
|
|
1275
|
-
("Sigmoid contrast (k=12, mid=0.4)", "single", f"sigmoid({a}, k=12, mid=0.4)"),
|
|
1276
|
-
("Gamma 0.6 (brighten midtones)", "single", f"gamma({a}, 0.6)"),
|
|
1277
|
-
("Percentile stretch 0.5–99.5%", "single",
|
|
1278
|
+
(self.tr("Normalize to 0–1 (per-channel)"), "single", f"normalize01({a})"),
|
|
1279
|
+
(self.tr("Sigmoid contrast (k=12, mid=0.4)"), "single", f"sigmoid({a}, k=12, mid=0.4)"),
|
|
1280
|
+
(self.tr("Gamma 0.6 (brighten midtones)"), "single", f"gamma({a}, 0.6)"),
|
|
1281
|
+
(self.tr("Percentile stretch 0.5–99.5%"), "single",
|
|
1278
1282
|
f"lo = percentile({a}, 0.5)\nhi = percentile({a}, 99.5)\nclamp(({a} - lo) / (hi - lo), 0, 1)"),
|
|
1279
1283
|
|
|
1280
1284
|
# --- blending & masking ---
|
|
1281
|
-
("Blend A→B by horizontal gradient X", "single", f"t = X\nlerp({a}, {b}, t)"),
|
|
1282
|
-
("Apply active mask to blend A→B", "single", f"m = mask()\napply_mask({a}, {b}, m)"),
|
|
1285
|
+
(self.tr("Blend A→B by horizontal gradient X"), "single", f"t = X\nlerp({a}, {b}, t)"),
|
|
1286
|
+
(self.tr("Apply active mask to blend A→B"), "single", f"m = mask()\napply_mask({a}, {b}, m)"),
|
|
1283
1287
|
|
|
1284
1288
|
# --- sharpening with mask (multiline) ---
|
|
1285
|
-
("Masked unsharp (luma-based)", "single",
|
|
1289
|
+
(self.tr("Masked unsharp (luma-based)"), "single",
|
|
1286
1290
|
f"base = {a}\nsh = unsharp({a}, sigma=1.2, amount=0.8)\n"
|
|
1287
1291
|
f"m = smoothstep(0.10, 0.60, luma({a}))\napply_mask(base, sh, m)"),
|
|
1288
1292
|
|
|
1289
1293
|
# --- view matching / calibration ---
|
|
1290
|
-
("Match medians of A to B", "single", f"{a} * (med({b}) / med({a}))"),
|
|
1294
|
+
(self.tr("Match medians of A to B"), "single", f"{a} * (med({b}) / med({a}))"),
|
|
1291
1295
|
|
|
1292
1296
|
# --- small filters ---
|
|
1293
|
-
("Gaussian blur σ=2", "single", f"gauss({a}, sigma=2.0)"),
|
|
1294
|
-
("Median filter k=3", "single", f"median({a}, k=3)"),
|
|
1297
|
+
(self.tr("Gaussian blur σ=2"), "single", f"gauss({a}, sigma=2.0)"),
|
|
1298
|
+
(self.tr("Median filter k=3"), "single", f"median({a}, k=3)"),
|
|
1295
1299
|
|
|
1296
1300
|
# --- per-channel examples using new helpers ---
|
|
1297
|
-
("Per-channel: luma to all channels", "rgb", (f"luma({a})", f"luma({a})", f"luma({a})")),
|
|
1298
|
-
("Per-channel: A’s R, B’s G, C’s B (normed)", "rgb",
|
|
1301
|
+
(self.tr("Per-channel: luma to all channels"), "rgb", (f"luma({a})", f"luma({a})", f"luma({a})")),
|
|
1302
|
+
(self.tr("Per-channel: A’s R, B’s G, C’s B (normed)"), "rgb",
|
|
1299
1303
|
(f"normalize01({a}[0])", f"normalize01({b}[1])", f"normalize01({c}[2])")),
|
|
1300
1304
|
]
|
|
1301
1305
|
|
|
1302
1306
|
def _function_glossary(self):
|
|
1303
1307
|
# name -> (signature / template, short description)
|
|
1304
1308
|
return {
|
|
1305
|
-
"clamp": ("clamp(x, lo=0, hi=1)", "Limit values to [lo..hi]."),
|
|
1306
|
-
"rescale": ("rescale(x, a, b, lo=0, hi=1)", "Map range [a..b] to [lo..hi]."),
|
|
1307
|
-
"gamma": ("gamma(x, g)", "Apply gamma curve."),
|
|
1308
|
-
"pow_safe": ("pow_safe(x, p)", "Power with EPS floor."),
|
|
1309
|
-
"absf": ("absf(x)", "Absolute value."),
|
|
1310
|
-
"expf": ("expf(x)", "Exponential."),
|
|
1311
|
-
"sqrtf": ("sqrtf(x)", "Square root (clamped to ≥0)."),
|
|
1312
|
-
"arcsin": ("arcsin(x)", "Inverse sine (radians), input clipped to [-1,1]."),
|
|
1313
|
-
"sigmoid": ("sigmoid(x, k=10, mid=0.5)", "S-shaped tone curve."),
|
|
1314
|
-
"smoothstep": ("smoothstep(e0, e1, x)", "Cubic smooth ramp."),
|
|
1315
|
-
"lerp/mix": ("lerp(a, b, t)", "Linear blend."),
|
|
1316
|
-
"percentile": ("percentile(x, p)", "Per-channel percentile image."),
|
|
1317
|
-
"normalize01": ("normalize01(x)", "Per-channel [0..1] normalization."),
|
|
1318
|
-
"zscore": ("zscore(x)", "Per-channel (x-mean)/std."),
|
|
1319
|
-
"ch": ("ch(x, i)", "Extract channel i (0/1/2) as 2-D."),
|
|
1320
|
-
"luma": ("luma(x)", "Rec.709 luminance as 2-D."),
|
|
1321
|
-
"compose": ("compose(R, G, B)", "Stack three planes to RGB."),
|
|
1322
|
-
"mask": ("m = mask()", "Active mask (2-D, [0..1])."),
|
|
1323
|
-
"apply_mask": ("apply_mask(base, out, m)", "Blend by mask."),
|
|
1324
|
-
"boxblur": ("boxblur(x, k=3)", "Box blur (cv2 if available)."),
|
|
1325
|
-
"gauss": ("gauss(x, sigma=1.0)", "Gaussian blur."),
|
|
1326
|
-
"median": ("median(x, k=3)", "Median filter (cv2 if avail)."),
|
|
1327
|
-
"unsharp": ("unsharp(x, sigma=1.5, amount=1.0)", "Unsharp mask."),
|
|
1328
|
-
"mtf": ("mtf(x, m)", "Midtones transfer (existing)."),
|
|
1329
|
-
"iff": ("iff(cond, a, b)", "Conditional (existing)."),
|
|
1330
|
-
"X / Y": ("X, Y", "Normalized coordinates in [0..1]."),
|
|
1331
|
-
"H/W/C": ("H, W, C, shape", "Image dimensions."),
|
|
1309
|
+
"clamp": ("clamp(x, lo=0, hi=1)", self.tr("Limit values to [lo..hi].")),
|
|
1310
|
+
"rescale": ("rescale(x, a, b, lo=0, hi=1)", self.tr("Map range [a..b] to [lo..hi].")),
|
|
1311
|
+
"gamma": ("gamma(x, g)", self.tr("Apply gamma curve.")),
|
|
1312
|
+
"pow_safe": ("pow_safe(x, p)", self.tr("Power with EPS floor.")),
|
|
1313
|
+
"absf": ("absf(x)", self.tr("Absolute value.")),
|
|
1314
|
+
"expf": ("expf(x)", self.tr("Exponential.")),
|
|
1315
|
+
"sqrtf": ("sqrtf(x)", self.tr("Square root (clamped to ≥0).")),
|
|
1316
|
+
"arcsin": ("arcsin(x)", self.tr("Inverse sine (radians), input clipped to [-1,1].")),
|
|
1317
|
+
"sigmoid": ("sigmoid(x, k=10, mid=0.5)", self.tr("S-shaped tone curve.")),
|
|
1318
|
+
"smoothstep": ("smoothstep(e0, e1, x)", self.tr("Cubic smooth ramp.")),
|
|
1319
|
+
"lerp/mix": ("lerp(a, b, t)", self.tr("Linear blend.")),
|
|
1320
|
+
"percentile": ("percentile(x, p)", self.tr("Per-channel percentile image.")),
|
|
1321
|
+
"normalize01": ("normalize01(x)", self.tr("Per-channel [0..1] normalization.")),
|
|
1322
|
+
"zscore": ("zscore(x)", self.tr("Per-channel (x-mean)/std.")),
|
|
1323
|
+
"ch": ("ch(x, i)", self.tr("Extract channel i (0/1/2) as 2-D.")),
|
|
1324
|
+
"luma": ("luma(x)", self.tr("Rec.709 luminance as 2-D.")),
|
|
1325
|
+
"compose": ("compose(R, G, B)", self.tr("Stack three planes to RGB.")),
|
|
1326
|
+
"mask": ("m = mask()", self.tr("Active mask (2-D, [0..1]).")),
|
|
1327
|
+
"apply_mask": ("apply_mask(base, out, m)", self.tr("Blend by mask.")),
|
|
1328
|
+
"boxblur": ("boxblur(x, k=3)", self.tr("Box blur (cv2 if available).")),
|
|
1329
|
+
"gauss": ("gauss(x, sigma=1.0)", self.tr("Gaussian blur.")),
|
|
1330
|
+
"median": ("median(x, k=3)", self.tr("Median filter (cv2 if avail).")),
|
|
1331
|
+
"unsharp": ("unsharp(x, sigma=1.5, amount=1.0)", self.tr("Unsharp mask.")),
|
|
1332
|
+
"mtf": ("mtf(x, m)", self.tr("Midtones transfer (existing).")),
|
|
1333
|
+
"iff": ("iff(cond, a, b)", self.tr("Conditional (existing).")),
|
|
1334
|
+
"X / Y": ("X, Y", self.tr("Normalized coordinates in [0..1].")),
|
|
1335
|
+
"H/W/C": ("H, W, C, shape", self.tr("Image dimensions.")),
|
|
1332
1336
|
}
|
|
1333
1337
|
|
|
1334
1338
|
def _open_glossary(self):
|
|
1335
1339
|
dlg = QDialog(self)
|
|
1336
|
-
dlg.setWindowTitle("Pixel Math Glossary")
|
|
1340
|
+
dlg.setWindowTitle(self.tr("Pixel Math Glossary"))
|
|
1337
1341
|
lay = QVBoxLayout(dlg)
|
|
1338
1342
|
|
|
1339
|
-
info = QLabel("Double-click to insert a template at the cursor.")
|
|
1343
|
+
info = QLabel(self.tr("Double-click to insert a template at the cursor."))
|
|
1340
1344
|
info.setStyleSheet("color: gray;")
|
|
1341
1345
|
lay.addWidget(info)
|
|
1342
1346
|
|
|
1343
1347
|
from PyQt6.QtWidgets import QLineEdit, QListWidget, QListWidgetItem, QHBoxLayout, QPushButton
|
|
1344
1348
|
search = QLineEdit()
|
|
1345
|
-
search.setPlaceholderText("Search…")
|
|
1349
|
+
search.setPlaceholderText(self.tr("Search…"))
|
|
1346
1350
|
lay.addWidget(search)
|
|
1347
1351
|
|
|
1348
1352
|
lst = QListWidget()
|
|
@@ -1372,7 +1376,7 @@ class PixelMathDialogPro(QDialog):
|
|
|
1372
1376
|
search.textChanged.connect(lambda *_: _refill())
|
|
1373
1377
|
|
|
1374
1378
|
btns = QDialogButtonBox(QDialogButtonBox.StandardButton.Close)
|
|
1375
|
-
insert_btn = QPushButton("Insert")
|
|
1379
|
+
insert_btn = QPushButton(self.tr("Insert"))
|
|
1376
1380
|
btns.addButton(insert_btn, QDialogButtonBox.ButtonRole.ApplyRole)
|
|
1377
1381
|
insert_btn.clicked.connect(_insert_current)
|
|
1378
1382
|
btns.rejected.connect(dlg.reject)
|
|
@@ -1384,7 +1388,7 @@ class PixelMathDialogPro(QDialog):
|
|
|
1384
1388
|
|
|
1385
1389
|
def _delete_favorite(self):
|
|
1386
1390
|
text = self.cb_fav.currentText()
|
|
1387
|
-
if text == "Select a favorite expression":
|
|
1391
|
+
if text == self.tr("Select a favorite expression"):
|
|
1388
1392
|
return
|
|
1389
1393
|
# Remove from in-memory list
|
|
1390
1394
|
try:
|
|
@@ -1397,7 +1401,7 @@ class PixelMathDialogPro(QDialog):
|
|
|
1397
1401
|
# Rebuild combo to keep indices clean
|
|
1398
1402
|
self.cb_fav.blockSignals(True)
|
|
1399
1403
|
self.cb_fav.clear()
|
|
1400
|
-
self.cb_fav.addItem("Select a favorite expression")
|
|
1404
|
+
self.cb_fav.addItem(self.tr("Select a favorite expression"))
|
|
1401
1405
|
for f in self._favs:
|
|
1402
1406
|
self.cb_fav.addItem(f)
|
|
1403
1407
|
self.cb_fav.setCurrentIndex(0)
|
|
@@ -1456,7 +1460,7 @@ class PixelMathDialogPro(QDialog):
|
|
|
1456
1460
|
if s: s.setValue("pixelmath_favorites", json.dumps(self._favs))
|
|
1457
1461
|
|
|
1458
1462
|
def _pick_favorite(self, text):
|
|
1459
|
-
if text == "Select a favorite expression": return
|
|
1463
|
+
if text == self.tr("Select a favorite expression"): return
|
|
1460
1464
|
if "[R]" in text or "[G]" in text or "[B]" in text:
|
|
1461
1465
|
self.rb_sep.setChecked(True); self._mode(False)
|
|
1462
1466
|
parts = {}
|
|
@@ -1502,24 +1506,24 @@ class PixelMathDialogPro(QDialog):
|
|
|
1502
1506
|
def _help(self):
|
|
1503
1507
|
gl = self._function_glossary()
|
|
1504
1508
|
lines = [
|
|
1505
|
-
"Operators: + - * / ^(power) ~(invert)",
|
|
1506
|
-
"Comparisons: <, == (use inside iff)",
|
|
1509
|
+
self.tr("Operators: + - * / ^(power) ~(invert)"),
|
|
1510
|
+
self.tr("Comparisons: <, == (use inside iff)"),
|
|
1507
1511
|
"",
|
|
1508
|
-
"Variables:",
|
|
1509
|
-
" • img (active) and one per open view (by window title, auto-mapped).",
|
|
1510
|
-
" • Coordinates: X, Y in [0..1].",
|
|
1511
|
-
" • Sizes: H, W, C, shape.",
|
|
1512
|
+
self.tr("Variables:"),
|
|
1513
|
+
self.tr(" • img (active) and one per open view (by window title, auto-mapped)."),
|
|
1514
|
+
self.tr(" • Coordinates: X, Y in [0..1]."),
|
|
1515
|
+
self.tr(" • Sizes: H, W, C, shape."),
|
|
1512
1516
|
"",
|
|
1513
|
-
"Per-channel indexing: view[0], view[1], view[2].",
|
|
1514
|
-
"Multiline: last line is the result.",
|
|
1515
|
-
"Output: Overwrite active or Create new view.",
|
|
1517
|
+
self.tr("Per-channel indexing: view[0], view[1], view[2]."),
|
|
1518
|
+
self.tr("Multiline: last line is the result."),
|
|
1519
|
+
self.tr("Output: Overwrite active or Create new view."),
|
|
1516
1520
|
"",
|
|
1517
|
-
"Functions:"
|
|
1521
|
+
self.tr("Functions:")
|
|
1518
1522
|
]
|
|
1519
1523
|
# Pretty column-ish dump
|
|
1520
1524
|
for name, (sig, desc) in gl.items():
|
|
1521
1525
|
lines.append(f" {sig}\n {desc}")
|
|
1522
|
-
QMessageBox.information(self, "Pixel Math Help", "\n".join(lines))
|
|
1526
|
+
QMessageBox.information(self, self.tr("Pixel Math Help"), "\n".join(lines))
|
|
1523
1527
|
|
|
1524
1528
|
# ---------- Apply ----------------------------------------------------------
|
|
1525
1529
|
# ---------- Apply ----------------------------------------------------------
|
|
@@ -1595,6 +1599,6 @@ class PixelMathDialogPro(QDialog):
|
|
|
1595
1599
|
except Exception as e:
|
|
1596
1600
|
msg = str(e)
|
|
1597
1601
|
if "name '" in msg and "' is not defined" in msg:
|
|
1598
|
-
msg += "\n\nTip: use the identifier shown beside Variables (e.g. 'andromeda_png'), "
|
|
1599
|
-
msg += "or just type the raw title; it will be auto-mapped."
|
|
1602
|
+
msg += self.tr("\n\nTip: use the identifier shown beside Variables (e.g. 'andromeda_png'), ")
|
|
1603
|
+
msg += self.tr("or just type the raw title; it will be auto-mapped.")
|
|
1600
1604
|
QMessageBox.critical(self, "Pixel Math", f"Failed:\n{msg}")
|