-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutils.py
267 lines (230 loc) · 12.9 KB
/
utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
from pathlib import Path
import json
import gpxpy
import sys
from tkinter import *
from tkinter import ttk
from ttkthemes import ThemedTk
import xml.etree.ElementTree as ET
# ------------------------------------------------------------------------------------------
# _____
# | ____|_ __ _ __ ___ _ __ ___
# | _| | '__| '__/ _ \| '__/ __|
# | |___| | | | | (_) | | \__ \
# |_____|_| |_| \___/|_| |___/
# ------------------------------------------------------------------------------------------
def error_message(error, quit):
''' Error Section. Hand over error-level. Program will be quit. '''
def exit_now():
if quit:
sys.exit('Oh weh - ein Fehler!')
else:
root.destroy()
# root = Tk()
root = ThemedTk(theme='radiance')
root.title("Error!!")
root.eval('tk::PlaceWindow . center')
mainframe = ttk.Frame(root, padding="25 25 25 25")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
quitbutton = ttk.Button(mainframe, text='Exit', command=exit_now)
quitbutton.grid(column=1, row=4, sticky="S")
# .............................................................
# JSON Errors
# .............................................................
if error == "json_01":
ttk.Label(mainframe, text="The configuration (JSON) is missing.").grid(column=1, row=1, sticky=W)
# .............................................................
# GPX Errors
# .............................................................
if error == "gpx_01":
ttk.Label(mainframe, text="No GPX FileName has been passed. Use drag & drop.").grid(column=1, row=1, sticky=W)
if error == "gpx_02":
ttk.Label(mainframe, text="Wrong FileType has been provided to work on. Must be GPX.").grid(column=1, row=1, sticky=W)
if error == "gpx_03":
ttk.Label(mainframe, text="There is a mix of standard GPX and Garmin GPX in this file. That doen't work. Fix it.").grid(column=1, row=1, sticky=W)
if error == "gpx_04":
ttk.Label(mainframe, text="There is no such GPX file!\nUse drag & drop.").grid(column=1, row=1, sticky=W)
# .............................................................
# Paramater passing Errors
# .............................................................
# .............................................................
# Traccar Errors
# .............................................................
if error == "traccar_1":
ttk.Label(mainframe, text="The configuration <traccar2gpx.json> is missing.").grid(column=1, row=1, sticky=W)
ttk.Label(mainframe, text="A new version has been created ").grid(column=1, row=2, sticky=W)
ttk.Label(mainframe, text="YOU MUST UPDATE the created version with your credentials before you can carry on!").grid(column=1, row=3, sticky=W)
for child in mainframe.winfo_children():
child.grid_configure(padx=5, pady=5)
quitbutton.focus()
root.mainloop()
# -------------------------------------------------------------
# ____ _ _ ____ _ _
# / ___|| |_ __ _ _ __| |_ / ___| ___ _ __(_)_ __ | |_
# \___ \| __/ _` | '__| __| \___ \ / __| '__| | '_ \| __|
# ___) | || (_| | | | |_ ___) | (__| | | | |_) | |_
# |____/ \__\__,_|_| \__| |____/ \___|_| |_| .__/ \__|
# |_|
# ____ _
# | _ \ __ _ _ __ __ _ _ __ ___ ___| |_ ___ _ __
# | |_) / _` | '__/ _` | '_ ` _ \ / _ \ __/ _ \ '__|
# | __/ (_| | | | (_| | | | | | | __/ || __/ |
# |_| \__,_|_| \__,_|_| |_| |_|\___|\__\___|_|
# -------------------------------------------------------------
class IchSelbst:
'''
Make Names from running Script.
sys.argv[0] zeigt, wenn man die py laufen lässt, auf den Python Interpreter bzw. die py.
Sobald die py zur Exe wird zeigt der Pfad zur Working Directory des Callers, also des GPX das ich Droppe.
Damit müsste immer dort wo die GPX liegt auch die JSON liegen.
sys.executable ist der Workaround.
Mehr dazu hier: https://pyinstaller.org/en/stable/runtime-information.html
self.script_with_path -> c:\SynologyDrive\Python\00_test\test2.py
self.script -> test2.py
self.name -> test2
self.path -> c:\SynologyDrive\Python\00_test
self.path_name_without_suffix -> c:\SynologyDrive\Python\00_test\test2
'''
def __init__(self):
if getattr(sys, 'frozen', False): # Code is running from a compiled executable
SysArg0 = sys.executable
else: # Code is running as a regular Python script
SysArg0 = sys.argv[0]
self.script_with_path = SysArg0 # Script mit vollem Path
self.script_with_suffix = Path(SysArg0).name # Der Dateiname mit Suffix
self.script_without_suffix = Path(SysArg0).stem # Das ist der DateiName OHNE Suffix
self.path = Path(SysArg0).parent # Das ist der Path ohne trailing \
self.path_name_without_suffix = str(Path(SysArg0).parent) + "\\" + Path(SysArg0).stem
# ------------------------------------------------------------------------------------------
# _ ____ ___ _ _
# | / ___| / _ \| \ | |
# _ | \___ \| | | | \| |
# | |_| |___) | |_| | |\ |
# \___/|____/ \___/|_| \_|
# ------------------------------------------------------------------------------------------
def load_json(json_file_name):
# ------------------------------------------------------------------------------------------
# Load Translation Table
# 2024 02 04
# ------------------------------------------------------------------------------------------
''' If exists: Load JSON file. -> JSON '''
my_script = IchSelbst()
if json_file_name == None:
json_file_name = my_script.path_name_without_suffix+".json"
try:
with open(json_file_name) as f:
return json.load(f)
except FileNotFoundError:
error_message("json_01", False)
# ------------------------------------------------------------------------------------------
# ____ _ ____ _ _
# / ___| __ _ _ __ _ __ ___ (_)_ __ / ___| _ __ ___ ___(_) __ _| |
# | | _ / _` | '__| '_ ` _ \| | '_ \ ____\___ \| '_ \ / _ \_ / |/ _` | |
# | |_| | (_| | | | | | | | | | | | |_____|__) | |_) | __// /| | (_| | |
# \____|\__,_|_| |_| |_| |_|_|_| |_| |____/| .__/ \___/___|_|\__,_|_|
# |_|
# ------------------------------------------------------------------------------------------
def read_garmin_DisplayColor(gpx_file_path):
'''
Ich lese den GPX Track per XML Parser ein, lese die DisplayColors aus und übergebe diese
in einer Liste: display_colors
'''
# ....................................................
# Spezialbehandlung für den GPX Track!
# Ich hole die DisplayColor aus dem GPX Track. GPXPY kann keine Garmin codes lesen!
# Die alte Bibliothek gpxdata, obwohl sie eigentlich passen müsste, liess sich nicht mehr nutzen.
# Ich habe Stunden damit zugebracht die Garmin Struktur ansprechen zu können. NUR dieser Weg ging bislang!
# Also jede einzelne Elementstruktur in der Tiefe der GPX / XML mit ihrem Namespace ansprechen.
# So zerlegt sich das:
# <gpx creator="Garmin........ = . = root
# <trk> = ./h_main:trk/
# <name>Track 005</name>
# <extensions> = ./h_main:trk/h_main:extensions
# <gpxx:TrackExtension> = ./h_main:trk/h_main:extensions/h_gpxx:TrackExtension
# <gpxx:DisplayColor>DarkGray</gpxx:DisplayColor> = ./h_main:trk/h_main:extensions/h_gpxx:TrackExtension/h_gpxx:DisplayColor
# </gpxx:TrackExtension>
# </extensions>
# <trkseg>....
# </gpx>
# ....................................................
tree = ET.parse(gpx_file_path)
root = tree.getroot()
ns = {'h_main': 'http://www.topografix.com/GPX/1/1' ,
'h_gpxx': 'http://www.garmin.com/xmlschemas/GpxExtensions/v3'}
display_colors = root.findall("./h_main:trk/h_main:extensions/h_gpxx:TrackExtension/h_gpxx:DisplayColor", ns)
return display_colors
def read_gpx(file_path):
'''
Receive the name of the GPX file.
Return a parsed GPX and the colors of the tracks if there are any.
'''
try:
with open(file_path, 'r', encoding='utf-8') as gpx_file: # Parse die GPX mit dem Standard gpxpy
gpx_data = gpx_file.read()
gpx = gpxpy.parse(gpx_data)
except FileNotFoundError:
error_message("gpx_04", True)
display_colors = read_garmin_DisplayColor(file_path) # Hole die Garmin Trackfarben als Speziallösung weil gpxpy die nicht lesen kann!
# prüfe ob du nicht einen Mix aus normalen und Garmin Tracks hast. Das geht sonst nicht, weil ich nie weiß, wo die Farben sitzten.
if len(display_colors) >0 and (len(display_colors) != len(gpx.tracks)):
error_message("gpx_03", True)
return gpx, display_colors
def make_gpx_name(gpx_in_file_name):
# ...................................................
# Make GPX FileName
# 2022 12 06
# ...................................................
'''
Make a valid GPX name
### Args:
- Input : GPX File Name to be analyzed
- Returns: GPX File Name to be used. May be blank
'''
if gpx_in_file_name == None:
if len(sys.argv[1:]) > 0:
file_paths = sys.argv[1:] # the first argument (0) is the script itself. 1: heisst, wir haben nun in der file_paths alle anderen Argumente
gpx_in_file_name = file_paths[0]
else:
error_message("gpx_01", True)
if gpx_in_file_name:
in_path = Path(gpx_in_file_name).parent # Der Pfad zur EingabeDatei
in_name = Path(gpx_in_file_name).stem # Der Name der Datei ohne Suffix
in_suffix = Path(gpx_in_file_name).suffix
if in_suffix.lower() != '.gpx': # Prüfe ob das richtige Datenformat eingegeben wurde
# in_name = "" # Wenn falsch, dann kein EingabeName
# in_suffix = "" # Wenn falsch, dann kein EingabeName
# in_path = my_path # Setze den Pfad dieses Programms als Default
gpx_file_name = ''
else:
gpx_file_name = str(in_path) + '\\' + str(in_name) + str(in_suffix)
else:
gpx_file_name = ''
return gpx_file_name
# ------------------------------------------------------------------------------------------
# ____ _ ___ _
# / ___| __ _ _ __ _ __ ___ (_)_ __ |_ _|_ __ ___| |_ __ _ _ __ ____
# | | _ / _` | '__| '_ ` _ \| | '_ \ | || '_ \/ __| __/ _` | '_ \|_ /
# | |_| | (_| | | | | | | | | | | | | | || | | \__ \ || (_| | | | |/ /
# \____|\__,_|_| |_| |_| |_|_|_| |_| |___|_| |_|___/\__\__,_|_| |_/___|
# ------------------------------------------------------------------------------------------
class mein_gpx:
'''
Input: Entweder ein validierter Name für die GPX Datei, oder None
Mit None holt er sich den ersten Parameter der mitgegeben wurde (Drag & Drop)
Output: Eine Instanz mit dem Namen des GPX, allen GPX Daten fertig geparsed, die Farben der Tracks sofern vorhanden.
'''
def __init__(self, gpx_in_file_name):
if gpx_in_file_name == None:
if len(sys.argv[1:]) > 0:
gpx_in_file_name = sys.argv[1:][0]
else:
error_message("gpx_01", True)
self.gpx_name_with_path = make_gpx_name(gpx_in_file_name)
self.gpx, self.display_color = read_gpx(self.gpx_name_with_path)
SysArg0 = self.gpx_name_with_path # Der komplete Pfad mit Dateinamen und Suffix
self.gpx_name_with_suffix = Path(SysArg0).name # Nur der Dateiname mit Suffix
self.gpx_name_without_suffix = Path(SysArg0).stem # Nur der DateiName OHNE Suffix
self.gpx_path_name_without_suffix = Path(SysArg0).parent # Das ist der Path ohne trailing \
self.gpx_path_with_name_no_suffix = str(Path(SysArg0).parent) + "\\" + Path(SysArg0).stem # Der Pfad mit Dateinamen aber ohne den Suffix