pdflinkcheck 1.1.73__py3-none-any.whl → 1.2.29__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.
- pdflinkcheck/__init__.py +88 -21
- pdflinkcheck/__main__.py +6 -0
- pdflinkcheck/analysis_pdfium.py +131 -0
- pdflinkcheck/{analyze_pymupdf.py → analysis_pymupdf.py} +109 -145
- pdflinkcheck/{analyze_pypdf.py → analysis_pypdf.py} +67 -37
- pdflinkcheck/cli.py +111 -116
- pdflinkcheck/data/I Have Questions.md +51 -0
- pdflinkcheck/data/LICENSE +20 -654
- pdflinkcheck/data/README.md +65 -67
- pdflinkcheck/data/icons/BoxArt-1080x1080.png +0 -0
- pdflinkcheck/data/icons/Logo-150x150.png +0 -0
- pdflinkcheck/data/icons/Logo-300x300.png +0 -0
- pdflinkcheck/data/icons/Logo-71x71.png +0 -0
- pdflinkcheck/data/icons/PosterArt-720x1080.png +0 -0
- pdflinkcheck/data/icons/SmallLogo-44x44.png +0 -0
- pdflinkcheck/data/icons/SplashScreen-620x300.png +0 -0
- pdflinkcheck/data/icons/StoreLogo-50x50.png +0 -0
- pdflinkcheck/data/icons/WideLogo-310x150.png +0 -0
- pdflinkcheck/data/icons/red_pdf_512px.ico +0 -0
- pdflinkcheck/data/pyproject.toml +25 -37
- pdflinkcheck/data/themes/forest/forest-dark/border-accent-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/border-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/border-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/border-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/border-invalid.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/card.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/check-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/check-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/check-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/check-tri-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/check-tri-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/check-tri-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/check-unsel-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/check-unsel-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/check-unsel-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/check-unsel-pressed.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/combo-button-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/combo-button-focus.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/combo-button-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/down.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/empty.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/hor-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/hor-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/hor-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/notebook.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/off-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/off-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/off-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/on-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/on-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/on-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/radio-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/radio-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/radio-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/radio-tri-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/radio-tri-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/radio-tri-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/radio-unsel-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/radio-unsel-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/radio-unsel-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/radio-unsel-pressed.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/rect-accent-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/rect-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/rect-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/rect-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/right.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/scale-hor.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/scale-vert.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/separator.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/sizegrip.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/spin-button-down-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/spin-button-down-focus.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/spin-button-up.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/tab-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/tab-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/tab-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/thumb-hor-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/thumb-hor-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/thumb-hor-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/thumb-vert-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/thumb-vert-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/thumb-vert-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/tree-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/tree-pressed.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/up.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/vert-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/vert-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark/vert-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-dark.tcl +536 -0
- pdflinkcheck/data/themes/forest/forest-light/border-accent-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/border-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/border-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/border-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/border-invalid.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/card.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/check-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/check-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/check-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/check-tri-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/check-tri-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/check-tri-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/check-unsel-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/check-unsel-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/check-unsel-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/check-unsel-pressed.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/combo-button-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/combo-button-focus.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/combo-button-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/down-focus.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/down.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/empty.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/hor-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/hor-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/hor-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/notebook.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/off-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/off-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/off-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/on-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/on-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/on-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/radio-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/radio-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/radio-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/radio-tri-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/radio-tri-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/radio-tri-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/radio-unsel-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/radio-unsel-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/radio-unsel-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/radio-unsel-pressed.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/rect-accent-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/rect-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/rect-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/rect-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/right-focus.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/right.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/scale-hor.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/scale-vert.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/separator.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/sizegrip.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/spin-button-down-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/spin-button-down-focus.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/spin-button-up.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/tab-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/tab-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/tab-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/thumb-hor-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/thumb-hor-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/thumb-hor-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/thumb-vert-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/thumb-vert-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/thumb-vert-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/tree-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/tree-pressed.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/up.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/vert-accent.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/vert-basic.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light/vert-hover.png +0 -0
- pdflinkcheck/data/themes/forest/forest-light.tcl +544 -0
- pdflinkcheck/datacopy.py +18 -1
- pdflinkcheck/dev.py +12 -25
- pdflinkcheck/environment.py +76 -0
- pdflinkcheck/gui.py +366 -457
- pdflinkcheck/helpers.py +88 -0
- pdflinkcheck/io.py +27 -23
- pdflinkcheck/report.py +692 -121
- pdflinkcheck/security.py +189 -0
- pdflinkcheck/splash.py +38 -0
- pdflinkcheck/stdlib_server.py +14 -20
- pdflinkcheck/stdlib_server_alt.py +571 -0
- pdflinkcheck/tk_utils.py +188 -0
- pdflinkcheck/update_msix_version.py +49 -0
- pdflinkcheck/validate.py +129 -218
- pdflinkcheck/version_info.py +6 -3
- {pdflinkcheck-1.1.73.dist-info → pdflinkcheck-1.2.29.dist-info}/METADATA +84 -81
- pdflinkcheck-1.2.29.dist-info/RECORD +183 -0
- pdflinkcheck-1.2.29.dist-info/WHEEL +5 -0
- {pdflinkcheck-1.1.73.dist-info → pdflinkcheck-1.2.29.dist-info}/entry_points.txt +0 -1
- pdflinkcheck-1.2.29.dist-info/licenses/LICENSE +27 -0
- pdflinkcheck-1.2.29.dist-info/licenses/LICENSE-MIT +9 -0
- pdflinkcheck-1.2.29.dist-info/top_level.txt +1 -0
- pdflinkcheck/analyze_pypdf_v2.py +0 -218
- pdflinkcheck-1.1.73.dist-info/RECORD +0 -21
- pdflinkcheck-1.1.73.dist-info/WHEEL +0 -4
- /pdflinkcheck-1.1.73.dist-info/licenses/LICENSE → /pdflinkcheck-1.2.29.dist-info/licenses/LICENSE-AGPL3 +0 -0
pdflinkcheck/tk_utils.py
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# src/pdflinkcheck/tk_utils.py
|
|
2
|
+
import tkinter as tk
|
|
3
|
+
import subprocess
|
|
4
|
+
import re
|
|
5
|
+
import platform
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def get_primary_monitor_geometry():
|
|
10
|
+
"""
|
|
11
|
+
Queries xrandr to find the actual primary monitor's dimensions and offsets.
|
|
12
|
+
Returns (width, height, x_offset, y_offset) or None.
|
|
13
|
+
|
|
14
|
+
Not used.
|
|
15
|
+
"""
|
|
16
|
+
try:
|
|
17
|
+
# Query xrandr for the primary monitor
|
|
18
|
+
result = subprocess.run(['xrandr', '--query'], capture_output=True, text=True, check=True)
|
|
19
|
+
# Look for a line like: "DP-0 connected primary 1920x1080+1200+0"
|
|
20
|
+
match = re.search(r'(\d+)x(\d+)\+(\d+)\+(\d+)', re.search(r'^.*primary.*$', result.stdout, re.M).group())
|
|
21
|
+
if match:
|
|
22
|
+
return map(int, match.groups())
|
|
23
|
+
except Exception:
|
|
24
|
+
return None
|
|
25
|
+
|
|
26
|
+
def center_window_on_primary_stable(window: tk.Toplevel | tk.Tk, width: int, height: int):
|
|
27
|
+
"""
|
|
28
|
+
Docstring for center_window_on_primary_stable
|
|
29
|
+
|
|
30
|
+
:param window: Description
|
|
31
|
+
:type window: tk.Toplevel | tk.Tk
|
|
32
|
+
:param width: Description
|
|
33
|
+
:type width: int
|
|
34
|
+
:param height: Description
|
|
35
|
+
:type height: int
|
|
36
|
+
|
|
37
|
+
Not used.
|
|
38
|
+
"""
|
|
39
|
+
window.update_idletasks()
|
|
40
|
+
|
|
41
|
+
# 1. Try to assess via X11/XRandR (Best for WSL2)
|
|
42
|
+
geom = get_primary_monitor_geometry()
|
|
43
|
+
|
|
44
|
+
if geom:
|
|
45
|
+
pw, ph, px, py = geom
|
|
46
|
+
print(f"[DEBUG] XRandR Primary: {pw}x{ph} at +{px}+{py}")
|
|
47
|
+
else:
|
|
48
|
+
# 2. Fallback: Center on Mouse Pointer (Best for Multi-monitor without XRandR)
|
|
49
|
+
# Since we can't find 'Primary', we put it where the user's attention is.
|
|
50
|
+
pw, ph = window.winfo_screenwidth(), window.winfo_screenheight()
|
|
51
|
+
px, py = 0, 0
|
|
52
|
+
|
|
53
|
+
# If it's a giant span, let's just use the pointer as the anchor
|
|
54
|
+
if pw > 2500:
|
|
55
|
+
pointer_x = window.winfo_pointerx()
|
|
56
|
+
pointer_y = window.winfo_pointery()
|
|
57
|
+
# We treat a 1920x1080 box around the pointer as our 'virtual primary'
|
|
58
|
+
px, py = pointer_x - 960, pointer_y - 540
|
|
59
|
+
pw, ph = 1920, 1080
|
|
60
|
+
|
|
61
|
+
# 3. Final Math
|
|
62
|
+
x = px + (pw // 2) - (width // 2)
|
|
63
|
+
y = py + (ph // 2) - (height // 2)
|
|
64
|
+
|
|
65
|
+
# Final clamp to ensure it's not off-screen
|
|
66
|
+
x = max(0, x)
|
|
67
|
+
y = max(0, y)
|
|
68
|
+
|
|
69
|
+
print(f"[DEBUG] Final Positioning: x={x}, y={y}")
|
|
70
|
+
window.geometry(f"{width}x{height}+{int(x)}+{int(y)}")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def get_monitor_geometries():
|
|
74
|
+
"""
|
|
75
|
+
Queries xrandr to find all connected monitor dimensions and offsets.
|
|
76
|
+
Returns a list of dicts: [{'w', 'h', 'x', 'y', 'is_primary'}]
|
|
77
|
+
Essential for WSL2/WSLg multi-monitor accuracy.
|
|
78
|
+
|
|
79
|
+
Active.
|
|
80
|
+
"""
|
|
81
|
+
monitors = []
|
|
82
|
+
os_name = platform.system()
|
|
83
|
+
|
|
84
|
+
# --- LINUX / WSL2 Logic ---
|
|
85
|
+
if os_name == "Linux":
|
|
86
|
+
try:
|
|
87
|
+
# Run xrandr
|
|
88
|
+
xrandr_result = subprocess.run(['xrandr', '--query'], capture_output=True, text=True, check=True)
|
|
89
|
+
#print(f"xrandr_result = {xrandr_result}")
|
|
90
|
+
# Regex to find: "1920x1080+1920+0" or "1920x1080+0+0"
|
|
91
|
+
# We look for lines that contain 'connected' and a geometry string
|
|
92
|
+
lines = xrandr_result.stdout.splitlines()
|
|
93
|
+
for line in lines:
|
|
94
|
+
if " connected " in line:
|
|
95
|
+
is_primary = "primary" in line
|
|
96
|
+
match = re.search(r'(\d+)x(\d+)\+(\d+)\+(\d+)', line)
|
|
97
|
+
if match:
|
|
98
|
+
w, h, x, y = map(int, match.groups())
|
|
99
|
+
monitors.append({
|
|
100
|
+
'w': w, 'h': h, 'x': x, 'y': y,
|
|
101
|
+
'is_primary': is_primary
|
|
102
|
+
})
|
|
103
|
+
except Exception as e:
|
|
104
|
+
print(f"[DEBUG] xrandr query failed: {e}")
|
|
105
|
+
|
|
106
|
+
# --- WINDOWS Native Logic ---
|
|
107
|
+
if os_name == "Windows":
|
|
108
|
+
# On native Windows, we can use ctypes to call GetSystemMetrics
|
|
109
|
+
# or rely on the fact that the Primary monitor is almost always at 0,0
|
|
110
|
+
# and its size is reported by winfo_screenwidth if we don't have multiple monitors
|
|
111
|
+
# (For true multi-monitor on native Windows, win32api is usually needed)
|
|
112
|
+
pass
|
|
113
|
+
|
|
114
|
+
return monitors
|
|
115
|
+
|
|
116
|
+
def center_window_on_primary_goose(window: tk.Toplevel | tk.Tk, width: int, height: int):
|
|
117
|
+
"""
|
|
118
|
+
Standardizes window centering by identifying the physical monitor
|
|
119
|
+
bounds and offsets.
|
|
120
|
+
|
|
121
|
+
:param window: Description
|
|
122
|
+
:type window: tk.Toplevel | tk.Tk
|
|
123
|
+
:param width: Description
|
|
124
|
+
:type width: int
|
|
125
|
+
:param height: Description
|
|
126
|
+
:type height: int
|
|
127
|
+
|
|
128
|
+
Active.
|
|
129
|
+
"""
|
|
130
|
+
window.update_idletasks()
|
|
131
|
+
|
|
132
|
+
monitors = get_monitor_geometries()
|
|
133
|
+
target_monitor = None
|
|
134
|
+
|
|
135
|
+
if monitors:
|
|
136
|
+
# 1. Prefer the one explicitly marked 'primary'
|
|
137
|
+
target_monitor = next((m for m in monitors if m['is_primary']), None)
|
|
138
|
+
|
|
139
|
+
# 2. Fallback to the first monitor (usually the one at +0+0)
|
|
140
|
+
if not target_monitor:
|
|
141
|
+
target_monitor = monitors[0]
|
|
142
|
+
|
|
143
|
+
print(f"[DEBUG] Assessed Monitor: {target_monitor['w']}x{target_monitor['h']} at +{target_monitor['x']}+{target_monitor['y']}")
|
|
144
|
+
else:
|
|
145
|
+
print("[DEBUG] No monitors found via xrandr. Falling back to screenwidth.")
|
|
146
|
+
# Total fallback: use winfo_screenwidth but assume 1080p width
|
|
147
|
+
# to avoid the L-gap if it's clearly a massive span.
|
|
148
|
+
sw = window.winfo_screenwidth()
|
|
149
|
+
sh = window.winfo_screenheight()
|
|
150
|
+
target_monitor = {
|
|
151
|
+
'w': 1920 if sw > 2500 else sw,
|
|
152
|
+
'h': 1080 if sh > 2000 else sh,
|
|
153
|
+
'x': 0, 'y': 0
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
# 3. Calculate Center relative to the identified monitor's geometry
|
|
157
|
+
x = target_monitor['x'] + (target_monitor['w'] // 2) - (width // 2)
|
|
158
|
+
y = target_monitor['y'] + (target_monitor['h'] // 2) - (height // 2)
|
|
159
|
+
|
|
160
|
+
print(f"[DEBUG] Final Positioning: x={x}, y={y}")
|
|
161
|
+
window.geometry(f"{width}x{height}+{int(x)}+{int(y)}")
|
|
162
|
+
|
|
163
|
+
def center_window_on_primary(window: tk.Toplevel | tk.Tk, width: int, height: int):
|
|
164
|
+
window.update_idletasks()
|
|
165
|
+
monitors = get_monitor_geometries()
|
|
166
|
+
|
|
167
|
+
target = None
|
|
168
|
+
if monitors:
|
|
169
|
+
target = next((m for m in monitors if m['is_primary']), monitors[0])
|
|
170
|
+
|
|
171
|
+
if target:
|
|
172
|
+
# Use the precisely assessed hardware monitor
|
|
173
|
+
x = target['x'] + (target['w'] // 2) - (width // 2)
|
|
174
|
+
y = target['y'] + (target['h'] // 2) - (height // 2)
|
|
175
|
+
else:
|
|
176
|
+
# Fallback for Windows/Mac where xrandr doesn't exist
|
|
177
|
+
# We use wm_maxsize which is surprisingly accurate for the 'Primary' on Windows/Mac
|
|
178
|
+
pw, ph = window.wm_maxsize()
|
|
179
|
+
|
|
180
|
+
# If maxsize is also reporting the huge span (rare on native),
|
|
181
|
+
# then we use your 1920/1080 safe-zone heuristic.
|
|
182
|
+
if pw > 2500:
|
|
183
|
+
pw, ph = 1920, 1080
|
|
184
|
+
|
|
185
|
+
x = (pw // 2) - (width // 2)
|
|
186
|
+
y = (ph // 2) - (height // 2)
|
|
187
|
+
|
|
188
|
+
window.geometry(f"{width}x{height}+{int(x)}+{int(y)}")
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# src/pdflinkcheck/update_msix_version.py
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from pdflinkcheck.version_info import get_version_from_pyproject
|
|
5
|
+
|
|
6
|
+
PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent
|
|
7
|
+
|
|
8
|
+
UNVERSIONED_MANIFEST = PROJECT_ROOT / "msix" / "AppxManifest_unversioned.xml"
|
|
9
|
+
OUTPUT_MANIFEST = PROJECT_ROOT / "msix" / "AppxManifest.xml"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
PLACEHOLDER = "@@VERSION_PLACEHOLDER@@"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def generate_versioned_manifest(version):
|
|
16
|
+
|
|
17
|
+
# Pad to four parts: 1.1 -> 1.1.0.0, 1.1.92 -> 1.1.92.0
|
|
18
|
+
parts = version.split(".")
|
|
19
|
+
if len(parts) == 2:
|
|
20
|
+
parts += ["0", "0"]
|
|
21
|
+
elif len(parts) == 3:
|
|
22
|
+
parts.append("0")
|
|
23
|
+
elif len(parts) > 4:
|
|
24
|
+
raise ValueError(f"Version has too many parts: {version}")
|
|
25
|
+
|
|
26
|
+
msix_version = ".".join(parts[:4])
|
|
27
|
+
|
|
28
|
+
if not UNVERSIONED_MANIFEST.exists():
|
|
29
|
+
raise FileNotFoundError(f"Unversioned manifest not found: {UNVERSIONED_MANIFEST}")
|
|
30
|
+
|
|
31
|
+
text = UNVERSIONED_MANIFEST.read_text(encoding="utf-8")
|
|
32
|
+
|
|
33
|
+
placeholder_full = f'Version="{PLACEHOLDER}"'
|
|
34
|
+
|
|
35
|
+
if placeholder_full not in text:
|
|
36
|
+
raise ValueError(f"Placeholder {placeholder_full} not found in the unversioned manifest!")
|
|
37
|
+
|
|
38
|
+
updated_text = text.replace(placeholder_full, f'Version="{msix_version}"')
|
|
39
|
+
|
|
40
|
+
# Ensure the directory exists and write the new manifest
|
|
41
|
+
OUTPUT_MANIFEST.parent.mkdir(parents=True, exist_ok=True)
|
|
42
|
+
OUTPUT_MANIFEST.write_text(updated_text, encoding="utf-8")
|
|
43
|
+
|
|
44
|
+
print(f"Successfully generated AppxManifest.xml with version {msix_version}")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
if __name__ == "__main__":
|
|
48
|
+
version = get_version_from_pyproject()
|
|
49
|
+
generate_versioned_manifest(version)
|