mobipick-labs-docker-gui 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. mobipick_labs_docker_gui-0.1.0/MANIFEST.in +2 -0
  2. mobipick_labs_docker_gui-0.1.0/PKG-INFO +202 -0
  3. mobipick_labs_docker_gui-0.1.0/README.md +176 -0
  4. mobipick_labs_docker_gui-0.1.0/mobipick_gui/__init__.py +7 -0
  5. mobipick_labs_docker_gui-0.1.0/mobipick_gui/__main__.py +9 -0
  6. mobipick_labs_docker_gui-0.1.0/mobipick_gui/ansi.py +58 -0
  7. mobipick_labs_docker_gui-0.1.0/mobipick_gui/cli.py +53 -0
  8. mobipick_labs_docker_gui-0.1.0/mobipick_gui/config.py +206 -0
  9. mobipick_labs_docker_gui-0.1.0/mobipick_gui/log_widget.py +74 -0
  10. mobipick_labs_docker_gui-0.1.0/mobipick_gui/main_window.py +3257 -0
  11. mobipick_labs_docker_gui-0.1.0/mobipick_gui/process_tab.py +118 -0
  12. mobipick_labs_docker_gui-0.1.0/mobipick_gui/resources/__init__.py +0 -0
  13. mobipick_labs_docker_gui-0.1.0/mobipick_gui/resources/clean.bash +102 -0
  14. mobipick_labs_docker_gui-0.1.0/mobipick_gui/resources/config/docker_cp_image_tag.yaml +30 -0
  15. mobipick_labs_docker_gui-0.1.0/mobipick_gui/resources/config/gui_settings.yaml +59 -0
  16. mobipick_labs_docker_gui-0.1.0/mobipick_gui/resources/config/worlds.yaml +1 -0
  17. mobipick_labs_docker_gui-0.1.0/mobipick_gui/resources/docker-compose.yml +57 -0
  18. mobipick_labs_docker_gui-0.1.0/mobipick_gui/resources/scripts/.gitkeep +0 -0
  19. mobipick_labs_docker_gui-0.1.0/mobipick_labs_docker_gui.egg-info/PKG-INFO +202 -0
  20. mobipick_labs_docker_gui-0.1.0/mobipick_labs_docker_gui.egg-info/SOURCES.txt +25 -0
  21. mobipick_labs_docker_gui-0.1.0/mobipick_labs_docker_gui.egg-info/dependency_links.txt +1 -0
  22. mobipick_labs_docker_gui-0.1.0/mobipick_labs_docker_gui.egg-info/entry_points.txt +2 -0
  23. mobipick_labs_docker_gui-0.1.0/mobipick_labs_docker_gui.egg-info/not-zip-safe +1 -0
  24. mobipick_labs_docker_gui-0.1.0/mobipick_labs_docker_gui.egg-info/requires.txt +5 -0
  25. mobipick_labs_docker_gui-0.1.0/mobipick_labs_docker_gui.egg-info/top_level.txt +1 -0
  26. mobipick_labs_docker_gui-0.1.0/pyproject.toml +45 -0
  27. mobipick_labs_docker_gui-0.1.0/setup.cfg +4 -0
@@ -0,0 +1,2 @@
1
+ include README.md
2
+ recursive-include mobipick_gui/resources *
@@ -0,0 +1,202 @@
1
+ Metadata-Version: 2.4
2
+ Name: mobipick-labs-docker-gui
3
+ Version: 0.1.0
4
+ Summary: PyQt5 desktop controller for the Mobipick Labs Docker simulation
5
+ Author: Mobipick Labs
6
+ License: Proprietary
7
+ Project-URL: Homepage, https://github.com/openai/mobipick_labs_docker_gui
8
+ Keywords: mobipick,docker,gui,ros,simulation
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: Other/Proprietary License
12
+ Classifier: Programming Language :: Python
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Operating System :: POSIX :: Linux
20
+ Classifier: Topic :: Software Development :: User Interfaces
21
+ Requires-Python: >=3.8
22
+ Description-Content-Type: text/markdown
23
+ Requires-Dist: PyQt5>=5.15
24
+ Requires-Dist: PyYAML>=6.0
25
+ Requires-Dist: importlib-resources>=5.0; python_version < "3.9"
26
+
27
+ # Mobipick Labs Docker GUI
28
+
29
+ The Mobipick Labs Docker GUI is a PyQt5 desktop application that orchestrates the
30
+ Docker-based Mobipick Labs robotics simulation. Instead of manually invoking
31
+ `docker compose` yourself, you launch the `mobipick-labs-docker-gui` command (or
32
+ `python -m mobipick_gui`) and drive the bring-up,
33
+ monitoring, and shutdown of the simulation through an interactive interface.
34
+ The GUI reads the bundled configuration files, runs Docker commands on your
35
+ behalf, and streams live logs so you can follow what is happening in each
36
+ container.
37
+
38
+ <img src="doc/mobipick_labs_docker_gui.png" alt="mobipick tables sim and real" width="420">
39
+
40
+ ## Repository layout
41
+
42
+ ```
43
+ ├── gui.py # Legacy CLI shim that forwards to the packaged entry point
44
+ ├── mobipick_gui/
45
+ │ ├── resources/ # Bundled compose file, default configs, helper scripts
46
+ │ └── … # PyQt5 widgets, process orchestration, and helpers
47
+ ├── MANIFEST.in # Source distribution manifest
48
+ └── pyproject.toml # Packaging metadata for PyPI distribution
49
+ ```
50
+
51
+ The compose file is **not** intended to be executed directly. The GUI manages it
52
+ for you by spawning `docker compose` subprocesses, supervising their lifecycle,
53
+ and performing cleanup logic when you close the application.
54
+
55
+ ## Prerequisites
56
+
57
+ * Ubuntu Linux (tested on versions 20.04, 22.04, and 24.04)
58
+ * Python 3.8+ with PyQt5 available (e.g. `pip install PyQt5`).
59
+ * Docker Engine and the Docker Compose plugin accessible to your user.
60
+ * Access to the Mobipick Labs image repository (for example
61
+ `ozkrelo/mobipick_labs:noetic`).
62
+ * An X11 server that allows the containers to create GUI windows. The GUI
63
+ issues the required `xhost` commands automatically when needed.
64
+
65
+ ## Installation
66
+
67
+ - Install Docker Engine (`docker.io`) and ensure it is running.
68
+ ```bash
69
+ sudo apt update && sudo apt install docker.io
70
+ sudo systemctl enable docker
71
+ sudo systemctl start docker
72
+ ```
73
+
74
+ - Configure Docker to run without sudo:
75
+
76
+ ```bash
77
+ sudo usermod -aG docker $USER
78
+ ```
79
+
80
+ Then log out and back in.
81
+
82
+ - Install the Mobipick Labs GUI from PyPI (this also installs the package dependencies):
83
+
84
+ ```bash
85
+ pip install mobipick-labs-docker-gui
86
+ ```
87
+
88
+ - Install the Docker Compose plugin and pull the Mobipick Labs image.
89
+
90
+ ```bash
91
+ sudo apt install docker-compose-plugin
92
+ # Verify that the Compose plugin is available
93
+ docker compose version
94
+ # pull mobipick labs docker image from docker hub
95
+ docker pull ozkrelo/mobipick_labs:noetic
96
+ ```
97
+
98
+ - Optional but strongly recommended if you have an NVIDIA graphics card: install [nvidia-docker2](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/nvidia-docker.html). After installation, restart Docker and test with:
99
+
100
+ ```bash
101
+ docker run --rm --gpus all nvidia/cuda:12.4.1-base nvidia-smi
102
+ ```
103
+
104
+ Note: If you run Mobipick Labs on the CPU, the simulation will be very slow.
105
+
106
+ ## Launching the GUI
107
+
108
+ 1. Clone the repository *or* install the package from PyPI.
109
+ 1. Start the application:
110
+ ```bash
111
+ mobipick-labs-docker-gui
112
+ ```
113
+ 1. When the window opens, use the top row of buttons to bring up ROS core,
114
+ start or stop the simulator, toggle RViz/RQt, or open a Docker-backed
115
+ terminal. The GUI ensures the correct container sequence is followed.
116
+
117
+ You can interrupt the GUI with <kbd>Ctrl</kbd>+<kbd>C</kbd> in the launch
118
+ terminal; the application traps the signal, stops the running containers, and
119
+ then exits gracefully.
120
+
121
+ ### Command-line options
122
+
123
+ The CLI accepts a single verbosity switch that controls how much diagnostic
124
+ information the GUI prints to its log tabs and the launch terminal:
125
+
126
+ ```bash
127
+ mobipick-labs-docker-gui --verbose # Same as -v or --v
128
+ mobipick-labs-docker-gui -v 3 # Maximum verbosity
129
+ mobipick-labs-docker-gui -v 1 # Quietest mode (default)
130
+ ```
131
+
132
+ You can also pass through any Qt-specific arguments (for example `-platform`)
133
+ after the GUI options; they are forwarded automatically to `QApplication`.
134
+
135
+ ## Understanding the GUI workflow
136
+
137
+ * **Process supervision:** Each button spawns a `QProcess` that executes a
138
+ Docker command (`docker compose up`, `docker compose exec`, `docker cp`, etc.).
139
+ Environment variables from `mobipick_gui/resources/config/gui_settings.yaml` ensure the commands run
140
+ with consistent settings (for example `COMPOSE_IGNORE_ORPHANS=1`).
141
+ * **State polling:** Timers defined in `config/gui_settings.yaml` periodically
142
+ inspect Docker to reflect whether the ROS core, simulator, RViz, or RQt
143
+ containers are alive before updating the button states.
144
+ * **Log streaming:** Every subprocess pipes its stdout/stderr into a dedicated
145
+ tab, colourised via `mobipick_gui/ansi.py` so you can tail the container logs
146
+ without leaving the GUI.
147
+ * **Graceful shutdown:** When you exit, the GUI stops active containers in a
148
+ safe order, runs `clean.bash` (bundled in `mobipick_gui/resources/`) to remove
149
+ temporary resources, and only then closes the window.
150
+
151
+ ## Configuring the GUI
152
+
153
+ All customisation lives in the `mobipick_gui/resources/config/` directory. You
154
+ can copy these files and adapt them to your workflow. When running from an
155
+ installed package the directory is read-only; export the environment variable
156
+ `MOBIPICK_GUI_DATA_ROOT` and point it at a writable copy of the resources if you
157
+ need to override the defaults.
158
+
159
+ * **`config/gui_settings.yaml`** – Controls UI behaviour such as window geometry
160
+ and log styling, defines timer intervals, button colours, terminal launcher
161
+ settings, and Docker environment variables. Most keys mirror the defaults
162
+ declared in `mobipick_gui/config.py` so you can override just the values you
163
+ need.
164
+ * **`config/worlds.yaml`** – Lists the world configurations that populate the
165
+ drop-down selector when launching the simulator. Edit or append entries to
166
+ expose additional Gazebo worlds shipped in your Mobipick Labs Docker image.
167
+ * **`config/docker_cp_image_tag.yaml`** – Declares optional `docker cp`
168
+ synchronisation rules keyed by image name. Host-to-container copies run
169
+ automatically after the container starts, while container-to-host copies are
170
+ triggered by the "Execute Docker cp" button inside the GUI.
171
+
172
+ ## Working with the compose file
173
+
174
+ Although `docker-compose.yml` lives in the repository, the GUI is responsible for
175
+ translating user actions into compose commands. Typical sequences are:
176
+
177
+ 1. **ROS core toggle:** `docker compose up roscore` starts the lightweight
178
+ orchestration container. The GUI remembers the container name and watches for
179
+ it to become healthy before enabling the simulator button.
180
+ 2. **Simulator toggle:** `docker compose up mobipick-run` launches the main
181
+ Gazebo environment. When you stop it, the GUI optionally synchronises files
182
+ defined in `docker_cp_image_tag.yaml` and then calls `docker compose stop`
183
+ with a configurable timeout.
184
+ 3. **Visualization tools:** RViz and RQt are launched with `docker compose run`
185
+ so each tool receives its own tabbed log stream.
186
+
187
+ Because the GUI tracks container state, you should avoid running the compose
188
+ file manually in parallel—it can confuse the state machine and lead to orphaned
189
+ containers. If you need a manual clean slate, run `mobipick_gui/resources/clean.bash`
190
+ with the GUI closed to remove stopped containers and networks.
191
+
192
+ ## Tips and troubleshooting
193
+
194
+ * Verify that Docker commands succeed from your shell before launching the GUI;
195
+ it executes the same binaries with your current user.
196
+ * If the GUI cannot discover your Mobipick Labs image, adjust the
197
+ `images.discovery_filters` list in `mobipick_gui/resources/config/gui_settings.yaml`.
198
+ * When experimenting with new Gazebo worlds or launch files, consider adding a
199
+ custom button tab via `mobipick_gui/process_tab.py` so you can track logs in
200
+ the same window.
201
+ * Logs are retained up to `log.max_block_count` lines per tab. Lower the value
202
+ if you experience sluggishness on resource-constrained machines.
@@ -0,0 +1,176 @@
1
+ # Mobipick Labs Docker GUI
2
+
3
+ The Mobipick Labs Docker GUI is a PyQt5 desktop application that orchestrates the
4
+ Docker-based Mobipick Labs robotics simulation. Instead of manually invoking
5
+ `docker compose` yourself, you launch the `mobipick-labs-docker-gui` command (or
6
+ `python -m mobipick_gui`) and drive the bring-up,
7
+ monitoring, and shutdown of the simulation through an interactive interface.
8
+ The GUI reads the bundled configuration files, runs Docker commands on your
9
+ behalf, and streams live logs so you can follow what is happening in each
10
+ container.
11
+
12
+ <img src="doc/mobipick_labs_docker_gui.png" alt="mobipick tables sim and real" width="420">
13
+
14
+ ## Repository layout
15
+
16
+ ```
17
+ ├── gui.py # Legacy CLI shim that forwards to the packaged entry point
18
+ ├── mobipick_gui/
19
+ │ ├── resources/ # Bundled compose file, default configs, helper scripts
20
+ │ └── … # PyQt5 widgets, process orchestration, and helpers
21
+ ├── MANIFEST.in # Source distribution manifest
22
+ └── pyproject.toml # Packaging metadata for PyPI distribution
23
+ ```
24
+
25
+ The compose file is **not** intended to be executed directly. The GUI manages it
26
+ for you by spawning `docker compose` subprocesses, supervising their lifecycle,
27
+ and performing cleanup logic when you close the application.
28
+
29
+ ## Prerequisites
30
+
31
+ * Ubuntu Linux (tested on versions 20.04, 22.04, and 24.04)
32
+ * Python 3.8+ with PyQt5 available (e.g. `pip install PyQt5`).
33
+ * Docker Engine and the Docker Compose plugin accessible to your user.
34
+ * Access to the Mobipick Labs image repository (for example
35
+ `ozkrelo/mobipick_labs:noetic`).
36
+ * An X11 server that allows the containers to create GUI windows. The GUI
37
+ issues the required `xhost` commands automatically when needed.
38
+
39
+ ## Installation
40
+
41
+ - Install Docker Engine (`docker.io`) and ensure it is running.
42
+ ```bash
43
+ sudo apt update && sudo apt install docker.io
44
+ sudo systemctl enable docker
45
+ sudo systemctl start docker
46
+ ```
47
+
48
+ - Configure Docker to run without sudo:
49
+
50
+ ```bash
51
+ sudo usermod -aG docker $USER
52
+ ```
53
+
54
+ Then log out and back in.
55
+
56
+ - Install the Mobipick Labs GUI from PyPI (this also installs the package dependencies):
57
+
58
+ ```bash
59
+ pip install mobipick-labs-docker-gui
60
+ ```
61
+
62
+ - Install the Docker Compose plugin and pull the Mobipick Labs image.
63
+
64
+ ```bash
65
+ sudo apt install docker-compose-plugin
66
+ # Verify that the Compose plugin is available
67
+ docker compose version
68
+ # pull mobipick labs docker image from docker hub
69
+ docker pull ozkrelo/mobipick_labs:noetic
70
+ ```
71
+
72
+ - Optional but strongly recommended if you have an NVIDIA graphics card: install [nvidia-docker2](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/nvidia-docker.html). After installation, restart Docker and test with:
73
+
74
+ ```bash
75
+ docker run --rm --gpus all nvidia/cuda:12.4.1-base nvidia-smi
76
+ ```
77
+
78
+ Note: If you run Mobipick Labs on the CPU, the simulation will be very slow.
79
+
80
+ ## Launching the GUI
81
+
82
+ 1. Clone the repository *or* install the package from PyPI.
83
+ 1. Start the application:
84
+ ```bash
85
+ mobipick-labs-docker-gui
86
+ ```
87
+ 1. When the window opens, use the top row of buttons to bring up ROS core,
88
+ start or stop the simulator, toggle RViz/RQt, or open a Docker-backed
89
+ terminal. The GUI ensures the correct container sequence is followed.
90
+
91
+ You can interrupt the GUI with <kbd>Ctrl</kbd>+<kbd>C</kbd> in the launch
92
+ terminal; the application traps the signal, stops the running containers, and
93
+ then exits gracefully.
94
+
95
+ ### Command-line options
96
+
97
+ The CLI accepts a single verbosity switch that controls how much diagnostic
98
+ information the GUI prints to its log tabs and the launch terminal:
99
+
100
+ ```bash
101
+ mobipick-labs-docker-gui --verbose # Same as -v or --v
102
+ mobipick-labs-docker-gui -v 3 # Maximum verbosity
103
+ mobipick-labs-docker-gui -v 1 # Quietest mode (default)
104
+ ```
105
+
106
+ You can also pass through any Qt-specific arguments (for example `-platform`)
107
+ after the GUI options; they are forwarded automatically to `QApplication`.
108
+
109
+ ## Understanding the GUI workflow
110
+
111
+ * **Process supervision:** Each button spawns a `QProcess` that executes a
112
+ Docker command (`docker compose up`, `docker compose exec`, `docker cp`, etc.).
113
+ Environment variables from `mobipick_gui/resources/config/gui_settings.yaml` ensure the commands run
114
+ with consistent settings (for example `COMPOSE_IGNORE_ORPHANS=1`).
115
+ * **State polling:** Timers defined in `config/gui_settings.yaml` periodically
116
+ inspect Docker to reflect whether the ROS core, simulator, RViz, or RQt
117
+ containers are alive before updating the button states.
118
+ * **Log streaming:** Every subprocess pipes its stdout/stderr into a dedicated
119
+ tab, colourised via `mobipick_gui/ansi.py` so you can tail the container logs
120
+ without leaving the GUI.
121
+ * **Graceful shutdown:** When you exit, the GUI stops active containers in a
122
+ safe order, runs `clean.bash` (bundled in `mobipick_gui/resources/`) to remove
123
+ temporary resources, and only then closes the window.
124
+
125
+ ## Configuring the GUI
126
+
127
+ All customisation lives in the `mobipick_gui/resources/config/` directory. You
128
+ can copy these files and adapt them to your workflow. When running from an
129
+ installed package the directory is read-only; export the environment variable
130
+ `MOBIPICK_GUI_DATA_ROOT` and point it at a writable copy of the resources if you
131
+ need to override the defaults.
132
+
133
+ * **`config/gui_settings.yaml`** – Controls UI behaviour such as window geometry
134
+ and log styling, defines timer intervals, button colours, terminal launcher
135
+ settings, and Docker environment variables. Most keys mirror the defaults
136
+ declared in `mobipick_gui/config.py` so you can override just the values you
137
+ need.
138
+ * **`config/worlds.yaml`** – Lists the world configurations that populate the
139
+ drop-down selector when launching the simulator. Edit or append entries to
140
+ expose additional Gazebo worlds shipped in your Mobipick Labs Docker image.
141
+ * **`config/docker_cp_image_tag.yaml`** – Declares optional `docker cp`
142
+ synchronisation rules keyed by image name. Host-to-container copies run
143
+ automatically after the container starts, while container-to-host copies are
144
+ triggered by the "Execute Docker cp" button inside the GUI.
145
+
146
+ ## Working with the compose file
147
+
148
+ Although `docker-compose.yml` lives in the repository, the GUI is responsible for
149
+ translating user actions into compose commands. Typical sequences are:
150
+
151
+ 1. **ROS core toggle:** `docker compose up roscore` starts the lightweight
152
+ orchestration container. The GUI remembers the container name and watches for
153
+ it to become healthy before enabling the simulator button.
154
+ 2. **Simulator toggle:** `docker compose up mobipick-run` launches the main
155
+ Gazebo environment. When you stop it, the GUI optionally synchronises files
156
+ defined in `docker_cp_image_tag.yaml` and then calls `docker compose stop`
157
+ with a configurable timeout.
158
+ 3. **Visualization tools:** RViz and RQt are launched with `docker compose run`
159
+ so each tool receives its own tabbed log stream.
160
+
161
+ Because the GUI tracks container state, you should avoid running the compose
162
+ file manually in parallel—it can confuse the state machine and lead to orphaned
163
+ containers. If you need a manual clean slate, run `mobipick_gui/resources/clean.bash`
164
+ with the GUI closed to remove stopped containers and networks.
165
+
166
+ ## Tips and troubleshooting
167
+
168
+ * Verify that Docker commands succeed from your shell before launching the GUI;
169
+ it executes the same binaries with your current user.
170
+ * If the GUI cannot discover your Mobipick Labs image, adjust the
171
+ `images.discovery_filters` list in `mobipick_gui/resources/config/gui_settings.yaml`.
172
+ * When experimenting with new Gazebo worlds or launch files, consider adding a
173
+ custom button tab via `mobipick_gui/process_tab.py` so you can track logs in
174
+ the same window.
175
+ * Logs are retained up to `log.max_block_count` lines per tab. Lower the value
176
+ if you experience sluggishness on resource-constrained machines.
@@ -0,0 +1,7 @@
1
+ """Mobipick Labs GUI package."""
2
+
3
+ from .main_window import MainWindow, trigger_sigint
4
+
5
+ __version__ = "0.1.0"
6
+
7
+ __all__ = ["MainWindow", "trigger_sigint", "__version__"]
@@ -0,0 +1,9 @@
1
+ """Allow ``python -m mobipick_gui`` to launch the GUI."""
2
+ from __future__ import annotations
3
+
4
+ import sys
5
+
6
+ from .cli import main
7
+
8
+ if __name__ == '__main__':
9
+ sys.exit(main())
@@ -0,0 +1,58 @@
1
+ """ANSI escape code utilities."""
2
+ from __future__ import annotations
3
+
4
+ import html
5
+ import re
6
+
7
+ SGR_RE = re.compile(r'\x1b\[((?:\d+;)*\d*)m')
8
+ OSC_SEQ_RE = re.compile(r'\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)')
9
+ CSI_SEQ_RE = re.compile(r'\x1b\[[0-9;?]*[ -/]*[@-~]')
10
+
11
+ COLOR_MAP = {
12
+ 30: '#000000', 31: '#ff5555', 32: '#50fa7b', 33: '#f1fa8c',
13
+ 34: '#bd93f9', 35: '#ff79c6', 36: '#8be9fd', 37: '#bbbbbb',
14
+ 90: '#666666', 91: '#ff6e6e', 92: '#69ff94', 93: '#ffffa5',
15
+ 94: '#d6acff', 95: '#ff92df', 96: '#a4ffff', 97: '#ffffff'
16
+ }
17
+
18
+
19
+ def ansi_to_html(chunk: str) -> str:
20
+ """Convert ANSI escape sequences to HTML."""
21
+ text = html.escape(chunk)
22
+ span_stack, out = [], []
23
+ i = 0
24
+ for m in SGR_RE.finditer(text):
25
+ out.append(text[i:m.start()])
26
+ params = m.group(1) or '0'
27
+ if params == '0':
28
+ while span_stack:
29
+ out.append('</span>')
30
+ span_stack.pop()
31
+ i = m.end()
32
+ continue
33
+ styles = []
34
+ for p in params.split(';'):
35
+ try:
36
+ code = int(p)
37
+ except ValueError:
38
+ continue
39
+ if code == 1:
40
+ styles.append('font-weight:bold')
41
+ elif code in COLOR_MAP:
42
+ styles.append(f'color:{COLOR_MAP[code]}')
43
+ elif code == 39:
44
+ styles.append('color:#ffffff')
45
+ elif code == 22:
46
+ styles.append('font-weight:normal')
47
+ if styles:
48
+ out.append(f"<span style=\"{' ;'.join(styles)}\">")
49
+ span_stack.append('</span>')
50
+ i = m.end()
51
+ out.append(text[i:])
52
+ while span_stack:
53
+ out.append(span_stack.pop())
54
+ res = ''.join(out)
55
+ return res.replace('\r\n', '\n').replace('\r', '\n').replace('\n', '<br>')
56
+
57
+
58
+ __all__ = ['ansi_to_html', 'CSI_SEQ_RE', 'OSC_SEQ_RE']
@@ -0,0 +1,53 @@
1
+ """Command-line entry points for the Mobipick Labs GUI."""
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+ import signal
6
+ import sys
7
+ from typing import Sequence
8
+
9
+ from PyQt5.QtWidgets import QApplication
10
+
11
+ from . import MainWindow, trigger_sigint
12
+
13
+
14
+ def _build_parser() -> argparse.ArgumentParser:
15
+ parser = argparse.ArgumentParser(description='Mobipick Labs Control GUI')
16
+ parser.add_argument(
17
+ '-v',
18
+ '--v',
19
+ '--verbose',
20
+ dest='verbosity',
21
+ nargs='?',
22
+ const=3,
23
+ default=1,
24
+ type=int,
25
+ choices=[1, 2, 3],
26
+ help='Verbosity level (1=min, 3=max). If no value provided defaults to 3.',
27
+ )
28
+ return parser
29
+
30
+
31
+ def main(argv: Sequence[str] | None = None) -> int:
32
+ """Run the Qt application."""
33
+
34
+ if argv is None:
35
+ argv = sys.argv[1:]
36
+
37
+ parser = _build_parser()
38
+ parsed_args, qt_args = parser.parse_known_args(list(argv))
39
+ verbosity = parsed_args.verbosity or 1
40
+
41
+ app = QApplication([sys.argv[0]] + qt_args)
42
+ window = MainWindow(verbosity=verbosity)
43
+ window.show()
44
+
45
+ def _handle_sigint(_sig, _frame):
46
+ trigger_sigint()
47
+
48
+ signal.signal(signal.SIGINT, _handle_sigint)
49
+
50
+ return app.exec_()
51
+
52
+
53
+ __all__ = ['main']