#:kivy 2.1.0 # Custom On-Screen Keyboard Widget : size_hint: None, None width: root.parent.width * 0.5 if root.parent else dp(600) height: self.width / 3 pos: (root.parent.width - self.width) / 2 if root.parent else 0, 0 opacity: 0 canvas.before: Color: rgba: 0.1, 0.1, 0.1, 0.95 RoundedRectangle: size: self.size pos: self.pos radius: [dp(15), dp(15), 0, 0] BoxLayout: orientation: 'vertical' padding: dp(5) spacing: dp(5) # Close button bar BoxLayout: size_hint: 1, None height: dp(40) padding: [dp(5), 0] Widget: Button: text: '✕' size_hint: None, 1 width: dp(40) background_color: 0.8, 0.2, 0.2, 0.9 font_size: sp(20) bold: True on_press: root.parent.hide_keyboard() if root.parent and hasattr(root.parent, 'hide_keyboard') else None # Number row BoxLayout: size_hint: 1, 1 spacing: dp(3) Button: text: '1' on_press: root.parent.key_pressed('1') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: '2' on_press: root.parent.key_pressed('2') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: '3' on_press: root.parent.key_pressed('3') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: '4' on_press: root.parent.key_pressed('4') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: '5' on_press: root.parent.key_pressed('5') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: '6' on_press: root.parent.key_pressed('6') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: '7' on_press: root.parent.key_pressed('7') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: '8' on_press: root.parent.key_pressed('8') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: '9' on_press: root.parent.key_pressed('9') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: '0' on_press: root.parent.key_pressed('0') if root.parent and hasattr(root.parent, 'key_pressed') else None # Top letter row (QWERTYUIOP) BoxLayout: size_hint: 1, 1 spacing: dp(3) Button: text: 'Q' on_press: root.parent.key_pressed('q') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: 'W' on_press: root.parent.key_pressed('w') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: 'E' on_press: root.parent.key_pressed('e') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: 'R' on_press: root.parent.key_pressed('r') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: 'T' on_press: root.parent.key_pressed('t') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: 'Y' on_press: root.parent.key_pressed('y') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: 'U' on_press: root.parent.key_pressed('u') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: 'I' on_press: root.parent.key_pressed('i') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: 'O' on_press: root.parent.key_pressed('o') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: 'P' on_press: root.parent.key_pressed('p') if root.parent and hasattr(root.parent, 'key_pressed') else None # Middle letter row (ASDFGHJKL) BoxLayout: size_hint: 1, 1 spacing: dp(3) Widget: size_hint: 0.5, 1 Button: text: 'A' on_press: root.parent.key_pressed('a') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: 'S' on_press: root.parent.key_pressed('s') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: 'D' on_press: root.parent.key_pressed('d') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: 'F' on_press: root.parent.key_pressed('f') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: 'G' on_press: root.parent.key_pressed('g') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: 'H' on_press: root.parent.key_pressed('h') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: 'J' on_press: root.parent.key_pressed('j') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: 'K' on_press: root.parent.key_pressed('k') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: 'L' on_press: root.parent.key_pressed('l') if root.parent and hasattr(root.parent, 'key_pressed') else None Widget: size_hint: 0.5, 1 # Bottom letter row (ZXCVBNM) BoxLayout: size_hint: 1, 1 spacing: dp(3) Widget: size_hint: 1, 1 Button: text: 'Z' on_press: root.parent.key_pressed('z') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: 'X' on_press: root.parent.key_pressed('x') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: 'C' on_press: root.parent.key_pressed('c') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: 'V' on_press: root.parent.key_pressed('v') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: 'B' on_press: root.parent.key_pressed('b') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: 'N' on_press: root.parent.key_pressed('n') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: 'M' on_press: root.parent.key_pressed('m') if root.parent and hasattr(root.parent, 'key_pressed') else None Widget: size_hint: 1, 1 # Bottom row (Space, Backspace) BoxLayout: size_hint: 1, 1 spacing: dp(3) Button: text: '←' size_hint: 0.3, 1 font_size: sp(24) on_press: root.parent.key_pressed('backspace') if root.parent and hasattr(root.parent, 'key_pressed') else None Button: text: 'Space' size_hint: 0.7, 1 on_press: root.parent.key_pressed(' ') if root.parent and hasattr(root.parent, 'key_pressed') else None : size: root.screen_width, root.screen_height canvas.before: Color: rgba: 0, 0, 0, 1 Rectangle: size: self.size pos: self.pos # Main content area for images/videos FloatLayout: id: content_area size: root.screen_width, root.screen_height size_hint: None, None pos_hint: {'x': 0, 'y': 0} # Status label overlay (centered) Label: id: status_label text: 'Loading...' size_hint: 0.5, 0.5 size: dp(600), dp(120) pos_hint: {'center_x': 0.5, 'center_y': 0.5} color: 1, 1, 1, 1 font_size: sp(18) text_size: self.size halign: 'center' valign: 'middle' canvas.before: Color: rgba: 0, 0, 0, 0.7 RoundedRectangle: size: self.size pos: self.pos radius: [dp(15)] # New control panel overlay (bottom center, width for 6 buttons, 90% transparent) BoxLayout: id: controls_layout orientation: 'horizontal' size_hint: None, None width: dp(370) height: dp(70) pos: (root.width - self.width) / 2, dp(10) opacity: 1 spacing: dp(10) padding: dp(10) canvas.before: Color: rgba: 0.1, 0.1, 0.1, 0.9 # 90% transparent RoundedRectangle: size: self.size pos: self.pos radius: [dp(20)] Button: id: backward_btn size_hint: None, None size: dp(50), dp(50) background_normal: root.resources_path + '/backward.png' background_down: root.resources_path + '/backward.png' border: (0, 0, 0, 0) on_press: root.previous_media() Button: id: play_pause_btn size_hint: None, None size: dp(50), dp(50) background_normal: root.resources_path + '/play.png' background_down: root.resources_path + '/pause.png' border: (0, 0, 0, 0) on_press: root.toggle_pause() Button: id: edit_btn size_hint: None, None size: dp(50), dp(50) background_normal: root.resources_path + '/pencil.png' background_down: root.resources_path + '/pencil.png' border: (0, 0, 0, 0) on_press: root.show_edit_interface() Button: id: settings_btn size_hint: None, None size: dp(50), dp(50) background_normal: root.resources_path + '/settings.png' background_down: root.resources_path + '/settings.png' border: (0, 0, 0, 0) on_press: root.show_settings() Button: id: exit_btn size_hint: None, None size: dp(50), dp(50) background_normal: root.resources_path + '/exit.png' background_down: root.resources_path + '/exit.png' border: (0, 0, 0, 0) on_press: root.show_exit_popup() Button: id: forward_btn size_hint: None, None size: dp(50), dp(50) background_normal: root.resources_path + '/forward.png' background_down: root.resources_path + '/forward.png' border: (0, 0, 0, 0) on_press: root.next_media() # Exit password popup : title: 'Exit Application' size_hint: 0.4, 0.3 auto_dismiss: False BoxLayout: orientation: 'vertical' padding: dp(20) spacing: dp(15) Label: text: 'Enter password to exit:' size_hint_y: None height: dp(30) TextInput: id: password_input multiline: False password: True font_size: sp(16) size_hint_y: None height: dp(40) write_tab: False readonly: True on_focus: root.on_input_focus(self, self.focus) Label: id: error_label text: '' color: 1, 0, 0, 1 size_hint_y: None height: dp(30) BoxLayout: orientation: 'horizontal' size_hint_y: None height: dp(50) spacing: dp(20) Button: text: 'Exit' background_color: 0.6, 0.2, 0.2, 1 on_press: root.check_password() Button: text: 'Cancel' background_color: 0.2, 0.6, 0.2, 1 on_press: root.dismiss() # Settings popup content : title: 'Player Settings' size_hint: 0.8, 0.8 auto_dismiss: True BoxLayout: orientation: 'vertical' padding: dp(20) spacing: dp(15) # Server configuration BoxLayout: orientation: 'horizontal' size_hint_y: None height: dp(40) spacing: dp(10) Label: text: 'Server IP:' size_hint_x: 0.3 text_size: self.size halign: 'left' valign: 'middle' TextInput: id: server_input size_hint_x: 0.7 multiline: False font_size: sp(14) write_tab: False on_touch_down: root.on_input_touch(self, args[1]) if self.collide_point(*args[1].pos) else None # Screen name BoxLayout: orientation: 'horizontal' size_hint_y: None height: dp(40) spacing: dp(10) Label: text: 'Screen Name:' size_hint_x: 0.3 text_size: self.size halign: 'left' valign: 'middle' TextInput: id: screen_input size_hint_x: 0.7 multiline: False font_size: sp(14) write_tab: False on_touch_down: root.on_input_touch(self, args[1]) if self.collide_point(*args[1].pos) else None # Quickconnect key BoxLayout: orientation: 'horizontal' size_hint_y: None height: dp(40) spacing: dp(10) Label: text: 'Quickconnect:' size_hint_x: 0.3 text_size: self.size halign: 'left' valign: 'middle' TextInput: id: quickconnect_input size_hint_x: 0.7 multiline: False font_size: sp(14) write_tab: False on_touch_down: root.on_input_touch(self, args[1]) if self.collide_point(*args[1].pos) else None # Orientation BoxLayout: orientation: 'horizontal' size_hint_y: None height: dp(40) spacing: dp(10) Label: text: 'Orientation:' size_hint_x: 0.3 text_size: self.size halign: 'left' valign: 'middle' TextInput: id: orientation_input size_hint_x: 0.7 multiline: False font_size: sp(14) write_tab: False on_touch_down: root.on_input_touch(self, args[1]) if self.collide_point(*args[1].pos) else None # Touch BoxLayout: orientation: 'horizontal' size_hint_y: None height: dp(40) spacing: dp(10) Label: text: 'Touch:' size_hint_x: 0.3 text_size: self.size halign: 'left' valign: 'middle' TextInput: id: touch_input size_hint_x: 0.7 multiline: False font_size: sp(14) write_tab: False on_touch_down: root.on_input_touch(self, args[1]) if self.collide_point(*args[1].pos) else None # Resolution BoxLayout: orientation: 'horizontal' size_hint_y: None height: dp(40) spacing: dp(10) Label: text: 'Max Resolution:' size_hint_x: 0.3 text_size: self.size halign: 'left' valign: 'middle' TextInput: id: resolution_input size_hint_x: 0.7 multiline: False font_size: sp(14) hint_text: '1920x1080 or auto' write_tab: False on_touch_down: root.on_input_touch(self, args[1]) if self.collide_point(*args[1].pos) else None Widget: size_hint_y: 0.05 # Test Connection Button Button: id: test_connection_btn text: 'Test Server Connection' size_hint_y: None height: dp(50) background_color: 0.2, 0.4, 0.8, 1 on_press: root.test_connection() # Connection Status Label Label: id: connection_status text: 'Click button to test connection' size_hint_y: None height: dp(40) text_size: self.size halign: 'center' valign: 'middle' color: 0.7, 0.7, 0.7, 1 Widget: size_hint_y: 0.05 # Status information Label: id: playlist_info text: 'Playlist Version: N/A' size_hint_y: None height: dp(30) text_size: self.size halign: 'left' valign: 'middle' Label: id: media_count_info text: 'Media Count: 0' size_hint_y: None height: dp(30) text_size: self.size halign: 'left' valign: 'middle' Label: id: status_info text: 'Status: Idle' size_hint_y: None height: dp(30) text_size: self.size halign: 'left' valign: 'middle' Widget: size_hint_y: 0.2 # Action buttons BoxLayout: orientation: 'horizontal' size_hint_y: None height: dp(50) spacing: dp(20) Button: text: 'Save & Close' background_color: 0.2, 0.6, 0.2, 1 on_press: root.save_and_close() Button: text: 'Cancel' background_color: 0.6, 0.2, 0.2, 1 on_press: root.dismiss()