diff --git a/.gitmodules b/.gitmodules index 4fd1c93..d366899 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "report"] path = report url = https://git.mount-mockery.de/pylib/report.git +[submodule "mytui"] + path = mytui + url = https://git.mount-mockery.de/pylib/mytui.git diff --git a/mqtt_sniffer.py b/mqtt_sniffer.py index d5621a7..54bf9a0 100644 --- a/mqtt_sniffer.py +++ b/mqtt_sniffer.py @@ -11,6 +11,8 @@ from textual.app import App, ComposeResult from textual.containers import Vertical from textual.widgets import Footer, Header, Input, RichLog, Button, Select +from mytui import MultiSelect + try: from config import APP_NAME as ROOT_LOGGER_NAME except ImportError: @@ -41,73 +43,6 @@ class MqttHandler(object): self.mqtt_client.send(topic, payload) -class OptionSelectList(dict): - def __init__(self): - super().__init__(self) - # - self.__default_value__ = True - self.__selection_regex__ = "" - - def __sorted_keys__(self): - rv = list(self.keys()) - rv.sort() - return rv - - def SetSelectionRegEx(self, regex: str) -> None: - self.__selection_regex__ = regex - - def AddEntry(self, entry) -> None: - if entry not in self: - self[entry] = self.__default_value__ - - def Toggle(self, entry_num): - if entry_num < 0: - if not self.__selection_regex__: - self.__default_value__ = entry_num == -1 - for key in self: - if self.__match__(key): - self[key] = entry_num == -1 - elif entry_num > len(self): - raise ValueError(f"The Entry '{entry} is not in the list") - else: - entry = self.__sorted_keys__()[entry_num] - self[entry] = not self[entry] - - def __match__(self, key): - try: - match = len(re.findall(self.__selection_regex__, key)) > 0 - except re.error: - match = True # No valid regular expression - return match - - def GetSelectList(self): - rv = [] - if len(self) > 2: - rv.append(('All', -1)) - rv.append(('None', -2)) - for index, key in enumerate(self.__sorted_keys__()): - if self.__match__(key): - prefix = "\\[X] " if self[key] else "\\[-] " - rv.append((prefix + key, index)) - return rv - - def IsSelected(self, entry): - return self.get(entry, False) - - -class MySelect(Select): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.__new_options__ = [] - - def set_options(self, options): - self.__new_options__ = options - - def _on_enter(self, event): - super().set_options(self.__new_options__) - return super()._on_enter(event) - - class MqttSniffer(App): """a textual application for viewing mqtt messages.""" @@ -125,8 +60,7 @@ class MqttSniffer(App): # self.mqtt = None self.all_logs = [] - self.__topic_select_list__ = OptionSelectList() - self.__topic_selection__ = MySelect((), prompt="Full", id="topic_filter") + self.__topic_selection__ = MultiSelect((), prompt="Full", id="topic_filter") self.send_topic = "" self.send_payload = "" self.log_display = RichLog(highlight=True, markup=True) @@ -152,8 +86,7 @@ class MqttSniffer(App): def add_log(self, record) -> None: """Add new mqt messages and update the tui.""" asctime = time.asctime() - self.__topic_select_list__.AddEntry(record.topic) - self.__topic_selection__.set_options(self.__topic_select_list__.GetSelectList()) + self.__topic_selection__.AddEntry(record.topic) self.all_logs.append((asctime, record)) if len(self.all_logs) > self.MAX_LOGS: self.all_logs = self.all_logs[-self.MAX_LOGS:] @@ -162,7 +95,7 @@ class MqttSniffer(App): def _apply_filters_to_log(self, data: logging.LogRecord): asctime, record = data - if self.__topic_select_list__.IsSelected(record.topic): + if self.__topic_selection__.IsSelected(record.topic): message = ( f"[[dim]{asctime}[/dim]] " f"[bold]{record.topic}[/bold] - " @@ -184,22 +117,15 @@ class MqttSniffer(App): def on_input_changed(self, message: Input.Changed) -> None: """Update the tui inputs and execute task, if requireed.""" if message.input.id == "select_filter": - self.__topic_select_list__.SetSelectionRegEx(message.value) - self.__topic_selection__.set_options(self.__topic_select_list__.GetSelectList()) - self.__topic_selection__.prompt = "Full" if not message.value else "Filtered" - if message.input.id == "send_topic": + self.__topic_selection__.SetSelectionRegEx(message.value) + elif message.input.id == "send_topic": self.send_topic = message.value elif message.input.id == "send_payload": self.send_payload = message.value def on_select_changed(self, message: Select.Changed) -> None: - if message.select.id == 'topic_filter': - if type(message.value) is int: - self.__topic_select_list__.Toggle(message.value) - self.__topic_selection__.clear() - self.__topic_selection__.set_options(self.__topic_select_list__.GetSelectList()) - - self._update_display() + if message.select.id in ('topic_filter', ): + self._update_display() def on_button_pressed(self, event: Button.Pressed) -> None: """Event handler called when a button is pressed.""" diff --git a/mytui b/mytui new file mode 160000 index 0000000..bd390d2 --- /dev/null +++ b/mytui @@ -0,0 +1 @@ +Subproject commit bd390d27f00147c1305e244fbd6d0650a6bdcec9