From 8fee0bae587ca64e3e1907de949426885fe569a7 Mon Sep 17 00:00:00 2001 From: Mark Qvist Date: Tue, 24 Oct 2023 01:14:59 +0200 Subject: [PATCH] Implemented object details view --- sbapp/main.py | 81 +++++++++--- sbapp/sideband/core.py | 78 ++++++++---- sbapp/ui/layouts.py | 39 ++++++ sbapp/ui/messages.py | 12 +- sbapp/ui/objectdetails.py | 256 +++++++++++++++++++++++++++++++++++--- 5 files changed, 406 insertions(+), 60 deletions(-) diff --git a/sbapp/main.py b/sbapp/main.py index 5c6353e..f5946c3 100644 --- a/sbapp/main.py +++ b/sbapp/main.py @@ -723,6 +723,8 @@ class SidebandApp(MDApp): if len(modifiers) > 0 and modifiers[0] == 'ctrl' and (text == "w"): if self.root.ids.screen_manager.current == "conversations_screen": self.quit_action(self) + elif self.root.ids.screen_manager.current == "object_details_screen": + self.object_details_screen.close_action() else: self.open_conversations(direction="right") if len(modifiers) > 0 and modifiers[0] == 'ctrl' and (text == "s" or text == "d"): @@ -759,6 +761,8 @@ class SidebandApp(MDApp): self.close_sub_hardware_action() elif self.root.ids.screen_manager.current == "hardware_serial_screen": self.close_sub_hardware_action() + if self.root.ids.screen_manager.current == "object_details_screen": + self.object_details_screen.close_action() else: self.open_conversations(direction="right") @@ -847,14 +851,14 @@ class SidebandApp(MDApp): Clock.schedule_once(cb, 0.15) Clock.schedule_once(cbu, 0.15+0.25) - def open_conversation(self, context_dest): + def open_conversation(self, context_dest, direction="left"): self.outbound_mode_paper = False if self.sideband.config["propagation_by_default"]: self.outbound_mode_propagation = True else: self.outbound_mode_propagation = False - self.root.ids.screen_manager.transition.direction = "left" + self.root.ids.screen_manager.transition.direction = direction self.messages_view = Messages(self, context_dest) self.messages_view.ids.messages_scrollview.effect_cls = ScrollEffect @@ -952,6 +956,10 @@ class SidebandApp(MDApp): context_dest = self.messages_view.ids.messages_scrollview.active_conversation self.map_show_peer_location(context_dest) + def peer_show_telemetry_action(self, sender): + if self.root.ids.screen_manager.current == "messages_screen": + self.object_details_action(self.messages_view, from_conv=True) + def message_propagation_action(self, sender): if self.outbound_mode_paper: self.outbound_mode_paper = False @@ -1248,10 +1256,7 @@ class SidebandApp(MDApp): def lj(): import webbrowser webbrowser.open("https://unsigned.io/donate") - if not RNS.vendor.platformutils.is_android(): - threading.Thread(target=lj, daemon=True).start() - else: - lj() + threading.Thread(target=lj, daemon=True).start() self.information_screen.ids.information_scrollview.effect_cls = ScrollEffect self.information_screen.ids.information_logo.icon = self.sideband.asset_dir+"/rns_256.png" @@ -2935,6 +2940,17 @@ class SidebandApp(MDApp): self.telemetry_screen.ids.telemetry_s_location.active = self.sideband.config["telemetry_s_location"] self.telemetry_screen.ids.telemetry_s_location.bind(active=self.telemetry_location_toggle) + self.telemetry_screen.ids.telemetry_s_fixed_location.active = self.sideband.config["telemetry_s_fixed_location"] + self.telemetry_screen.ids.telemetry_s_fixed_location.bind(active=self.telemetry_location_toggle) + self.telemetry_screen.ids.telemetry_s_fixed_latlon.bind(focus=self.telemetry_save) + self.telemetry_screen.ids.telemetry_s_fixed_altitude.bind(focus=self.telemetry_save) + self.telemetry_screen.ids.telemetry_s_fixed_altitude.text = str(self.sideband.config["telemetry_s_fixed_altitude"]) + try: + lat = self.sideband.config["telemetry_s_fixed_latlon"][0]; lon = self.sideband.config["telemetry_s_fixed_latlon"][1] + except: + lat = 0.0; lon = 0.0 + self.telemetry_screen.ids.telemetry_s_fixed_latlon.text = f"{lat}, {lon}" + self.telemetry_screen.ids.telemetry_s_battery.active = self.sideband.config["telemetry_s_battery"] self.telemetry_screen.ids.telemetry_s_battery.bind(active=self.telemetry_save) @@ -2986,6 +3002,14 @@ class SidebandApp(MDApp): self.sideband.stop_telemetry() def telemetry_location_toggle(self, sender=None, event=None): + if sender == self.telemetry_screen.ids.telemetry_s_location: + if self.telemetry_screen.ids.telemetry_s_location.active: + self.telemetry_screen.ids.telemetry_s_fixed_location.active = False + if sender == self.telemetry_screen.ids.telemetry_s_fixed_location: + if self.telemetry_screen.ids.telemetry_s_fixed_location.active: + self.telemetry_screen.ids.telemetry_s_location.active = False + + if self.telemetry_screen.ids.telemetry_s_location.active: if RNS.vendor.platformutils.is_android(): if not check_permission("android.permission.ACCESS_COARSE_LOCATION") or not check_permission("android.permission.ACCESS_FINE_LOCATION"): @@ -3012,6 +3036,7 @@ class SidebandApp(MDApp): self.sideband.config["telemetry_send_appearance"] = self.telemetry_screen.ids.telemetry_send_appearance.active self.sideband.config["telemetry_s_location"] = self.telemetry_screen.ids.telemetry_s_location.active + self.sideband.config["telemetry_s_fixed_location"] = self.telemetry_screen.ids.telemetry_s_fixed_location.active self.sideband.config["telemetry_s_battery"] = self.telemetry_screen.ids.telemetry_s_battery.active self.sideband.config["telemetry_s_pressure"] = self.telemetry_screen.ids.telemetry_s_barometer.active self.sideband.config["telemetry_s_temperature"] = self.telemetry_screen.ids.telemetry_s_temperature.active @@ -3022,6 +3047,28 @@ class SidebandApp(MDApp): self.sideband.config["telemetry_s_angular_velocity"] = self.telemetry_screen.ids.telemetry_s_gyroscope.active self.sideband.config["telemetry_s_acceleration"] = self.telemetry_screen.ids.telemetry_s_accelerometer.active self.sideband.config["telemetry_s_proximity"] = self.telemetry_screen.ids.telemetry_s_proximity.active + + try: + alt = float(self.telemetry_screen.ids.telemetry_s_fixed_altitude.text.strip().replace(" ", "")) + self.telemetry_screen.ids.telemetry_s_fixed_altitude.text = str(alt) + self.sideband.config["telemetry_s_fixed_altitude"] = alt + except: + self.telemetry_screen.ids.telemetry_s_fixed_altitude.text = str(self.sideband.config["telemetry_s_fixed_altitude"]) + + try: + s = self.telemetry_screen.ids.telemetry_s_fixed_latlon.text + l = s.strip().replace(" ","").split(",") + lat = float(l[0]); lon = float(l[1]) + self.sideband.config["telemetry_s_fixed_latlon"] = [lat, lon] + self.telemetry_screen.ids.telemetry_s_fixed_latlon.text = f"{lat}, {lon}" + except: + try: + lat = self.sideband.config["telemetry_s_fixed_latlon"][0] + lon = self.sideband.config["telemetry_s_fixed_latlon"][1] + self.telemetry_screen.ids.telemetry_s_fixed_latlon.text = f"{lat}, {lon}" + except: + self.sideband.config["telemetry_s_fixed_latlon"] = [0.0, 0.0] + self.telemetry_screen.ids.telemetry_s_fixed_latlon.text = "0.0, 0.0" self.sideband.save_configuration() self.sideband.setstate("app.flags.last_telemetry", time.time()) @@ -3205,22 +3252,24 @@ class SidebandApp(MDApp): self.map_action() self.map_show(location) - def map_display_telemetry(self, sender): - RNS.log("Display telemetry from "+str(sender), RNS.LOG_WARNING) - self.object_details_action() + def map_display_telemetry(self, sender=None): + self.object_details_action(sender) def close_sub_map_action(self, sender=None): self.map_action(direction="right") - def object_details_action(self, sender=None): + def object_details_action(self, sender=None, from_conv=False): self.root.ids.screen_manager.transition.direction = "left" self.root.ids.nav_drawer.set_state("closed") - - if self.object_details_screen == None: - self.object_details_screen = ObjectDetails(self) - self.root.ids.screen_manager.current = "object_details_screen" - self.sideband.setstate("app.displaying", self.root.ids.screen_manager.current) + if sender != None and hasattr(sender, "source_dest") and sender.source_dest != None: + if self.object_details_screen == None: + self.object_details_screen = ObjectDetails(self) + + self.object_details_screen.set_source(sender.source_dest, from_conv=from_conv) + + self.root.ids.screen_manager.current = "object_details_screen" + self.sideband.setstate("app.displaying", self.root.ids.screen_manager.current) def map_create_marker(self, source, telemetry, appearance): try: @@ -3228,6 +3277,7 @@ class SidebandApp(MDApp): a_icon = appearance[0] a_fg = appearance[1]; a_bg = appearance[2] marker = CustomMapMarker(lat=l["latitude"], lon=l["longtitude"], icon_bg=a_bg) + marker.app = self marker.source_dest = source marker.location_time = l["last_update"] marker.icon = MDMapIconButton( @@ -3237,6 +3287,7 @@ class SidebandApp(MDApp): on_release=self.map_display_telemetry, ) marker.icon._default_icon_pad = dp(16) + marker.icon.source_dest = marker.source_dest marker.add_widget(marker.icon) ######## diff --git a/sbapp/sideband/core.py b/sbapp/sideband/core.py index 770a167..12b3667 100644 --- a/sbapp/sideband/core.py +++ b/sbapp/sideband/core.py @@ -472,6 +472,8 @@ class SidebandCore(): self.config["telemetry_bg"] = SidebandCore.DEFAULT_APPEARANCE[2] if not "telemetry_send_appearance" in self.config: self.config["telemetry_send_appearance"] = False + if not "telemetry_display_trusted_only" in self.config: + self.config["telemetry_display_trusted_only"] = False if not "telemetry_s_location" in self.config: self.config["telemetry_s_location"] = False @@ -495,8 +497,12 @@ class SidebandCore(): self.config["telemetry_s_acceleration"] = False if not "telemetry_s_proximity" in self.config: self.config["telemetry_s_proximity"] = False - if not "telemetry_display_trusted_only" in self.config: - self.config["telemetry_display_trusted_only"] = False + if not "telemetry_s_fixed_location" in self.config: + self.config["telemetry_s_fixed_location"] = False + if not "telemetry_s_fixed_latlon" in self.config: + self.config["telemetry_s_fixed_latlon"] = [0.0, 0.0] + if not "telemetry_s_fixed_altitude" in self.config: + self.config["telemetry_s_fixed_altitude"] = 0.0 if not "map_history_limit" in self.config: self.config["map_history_limit"] = 7*24*60*60 @@ -671,6 +677,8 @@ class SidebandCore(): return self._db_get_appearance(context_dest) or SidebandCore.DEFAULT_APPEARANCE def peer_display_name(self, context_dest): + if context_dest == self.lxmf_destination.hash: + return self.config["display_name"] try: existing_conv = self._db_conversation(context_dest) if existing_conv != None: @@ -753,10 +761,20 @@ class SidebandCore(): return self._db_telemetry(context_dest = context_dest, after = after, before = before, limit = limit) or [] def peer_telemetry(self, context_dest, after = None, before = None, limit = None): - pts = self._db_telemetry(context_dest, after = after, before = before, limit = limit) - if pts != None: - if context_dest in pts: - return pts[context_dest] + if context_dest == self.lxmf_destination.hash and limit == 1: + try: + return [[self.latest_telemetry["time"]["utc"], self.latest_packed_telemetry]] + except: + RNS.log("An error occurred while retrieving telemetry from the database: "+str(e), RNS.LOG_ERROR) + return [] + + try: + pts = self._db_telemetry(context_dest, after = after, before = before, limit = limit) + if pts != None: + if context_dest in pts: + return pts[context_dest] + except Exception as e: + RNS.log("An error occurred while retrieving telemetry from the database: "+str(e), RNS.LOG_ERROR) return [] @@ -1142,8 +1160,10 @@ class SidebandCore(): dbc = db.cursor() # TODO: Implement limit - - order_part = " order by ts DESC" + limit_part = "" + if limit: + limit_part = " LIMIT "+str(int(limit)) + order_part = " order by ts DESC"+limit_part if context_dest == None: if after != None and before == None: query = "select * from telemetry where ts>:after_ts"+order_part @@ -1211,6 +1231,7 @@ class SidebandCore(): if "snr" in physical_link: remote_telemeter.sensors["physical_link"].snr = physical_link["snr"] if "q" in physical_link: remote_telemeter.sensors["physical_link"].q = physical_link["q"] remote_telemeter.sensors["physical_link"].update_data() + telemetry = remote_telemeter.packed() query = "INSERT INTO telemetry (dest_context, ts, data) values (?, ?, ?)" data = (context_dest, telemetry_timestamp, telemetry) @@ -1245,22 +1266,26 @@ class SidebandCore(): db.commit() def _db_get_appearance(self, context_dest): - conv = self._db_conversation(context_dest) - data_dict = conv["data"] - try: - if data_dict != None and "appearance" in data_dict: - def htf(cbytes): - d = 1.0/255.0 - r = round(struct.unpack("!B", bytes([cbytes[0]]))[0]*d, 4) - g = round(struct.unpack("!B", bytes([cbytes[1]]))[0]*d, 4) - b = round(struct.unpack("!B", bytes([cbytes[2]]))[0]*d, 4) - return [r,g,b] + if context_dest == self.lxmf_destination.hash: + return [self.config["telemetry_icon"], self.config["telemetry_fg"], self.config["telemetry_bg"]] + else: + conv = self._db_conversation(context_dest) + if conv != None and "data" in conv: + data_dict = conv["data"] + try: + if data_dict != None and "appearance" in data_dict: + def htf(cbytes): + d = 1.0/255.0 + r = round(struct.unpack("!B", bytes([cbytes[0]]))[0]*d, 4) + g = round(struct.unpack("!B", bytes([cbytes[1]]))[0]*d, 4) + b = round(struct.unpack("!B", bytes([cbytes[2]]))[0]*d, 4) + return [r,g,b] - appearance = [data_dict["appearance"][0], htf(data_dict["appearance"][1]), htf(data_dict["appearance"][2])] - - return appearance - except Exception as e: - RNS.log("Could not retrieve appearance for "+RNS.prettyhexrep(context_dest)+": "+str(e), RNS.LOG_ERROR) + appearance = [data_dict["appearance"][0], htf(data_dict["appearance"][1]), htf(data_dict["appearance"][2])] + + return appearance + except Exception as e: + RNS.log("Could not retrieve appearance for "+RNS.prettyhexrep(context_dest)+": "+str(e), RNS.LOG_ERROR) return None @@ -1744,6 +1769,13 @@ class SidebandCore(): self.telemeter.enable(sensor) else: self.telemeter.disable(sensor) + + if self.config["telemetry_s_fixed_location"]: + self.telemeter.synthesize("location") + self.telemeter.sensors["location"].latitude = self.config["telemetry_s_fixed_latlon"][0] + self.telemeter.sensors["location"].longtitude = self.config["telemetry_s_fixed_latlon"][1] + self.telemeter.sensors["location"].altitude = self.config["telemetry_s_fixed_altitude"] + def get_telemetry(self): if self.config["telemetry_enabled"] == True: diff --git a/sbapp/ui/layouts.py b/sbapp/ui/layouts.py index 94ea8e3..c4b022c 100644 --- a/sbapp/ui/layouts.py +++ b/sbapp/ui/layouts.py @@ -868,6 +868,7 @@ MDScreen: [ ['arrow-down-bold-hexagon-outline', lambda x: root.app.telemetry_request_action(self)], ['upload-lock', lambda x: root.app.telemetry_send_update(self)], + ['wrench-cog', lambda x: root.app.close_any_action(self)], ['close', lambda x: root.app.close_any_action(self)], ] @@ -1323,6 +1324,44 @@ MDScreen: pos_hint: {"center_y": 0.3} active: False + MDBoxLayout: + orientation: "horizontal" + size_hint_y: None + padding: [0,0,dp(24),dp(0)] + height: dp(48) + + MDLabel: + text: "Fixed Location" + font_style: "H6" + + MDSwitch: + id: telemetry_s_fixed_location + pos_hint: {"center_y": 0.3} + active: False + + MDBoxLayout: + id: telemetry_fixed_location_fields + orientation: "horizontal" + size_hint_y: None + spacing: dp(16) + height: dp(64) + padding: [0, dp(0), 0, dp(0)] + # md_bg_color: [1,0,0,1] + + MDTextField: + id: telemetry_s_fixed_latlon + size_hint: [0.618, None] + hint_text: "Latitude, longtitude" + text: "" + font_size: dp(24) + + MDTextField: + id: telemetry_s_fixed_altitude + size_hint: [0.382, None] + hint_text: "Altitude" + text: "" + font_size: dp(24) + MDLabel: markup: True text: "\\n" diff --git a/sbapp/ui/messages.py b/sbapp/ui/messages.py index 5f4d5c2..e06416f 100644 --- a/sbapp/ui/messages.py +++ b/sbapp/ui/messages.py @@ -41,6 +41,7 @@ class Messages(): def __init__(self, app, context_dest): self.app = app self.context_dest = context_dest + self.source_dest = context_dest self.screen = self.app.root.ids.screen_manager.get_screen("messages_screen") self.ids = self.screen.ids @@ -302,9 +303,15 @@ class Messages(): def x(): try: telemeter = Telemeter.from_packed(packed_telemetry) - tlm = telemeter.read_all() if extra_telemetry and len(extra_telemetry) != 0: - tlm["physical_link"] = extra_telemetry + physical_link = extra_telemetry + telemeter.synthesize("physical_link") + if "rssi" in physical_link: telemeter.sensors["physical_link"].rssi = physical_link["rssi"] + if "snr" in physical_link: telemeter.sensors["physical_link"].snr = physical_link["snr"] + if "quality" in physical_link: telemeter.sensors["physical_link"].q = physical_link["quality"] + telemeter.sensors["physical_link"].update_data() + + tlm = telemeter.read_all() Clipboard.copy(str(tlm)) item.dmenu.dismiss() except Exception as e: @@ -598,6 +605,7 @@ MDScreen: [['menu', lambda x: root.app.nav_drawer.set_state("open")],] right_action_items: [ + ['map-marker-path', lambda x: root.app.peer_show_telemetry_action(self)], ['map-search', lambda x: root.app.peer_show_location_action(self)], ['lan-connect', lambda x: root.app.message_propagation_action(self)], ['close', lambda x: root.app.close_settings_action(self)], diff --git a/sbapp/ui/objectdetails.py b/sbapp/ui/objectdetails.py index 449cf87..2c70a83 100644 --- a/sbapp/ui/objectdetails.py +++ b/sbapp/ui/objectdetails.py @@ -3,6 +3,17 @@ import RNS from kivy.metrics import dp,sp from kivy.lang.builder import Builder +from kivy.core.clipboard import Clipboard +from kivymd.uix.recycleview import MDRecycleView +from kivymd.uix.list import OneLineIconListItem +from kivy.properties import StringProperty, BooleanProperty +from kivy.effects.scroll import ScrollEffect +from sideband.sense import Telemeter +import threading +import webbrowser + +from datetime import datetime + if RNS.vendor.platformutils.get_platform() == "android": from ui.helpers import ts_format @@ -14,13 +25,60 @@ class ObjectDetails(): self.app = app self.widget = None self.object_hash = object_hash + self.coords = None + self.raw_telemetry = None + self.from_conv = False if not self.app.root.ids.screen_manager.has_screen("object_details_screen"): self.screen = Builder.load_string(layou_object_details) self.screen.app = self.app + self.screen.delegate = self self.ids = self.screen.ids self.app.root.ids.screen_manager.add_widget(self.screen) + self.screen.ids.object_details_scrollview.effect_cls = ScrollEffect + self.telemetry_list = RVDetails() + self.telemetry_list.delegate = self + self.telemetry_list.app = self.app + self.screen.ids.object_details_scrollview.add_widget(self.telemetry_list) + + def close_action(self, sender=None): + if self.from_conv: + self.app.open_conversation(self.object_hash, direction="right") + else: + self.app.close_sub_map_action() + + def set_source(self, source_dest, from_conv=False): + self.object_hash = source_dest + + if from_conv: + self.from_conv = True + else: + self.from_conv = False + + self.coords = None + self.telemetry_list.data = [] + appearance = self.app.sideband.peer_appearance(source_dest) + self.screen.ids.name_label.text = self.app.sideband.peer_display_name(source_dest) + self.screen.ids.coordinates_button.disabled = True + self.screen.ids.object_appearance.icon = appearance[0] + self.screen.ids.object_appearance.icon_color = appearance[1] + self.screen.ids.object_appearance.md_bg_color = appearance[2] + + latest_telemetry = self.app.sideband.peer_telemetry(source_dest, limit=1) + if latest_telemetry != None and len(latest_telemetry) > 0: + telemeter = Telemeter.from_packed(latest_telemetry[0][1]) + self.raw_telemetry = telemeter.read_all() + + rendered_telemetry = telemeter.render() + if "location" in telemeter.sensors: + self.screen.ids.coordinates_button.disabled = False + self.telemetry_list.update_source(rendered_telemetry) + self.screen.ids.telemetry_button.disabled = False + else: + self.screen.ids.telemetry_button.disabled = True + self.telemetry_list.update_source(None) + def reload(self): self.clear_widget() self.update() @@ -40,7 +98,131 @@ class ObjectDetails(): def get_widget(self): return self.widget + def copy_coordinates(self, sender=None): + Clipboard.copy(str(self.coords or "No data")) + + def copy_telemetry(self, sender=None): + Clipboard.copy(str(self.raw_telemetry or "No data")) + +class ODView(OneLineIconListItem): + icon = StringProperty() + def __init__(self): + super().__init__() + +class RVDetails(MDRecycleView): + def __init__(self): + super().__init__() + self.data = [] + + def update_source(self, rendered_telemetry=None): + if not rendered_telemetry: + rendered_telemetry = [] + + sort = { + "Physical Link": 10, + "Location": 20, + "Ambient Light": 30, + "Ambient Temperature": 40, + "Relative Humidity": 50, + "Ambient Pressure": 60, + "Battery": 70, + "Timestamp": 80, + } + self.entries = [] + rendered_telemetry.sort(key=lambda s: sort[s["name"]] if s["name"] in sort else 1000) + for s in rendered_telemetry: + extra_entries = [] + release_function = None + name = s["name"] + if name == "Timestamp": + ts = s["values"]["UTC"] + ts_str = datetime.fromtimestamp(ts).strftime("%Y-%m-%d %H:%M:%S") + formatted_values = f"Recorded: [b]{RNS.prettytime(time.time()-ts, compact=True)} ago[/b] ({ts_str})" + elif name == "Battery": + p = s["values"]["percent"] + cs = s["values"]["_meta"] + formatted_values = f"{name}: [b]{p}%[/b] ({cs})" + elif name == "Ambient Pressure": + p = s["values"]["mbar"] + formatted_values = f"{name}: [b]{p} mbar[/b]" + elif name == "Ambient Temperature": + c = s["values"]["c"] + formatted_values = f"{name}: [b]{c}° C[/b]" + elif name == "Relative Humidity": + r = s["values"]["percent"] + formatted_values = f"{name}: [b]{r}%[/b]" + elif name == "Physical Link": + rssi = s["values"]["rssi"] + snr = s["values"]["snr"] + q = s["values"]["q"] + formatted_values = f"Link Quality: [b]{q}%[/b], RSSI: [b]{rssi} dBm[/b], SNR: [b]{snr} dB[/b]" + elif name == "Location": + lat = s["values"]["latitude"] + lon = s["values"]["longtitude"] + alt = s["values"]["altitude"] + speed = s["values"]["speed"] + bearing = s["values"]["bearing"] + accuracy = s["values"]["accuracy"] + updated = s["values"]["updated"] + updated_str = f", Logged: [b]{RNS.prettytime(time.time()-updated, compact=True)} ago[/b]" + if speed > 0.01: + speed_str = ", Speed: [b]{speed} Km/h[/b]" + else: + speed_str = "" + coords = f"{lat}, {lon}" + self.delegate.coords = coords + formatted_values = f"Coordinates: [b]{coords}[/b], Altitude: [b]{alt} meters[/b]"+speed_str+f", Bearing: [b]{bearing}°[/b]" + extra_formatted_values = f"Uncertainty: [b]{accuracy} meters[/b]"+updated_str + + data = {"icon": s["icon"], "text": f"{formatted_values}"} + extra_entries.append({"icon": "map-marker-question", "text": extra_formatted_values}) + def select(e=None): + geo_uri = f"geo:{lat},{lon}" + def lj(): + webbrowser.open(geo_uri) + threading.Thread(target=lj, daemon=True).start() + + release_function = select + else: + formatted_values = f"{name}:" + for vn in s["values"]: + v = s["values"][vn] + formatted_values += f" [b]{v} {vn}[/b]" + + if release_function: + data = {"icon": s["icon"], "text": f"{formatted_values}", "on_release": release_function} + else: + data = {"icon": s["icon"], "text": f"{formatted_values}"} + + self.entries.append(data) + for extra in extra_entries: + self.entries.append(extra) + + if len(self.entries) == 0: + self.entries.append({"icon": "account-question-outline", "text": f"No information known about this peer"}) + + self.data = self.entries + + + layou_object_details = """ +#:import MDLabel kivymd.uix.label.MDLabel +#:import OneLineIconListItem kivymd.uix.list.OneLineIconListItem +#:import Button kivy.uix.button.Button + + + IconLeftWidget: + icon: root.icon + +: + viewclass: "ODView" + RecycleBoxLayout: + default_size: None, dp(50) + default_size_hint: 1, None + size_hint_y: None + height: self.minimum_height + orientation: "vertical" + MDScreen: name: "object_details_screen" @@ -48,6 +230,7 @@ MDScreen: orientation: "vertical" MDTopAppBar: + id: details_bar title: "Details" anchor_title: "left" elevation: 0 @@ -55,29 +238,62 @@ MDScreen: [['menu', lambda x: root.app.nav_drawer.set_state("open")]] right_action_items: [ - ['close', lambda x: root.app.close_sub_map_action(self)], + ['close', lambda x: root.delegate.close_action()], ] + MDBoxLayout: + id: object_header + orientation: "horizontal" + spacing: dp(24) + size_hint_y: None + height: self.minimum_height + padding: dp(24) + + MDIconButton: + id: object_appearance + icon: "map-marker-star-outline" + icon_color: [0,0,0,1] + md_bg_color: [1,1,1,1] + theme_icon_color: "Custom" + icon_size: dp(32) + + MDLabel: + id: name_label + markup: True + text: "Object Name" + font_style: "H6" + + MDBoxLayout: + id: object_header + orientation: "horizontal" + spacing: dp(24) + size_hint_y: None + height: self.minimum_height + padding: [dp(24), dp(0), dp(24), dp(12)] + + MDRectangleFlatIconButton: + id: telemetry_button + icon: "content-copy" + text: "Copy Telemetry" + padding: [dp(0), dp(14), dp(0), dp(14)] + icon_size: dp(24) + font_size: dp(16) + size_hint: [1.0, None] + on_release: root.delegate.copy_telemetry(self) + disabled: False + + MDRectangleFlatIconButton: + id: coordinates_button + icon: "map-marker-outline" + text: "Copy Coordinates" + padding: [dp(0), dp(14), dp(0), dp(14)] + icon_size: dp(24) + font_size: dp(16) + size_hint: [1.0, None] + on_release: root.delegate.copy_coordinates(self) + disabled: False + ScrollView: id: object_details_scrollview - - MDBoxLayout: - orientation: "vertical" - spacing: dp(48) - size_hint_y: None - height: self.minimum_height - padding: [dp(28), dp(48), dp(28), dp(16)] - - MDLabel: - id: name_label - markup: True - text: "Object Name" - font_style: "H6" - - MDLabel: - id: test_label - markup: True - text: "Test" - font_style: "H6" """ \ No newline at end of file