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 )