232 lines
8.6 KiB
Python
232 lines
8.6 KiB
Python
import kivy
|
|
from kivy.app import App
|
|
from kivy.uix.screenmanager import ScreenManager, Screen
|
|
import os
|
|
import json
|
|
from kivy.clock import Clock
|
|
from kivy.properties import StringProperty, ListProperty, AliasProperty
|
|
from utils import (
|
|
generate_key, load_key, encrypt_data, decrypt_data,
|
|
check_server_settings, save_server_settings,
|
|
test_connection, get_devices_from_server, save_route_to_file, fetch_positions_for_selected_day,
|
|
process_preview_util
|
|
)
|
|
from datetime import date
|
|
from kivy.uix.popup import Popup
|
|
from kivy.uix.gridlayout import GridLayout
|
|
from kivy.uix.button import Button
|
|
from kivy.uix.label import Label
|
|
from kivy.uix.boxlayout import BoxLayout
|
|
from threading import Thread
|
|
from kivy.clock import mainthread
|
|
from kivy.uix.image import Image
|
|
from kivy.uix.behaviors import ButtonBehavior
|
|
from kivy.uix.progressbar import ProgressBar
|
|
from config import RESOURCES_FOLDER, CREDENTIALS_FILE
|
|
from selenium import webdriver
|
|
from selenium.webdriver.chrome.options import Options
|
|
from PIL import Image
|
|
import time
|
|
from selenium import webdriver
|
|
from selenium.webdriver.chrome.service import Service
|
|
from selenium.webdriver.chrome.options import Options
|
|
from PIL import Image
|
|
import time
|
|
import os
|
|
|
|
class CreateAnimationScreen(Screen):
|
|
project_name = StringProperty("")
|
|
preview_html_path = StringProperty("") # Path to the HTML file for preview
|
|
preview_image_path = StringProperty("") # Add this line
|
|
|
|
def get_preview_image_source(self):
|
|
project_folder = os.path.join(RESOURCES_FOLDER, "projects", self.project_name)
|
|
img_path = os.path.join(project_folder, "preview.png")
|
|
if os.path.exists(img_path):
|
|
return img_path
|
|
return "resources/images/track.png"
|
|
|
|
preview_image_source = AliasProperty(get_preview_image_source, None, bind=['project_name'])
|
|
|
|
def on_pre_enter(self):
|
|
# Update the route entries label with the actual number of entries
|
|
project_folder = os.path.join(RESOURCES_FOLDER, "projects", self.project_name)
|
|
positions_path = os.path.join(project_folder, "positions.json")
|
|
count = 0
|
|
if os.path.exists(positions_path):
|
|
with open(positions_path, "r") as f:
|
|
try:
|
|
positions = json.load(f)
|
|
count = len(positions)
|
|
except Exception:
|
|
count = 0
|
|
self.ids.route_entries_label.text = f"Your route has {count} entries,"
|
|
|
|
def open_rename_popup(self):
|
|
from kivy.uix.popup import Popup
|
|
from kivy.uix.boxlayout import BoxLayout
|
|
from kivy.uix.button import Button
|
|
from kivy.uix.textinput import TextInput
|
|
from kivy.uix.label import Label
|
|
|
|
layout = BoxLayout(orientation='vertical', spacing=10, padding=10)
|
|
label = Label(text="Enter new project name:")
|
|
input_field = TextInput(text=self.project_name, multiline=False)
|
|
btn_save = Button(text="Save", background_color=(0.008, 0.525, 0.290, 1))
|
|
btn_cancel = Button(text="Cancel")
|
|
|
|
layout.add_widget(label)
|
|
layout.add_widget(input_field)
|
|
layout.add_widget(btn_save)
|
|
layout.add_widget(btn_cancel)
|
|
|
|
popup = Popup(
|
|
title="Rename Project",
|
|
content=layout,
|
|
size_hint=(0.92, None),
|
|
size=(0, 260),
|
|
auto_dismiss=False
|
|
)
|
|
|
|
def do_rename(instance):
|
|
new_name = input_field.text.strip()
|
|
if new_name and new_name != self.project_name:
|
|
if self.rename_project_folder(self.project_name, new_name):
|
|
self.project_name = new_name
|
|
popup.dismiss()
|
|
self.on_pre_enter() # Refresh label
|
|
else:
|
|
label.text = "Rename failed (name exists?)"
|
|
else:
|
|
label.text = "Please enter a new name."
|
|
|
|
btn_save.bind(on_press=do_rename)
|
|
btn_cancel.bind(on_press=lambda x: popup.dismiss())
|
|
popup.open()
|
|
|
|
def rename_project_folder(self, old_name, new_name):
|
|
import os
|
|
old_path = os.path.join(RESOURCES_FOLDER, "projects", old_name)
|
|
new_path = os.path.join(RESOURCES_FOLDER, "projects", new_name)
|
|
if os.path.exists(old_path) and not os.path.exists(new_path):
|
|
os.rename(old_path, new_path)
|
|
return True
|
|
return False
|
|
|
|
def optimize_route_entries(self):
|
|
# Show popup with progress bar
|
|
layout = BoxLayout(orientation='vertical', spacing=10, padding=10)
|
|
label = Label(text="Processing route entries...")
|
|
progress = ProgressBar(max=100, value=0)
|
|
layout.add_widget(label)
|
|
layout.add_widget(progress)
|
|
popup = Popup(
|
|
title="Optimizing Route",
|
|
content=layout,
|
|
size_hint=(0.92, None),
|
|
size=(0, 260),
|
|
auto_dismiss=False
|
|
)
|
|
popup.open()
|
|
|
|
def process_entries(dt):
|
|
project_folder = os.path.join(RESOURCES_FOLDER, "projects", self.project_name)
|
|
positions_path = os.path.join(project_folder, "positions.json")
|
|
if not os.path.exists(positions_path):
|
|
label.text = "positions.json not found!"
|
|
progress.value = 100
|
|
return
|
|
|
|
with open(positions_path, "r") as f:
|
|
positions = json.load(f)
|
|
|
|
# Detect duplicate positions at the start
|
|
start_remove = 0
|
|
if positions:
|
|
first = positions[0]
|
|
for pos in positions:
|
|
if pos['latitude'] == first['latitude'] and pos['longitude'] == first['longitude']:
|
|
start_remove += 1
|
|
else:
|
|
break
|
|
if start_remove > 0:
|
|
start_remove -= 1
|
|
|
|
# Detect duplicate positions at the end
|
|
end_remove = 0
|
|
if positions:
|
|
last = positions[-1]
|
|
for pos in reversed(positions):
|
|
if pos['latitude'] == last['latitude'] and pos['longitude'] == last['longitude']:
|
|
end_remove += 1
|
|
else:
|
|
break
|
|
if end_remove > 0:
|
|
end_remove -= 1
|
|
|
|
progress.value = 100
|
|
label.text = (
|
|
f"Entries removable at start: {start_remove}\n"
|
|
f"Entries removable at end: {end_remove}"
|
|
)
|
|
|
|
btn_save = Button(text="Save optimized file", background_color=(0.008, 0.525, 0.290, 1))
|
|
btn_cancel = Button(text="Cancel")
|
|
btn_box = BoxLayout(orientation='horizontal', spacing=10, size_hint_y=None, height=44)
|
|
btn_box.add_widget(btn_save)
|
|
btn_box.add_widget(btn_cancel)
|
|
layout.add_widget(btn_box)
|
|
|
|
def save_optimized(instance):
|
|
new_positions = positions[start_remove:len(positions)-end_remove if end_remove > 0 else None]
|
|
with open(positions_path, "w") as f:
|
|
json.dump(new_positions, f, indent=2)
|
|
label.text = "File optimized and saved!"
|
|
btn_save.disabled = True
|
|
btn_cancel.disabled = True
|
|
def close_and_refresh(dt):
|
|
popup.dismiss()
|
|
self.on_pre_enter() # Refresh the screen
|
|
Clock.schedule_once(close_and_refresh, 1)
|
|
|
|
btn_save.bind(on_press=save_optimized)
|
|
btn_cancel.bind(on_press=lambda x: popup.dismiss())
|
|
|
|
Clock.schedule_once(process_entries, 0.5)
|
|
|
|
def preview_route(self):
|
|
# Show processing popup
|
|
layout = BoxLayout(orientation='vertical', spacing=10, padding=10)
|
|
label = Label(text="Processing route preview...")
|
|
progress = ProgressBar(max=100, value=0)
|
|
layout.add_widget(label)
|
|
layout.add_widget(progress)
|
|
popup = Popup(
|
|
title="Previewing Route",
|
|
content=layout,
|
|
size_hint=(0.8, None),
|
|
size=(0, 180),
|
|
auto_dismiss=False
|
|
)
|
|
popup.open()
|
|
|
|
def set_preview_image_path(path):
|
|
self.preview_image_path = path
|
|
self.property('preview_image_source').dispatch(self)
|
|
self.ids.preview_image.reload()
|
|
# Schedule the processing function
|
|
Clock.schedule_once(
|
|
lambda dt: process_preview_util(
|
|
self.project_name,
|
|
RESOURCES_FOLDER,
|
|
label,
|
|
progress,
|
|
popup,
|
|
self.ids.preview_image,
|
|
set_preview_image_path,
|
|
Clock
|
|
),
|
|
0.5
|
|
)
|
|
|