From 4ad4e1ed2009ea0a46de64332ff16fd3fb82c7c0 Mon Sep 17 00:00:00 2001 From: Thomas Farstrike Date: Tue, 13 Jan 2026 00:38:17 +0100 Subject: [PATCH] Refactor to simplify imports --- .../assets/confetti.py | 3 +- .../assets/connect4.py | 3 +- .../assets/main.py | 3 +- .../com.micropythonos.draw/assets/draw.py | 8 +-- .../assets/error.py | 2 +- .../assets/file_manager.py | 6 +- .../assets/hello.py | 2 +- .../assets/imageview.py | 3 +- .../apps/com.micropythonos.imu/assets/imu.py | 3 +- .../assets/music_player.py | 3 +- .../assets/hello.py | 3 +- .../assets/showfonts.py | 2 +- .../assets/sound_recorder.py | 3 +- .../com.micropythonos.about/assets/about.py | 4 +- .../assets/launcher.py | 6 +- .../assets/osupdate.py | 10 ++- .../assets/calibrate_imu.py | 7 +- .../assets/check_imu_calibration.py | 10 ++- .../assets/settings.py | 3 +- .../com.micropythonos.wifi/assets/wifi.py | 17 ++--- internal_filesystem/lib/mpos/__init__.py | 71 ++++++++++++++++++- .../lib/mpos/activity_navigator.py | 5 +- internal_filesystem/lib/mpos/apps.py | 7 +- .../lib/mpos/battery_voltage.py | 2 +- internal_filesystem/lib/mpos/bootloader.py | 4 +- internal_filesystem/lib/mpos/main.py | 5 +- internal_filesystem/lib/mpos/time.py | 6 +- internal_filesystem/lib/mpos/ui/__init__.py | 9 ++- .../lib/mpos/ui/camera_activity.py | 20 +++--- .../lib/mpos/ui/camera_settings.py | 38 +++++----- .../lib/mpos/ui/setting_activity.py | 20 +++--- .../lib/mpos/ui/settings_activity.py | 5 +- internal_filesystem/lib/mpos/ui/topmenu.py | 21 +++--- internal_filesystem/lib/mpos/ui/view.py | 14 ++-- tests/base/graphical_test_base.py | 16 ++--- tests/base/keyboard_test_base.py | 4 +- tests/test_connectivity_manager.py | 12 ++-- tests/test_graphical_abc_button_debug.py | 3 +- tests/test_graphical_about_app.py | 2 +- ...test_graphical_animation_deleted_widget.py | 4 +- tests/test_graphical_camera_settings.py | 2 +- tests/test_graphical_custom_keyboard.py | 6 +- tests/test_graphical_custom_keyboard_basic.py | 3 +- tests/test_graphical_imu_calibration.py | 2 +- .../test_graphical_imu_calibration_ui_bug.py | 4 +- ...t_graphical_keyboard_crash_reproduction.py | 3 +- ...st_graphical_keyboard_default_vs_custom.py | 3 +- ...est_graphical_keyboard_layout_switching.py | 3 +- ...st_graphical_keyboard_method_forwarding.py | 2 +- tests/test_graphical_keyboard_mode_switch.py | 3 +- ...st_graphical_keyboard_rapid_mode_switch.py | 3 +- tests/test_graphical_keyboard_styling.py | 2 +- tests/test_graphical_launch_all_apps.py | 5 +- tests/test_graphical_osupdate.py | 2 +- tests/test_graphical_start_app.py | 3 +- tests/test_graphical_wifi_keyboard.py | 3 +- tests/test_intent.py | 2 +- tests/test_rtttl.py | 2 +- tests/test_shared_preferences.py | 3 +- 59 files changed, 231 insertions(+), 194 deletions(-) diff --git a/internal_filesystem/apps/com.micropythonos.confetti/assets/confetti.py b/internal_filesystem/apps/com.micropythonos.confetti/assets/confetti.py index 5ec95d77..f18409f1 100644 --- a/internal_filesystem/apps/com.micropythonos.confetti/assets/confetti.py +++ b/internal_filesystem/apps/com.micropythonos.confetti/assets/confetti.py @@ -2,8 +2,7 @@ import time import random import lvgl as lv -from mpos.apps import Activity, Intent -import mpos.config +from mpos import Activity, Intent, config import mpos.ui class Confetti(Activity): diff --git a/internal_filesystem/apps/com.micropythonos.connect4/assets/connect4.py b/internal_filesystem/apps/com.micropythonos.connect4/assets/connect4.py index 70c07559..94526c80 100644 --- a/internal_filesystem/apps/com.micropythonos.connect4/assets/connect4.py +++ b/internal_filesystem/apps/com.micropythonos.connect4/assets/connect4.py @@ -1,8 +1,7 @@ import time import random -from mpos.apps import Activity -import mpos.ui +from mpos import Activity, ui try: import lvgl as lv diff --git a/internal_filesystem/apps/com.micropythonos.doom_launcher/assets/main.py b/internal_filesystem/apps/com.micropythonos.doom_launcher/assets/main.py index e3b40d96..2cbcc603 100644 --- a/internal_filesystem/apps/com.micropythonos.doom_launcher/assets/main.py +++ b/internal_filesystem/apps/com.micropythonos.doom_launcher/assets/main.py @@ -1,7 +1,6 @@ import lvgl as lv import os -from mpos.apps import Activity -from mpos import TaskManager, sdcard +from mpos import Activity, TaskManager, sdcard class Main(Activity): diff --git a/internal_filesystem/apps/com.micropythonos.draw/assets/draw.py b/internal_filesystem/apps/com.micropythonos.draw/assets/draw.py index d341b94a..237d3d45 100644 --- a/internal_filesystem/apps/com.micropythonos.draw/assets/draw.py +++ b/internal_filesystem/apps/com.micropythonos.draw/assets/draw.py @@ -1,5 +1,5 @@ -from mpos.apps import Activity -import mpos.ui +import lvgl as lv +from mpos import Activity, ui indev_error_x = 160 indev_error_y = 120 @@ -35,11 +35,11 @@ class Draw(Activity): def touch_cb(self, event): event_code=event.get_code() if event_code not in [19,23,25,26,27,28,29,30,49]: - name = mpos.ui.get_event_name(event_code) + name = ui.get_event_name(event_code) #print(f"lv_event_t: code={event_code}, name={name}") # target={event.get_target()}, user_data={event.get_user_data()}, param={event.get_param()} if event_code == lv.EVENT.PRESSING: # this is probably enough #if event_code in [lv.EVENT.PRESSED, lv.EVENT.PRESSING, lv.EVENT.LONG_PRESSED, lv.EVENT.LONG_PRESSED_REPEAT]: - x, y = mpos.ui.get_pointer_xy() + x, y = ui.get_pointer_xy() #canvas.set_px(x,y,lv.color_black(),lv.OPA.COVER) # draw a tiny point self.draw_rect(x,y) #self.draw_line(x,y) diff --git a/internal_filesystem/apps/com.micropythonos.errortest/assets/error.py b/internal_filesystem/apps/com.micropythonos.errortest/assets/error.py index db63482d..979328e7 100644 --- a/internal_filesystem/apps/com.micropythonos.errortest/assets/error.py +++ b/internal_filesystem/apps/com.micropythonos.errortest/assets/error.py @@ -1,4 +1,4 @@ -from mpos.apps import ActivityDoesntExist # should fail here +from mpos import ActivityDoesntExist # should fail here class Error(Activity): diff --git a/internal_filesystem/apps/com.micropythonos.filemanager/assets/file_manager.py b/internal_filesystem/apps/com.micropythonos.filemanager/assets/file_manager.py index 39a0d868..12021624 100644 --- a/internal_filesystem/apps/com.micropythonos.filemanager/assets/file_manager.py +++ b/internal_filesystem/apps/com.micropythonos.filemanager/assets/file_manager.py @@ -1,5 +1,5 @@ -from mpos.apps import Activity -import mpos.ui +import lvgl as lv +from mpos import Activity, ui class FileManager(Activity): @@ -40,7 +40,7 @@ class FileManager(Activity): # GET_SELF_SIZE # 47 STYLE CHANGED if event_code not in [2,19,23,24,25,26,27,28,29,30,31,32,33,47,49,52]: - name = mpos.ui.get_event_name(event_code) + name = ui.get_event_name(event_code) print(f"file_explorer_event_cb {event_code} with name {name}") if event_code == lv.EVENT.VALUE_CHANGED: path = self.file_explorer.explorer_get_current_path() diff --git a/internal_filesystem/apps/com.micropythonos.helloworld/assets/hello.py b/internal_filesystem/apps/com.micropythonos.helloworld/assets/hello.py index 7682beec..87ed4dd3 100644 --- a/internal_filesystem/apps/com.micropythonos.helloworld/assets/hello.py +++ b/internal_filesystem/apps/com.micropythonos.helloworld/assets/hello.py @@ -1,4 +1,4 @@ -from mpos.apps import Activity +from mpos import Activity class Hello(Activity): diff --git a/internal_filesystem/apps/com.micropythonos.imageview/assets/imageview.py b/internal_filesystem/apps/com.micropythonos.imageview/assets/imageview.py index 4433b503..d25588cd 100644 --- a/internal_filesystem/apps/com.micropythonos.imageview/assets/imageview.py +++ b/internal_filesystem/apps/com.micropythonos.imageview/assets/imageview.py @@ -1,8 +1,7 @@ import gc import os -from mpos.apps import Activity -import mpos.ui +from mpos import Activity, ui import mpos.ui.anim class ImageView(Activity): diff --git a/internal_filesystem/apps/com.micropythonos.imu/assets/imu.py b/internal_filesystem/apps/com.micropythonos.imu/assets/imu.py index 4cf3cb51..fb7fdda1 100644 --- a/internal_filesystem/apps/com.micropythonos.imu/assets/imu.py +++ b/internal_filesystem/apps/com.micropythonos.imu/assets/imu.py @@ -1,5 +1,4 @@ -from mpos.apps import Activity -import mpos.sensor_manager as SensorManager +from mpos import Activity, sensor_manager as SensorManager class IMU(Activity): diff --git a/internal_filesystem/apps/com.micropythonos.musicplayer/assets/music_player.py b/internal_filesystem/apps/com.micropythonos.musicplayer/assets/music_player.py index 428f773f..6895a87a 100644 --- a/internal_filesystem/apps/com.micropythonos.musicplayer/assets/music_player.py +++ b/internal_filesystem/apps/com.micropythonos.musicplayer/assets/music_player.py @@ -2,8 +2,7 @@ import machine import os import time -from mpos.apps import Activity, Intent -import mpos.sdcard +from mpos import Activity, Intent, sdcard import mpos.ui import mpos.audio.audioflinger as AudioFlinger diff --git a/internal_filesystem/apps/com.micropythonos.showbattery/assets/hello.py b/internal_filesystem/apps/com.micropythonos.showbattery/assets/hello.py index 7e0ac09e..d709d398 100644 --- a/internal_filesystem/apps/com.micropythonos.showbattery/assets/hello.py +++ b/internal_filesystem/apps/com.micropythonos.showbattery/assets/hello.py @@ -49,8 +49,7 @@ battery power: import lvgl as lv import time -import mpos.battery_voltage -from mpos.apps import Activity +from mpos import battery_voltage, Activity class Hello(Activity): diff --git a/internal_filesystem/apps/com.micropythonos.showfonts/assets/showfonts.py b/internal_filesystem/apps/com.micropythonos.showfonts/assets/showfonts.py index d03e8119..e3a7bdf2 100644 --- a/internal_filesystem/apps/com.micropythonos.showfonts/assets/showfonts.py +++ b/internal_filesystem/apps/com.micropythonos.showfonts/assets/showfonts.py @@ -1,4 +1,4 @@ -from mpos.apps import Activity +from mpos import Activity import lvgl as lv class ShowFonts(Activity): diff --git a/internal_filesystem/apps/com.micropythonos.soundrecorder/assets/sound_recorder.py b/internal_filesystem/apps/com.micropythonos.soundrecorder/assets/sound_recorder.py index 3fe52476..6931cdc0 100644 --- a/internal_filesystem/apps/com.micropythonos.soundrecorder/assets/sound_recorder.py +++ b/internal_filesystem/apps/com.micropythonos.soundrecorder/assets/sound_recorder.py @@ -2,8 +2,7 @@ import os import time -from mpos.apps import Activity -import mpos.ui +from mpos import Activity, ui import mpos.audio.audioflinger as AudioFlinger diff --git a/internal_filesystem/builtin/apps/com.micropythonos.about/assets/about.py b/internal_filesystem/builtin/apps/com.micropythonos.about/assets/about.py index 7c5e05c0..5a632283 100644 --- a/internal_filesystem/builtin/apps/com.micropythonos.about/assets/about.py +++ b/internal_filesystem/builtin/apps/com.micropythonos.about/assets/about.py @@ -1,4 +1,4 @@ -from mpos.apps import Activity +from mpos import Activity, pct_of_display_width import mpos.info import sys @@ -9,7 +9,7 @@ class About(Activity): screen = lv.obj() screen.set_style_border_width(0, 0) screen.set_flex_flow(lv.FLEX_FLOW.COLUMN) - screen.set_style_pad_all(mpos.ui.pct_of_display_width(2), 0) + screen.set_style_pad_all(pct_of_display_width(2), 0) # Make the screen focusable so it can be scrolled with the arrow keys focusgroup = lv.group_get_default() if focusgroup: diff --git a/internal_filesystem/builtin/apps/com.micropythonos.launcher/assets/launcher.py b/internal_filesystem/builtin/apps/com.micropythonos.launcher/assets/launcher.py index 02e41ae1..58ff785c 100644 --- a/internal_filesystem/builtin/apps/com.micropythonos.launcher/assets/launcher.py +++ b/internal_filesystem/builtin/apps/com.micropythonos.launcher/assets/launcher.py @@ -10,9 +10,7 @@ # Most of this time is actually spent reading and parsing manifests. import lvgl as lv import mpos.apps -import mpos.ui -from mpos.content.package_manager import PackageManager -from mpos import Activity +from mpos import ui, PackageManager, Activity, pct_of_display_width import time import uhashlib import ubinascii @@ -31,7 +29,7 @@ class Launcher(Activity): main_screen.set_style_border_width(0, lv.PART.MAIN) main_screen.set_style_radius(0, 0) main_screen.set_pos(0, mpos.ui.topmenu.NOTIFICATION_BAR_HEIGHT) - main_screen.set_style_pad_hor(mpos.ui.pct_of_display_width(2), 0) + main_screen.set_style_pad_hor(pct_of_display_width(2), 0) main_screen.set_style_pad_ver(mpos.ui.topmenu.NOTIFICATION_BAR_HEIGHT, 0) main_screen.set_flex_flow(lv.FLEX_FLOW.ROW_WRAP) self.setContentView(main_screen) diff --git a/internal_filesystem/builtin/apps/com.micropythonos.osupdate/assets/osupdate.py b/internal_filesystem/builtin/apps/com.micropythonos.osupdate/assets/osupdate.py index b0143613..7afd08de 100644 --- a/internal_filesystem/builtin/apps/com.micropythonos.osupdate/assets/osupdate.py +++ b/internal_filesystem/builtin/apps/com.micropythonos.osupdate/assets/osupdate.py @@ -3,10 +3,8 @@ import requests import ujson import time -from mpos.apps import Activity -from mpos import PackageManager, ConnectivityManager, TaskManager, DownloadManager +from mpos import Activity, PackageManager, ConnectivityManager, TaskManager, DownloadManager, pct_of_display_width, pct_of_display_height import mpos.info -import mpos.ui class OSUpdate(Activity): @@ -42,7 +40,7 @@ class OSUpdate(Activity): def onCreate(self): self.main_screen = lv.obj() - self.main_screen.set_style_pad_all(mpos.ui.pct_of_display_width(2), 0) + self.main_screen.set_style_pad_all(pct_of_display_width(2), 0) # Make the screen focusable so it can be scrolled with the arrow keys if focusgroup := lv.group_get_default(): @@ -55,7 +53,7 @@ class OSUpdate(Activity): self.force_update.set_text("Force Update") self.force_update.add_event_cb(lambda *args: self.force_update_clicked(), lv.EVENT.VALUE_CHANGED, None) #self.force_update.add_event_cb(lambda e: mpos.ui.print_event(e), lv.EVENT.ALL, None) - self.force_update.align_to(self.current_version_label, lv.ALIGN.OUT_BOTTOM_LEFT, 0, mpos.ui.pct_of_display_height(5)) + self.force_update.align_to(self.current_version_label, lv.ALIGN.OUT_BOTTOM_LEFT, 0, pct_of_display_height(5)) self.install_button = lv.button(self.main_screen) self.install_button.align(lv.ALIGN.TOP_RIGHT, 0, 0) self.install_button.add_state(lv.STATE.DISABLED) # button will be enabled if there is an update available @@ -76,7 +74,7 @@ class OSUpdate(Activity): check_again_label.center() self.status_label = lv.label(self.main_screen) - self.status_label.align_to(self.force_update, lv.ALIGN.OUT_BOTTOM_LEFT, 0, mpos.ui.pct_of_display_height(5)) + self.status_label.align_to(self.force_update, lv.ALIGN.OUT_BOTTOM_LEFT, 0, pct_of_display_height(5)) self.setContentView(self.main_screen) def _update_ui_for_state(self): diff --git a/internal_filesystem/builtin/apps/com.micropythonos.settings/assets/calibrate_imu.py b/internal_filesystem/builtin/apps/com.micropythonos.settings/assets/calibrate_imu.py index 45804de8..e07ed2de 100644 --- a/internal_filesystem/builtin/apps/com.micropythonos.settings/assets/calibrate_imu.py +++ b/internal_filesystem/builtin/apps/com.micropythonos.settings/assets/calibrate_imu.py @@ -10,10 +10,7 @@ Guides user through IMU calibration process: import lvgl as lv import time import sys -from mpos.app.activity import Activity -import mpos.ui -import mpos.sensor_manager as SensorManager -from mpos.ui.testing import wait_for_render +from mpos import Activity, sensor_manager as SensorManager, wait_for_render, pct_of_display_width class CalibrationState: @@ -43,7 +40,7 @@ class CalibrateIMUActivity(Activity): def onCreate(self): screen = lv.obj() - screen.set_style_pad_all(mpos.ui.pct_of_display_width(3), 0) + screen.set_style_pad_all(pct_of_display_width(3), 0) screen.set_flex_flow(lv.FLEX_FLOW.COLUMN) screen.set_flex_align(lv.FLEX_ALIGN.CENTER, lv.FLEX_ALIGN.START, lv.FLEX_ALIGN.CENTER) focusgroup = lv.group_get_default() diff --git a/internal_filesystem/builtin/apps/com.micropythonos.settings/assets/check_imu_calibration.py b/internal_filesystem/builtin/apps/com.micropythonos.settings/assets/check_imu_calibration.py index 097aa75e..64115d4b 100644 --- a/internal_filesystem/builtin/apps/com.micropythonos.settings/assets/check_imu_calibration.py +++ b/internal_filesystem/builtin/apps/com.micropythonos.settings/assets/check_imu_calibration.py @@ -7,9 +7,7 @@ variance, expected value comparison, and overall quality score. import lvgl as lv import time import sys -from mpos.app.activity import Activity -import mpos.ui -import mpos.sensor_manager as SensorManager +from mpos import Activity, sensor_manager as SensorManager, pct_of_display_width class CheckIMUCalibrationActivity(Activity): @@ -36,7 +34,7 @@ class CheckIMUCalibrationActivity(Activity): def onCreate(self): screen = lv.obj() - screen.set_style_pad_all(mpos.ui.pct_of_display_width(1), 0) + screen.set_style_pad_all(pct_of_display_width(1), 0) #screen.set_style_pad_all(0, 0) screen.set_flex_flow(lv.FLEX_FLOW.COLUMN) focusgroup = lv.group_get_default() @@ -98,7 +96,7 @@ class CheckIMUCalibrationActivity(Activity): # Gyroscope section gyro_cont = lv.obj(data_cont) - gyro_cont.set_width(mpos.ui.pct_of_display_width(45)) + gyro_cont.set_width(pct_of_display_width(45)) gyro_cont.set_height(lv.SIZE_CONTENT) gyro_cont.set_style_border_width(0, 0) gyro_cont.set_style_pad_all(0, 0) @@ -261,7 +259,7 @@ class CheckIMUCalibrationActivity(Activity): def start_calibration(self, event): """Navigate to calibration activity.""" - from mpos.content.intent import Intent + from mpos import Intent from calibrate_imu import CalibrateIMUActivity intent = Intent(activity_class=CalibrateIMUActivity) diff --git a/internal_filesystem/builtin/apps/com.micropythonos.settings/assets/settings.py b/internal_filesystem/builtin/apps/com.micropythonos.settings/assets/settings.py index 64a11ca6..589cd481 100644 --- a/internal_filesystem/builtin/apps/com.micropythonos.settings/assets/settings.py +++ b/internal_filesystem/builtin/apps/com.micropythonos.settings/assets/settings.py @@ -1,7 +1,6 @@ import lvgl as lv -from mpos.apps import Intent -from mpos import PackageManager, SettingActivity, SettingsActivity +from mpos import Intent, PackageManager, SettingActivity, SettingsActivity from calibrate_imu import CalibrateIMUActivity from check_imu_calibration import CheckIMUCalibrationActivity diff --git a/internal_filesystem/builtin/apps/com.micropythonos.wifi/assets/wifi.py b/internal_filesystem/builtin/apps/com.micropythonos.wifi/assets/wifi.py index 17c92161..ee1a2754 100644 --- a/internal_filesystem/builtin/apps/com.micropythonos.wifi/assets/wifi.py +++ b/internal_filesystem/builtin/apps/com.micropythonos.wifi/assets/wifi.py @@ -2,13 +2,8 @@ import time import lvgl as lv import _thread -from mpos.apps import Activity, Intent -from mpos.ui.keyboard import MposKeyboard - +from mpos import Activity, Intent, MposKeyboard, WifiService, CameraActivity, pct_of_display_width import mpos.apps -from mpos.net.wifi_service import WifiService - -from mpos import CameraActivity class WiFi(Activity): """ @@ -243,8 +238,8 @@ class EditNetwork(Activity): label.set_text(f"Network name:") self.ssid_ta = lv.textarea(password_page) self.ssid_ta.set_width(lv.pct(100)) - self.ssid_ta.set_style_margin_left(mpos.ui.pct_of_display_width(2), lv.PART.MAIN) - self.ssid_ta.set_style_margin_right(mpos.ui.pct_of_display_width(2), lv.PART.MAIN) + self.ssid_ta.set_style_margin_left(pct_of_display_width(2), lv.PART.MAIN) + self.ssid_ta.set_style_margin_right(pct_of_display_width(2), lv.PART.MAIN) self.ssid_ta.set_one_line(True) self.ssid_ta.set_placeholder_text("Enter the SSID") self.keyboard = MposKeyboard(password_page) @@ -259,8 +254,8 @@ class EditNetwork(Activity): label.set_text(f"Password for '{self.selected_ssid}':") self.password_ta = lv.textarea(password_page) self.password_ta.set_width(lv.pct(100)) - self.password_ta.set_style_margin_left(mpos.ui.pct_of_display_width(2), lv.PART.MAIN) - self.password_ta.set_style_margin_right(mpos.ui.pct_of_display_width(2), lv.PART.MAIN) + self.password_ta.set_style_margin_left(pct_of_display_width(2), lv.PART.MAIN) + self.password_ta.set_style_margin_right(pct_of_display_width(2), lv.PART.MAIN) self.password_ta.set_one_line(True) if known_password: self.password_ta.set_text(known_password) @@ -272,7 +267,7 @@ class EditNetwork(Activity): # Hidden network: self.hidden_cb = lv.checkbox(password_page) self.hidden_cb.set_text("Hidden network (always try connecting)") - self.hidden_cb.set_style_margin_left(mpos.ui.pct_of_display_width(2), lv.PART.MAIN) + self.hidden_cb.set_style_margin_left(pct_of_display_width(2), lv.PART.MAIN) if known_hidden: self.hidden_cb.set_state(lv.STATE.CHECKED, True) diff --git a/internal_filesystem/lib/mpos/__init__.py b/internal_filesystem/lib/mpos/__init__.py index d63507f3..de4b03a6 100644 --- a/internal_filesystem/lib/mpos/__init__.py +++ b/internal_filesystem/lib/mpos/__init__.py @@ -4,12 +4,13 @@ from .app.activity import Activity from .config import SharedPreferences from .net.connectivity_manager import ConnectivityManager from .net import download_manager as DownloadManager +from .net.wifi_service import WifiService from .content.intent import Intent from .activity_navigator import ActivityNavigator from .content.package_manager import PackageManager from .task_manager import TaskManager -# Common activities (optional) +# Common activities from .app.activities.chooser import ChooserActivity from .app.activities.view import ViewActivity from .app.activities.share import ShareActivity @@ -17,13 +18,77 @@ from .app.activities.share import ShareActivity from .ui.setting_activity import SettingActivity from .ui.settings_activity import SettingsActivity from .ui.camera_activity import CameraActivity +from .ui.keyboard import MposKeyboard +from .ui.testing import ( + wait_for_render, capture_screenshot, simulate_click, + find_label_with_text, verify_text_present, print_screen_labels, + click_button, click_label +) + +# UI utility functions +from .ui.display import ( + pct_of_display_width, pct_of_display_height, + get_display_width, get_display_height, + min_resolution, max_resolution, get_pointer_xy +) +from .ui.event import get_event_name, print_event +from .ui.view import setContentView, back_screen +from .ui.theme import set_theme +from .ui.topmenu import open_bar, close_bar, open_drawer, drawer_open, NOTIFICATION_BAR_HEIGHT +from .ui.focus import save_and_clear_current_focusgroup +from .ui.gesture_navigation import handle_back_swipe, handle_top_swipe +from .ui.util import shutdown, set_foreground_app, get_foreground_app +from .ui import focus_direction + +# Utility modules +from . import apps +from . import ui +from . import config +from . import net +from . import content +from . import time +from . import sensor_manager +from . import sdcard +from . import battery_voltage +from . import audio +from . import hardware + +# Lazy import to avoid circular dependencies +def __getattr__(name): + if name == 'bootloader': + from . import bootloader + return bootloader + raise AttributeError(f"module '{__name__}' has no attribute '{name}'") __all__ = [ + # Core framework "App", "Activity", "SharedPreferences", - "ConnectivityManager", "DownloadManager", "Intent", + "ConnectivityManager", "DownloadManager", "WifiService", "Intent", "ActivityNavigator", "PackageManager", "TaskManager", + # Common activities "ChooserActivity", "ViewActivity", "ShareActivity", - "SettingActivity", "SettingsActivity", "CameraActivity" + "SettingActivity", "SettingsActivity", "CameraActivity", + # UI components + "MposKeyboard", + # UI utility functions + "pct_of_display_width", "pct_of_display_height", + "get_display_width", "get_display_height", + "min_resolution", "max_resolution", "get_pointer_xy", + "get_event_name", "print_event", + "setContentView", "back_screen", + "set_theme", + "open_bar", "close_bar", "open_drawer", "drawer_open", "NOTIFICATION_BAR_HEIGHT", + "save_and_clear_current_focusgroup", + "handle_back_swipe", "handle_top_swipe", + "shutdown", "set_foreground_app", "get_foreground_app", + "focus_direction", + # Testing utilities + "wait_for_render", "capture_screenshot", "simulate_click", + "find_label_with_text", "verify_text_present", "print_screen_labels", + "click_button", "click_label", + # Submodules + "apps", "ui", "config", "net", "content", "time", "sensor_manager", + "sdcard", "battery_voltage", "audio", "hardware", "bootloader" ] diff --git a/internal_filesystem/lib/mpos/activity_navigator.py b/internal_filesystem/lib/mpos/activity_navigator.py index 7dccee3d..83330b01 100644 --- a/internal_filesystem/lib/mpos/activity_navigator.py +++ b/internal_filesystem/lib/mpos/activity_navigator.py @@ -1,4 +1,6 @@ +import sys import utime + from .content.intent import Intent from .content.package_manager import PackageManager @@ -53,7 +55,8 @@ class ActivityNavigator: try: activity.onCreate() except Exception as e: - print(f"activity.onCreate caught exception: {e}") + print(f"activity.onCreate caught exception:") + sys.print_exception(e) end_time = utime.ticks_diff(utime.ticks_ms(), start_time) print(f"apps.py _launch_activity: activity.onCreate took {end_time}ms") return activity diff --git a/internal_filesystem/lib/mpos/apps.py b/internal_filesystem/lib/mpos/apps.py index 172f6178..31a319fb 100644 --- a/internal_filesystem/lib/mpos/apps.py +++ b/internal_filesystem/lib/mpos/apps.py @@ -5,9 +5,6 @@ import traceback import mpos.info import mpos.ui -from mpos.app.activity import Activity -from mpos.content.intent import Intent -from mpos.content.package_manager import PackageManager def good_stack_size(): stacksize = 24*1024 # less than 20KB crashes on desktop when doing heavy apps, like LightningPiggy's Wallet connections @@ -58,6 +55,8 @@ def execute_script(script_source, is_file, classname, cwd=None): print("Variables:", variables.keys()) main_activity = script_globals.get(classname) if main_activity: + from .app.activity import Activity + from .content.intent import Intent start_time = utime.ticks_ms() Activity.startActivity(None, Intent(activity_class=main_activity)) end_time = utime.ticks_diff(utime.ticks_ms(), start_time) @@ -112,6 +111,7 @@ def execute_script_new_thread(scriptname, is_file): # Returns True if successful def start_app(fullname): + from .content.package_manager import PackageManager mpos.ui.set_foreground_app(fullname) import utime start_time = utime.ticks_ms() @@ -142,6 +142,7 @@ def start_app(fullname): # Starts the first launcher that's found def restart_launcher(): + from .content.package_manager import PackageManager print("restart_launcher") # Stop all apps mpos.ui.remove_and_stop_all_activities() diff --git a/internal_filesystem/lib/mpos/battery_voltage.py b/internal_filesystem/lib/mpos/battery_voltage.py index c1615b8c..c25dfd5e 100644 --- a/internal_filesystem/lib/mpos/battery_voltage.py +++ b/internal_filesystem/lib/mpos/battery_voltage.py @@ -94,7 +94,7 @@ def read_raw_adc(force_refresh=False): WifiService = None if needs_wifi_disable: try: - from mpos.net.wifi_service import WifiService + from mpos import WifiService except ImportError: pass diff --git a/internal_filesystem/lib/mpos/bootloader.py b/internal_filesystem/lib/mpos/bootloader.py index cda291b5..f84ed819 100644 --- a/internal_filesystem/lib/mpos/bootloader.py +++ b/internal_filesystem/lib/mpos/bootloader.py @@ -1,7 +1,9 @@ -from mpos.apps import Activity import lvgl as lv +from .app.activity import Activity + class ResetIntoBootloader(Activity): + message = "Bootloader mode activated.\nYou can now install firmware over USB.\n\nReset the device to cancel." def onCreate(self): diff --git a/internal_filesystem/lib/mpos/main.py b/internal_filesystem/lib/mpos/main.py index 88caabcd..2ddda71c 100644 --- a/internal_filesystem/lib/mpos/main.py +++ b/internal_filesystem/lib/mpos/main.py @@ -5,9 +5,10 @@ import mpos import mpos.apps import mpos.config import mpos.ui -import mpos.ui.topmenu +from . import ui +from .content.package_manager import PackageManager from mpos.ui.display import init_rootscreen -from mpos.content.package_manager import PackageManager +import mpos.ui.topmenu # Auto-detect and initialize hardware import sys diff --git a/internal_filesystem/lib/mpos/time.py b/internal_filesystem/lib/mpos/time.py index 4afa51a9..b04e0e25 100644 --- a/internal_filesystem/lib/mpos/time.py +++ b/internal_filesystem/lib/mpos/time.py @@ -1,6 +1,6 @@ import time -import mpos.config -from mpos.timezones import TIMEZONE_MAP +from . import config +from .timezones import TIMEZONE_MAP import localPTZtime @@ -29,7 +29,7 @@ def sync_time(): def refresh_timezone_preference(): global timezone_preference - prefs = mpos.config.SharedPreferences("com.micropythonos.settings") + prefs = config.SharedPreferences("com.micropythonos.settings") timezone_preference = prefs.get_string("timezone") if not timezone_preference: timezone_preference = "Etc/GMT" # Use a default value so that it doesn't refresh every time the time is requested diff --git a/internal_filesystem/lib/mpos/ui/__init__.py b/internal_filesystem/lib/mpos/ui/__init__.py index 4290b83f..483b42e9 100644 --- a/internal_filesystem/lib/mpos/ui/__init__.py +++ b/internal_filesystem/lib/mpos/ui/__init__.py @@ -16,9 +16,13 @@ from .event import get_event_name, print_event from .util import shutdown, set_foreground_app, get_foreground_app from .setting_activity import SettingActivity from .settings_activity import SettingsActivity +from . import focus_direction + +# main_display is assigned by board-specific initialization code +main_display = None __all__ = [ - "setContentView", "back_screen", "remove_and_stop_current_activity", "remove_and_stop_all_activities" + "setContentView", "back_screen", "remove_and_stop_current_activity", "remove_and_stop_all_activities", "handle_back_swipe", "handle_top_swipe", "set_theme", "open_bar", "close_bar", "open_drawer", "drawer_open", "NOTIFICATION_BAR_HEIGHT", @@ -30,5 +34,6 @@ __all__ = [ "get_event_name", "print_event", "shutdown", "set_foreground_app", "get_foreground_app", "SettingActivity", - "SettingsActivity" + "SettingsActivity", + "focus_direction" ] diff --git a/internal_filesystem/lib/mpos/ui/camera_activity.py b/internal_filesystem/lib/mpos/ui/camera_activity.py index 9ddd2b5a..fc9e686d 100644 --- a/internal_filesystem/lib/mpos/ui/camera_activity.py +++ b/internal_filesystem/lib/mpos/ui/camera_activity.py @@ -6,11 +6,10 @@ try: except Exception as e: print(f"Info: could not import webcam module: {e}") -import mpos.time -from mpos.apps import Activity -from mpos.content.intent import Intent - +from ..time import epoch_seconds from .camera_settings import CameraSettingsActivity +from .. import ui as mpos_ui +from ..app.activity import Activity class CameraActivity(Activity): @@ -100,11 +99,11 @@ class CameraActivity(Activity): self.status_label_cont = lv.obj(self.main_screen) - width = mpos.ui.pct_of_display_width(70) - height = mpos.ui.pct_of_display_width(60) + width = mpos_ui.pct_of_display_width(70) + height = mpos_ui.pct_of_display_width(60) self.status_label_cont.set_size(width,height) - center_w = round((mpos.ui.pct_of_display_width(100) - self.button_width - 5 - width)/2) - center_h = round((mpos.ui.pct_of_display_height(100) - height)/2) + center_w = round((mpos_ui.pct_of_display_width(100) - self.button_width - 5 - width)/2) + center_h = round((mpos_ui.pct_of_display_height(100) - height)/2) self.status_label_cont.set_pos(center_w,center_h) self.status_label_cont.set_style_bg_color(lv.color_white(), 0) self.status_label_cont.set_style_bg_opa(66, 0) @@ -184,7 +183,7 @@ class CameraActivity(Activity): self.image_dsc.data = None def load_settings_cached(self): - from mpos.config import SharedPreferences + from mpos import SharedPreferences if self.scanqr_mode: print("loading scanqr settings...") if not self.scanqr_prefs: @@ -296,7 +295,7 @@ class CameraActivity(Activity): self.status_label_cont.remove_flag(lv.obj.FLAG.HIDDEN) return colorname = "RGB565" if self.colormode else "GRAY" - filename=f"{path}/picture_{mpos.time.epoch_seconds()}_{self.width}x{self.height}_{colorname}.raw" + filename=f"{path}/picture_{epoch_seconds()}_{self.width}x{self.height}_{colorname}.raw" try: with open(filename, 'wb') as f: f.write(self.current_cam_buffer) # This takes around 17 seconds to store 921600 bytes, so ~50KB/s, so would be nice to show some progress bar @@ -349,6 +348,7 @@ class CameraActivity(Activity): self.stop_qr_decoding() def open_settings(self): + from ..content.intent import Intent intent = Intent(activity_class=CameraSettingsActivity, extras={"prefs": self.prefs if not self.scanqr_mode else self.scanqr_prefs, "use_webcam": self.use_webcam, "scanqr_mode": self.scanqr_mode}) self.startActivity(intent) diff --git a/internal_filesystem/lib/mpos/ui/camera_settings.py b/internal_filesystem/lib/mpos/ui/camera_settings.py index f6468a35..406c9d52 100644 --- a/internal_filesystem/lib/mpos/ui/camera_settings.py +++ b/internal_filesystem/lib/mpos/ui/camera_settings.py @@ -1,9 +1,9 @@ import lvgl as lv -import mpos.ui -from mpos.apps import Activity -from mpos.config import SharedPreferences -from mpos.content.intent import Intent +from ..config import SharedPreferences +from ..app.activity import Activity +from .display import pct_of_display_width, pct_of_display_height +from . import anim class CameraSettingsActivity(Activity): @@ -124,8 +124,8 @@ class CameraSettingsActivity(Activity): # Create tabview tabview = lv.tabview(screen) - tabview.set_tab_bar_size(mpos.ui.pct_of_display_height(15)) - #tabview.set_size(lv.pct(100), mpos.ui.pct_of_display_height(80)) + tabview.set_tab_bar_size(pct_of_display_height(15)) + #tabview.set_size(lv.pct(100), pct_of_display_height(80)) # Create Basic tab (always) basic_tab = tabview.add_tab("Basic") @@ -227,7 +227,7 @@ class CameraSettingsActivity(Activity): textarea.align(lv.ALIGN.TOP_RIGHT, 0, 0) # Initialize keyboard (hidden initially) - from mpos.ui.keyboard import MposKeyboard + from ..indev.mpos_sdl_keyboard import MposKeyboard keyboard = MposKeyboard(parent) keyboard.align(lv.ALIGN.BOTTOM_MID, 0, 0) keyboard.add_flag(lv.obj.FLAG.HIDDEN) @@ -238,7 +238,7 @@ class CameraSettingsActivity(Activity): def add_buttons(self, parent): # Save/Cancel buttons at bottom button_cont = lv.obj(parent) - button_cont.set_size(lv.pct(100), mpos.ui.pct_of_display_height(20)) + button_cont.set_size(lv.pct(100), pct_of_display_height(20)) button_cont.remove_flag(lv.obj.FLAG.SCROLLABLE) button_cont.align(lv.ALIGN.BOTTOM_MID, 0, 0) button_cont.set_style_border_width(0, 0) @@ -255,9 +255,9 @@ class CameraSettingsActivity(Activity): save_label.center() cancel_button = lv.button(button_cont) - cancel_button.set_size(mpos.ui.pct_of_display_width(25), lv.SIZE_CONTENT) + cancel_button.set_size(pct_of_display_width(25), lv.SIZE_CONTENT) if self.scanqr_mode: - cancel_button.align(lv.ALIGN.BOTTOM_MID, mpos.ui.pct_of_display_width(10), 0) + cancel_button.align(lv.ALIGN.BOTTOM_MID, pct_of_display_width(10), 0) else: cancel_button.align(lv.ALIGN.BOTTOM_MID, 0, 0) cancel_button.add_event_cb(lambda e: self.finish(), lv.EVENT.CLICKED, None) @@ -266,7 +266,7 @@ class CameraSettingsActivity(Activity): cancel_label.center() erase_button = lv.button(button_cont) - erase_button.set_size(mpos.ui.pct_of_display_width(20), lv.SIZE_CONTENT) + erase_button.set_size(pct_of_display_width(20), lv.SIZE_CONTENT) erase_button.align(lv.ALIGN.BOTTOM_RIGHT, 0, 0) erase_button.add_event_cb(lambda e: self.erase_and_close(), lv.EVENT.CLICKED, None) erase_label = lv.label(erase_button) @@ -353,11 +353,11 @@ class CameraSettingsActivity(Activity): def exposure_ctrl_changed(e=None): is_auto = aec_checkbox.get_state() & lv.STATE.CHECKED if is_auto: - mpos.ui.anim.smooth_hide(me_cont, duration=1000) - mpos.ui.anim.smooth_show(ae_cont, delay=1000) + anim.smooth_hide(me_cont, duration=1000) + anim.smooth_show(ae_cont, delay=1000) else: - mpos.ui.anim.smooth_hide(ae_cont, duration=1000) - mpos.ui.anim.smooth_show(me_cont, delay=1000) + anim.smooth_hide(ae_cont, duration=1000) + anim.smooth_show(me_cont, delay=1000) aec_checkbox.add_event_cb(exposure_ctrl_changed, lv.EVENT.VALUE_CHANGED, None) exposure_ctrl_changed() @@ -381,9 +381,9 @@ class CameraSettingsActivity(Activity): is_auto = agc_checkbox.get_state() & lv.STATE.CHECKED gain_slider = self.ui_controls["agc_gain"] if is_auto: - mpos.ui.anim.smooth_hide(agc_cont, duration=1000) + anim.smooth_hide(agc_cont, duration=1000) else: - mpos.ui.anim.smooth_show(agc_cont, duration=1000) + anim.smooth_show(agc_cont, duration=1000) agc_checkbox.add_event_cb(gain_ctrl_changed, lv.EVENT.VALUE_CHANGED, None) gain_ctrl_changed() @@ -413,9 +413,9 @@ class CameraSettingsActivity(Activity): def whitebal_changed(e=None): is_auto = wbcheckbox.get_state() & lv.STATE.CHECKED if is_auto: - mpos.ui.anim.smooth_hide(wb_cont, duration=1000) + anim.smooth_hide(wb_cont, duration=1000) else: - mpos.ui.anim.smooth_show(wb_cont, duration=1000) + anim.smooth_show(wb_cont, duration=1000) wbcheckbox.add_event_cb(whitebal_changed, lv.EVENT.VALUE_CHANGED, None) whitebal_changed() diff --git a/internal_filesystem/lib/mpos/ui/setting_activity.py b/internal_filesystem/lib/mpos/ui/setting_activity.py index e63d3e02..68ab2976 100644 --- a/internal_filesystem/lib/mpos/ui/setting_activity.py +++ b/internal_filesystem/lib/mpos/ui/setting_activity.py @@ -1,9 +1,9 @@ import lvgl as lv -import mpos -from mpos.apps import Activity, Intent -from mpos.ui.keyboard import MposKeyboard +from ..app.activity import Activity from .camera_activity import CameraActivity +from .display import pct_of_display_width +from . import anim """ SettingActivity is used to edit one setting. @@ -20,10 +20,6 @@ class SettingActivity(Activity): dropdown = None radio_container = None - def __init__(self): - super().__init__() - self.setting = None - def onCreate(self): self.prefs = self.getIntent().extras.get("prefs") setting = self.getIntent().extras.get("setting") @@ -83,15 +79,16 @@ class SettingActivity(Activity): ui = "textarea" self.textarea = lv.textarea(settings_screen_detail) self.textarea.set_width(lv.pct(100)) - self.textarea.set_style_pad_all(mpos.ui.pct_of_display_width(2), lv.PART.MAIN) - self.textarea.set_style_margin_left(mpos.ui.pct_of_display_width(2), lv.PART.MAIN) - self.textarea.set_style_margin_right(mpos.ui.pct_of_display_width(2), lv.PART.MAIN) + self.textarea.set_style_pad_all(pct_of_display_width(2), lv.PART.MAIN) + self.textarea.set_style_margin_left(pct_of_display_width(2), lv.PART.MAIN) + self.textarea.set_style_margin_right(pct_of_display_width(2), lv.PART.MAIN) self.textarea.set_one_line(True) if current_setting: self.textarea.set_text(current_setting) placeholder = setting.get("placeholder") if placeholder: self.textarea.set_placeholder_text(placeholder) + from mpos import MposKeyboard self.keyboard = MposKeyboard(settings_screen_detail) self.keyboard.add_flag(lv.obj.FLAG.HIDDEN) self.keyboard.set_textarea(self.textarea) @@ -136,7 +133,7 @@ class SettingActivity(Activity): def onStop(self, screen): if self.keyboard: - mpos.ui.anim.smooth_hide(self.keyboard) + anim.smooth_hide(self.keyboard) def radio_event_handler(self, event): print("radio_event_handler called") @@ -180,6 +177,7 @@ class SettingActivity(Activity): self.textarea.set_text(data) def cambutton_cb(self, event): + from ..content.intent import Intent print("cambutton clicked!") self.startActivityForResult(Intent(activity_class=CameraActivity).putExtra("scanqr_intent", True), self.gotqr_result_callback) diff --git a/internal_filesystem/lib/mpos/ui/settings_activity.py b/internal_filesystem/lib/mpos/ui/settings_activity.py index 76a5c537..cc968b54 100644 --- a/internal_filesystem/lib/mpos/ui/settings_activity.py +++ b/internal_filesystem/lib/mpos/ui/settings_activity.py @@ -1,8 +1,8 @@ import lvgl as lv -import mpos -from mpos.apps import Activity, Intent +from ..app.activity import Activity from .setting_activity import SettingActivity +import mpos.ui # Used to list and edit all settings: class SettingsActivity(Activity): @@ -77,6 +77,7 @@ class SettingsActivity(Activity): container.set_style_border_width(0, lv.PART.MAIN) def startSettingActivity(self, setting): + from ..content.intent import Intent activity_class = SettingActivity if setting.get("ui") == "activity": activity_class = setting.get("activity_class") diff --git a/internal_filesystem/lib/mpos/ui/topmenu.py b/internal_filesystem/lib/mpos/ui/topmenu.py index f67616a5..0486d07d 100644 --- a/internal_filesystem/lib/mpos/ui/topmenu.py +++ b/internal_filesystem/lib/mpos/ui/topmenu.py @@ -1,12 +1,11 @@ import lvgl as lv -import mpos.ui import mpos.time import mpos.battery_voltage -from .display import (get_display_width, get_display_height) +from .display import (get_display_width, get_display_height, pct_of_display_width, pct_of_display_height, get_pointer_xy) from .util import (get_foreground_app) - -from mpos.ui.anim import WidgetAnimator +from . import focus_direction +from .anim import WidgetAnimator NOTIFICATION_BAR_HEIGHT=24 @@ -89,14 +88,14 @@ def create_notification_bar(): # Time label time_label = lv.label(notification_bar) time_label.set_text("00:00:00") - time_label.align(lv.ALIGN.LEFT_MID, mpos.ui.pct_of_display_width(10), 0) + time_label.align(lv.ALIGN.LEFT_MID, pct_of_display_width(10), 0) temp_label = lv.label(notification_bar) temp_label.set_text("00°C") - temp_label.align_to(time_label, lv.ALIGN.OUT_RIGHT_MID, mpos.ui.pct_of_display_width(7) , 0) + temp_label.align_to(time_label, lv.ALIGN.OUT_RIGHT_MID, pct_of_display_width(7) , 0) if False: memfree_label = lv.label(notification_bar) memfree_label.set_text("") - memfree_label.align_to(temp_label, lv.ALIGN.OUT_RIGHT_MID, mpos.ui.pct_of_display_width(7), 0) + memfree_label.align_to(temp_label, lv.ALIGN.OUT_RIGHT_MID, pct_of_display_width(7), 0) #style = lv.style_t() #style.init() #style.set_text_font(lv.font_montserrat_8) # tiny font @@ -114,12 +113,12 @@ def create_notification_bar(): battery_icon = lv.label(notification_bar) battery_icon.set_text(lv.SYMBOL.BATTERY_FULL) #battery_icon.align_to(battery_label, lv.ALIGN.OUT_LEFT_MID, 0, 0) - battery_icon.align(lv.ALIGN.RIGHT_MID, -mpos.ui.pct_of_display_width(10), 0) + battery_icon.align(lv.ALIGN.RIGHT_MID, -pct_of_display_width(10), 0) battery_icon.add_flag(lv.obj.FLAG.HIDDEN) # keep it hidden until it has a correct value # WiFi icon wifi_icon = lv.label(notification_bar) wifi_icon.set_text(lv.SYMBOL.WIFI) - wifi_icon.align_to(battery_icon, lv.ALIGN.OUT_LEFT_MID, -mpos.ui.pct_of_display_width(1), 0) + wifi_icon.align_to(battery_icon, lv.ALIGN.OUT_LEFT_MID, -pct_of_display_width(1), 0) wifi_icon.add_flag(lv.obj.FLAG.HIDDEN) # Update time def update_time(timer): @@ -158,7 +157,7 @@ def create_notification_bar(): update_battery_icon() # run it immediately instead of waiting for the timer def update_wifi_icon(timer): - from mpos.net.wifi_service import WifiService + from mpos import WifiService if WifiService.is_connected(): wifi_icon.remove_flag(lv.obj.FLAG.HIDDEN) else: @@ -372,7 +371,7 @@ def create_drawer(display=None): def drawer_scroll_callback(event): global scroll_start_y event_code=event.get_code() - x, y = mpos.ui.get_pointer_xy() + x, y = get_pointer_xy() #name = mpos.ui.get_event_name(event_code) #print(f"drawer_scroll: code={event_code}, name={name}, ({x},{y})") if event_code == lv.EVENT.SCROLL_BEGIN and scroll_start_y == None: diff --git a/internal_filesystem/lib/mpos/ui/view.py b/internal_filesystem/lib/mpos/ui/view.py index 08da9788..377fa2bf 100644 --- a/internal_filesystem/lib/mpos/ui/view.py +++ b/internal_filesystem/lib/mpos/ui/view.py @@ -14,12 +14,12 @@ def setContentView(new_activity, new_screen): try: current_activity.onPause(current_screen) except Exception as e: - print(f"onPause caught exception: {e}") + print(f"onPause caught exception:") sys.print_exception(e) try: current_activity.onStop(current_screen) except Exception as e: - print(f"onStop caught exception: {e}") + print(f"onStop caught exception:") sys.print_exception(e) from .util import close_top_layer_msgboxes @@ -31,14 +31,14 @@ def setContentView(new_activity, new_screen): try: new_activity.onStart(new_screen) except Exception as e: - print(f"onStart caught exception: {e}") + print(f"onStart caught exception:") sys.print_exception(e) lv.screen_load_anim(new_screen, lv.SCR_LOAD_ANIM.OVER_LEFT, 500, 0, False) if new_activity: try: new_activity.onResume(new_screen) except Exception as e: - print(f"onResume caught exception: {e}") + print(f"onResume caught exception:") sys.print_exception(e) def remove_and_stop_all_activities(): @@ -52,17 +52,17 @@ def remove_and_stop_current_activity(): try: current_activity.onPause(current_screen) except Exception as e: - print(f"onPause caught exception: {e}") + print(f"onPause caught exception:") sys.print_exception(e) try: current_activity.onStop(current_screen) except Exception as e: - print(f"onStop caught exception: {e}") + print(f"onStop caught exception:") sys.print_exception(e) try: current_activity.onDestroy(current_screen) except Exception as e: - print(f"onDestroy caught exception: {e}") + print(f"onDestroy caught exception:") sys.print_exception(e) if current_screen: current_screen.clean() diff --git a/tests/base/graphical_test_base.py b/tests/base/graphical_test_base.py index 25927c8f..cac2993a 100644 --- a/tests/base/graphical_test_base.py +++ b/tests/base/graphical_test_base.py @@ -98,7 +98,7 @@ class GraphicalTestBase(unittest.TestCase): Args: iterations: Number of render iterations (default: DEFAULT_RENDER_ITERATIONS) """ - from mpos.ui.testing import wait_for_render + from mpos import wait_for_render if iterations is None: iterations = self.DEFAULT_RENDER_ITERATIONS wait_for_render(iterations) @@ -115,7 +115,7 @@ class GraphicalTestBase(unittest.TestCase): Returns: bytes: The screenshot buffer """ - from mpos.ui.testing import capture_screenshot + from mpos import capture_screenshot if width is None: width = self.SCREEN_WIDTH @@ -136,7 +136,7 @@ class GraphicalTestBase(unittest.TestCase): Returns: The label widget if found, None otherwise """ - from mpos.ui.testing import find_label_with_text + from mpos import find_label_with_text if parent is None: parent = lv.screen_active() return find_label_with_text(parent, text) @@ -152,7 +152,7 @@ class GraphicalTestBase(unittest.TestCase): Returns: bool: True if text is found """ - from mpos.ui.testing import verify_text_present + from mpos import verify_text_present if parent is None: parent = lv.screen_active() return verify_text_present(parent, text) @@ -164,7 +164,7 @@ class GraphicalTestBase(unittest.TestCase): Args: parent: Parent widget to search in (default: current screen) """ - from mpos.ui.testing import print_screen_labels + from mpos import print_screen_labels if parent is None: parent = lv.screen_active() print_screen_labels(parent) @@ -180,7 +180,7 @@ class GraphicalTestBase(unittest.TestCase): Returns: bool: True if button was found and clicked """ - from mpos.ui.testing import click_button + from mpos import click_button return click_button(text, use_send_event=use_send_event) def click_label(self, text, use_send_event=True): @@ -194,7 +194,7 @@ class GraphicalTestBase(unittest.TestCase): Returns: bool: True if label was found and clicked """ - from mpos.ui.testing import click_label + from mpos import click_label return click_label(text, use_send_event=use_send_event) def simulate_click(self, x, y): @@ -208,7 +208,7 @@ class GraphicalTestBase(unittest.TestCase): x: X coordinate y: Y coordinate """ - from mpos.ui.testing import simulate_click + from mpos import simulate_click simulate_click(x, y) self.wait_for_render() diff --git a/tests/base/keyboard_test_base.py b/tests/base/keyboard_test_base.py index f49be8e8..86670ec8 100644 --- a/tests/base/keyboard_test_base.py +++ b/tests/base/keyboard_test_base.py @@ -53,7 +53,7 @@ class KeyboardTestBase(GraphicalTestBase): Returns: tuple: (keyboard, textarea) """ - from mpos.ui.keyboard import MposKeyboard + from mpos import MposKeyboard # Create textarea self.textarea = lv.textarea(self.screen) @@ -84,7 +84,7 @@ class KeyboardTestBase(GraphicalTestBase): Returns: bool: True if button was clicked successfully """ - from mpos.ui.testing import click_keyboard_button + from mpos import click_keyboard_button if self.keyboard is None: raise RuntimeError("No keyboard created. Call create_keyboard_scene() first.") diff --git a/tests/test_connectivity_manager.py b/tests/test_connectivity_manager.py index 99ffd720..96384868 100644 --- a/tests/test_connectivity_manager.py +++ b/tests/test_connectivity_manager.py @@ -49,7 +49,7 @@ class TestConnectivityManagerWithNetwork(unittest.TestCase): del sys.modules['mpos.net.connectivity_manager'] # Import fresh - from mpos.net.connectivity_manager import ConnectivityManager + from mpos import ConnectivityManager self.ConnectivityManager = ConnectivityManager # Reset the singleton instance @@ -301,7 +301,7 @@ class TestConnectivityManagerWithoutNetwork(unittest.TestCase): if 'mpos.net.connectivity_manager' in sys.modules: del sys.modules['mpos.net.connectivity_manager'] - from mpos.net.connectivity_manager import ConnectivityManager + from mpos import ConnectivityManager self.ConnectivityManager = ConnectivityManager # Reset the singleton instance @@ -382,7 +382,7 @@ class TestConnectivityManagerWaitUntilOnline(unittest.TestCase): if 'mpos.net.connectivity_manager' in sys.modules: del sys.modules['mpos.net.connectivity_manager'] - from mpos.net.connectivity_manager import ConnectivityManager + from mpos import ConnectivityManager self.ConnectivityManager = ConnectivityManager ConnectivityManager._instance = None @@ -417,7 +417,7 @@ class TestConnectivityManagerWaitUntilOnline(unittest.TestCase): if 'mpos.net.connectivity_manager' in sys.modules: del sys.modules['mpos.net.connectivity_manager'] - from mpos.net.connectivity_manager import ConnectivityManager + from mpos import ConnectivityManager self.ConnectivityManager = ConnectivityManager ConnectivityManager._instance = None @@ -439,7 +439,7 @@ class TestConnectivityManagerEdgeCases(unittest.TestCase): if 'mpos.net.connectivity_manager' in sys.modules: del sys.modules['mpos.net.connectivity_manager'] - from mpos.net.connectivity_manager import ConnectivityManager + from mpos import ConnectivityManager self.ConnectivityManager = ConnectivityManager ConnectivityManager._instance = None @@ -550,7 +550,7 @@ class TestConnectivityManagerIntegration(unittest.TestCase): if 'mpos.net.connectivity_manager' in sys.modules: del sys.modules['mpos.net.connectivity_manager'] - from mpos.net.connectivity_manager import ConnectivityManager + from mpos import ConnectivityManager self.ConnectivityManager = ConnectivityManager ConnectivityManager._instance = None diff --git a/tests/test_graphical_abc_button_debug.py b/tests/test_graphical_abc_button_debug.py index dc8575da..83008c4b 100644 --- a/tests/test_graphical_abc_button_debug.py +++ b/tests/test_graphical_abc_button_debug.py @@ -9,8 +9,7 @@ Usage: import unittest import lvgl as lv -from mpos.ui.keyboard import MposKeyboard -from mpos.ui.testing import wait_for_render +from mpos import MposKeyboard, wait_for_render class TestAbcButtonDebug(unittest.TestCase): diff --git a/tests/test_graphical_about_app.py b/tests/test_graphical_about_app.py index 98c82308..96cb1498 100644 --- a/tests/test_graphical_about_app.py +++ b/tests/test_graphical_about_app.py @@ -21,7 +21,7 @@ import mpos.apps import mpos.info import mpos.ui import os -from mpos.ui.testing import ( +from mpos import ( wait_for_render, capture_screenshot, find_label_with_text, diff --git a/tests/test_graphical_animation_deleted_widget.py b/tests/test_graphical_animation_deleted_widget.py index 4fe367b3..0de85aee 100644 --- a/tests/test_graphical_animation_deleted_widget.py +++ b/tests/test_graphical_animation_deleted_widget.py @@ -19,7 +19,7 @@ import unittest import lvgl as lv import mpos.ui.anim import time -from mpos.ui.testing import wait_for_render +from mpos import wait_for_render class TestAnimationDeletedWidget(unittest.TestCase): @@ -130,7 +130,7 @@ class TestAnimationDeletedWidget(unittest.TestCase): """ print("Testing keyboard deletion scenario...") - from mpos.ui.keyboard import MposKeyboard + from mpos import MposKeyboard # Create textarea and keyboard (like QuasiNametag does) textarea = lv.textarea(self.screen) diff --git a/tests/test_graphical_camera_settings.py b/tests/test_graphical_camera_settings.py index 2a63a5b6..471a05d1 100644 --- a/tests/test_graphical_camera_settings.py +++ b/tests/test_graphical_camera_settings.py @@ -23,7 +23,7 @@ import mpos.apps import mpos.ui import os import sys -from mpos.ui.testing import ( +from mpos import ( wait_for_render, capture_screenshot, find_label_with_text, diff --git a/tests/test_graphical_custom_keyboard.py b/tests/test_graphical_custom_keyboard.py index 55d564db..94a81f0b 100644 --- a/tests/test_graphical_custom_keyboard.py +++ b/tests/test_graphical_custom_keyboard.py @@ -13,11 +13,7 @@ import unittest import lvgl as lv import sys import os -from mpos.ui.keyboard import MposKeyboard -from mpos.ui.testing import ( - wait_for_render, - capture_screenshot, -) +from mpos import MposKeyboard, wait_for_render, capture_screenshot class TestGraphicalMposKeyboard(unittest.TestCase): diff --git a/tests/test_graphical_custom_keyboard_basic.py b/tests/test_graphical_custom_keyboard_basic.py index bad39108..1f3cc25e 100644 --- a/tests/test_graphical_custom_keyboard_basic.py +++ b/tests/test_graphical_custom_keyboard_basic.py @@ -10,8 +10,7 @@ Usage: import unittest import lvgl as lv -from mpos.ui.keyboard import MposKeyboard -from mpos.ui.testing import simulate_click, wait_for_render +from mpos import MposKeyboard, simulate_click, wait_for_render class TestMposKeyboard(unittest.TestCase): diff --git a/tests/test_graphical_imu_calibration.py b/tests/test_graphical_imu_calibration.py index 08457d27..4686594a 100644 --- a/tests/test_graphical_imu_calibration.py +++ b/tests/test_graphical_imu_calibration.py @@ -16,7 +16,7 @@ import mpos.ui import os import sys import time -from mpos.ui.testing import ( +from mpos import ( wait_for_render, capture_screenshot, find_label_with_text, diff --git a/tests/test_graphical_imu_calibration_ui_bug.py b/tests/test_graphical_imu_calibration_ui_bug.py index c44430e0..f7ab6046 100755 --- a/tests/test_graphical_imu_calibration_ui_bug.py +++ b/tests/test_graphical_imu_calibration_ui_bug.py @@ -16,7 +16,7 @@ import unittest # Import graphical test infrastructure import lvgl as lv -from mpos.ui.testing import ( +from mpos import ( wait_for_render, simulate_click, find_button_with_text, @@ -91,7 +91,7 @@ class TestIMUCalibrationUI(unittest.TestCase): # Look for actual values (not "--") has_values_before = False widgets = [] - from mpos.ui.testing import get_all_widgets_with_text + from mpos import get_all_widgets_with_text for widget in get_all_widgets_with_text(lv.screen_active()): text = widget.get_text() # Look for patterns like "X: 0.00" or "Quality: Good" diff --git a/tests/test_graphical_keyboard_crash_reproduction.py b/tests/test_graphical_keyboard_crash_reproduction.py index 0710735f..4c37138e 100644 --- a/tests/test_graphical_keyboard_crash_reproduction.py +++ b/tests/test_graphical_keyboard_crash_reproduction.py @@ -9,8 +9,7 @@ Usage: import unittest import lvgl as lv -from mpos.ui.keyboard import MposKeyboard -from mpos.ui.testing import wait_for_render +from mpos import MposKeyboard, wait_for_render class TestKeyboardCrash(unittest.TestCase): diff --git a/tests/test_graphical_keyboard_default_vs_custom.py b/tests/test_graphical_keyboard_default_vs_custom.py index 5fba3b9b..ffc1976c 100644 --- a/tests/test_graphical_keyboard_default_vs_custom.py +++ b/tests/test_graphical_keyboard_default_vs_custom.py @@ -10,8 +10,7 @@ Usage: import unittest import lvgl as lv -from mpos.ui.keyboard import MposKeyboard -from mpos.ui.testing import wait_for_render +from mpos import MposKeyboard, wait_for_render class TestDefaultVsCustomKeyboard(unittest.TestCase): diff --git a/tests/test_graphical_keyboard_layout_switching.py b/tests/test_graphical_keyboard_layout_switching.py index 83c2bcec..d1a0d922 100644 --- a/tests/test_graphical_keyboard_layout_switching.py +++ b/tests/test_graphical_keyboard_layout_switching.py @@ -11,8 +11,7 @@ Usage: import unittest import lvgl as lv -from mpos.ui.keyboard import MposKeyboard -from mpos.ui.testing import wait_for_render +from mpos import MposKeyboard, wait_for_render class TestKeyboardLayoutSwitching(unittest.TestCase): diff --git a/tests/test_graphical_keyboard_method_forwarding.py b/tests/test_graphical_keyboard_method_forwarding.py index e96b3d63..883eadbf 100644 --- a/tests/test_graphical_keyboard_method_forwarding.py +++ b/tests/test_graphical_keyboard_method_forwarding.py @@ -10,7 +10,7 @@ Usage: import unittest import lvgl as lv -from mpos.ui.keyboard import MposKeyboard +from mpos import MposKeyboard class TestMethodForwarding(unittest.TestCase): diff --git a/tests/test_graphical_keyboard_mode_switch.py b/tests/test_graphical_keyboard_mode_switch.py index 85967d1d..774a194f 100644 --- a/tests/test_graphical_keyboard_mode_switch.py +++ b/tests/test_graphical_keyboard_mode_switch.py @@ -11,8 +11,7 @@ Usage: import unittest import lvgl as lv -from mpos.ui.keyboard import MposKeyboard -from mpos.ui.testing import wait_for_render +from mpos import MposKeyboard, wait_for_render class TestKeyboardModeSwitch(unittest.TestCase): diff --git a/tests/test_graphical_keyboard_rapid_mode_switch.py b/tests/test_graphical_keyboard_rapid_mode_switch.py index 7cded668..ab1204de 100644 --- a/tests/test_graphical_keyboard_rapid_mode_switch.py +++ b/tests/test_graphical_keyboard_rapid_mode_switch.py @@ -11,8 +11,7 @@ Usage: import unittest import lvgl as lv -from mpos.ui.keyboard import MposKeyboard -from mpos.ui.testing import wait_for_render +from mpos import MposKeyboard, wait_for_render class TestRapidModeSwitching(unittest.TestCase): diff --git a/tests/test_graphical_keyboard_styling.py b/tests/test_graphical_keyboard_styling.py index 1f925972..b840bd9a 100644 --- a/tests/test_graphical_keyboard_styling.py +++ b/tests/test_graphical_keyboard_styling.py @@ -22,7 +22,7 @@ import mpos.ui import mpos.config import sys import os -from mpos.ui.testing import ( +from mpos import ( wait_for_render, capture_screenshot, ) diff --git a/tests/test_graphical_launch_all_apps.py b/tests/test_graphical_launch_all_apps.py index dc6068da..7010285a 100644 --- a/tests/test_graphical_launch_all_apps.py +++ b/tests/test_graphical_launch_all_apps.py @@ -13,10 +13,7 @@ import time # This is a graphical test - needs boot and main to run first # Add tests directory to path for helpers -from mpos.ui.testing import wait_for_render -import mpos.apps -import mpos.ui -from mpos.content.package_manager import PackageManager +from mpos import wait_for_render, apps, ui, PackageManager class TestLaunchAllApps(unittest.TestCase): diff --git a/tests/test_graphical_osupdate.py b/tests/test_graphical_osupdate.py index 3f718e73..036397cb 100644 --- a/tests/test_graphical_osupdate.py +++ b/tests/test_graphical_osupdate.py @@ -6,7 +6,7 @@ import sys import os # Import graphical test helper -from mpos.ui.testing import ( +from mpos import ( wait_for_render, capture_screenshot, find_label_with_text, diff --git a/tests/test_graphical_start_app.py b/tests/test_graphical_start_app.py index e8634d7a..2aecc4a2 100644 --- a/tests/test_graphical_start_app.py +++ b/tests/test_graphical_start_app.py @@ -14,8 +14,7 @@ Usage: import unittest import mpos.apps -import mpos.ui -from mpos.ui.testing import wait_for_render +from mpos import ui, wait_for_render class TestStartApp(unittest.TestCase): diff --git a/tests/test_graphical_wifi_keyboard.py b/tests/test_graphical_wifi_keyboard.py index 59fd910a..cf9afaaf 100644 --- a/tests/test_graphical_wifi_keyboard.py +++ b/tests/test_graphical_wifi_keyboard.py @@ -11,8 +11,7 @@ Usage: import unittest import lvgl as lv -from mpos.ui.keyboard import MposKeyboard -from mpos.ui.testing import wait_for_render +from mpos import MposKeyboard, wait_for_render class TestWiFiKeyboard(unittest.TestCase): diff --git a/tests/test_intent.py b/tests/test_intent.py index 34ef5de5..c1b6dfd0 100644 --- a/tests/test_intent.py +++ b/tests/test_intent.py @@ -1,5 +1,5 @@ import unittest -from mpos.content.intent import Intent +from mpos import Intent class TestIntent(unittest.TestCase): diff --git a/tests/test_rtttl.py b/tests/test_rtttl.py index 07dbc801..7b5e03c1 100644 --- a/tests/test_rtttl.py +++ b/tests/test_rtttl.py @@ -30,7 +30,7 @@ sys.modules['machine'] = type('module', (), {'PWM': MockPWM, 'Pin': lambda x: x} # Now import the module to test -from mpos.audio.stream_rtttl import RTTTLStream +from mpos.audio.stream_rtttl import RTTTLStream # Keep this as-is since it's a specific internal module class TestRTTTL(unittest.TestCase): diff --git a/tests/test_shared_preferences.py b/tests/test_shared_preferences.py index f8e28215..634c225a 100644 --- a/tests/test_shared_preferences.py +++ b/tests/test_shared_preferences.py @@ -1,6 +1,7 @@ import unittest import os -from mpos.config import SharedPreferences, Editor +from mpos import SharedPreferences +from mpos.config import Editor class TestSharedPreferences(unittest.TestCase):