Added module for geolocation data, changed the way data is saved and fixed timestamp data timezone
This commit is contained in:
parent
eeae202a85
commit
fe18f37a2d
@ -20,6 +20,10 @@
|
|||||||
#TODO:
|
#TODO:
|
||||||
#Weather image is cropped
|
#Weather image is cropped
|
||||||
#Make save button red if any data is unparsable
|
#Make save button red if any data is unparsable
|
||||||
|
#Make it so that each module doesn't have an event id, instead store on the event data which modules got changed
|
||||||
|
#Add timezone setting for exif date
|
||||||
|
#Change the background of TitledFrames from the wnidow background
|
||||||
|
#Change button from save and exit to write and exit
|
||||||
|
|
||||||
#import stuff that's needed for both GUI and check mode plus tkinter to make inheritance easier (for now)
|
#import stuff that's needed for both GUI and check mode plus tkinter to make inheritance easier (for now)
|
||||||
import sys
|
import sys
|
||||||
@ -27,6 +31,7 @@ import hashlib
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from datetime import timezone
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import ttk
|
from tkinter import ttk
|
||||||
|
|
||||||
@ -47,11 +52,12 @@ def main():
|
|||||||
from PIL.ExifTags import TAGS
|
from PIL.ExifTags import TAGS
|
||||||
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
|
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
|
||||||
from time import strftime, localtime
|
from time import strftime, localtime
|
||||||
from datetime import datetime
|
import tkintermapview
|
||||||
#import tkintermapview
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from exif import Image as exifImage
|
from exif import Image as exifImage
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
|
import gpxpy
|
||||||
|
import gpxpy.gpx
|
||||||
|
|
||||||
device_data = {
|
device_data = {
|
||||||
"lights": [ { "id": 0, "brand":"", "name": "other" },
|
"lights": [ { "id": 0, "brand":"", "name": "other" },
|
||||||
@ -97,7 +103,8 @@ def main():
|
|||||||
elif tag == 'DateTimeOriginal':
|
elif tag == 'DateTimeOriginal':
|
||||||
dt_str = value
|
dt_str = value
|
||||||
dt = datetime.strptime(dt_str, '%Y:%m:%d %H:%M:%S')
|
dt = datetime.strptime(dt_str, '%Y:%m:%d %H:%M:%S')
|
||||||
create_datetime=int(dt.timestamp()) # Unix epoch time
|
utc_dt = dt.replace(tzinfo=timezone.utc)
|
||||||
|
create_datetime=int(utc_dt.timestamp()) # Unix epoch time
|
||||||
|
|
||||||
#JSON output template
|
#JSON output template
|
||||||
data = {
|
data = {
|
||||||
@ -125,8 +132,27 @@ def main():
|
|||||||
{ "event_id":1, "event_type": "metadata_modification", "timestamp": current_event_timestamp, "timestamp_accuracy_seconds": 0, "text": "Initial metadata written" },
|
{ "event_id":1, "event_type": "metadata_modification", "timestamp": current_event_timestamp, "timestamp_accuracy_seconds": 0, "text": "Initial metadata written" },
|
||||||
#{ "event_id":5, "event_type": "version_upgrade", "timestamp": 1759876088, "text": "Metadata version updated" }
|
#{ "event_id":5, "event_type": "version_upgrade", "timestamp": 1759876088, "text": "Metadata version updated" }
|
||||||
],
|
],
|
||||||
#"GPS_lat_dec_N": 51.500789280409016,
|
"geolocation_data" : {
|
||||||
#"GPS_long_dec_W": -0.12472196184719725,
|
"have_data": True,
|
||||||
|
"valid_data_source": "uninitialised",
|
||||||
|
"source_gpx_file":{
|
||||||
|
"have_data": False,
|
||||||
|
"GPS_latitude_decimal": 0,
|
||||||
|
"GPS_longitude_decimal": 0,
|
||||||
|
"gpx_device_time_offset_seconds": 0,
|
||||||
|
"gpx_file_path": "",
|
||||||
|
},
|
||||||
|
"source_original_media_file":{
|
||||||
|
"have_data": False,
|
||||||
|
"GPS_latitude_decimal": 0,
|
||||||
|
"GPS_longitude_decimal": 0,
|
||||||
|
},
|
||||||
|
"source_manual_entry":{
|
||||||
|
"have_data": False,
|
||||||
|
"GPS_latitude_decimal": 0,
|
||||||
|
"GPS_longitude_decimal": 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
#"lights": [{ "source":2, "type":"Flash", "Usage":"pointing to his face" },
|
#"lights": [{ "source":2, "type":"Flash", "Usage":"pointing to his face" },
|
||||||
# { "source":3, "type":"continuous", "Usage":"hair light" },
|
# { "source":3, "type":"continuous", "Usage":"hair light" },
|
||||||
# { "source":1, "type":"continuous", "Usage":"doing its thing" },
|
# { "source":1, "type":"continuous", "Usage":"doing its thing" },
|
||||||
@ -148,12 +174,7 @@ def main():
|
|||||||
data["texts"]["event_id"] = attribution_event
|
data["texts"]["event_id"] = attribution_event
|
||||||
|
|
||||||
#Capture Timestamp
|
#Capture Timestamp
|
||||||
data["capture_timestamp"]["capture_duration_seconds"] = float(cap_duration_var.get())
|
|
||||||
data["capture_timestamp"]["single_capture_picture"] = one_capture_var.get()
|
|
||||||
data["capture_timestamp"]["capture_start_time_offset_seconds"] = float(cap_offset_var.get())
|
|
||||||
data["capture_timestamp"]["event_id"] = attribution_event
|
data["capture_timestamp"]["event_id"] = attribution_event
|
||||||
data["events"][0]["timestamp"] = int(data["capture_timestamp"]["capture_start_time_offset_seconds"])+int(data["capture_timestamp"]["capture_start_on_original_metadata_timestamp"]) #TODO: don't hardcode this values
|
|
||||||
data["events"][0]["timestamp_accuracy_seconds"] = int(cap_accuracy_var.get()) #TODO: don't hardcode this values
|
|
||||||
|
|
||||||
output_path = Path(data["constants"]["image_file_full_path"]).with_suffix(".json")
|
output_path = Path(data["constants"]["image_file_full_path"]).with_suffix(".json")
|
||||||
|
|
||||||
@ -193,6 +214,120 @@ def main():
|
|||||||
description.grid (row=1,column=0,sticky='we',padx=3,pady=3)
|
description.grid (row=1,column=0,sticky='we',padx=3,pady=3)
|
||||||
texts_frame.grid_columnconfigure(0, weight=1)
|
texts_frame.grid_columnconfigure(0, weight=1)
|
||||||
|
|
||||||
|
####################
|
||||||
|
# Geolocation data #
|
||||||
|
####################
|
||||||
|
def try_gpx_file(filepath):
|
||||||
|
gpx_file = open(filepath, 'r')
|
||||||
|
gpx = gpxpy.parse(gpx_file)
|
||||||
|
point_found=0
|
||||||
|
data["geolocation_data"]["source_gpx_file"]["have_data"]=False
|
||||||
|
for track in gpx.tracks:
|
||||||
|
for segment in track.segments:
|
||||||
|
for point in segment.points:
|
||||||
|
if(point.time == datetime.fromtimestamp(data["events"][0]["timestamp"]-data["geolocation_data"]["source_gpx_file"]["gpx_device_time_offset_seconds"],tz=timezone.utc)): #TODO don't hardcode this value
|
||||||
|
data["geolocation_data"]["source_gpx_file"]["GPS_longitude_decimal"]=point.longitude
|
||||||
|
data["geolocation_data"]["source_gpx_file"]["GPS_latitude_decimal"]=point.latitude
|
||||||
|
data["geolocation_data"]["source_gpx_file"]["gpx_file_path"]=filepath
|
||||||
|
data["geolocation_data"]["source_gpx_file"]["gpx_file_sha512sum"]=sha512Checksum(filepath)
|
||||||
|
data["geolocation_data"]["source_gpx_file"]["have_data"]=True
|
||||||
|
point_found=1
|
||||||
|
break
|
||||||
|
if point_found==1:
|
||||||
|
break
|
||||||
|
if point_found==1:
|
||||||
|
break
|
||||||
|
if point_found==0:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def Geolocation_update(*args):
|
||||||
|
manual_lat=gnss_manual_entry_source.get_lat()
|
||||||
|
manual_long=gnss_manual_entry_source.get_long()
|
||||||
|
data["geolocation_data"]["valid_data_source"]=human_name_to_source[gnss_source_selection.get()]
|
||||||
|
try:
|
||||||
|
manual_lat=float(manual_lat)
|
||||||
|
manual_long=float(manual_long)
|
||||||
|
data["geolocation_data"]["source_manual_entry"]["GPS_latitude_decimal"]=manual_lat
|
||||||
|
data["geolocation_data"]["source_manual_entry"]["GPS_longitude_decimal"]=manual_long
|
||||||
|
data["geolocation_data"]["source_manual_entry"]["have_data"]=True
|
||||||
|
except ValueError as e:
|
||||||
|
data["geolocation_data"]["source_manual_entry"]["have_data"]=False
|
||||||
|
|
||||||
|
if data["geolocation_data"][data["geolocation_data"]["valid_data_source"]]["have_data"] == True:
|
||||||
|
new_lat=data["geolocation_data"][data["geolocation_data"]["valid_data_source"]]["GPS_latitude_decimal"]
|
||||||
|
new_long=data["geolocation_data"][data["geolocation_data"]["valid_data_source"]]["GPS_longitude_decimal"]
|
||||||
|
map_marker.set_position(new_lat,new_long)
|
||||||
|
map_widget.set_position(new_lat,new_long)
|
||||||
|
|
||||||
|
|
||||||
|
def Geolocation_update_time(*args):
|
||||||
|
try:
|
||||||
|
data["geolocation_data"]["source_gpx_file"]["gpx_device_time_offset_seconds"]=float(gpx_device_time_offset.get())
|
||||||
|
except ValueError as e:
|
||||||
|
data["geolocation_data"]["source_gpx_file"]["gpx_device_time_offset_seconds"]=0
|
||||||
|
for file in os.listdir("/home/user/gnss_test/"):
|
||||||
|
if file.endswith(".gpx"):
|
||||||
|
#print("Trying "+str(os.path.join("/home/user/gnss_test/", file)))
|
||||||
|
if try_gpx_file(os.path.join("/home/user/gnss_test/", file)) == 0:
|
||||||
|
break
|
||||||
|
if data["geolocation_data"]["source_gpx_file"]["have_data"] == True :
|
||||||
|
gnss_gpx_file_source.update_lat( data["geolocation_data"]["source_gpx_file"]["GPS_latitude_decimal"])
|
||||||
|
gnss_gpx_file_source.update_long( data["geolocation_data"]["source_gpx_file"]["GPS_longitude_decimal"])
|
||||||
|
else:
|
||||||
|
gnss_gpx_file_source.update_lat("")
|
||||||
|
gnss_gpx_file_source.update_long("")
|
||||||
|
Geolocation_update()
|
||||||
|
|
||||||
|
gnss_location_data_frame=TitledFrame(root,[("[3]", ("TkDefaultFont", 12, "bold")),("Geolocation data", ("TkDefaultFont", 10))])
|
||||||
|
|
||||||
|
#Map Widget
|
||||||
|
map_widget = tkintermapview.TkinterMapView(gnss_location_data_frame, width=400, height=250, corner_radius=10)
|
||||||
|
map_widget.set_position(data["geolocation_data"]["source_gpx_file"]["GPS_latitude_decimal"], data["geolocation_data"]["source_gpx_file"]["GPS_longitude_decimal"])
|
||||||
|
map_marker=map_widget.set_marker(data["geolocation_data"]["source_gpx_file"]["GPS_latitude_decimal"], data["geolocation_data"]["source_gpx_file"]["GPS_longitude_decimal"])
|
||||||
|
map_widget.set_zoom(15)
|
||||||
|
|
||||||
|
gnss_source_selection=TitledDropdown(gnss_location_data_frame,"Select geolocation source:",
|
||||||
|
("Original media file",
|
||||||
|
"GPX file",
|
||||||
|
"Manual entry")
|
||||||
|
,0,callback=Geolocation_update)
|
||||||
|
human_name_to_source = {
|
||||||
|
"Original media file": "source_original_media_file",
|
||||||
|
"GPX file": "source_gpx_file",
|
||||||
|
"Manual entry": "source_manual_entry"
|
||||||
|
}
|
||||||
|
gpx_device_time_offset=TitledEntry(gnss_location_data_frame,"GPX device time offset (seconds)",data["geolocation_data"]["source_gpx_file"]["gpx_device_time_offset_seconds"],callback=Geolocation_update_time)
|
||||||
|
|
||||||
|
#Sources
|
||||||
|
gnss_gpx_file_source=Geolocation_source(gnss_location_data_frame,
|
||||||
|
"GPX file:",
|
||||||
|
data["geolocation_data"]["source_gpx_file"]["GPS_latitude_decimal"],
|
||||||
|
data["geolocation_data"]["source_gpx_file"]["GPS_longitude_decimal"],
|
||||||
|
tk.DISABLED)
|
||||||
|
|
||||||
|
gnss_original_media_file_source=Geolocation_source(gnss_location_data_frame,
|
||||||
|
"Original media file:",
|
||||||
|
data["geolocation_data"]["source_original_media_file"]["GPS_latitude_decimal"],
|
||||||
|
data["geolocation_data"]["source_original_media_file"]["GPS_longitude_decimal"],
|
||||||
|
tk.DISABLED)
|
||||||
|
|
||||||
|
gnss_manual_entry_source=Geolocation_source(gnss_location_data_frame,
|
||||||
|
"Original media file:",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
tk.NORMAL, callback=Geolocation_update)
|
||||||
|
|
||||||
|
map_widget.grid (row=0,column=0,pady=(0,3),padx=5)
|
||||||
|
gnss_source_selection.grid (row=1,column=0,pady=(5,2),sticky='we')
|
||||||
|
gpx_device_time_offset.grid (row=2,column=0,pady=(2,5),sticky='w')
|
||||||
|
gnss_gpx_file_source.grid (row=3,column=0,sticky='we')
|
||||||
|
gnss_original_media_file_source.grid (row=4,column=0,sticky='we')
|
||||||
|
gnss_manual_entry_source.grid (row=5,column=0,sticky='we')
|
||||||
|
|
||||||
|
#Geolocation_update_time() #Note, not needed because the capture timestamp callback will call it
|
||||||
|
|
||||||
#####################
|
#####################
|
||||||
# Capture timestamp #
|
# Capture timestamp #
|
||||||
#####################
|
#####################
|
||||||
@ -200,29 +335,33 @@ def main():
|
|||||||
|
|
||||||
#Callback for updating the explanation
|
#Callback for updating the explanation
|
||||||
def update_capture_timestamp_description(*args):
|
def update_capture_timestamp_description(*args):
|
||||||
date_value = cap_start_var.get()
|
image_creation_event_id=0#TODO: don't hardcode this value
|
||||||
duration_value = cap_duration.get()
|
|
||||||
check_value = one_capture_var.get()
|
|
||||||
accuracy=cap_accuracy_var.get()
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
duration_value=str(float(duration_value))
|
data["capture_timestamp"]["capture_start_time_offset_seconds"] = float(cap_offset_var.get())
|
||||||
accuracy=float(accuracy)
|
#If the capture time changes, update it and a list of thing that depend on it
|
||||||
date=time.strftime('%A %-d of %B %Y %H:%M:%S',time.gmtime(data["capture_timestamp"]["capture_start_on_original_metadata_timestamp"]+int(cap_offset_var.get())))
|
if data["events"][image_creation_event_id]["timestamp"] != int(data["capture_timestamp"]["capture_start_time_offset_seconds"])+int(data["capture_timestamp"]["capture_start_on_original_metadata_timestamp"]):
|
||||||
|
data["events"][image_creation_event_id]["timestamp"] = int(data["capture_timestamp"]["capture_start_time_offset_seconds"])+int(data["capture_timestamp"]["capture_start_on_original_metadata_timestamp"])
|
||||||
if accuracy != 0.0:
|
Geolocation_update_time()
|
||||||
acc_string=" plus/minus "+str(accuracy)+" seconds"
|
data["capture_timestamp"]["capture_duration_seconds"] = float(cap_duration_var.get())
|
||||||
else:
|
data["capture_timestamp"]["single_capture_picture"] = one_capture_var.get()
|
||||||
acc_string=""
|
data["events"][image_creation_event_id]["timestamp_accuracy_seconds"] = float(cap_accuracy_var.get())
|
||||||
|
|
||||||
if check_value == False:
|
|
||||||
explanation_var.set("A multi-picture image (focus stack/exposure stack/etc) that started being taken at " + date + acc_string + " and took " + str(duration_value) + " seconds to capture" )
|
|
||||||
else:
|
|
||||||
explanation_var.set("An image taken at " + date + acc_string + " with a "+str(duration_value)+" second shutter speed")
|
|
||||||
explanation.config(bg="grey64")
|
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
explanation_var.set("Invalid values!")
|
explanation_var.set("Invalid values!")
|
||||||
explanation.config(bg="red")
|
explanation.config(bg="red")
|
||||||
|
return
|
||||||
|
|
||||||
|
date=time.strftime('%A %-d of %B %Y %H:%M:%S',time.gmtime(data["capture_timestamp"]["capture_start_on_original_metadata_timestamp"]+int(cap_offset_var.get())))
|
||||||
|
|
||||||
|
if data["events"][image_creation_event_id]["timestamp_accuracy_seconds"] != 0.0:
|
||||||
|
acc_string=" plus/minus "+str(data["events"][image_creation_event_id]["timestamp_accuracy_seconds"])+" seconds"
|
||||||
|
else:
|
||||||
|
acc_string=""
|
||||||
|
|
||||||
|
if data["capture_timestamp"]["capture_duration_seconds"] == False:
|
||||||
|
explanation_var.set("A multi-picture image (focus stack/exposure stack/etc) that started being taken at " + date + acc_string + " and took " + str(data["capture_timestamp"]["capture_duration_seconds"]) + " seconds to capture" )
|
||||||
|
else:
|
||||||
|
explanation_var.set("An image taken at " + date + acc_string + " with a " + str(data["capture_timestamp"]["capture_duration_seconds"]) + " second shutter speed")
|
||||||
|
explanation.config(bg="grey64")
|
||||||
|
|
||||||
# explanation text
|
# explanation text
|
||||||
explanation_var = tk.StringVar()
|
explanation_var = tk.StringVar()
|
||||||
@ -247,7 +386,7 @@ def main():
|
|||||||
cap_duration = tk.Entry(capture_timestamp,textvariable=cap_duration_var)
|
cap_duration = tk.Entry(capture_timestamp,textvariable=cap_duration_var)
|
||||||
|
|
||||||
# Capture accuracy
|
# Capture accuracy
|
||||||
cap_accuracy_var = tk.StringVar(value=str(data["events"][0]["timestamp_accuracy_seconds"]))
|
cap_accuracy_var = tk.StringVar(value=str(data["events"][0]["timestamp_accuracy_seconds"])) #TODO: don't hardcode this value
|
||||||
cap_accuracy_var.trace_add("write", update_capture_timestamp_description)
|
cap_accuracy_var.trace_add("write", update_capture_timestamp_description)
|
||||||
cap_accuracy_label=tk.Label(capture_timestamp, text="Capture start accuracy (±seconds):")
|
cap_accuracy_label=tk.Label(capture_timestamp, text="Capture start accuracy (±seconds):")
|
||||||
cap_accuracy = tk.Entry(capture_timestamp,textvariable=cap_accuracy_var)
|
cap_accuracy = tk.Entry(capture_timestamp,textvariable=cap_accuracy_var)
|
||||||
@ -291,7 +430,7 @@ def main():
|
|||||||
########
|
########
|
||||||
# Save #
|
# Save #
|
||||||
########
|
########
|
||||||
save_frame=TitledFrame(editables,[("[3]", ("TkDefaultFont", 12, "bold")),("Save", ("TkDefaultFont", 10))])
|
save_frame=TitledFrame(editables,[("[4]", ("TkDefaultFont", 12, "bold")),("Save", ("TkDefaultFont", 10))])
|
||||||
save_button = tk.Button(save_frame, text="Save and Exit", command=save_and_exit)
|
save_button = tk.Button(save_frame, text="Save and Exit", command=save_and_exit)
|
||||||
save_button.config(bg='green')
|
save_button.config(bg='green')
|
||||||
|
|
||||||
@ -306,16 +445,6 @@ def main():
|
|||||||
save_button.grid (row=0,column=1,padx=3,pady=3)
|
save_button.grid (row=0,column=1,padx=3,pady=3)
|
||||||
save_frame.grid_columnconfigure(0, weight=1)
|
save_frame.grid_columnconfigure(0, weight=1)
|
||||||
|
|
||||||
# ##############
|
|
||||||
# # Map widget #
|
|
||||||
# ##############
|
|
||||||
# map_frame=Frame(root)
|
|
||||||
# map_widget = tkintermapview.TkinterMapView(map_frame, width=400, height=400, corner_radius=10)
|
|
||||||
# map_widget.set_position(data["GPS_lat_dec_N"], data["GPS_long_dec_W"])
|
|
||||||
# marker_1=map_widget.set_marker(data["GPS_lat_dec_N"], data["GPS_long_dec_W"])
|
|
||||||
# map_widget.set_zoom(15)
|
|
||||||
# map_widget.pack(pady=15)
|
|
||||||
|
|
||||||
##################
|
##################
|
||||||
# timeline field #
|
# timeline field #
|
||||||
##################
|
##################
|
||||||
@ -356,21 +485,30 @@ def main():
|
|||||||
|
|
||||||
|
|
||||||
#Root frame layout
|
#Root frame layout
|
||||||
display_image_frame .grid(row=0,column=0,sticky='n')
|
display_image_frame .grid(row=0,column=0,sticky='n')
|
||||||
editables .grid(row=0,column=1,rowspan=2,sticky='ns')
|
editables .grid(row=0,column=1,rowspan=2,sticky='ns')
|
||||||
# map_frame .grid(row=1,column=0)
|
gnss_location_data_frame .grid(row=1,column=0)
|
||||||
timeline_frame .grid(row=2,column=0,columnspan=2)
|
timeline_frame .grid(row=2,column=0,columnspan=2)
|
||||||
|
|
||||||
#editables frame layout
|
#editables frame layout
|
||||||
texts_frame .grid(row=0,column=0,sticky="we",pady=5)
|
texts_frame .grid(row=0,column=0,sticky="we",pady=5)
|
||||||
capture_timestamp .grid(row=1,column=0,sticky="we",pady=5)
|
capture_timestamp .grid(row=1,column=0,sticky="we",pady=5)
|
||||||
save_frame .grid(row=2,column=0,sticky="we",pady=5)
|
save_frame .grid(row=2,column=0,sticky="we",pady=5)
|
||||||
constants_frame .grid(row=3,column=0,sticky="we",pady=5)
|
constants_frame .grid(row=3,column=0,sticky="we",pady=5)
|
||||||
# light_table .grid(row=6,column=0,sticky="we",pady=5)
|
# light_table .grid(row=6,column=0,sticky="we",pady=5)
|
||||||
|
|
||||||
|
#This updates the default gnss source after the timestamp callback calls the gnss callback that looks through all the files
|
||||||
|
if data["geolocation_data"]["source_original_media_file"]["have_data"] == True :
|
||||||
|
gnss_source_selection.set(0)
|
||||||
|
elif data["geolocation_data"]["source_gpx_file"]["have_data"] == True :
|
||||||
|
gnss_source_selection.set(1)
|
||||||
|
else:
|
||||||
|
gnss_source_selection.set(2)
|
||||||
|
|
||||||
root.mainloop()
|
root.mainloop()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#Got md5Checksum (sha512Checksum now) from someones blog https://www.joelverhagen.com/blog/2011/02/md5-hash-of-file-in-python/
|
#Got md5Checksum (sha512Checksum now) from someones blog https://www.joelverhagen.com/blog/2011/02/md5-hash-of-file-in-python/
|
||||||
def sha512Checksum(filePath):
|
def sha512Checksum(filePath):
|
||||||
with open(filePath, 'rb') as fh:
|
with open(filePath, 'rb') as fh:
|
||||||
@ -410,7 +548,7 @@ class TextScrollCombo(tk.Frame):
|
|||||||
|
|
||||||
class TitledDropdown(tk.Frame):
|
class TitledDropdown(tk.Frame):
|
||||||
|
|
||||||
def __init__(self, root_window, text, options, default_opt):
|
def __init__(self, root_window, text, options, default_opt, callback=None):
|
||||||
|
|
||||||
super().__init__(root_window)
|
super().__init__(root_window)
|
||||||
|
|
||||||
@ -420,23 +558,33 @@ class TitledDropdown(tk.Frame):
|
|||||||
tk.Label(self, text=text).grid (row=0,column=0,sticky='w')
|
tk.Label(self, text=text).grid (row=0,column=0,sticky='w')
|
||||||
self.titled_dropdown.grid (row=0,column=1,sticky='we')
|
self.titled_dropdown.grid (row=0,column=1,sticky='we')
|
||||||
self.grid_columnconfigure(1, weight=1)
|
self.grid_columnconfigure(1, weight=1)
|
||||||
|
self.callback=callback
|
||||||
|
if callback != None:
|
||||||
|
self.titled_dropdown.bind('<<ComboboxSelected>>', callback)
|
||||||
def get(c):
|
def get(c):
|
||||||
return c.titled_dropdown.get()
|
return c.titled_dropdown.get()
|
||||||
|
def set(self,n):
|
||||||
|
self.titled_dropdown.current(n)
|
||||||
|
if self.callback != None:
|
||||||
|
self.callback()
|
||||||
|
|
||||||
class TitledEntry(tk.Frame):
|
class TitledEntry(tk.Frame):
|
||||||
|
|
||||||
def __init__(self, root_window, text, init_text, input_state=tk.NORMAL, width=None):
|
def __init__(self, root_window, text, init_text, input_state=tk.NORMAL, width=None, callback=None):
|
||||||
|
|
||||||
super().__init__(root_window)
|
super().__init__(root_window)
|
||||||
|
|
||||||
self.title_entry = tk.Entry(self,state=input_state,textvariable=tk.StringVar(value=init_text),width=width)
|
self.titled_entry_var=tk.StringVar(value=init_text)
|
||||||
|
self.titled_entry = tk.Entry(self,state=input_state,textvariable=self.titled_entry_var,width=width)
|
||||||
|
if callback != None:
|
||||||
|
self.titled_entry_var.trace_add("write", callback)
|
||||||
|
|
||||||
self.label=tk.Label(self, text=text)
|
self.label=tk.Label(self, text=text)
|
||||||
self.label.grid(row=0,column=0,sticky='w')
|
self.label.grid(row=0,column=0,sticky='w')
|
||||||
self.title_entry.grid(row=0,column=1,sticky='we')
|
self.titled_entry.grid(row=0,column=1,sticky='we')
|
||||||
self.grid_columnconfigure(1, weight=1)
|
self.grid_columnconfigure(1, weight=1)
|
||||||
def get(c):
|
def get(c):
|
||||||
return c.title_entry.get()
|
return c.titled_entry.get()
|
||||||
|
|
||||||
class TitledTable(tk.Frame):
|
class TitledTable(tk.Frame):
|
||||||
|
|
||||||
@ -476,8 +624,53 @@ class TitledTable(tk.Frame):
|
|||||||
self.scrollb.grid(row=1,column=1,sticky='ns')
|
self.scrollb.grid(row=1,column=1,sticky='ns')
|
||||||
self.treeview['yscrollcommand'] = self.scrollb.set
|
self.treeview['yscrollcommand'] = self.scrollb.set
|
||||||
self.utility_frame.grid(row=1,column=2,sticky='n')
|
self.utility_frame.grid(row=1,column=2,sticky='n')
|
||||||
def get(c):
|
|
||||||
return c.title_entry.get()
|
class Geolocation_source(tk.Frame):
|
||||||
|
|
||||||
|
def __init__(self, root, text, lat_source, long_source, state, callback=None):
|
||||||
|
|
||||||
|
super().__init__(root)
|
||||||
|
|
||||||
|
self.separator = ttk.Separator(self, orient=tk.HORIZONTAL)
|
||||||
|
self.separator_label = tk.Label(self, text=text)
|
||||||
|
self.paste_button = tk.Button(self, text="Paste",state=state, command=self.paste_callback)
|
||||||
|
|
||||||
|
self.root=root
|
||||||
|
|
||||||
|
self.fields=tk.Frame(self)
|
||||||
|
self.lat_var = tk.StringVar(value=lat_source)
|
||||||
|
self.lat_label = tk.Label(self.fields, text="Latitude:")
|
||||||
|
self.lat = tk.Entry(self.fields,textvariable=self.lat_var,state=state)
|
||||||
|
self.long_var = tk.StringVar(value=long_source)
|
||||||
|
self.long_label = tk.Label(self.fields, text="Longtitude:")
|
||||||
|
self.long = tk.Entry(self.fields,textvariable=self.long_var,state=state)
|
||||||
|
|
||||||
|
self.lat_label.grid (row=0,column=0,pady=3)
|
||||||
|
self.lat.grid (row=0,column=1,pady=3)
|
||||||
|
self.long_label.grid (row=0,column=2,pady=3)
|
||||||
|
self.long.grid (row=0,column=3,pady=3)
|
||||||
|
|
||||||
|
self.separator.grid (row=0,column=0,columnspan=2,pady=4,sticky='we')
|
||||||
|
self.separator_label.grid (row=1,column=0,sticky='w')
|
||||||
|
self.paste_button.grid (row=1,column=1,sticky='e')
|
||||||
|
self.fields.grid (row=2,column=0,columnspan=2,sticky='w')
|
||||||
|
|
||||||
|
if callback != None:
|
||||||
|
self.lat_var.trace_add("write", callback)
|
||||||
|
self.long_var.trace_add("write", callback)
|
||||||
|
def get_lat(self):
|
||||||
|
return self.lat_var.get()
|
||||||
|
def get_long(self):
|
||||||
|
return self.long_var.get()
|
||||||
|
def update_lat(self,value):
|
||||||
|
self.lat_var.set(value)
|
||||||
|
def update_long(self,value):
|
||||||
|
self.long_var.set(value)
|
||||||
|
def paste_callback(self):
|
||||||
|
clipboard=self.root.clipboard_get()
|
||||||
|
self.lat_var.set(clipboard.split()[0])
|
||||||
|
self.long_var.set(clipboard.split()[1])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def event_timeline(window,events,plt,np,FigureCanvasTkAgg,background_color):
|
def event_timeline(window,events,plt,np,FigureCanvasTkAgg,background_color):
|
||||||
|
Loading…
Reference in New Issue
Block a user