mirror of
https://github.com/DYefremov/DemonEditor.git
synced 2026-02-08 15:47:58 +01:00
added logs display in the gui
This commit is contained in:
@@ -7,13 +7,12 @@ from gi.repository import GLib
|
||||
|
||||
_LOG_FILE = "demon-editor.log"
|
||||
_DATE_FORMAT = "%d-%m-%y %H:%M:%S"
|
||||
_LOGGER_NAME = None
|
||||
|
||||
LOGGER_NAME = "main_logger"
|
||||
|
||||
|
||||
def init_logger():
|
||||
global _LOGGER_NAME
|
||||
_LOGGER_NAME = "main_logger"
|
||||
logging.Logger(_LOGGER_NAME)
|
||||
logging.Logger(LOGGER_NAME)
|
||||
logging.basicConfig(level=logging.INFO,
|
||||
format="%(asctime)s %(message)s",
|
||||
datefmt=_DATE_FORMAT,
|
||||
@@ -23,7 +22,7 @@ def init_logger():
|
||||
|
||||
def log(message, level=logging.ERROR, debug=False, fmt_message="{}"):
|
||||
""" The main logging function. """
|
||||
logger = logging.getLogger(_LOGGER_NAME)
|
||||
logger = logging.getLogger(LOGGER_NAME)
|
||||
if debug:
|
||||
from traceback import format_exc
|
||||
logger.log(level, fmt_message.format(format_exc()))
|
||||
|
||||
@@ -147,6 +147,10 @@
|
||||
<attribute name="label" translatable="yes">Telnet</attribute>
|
||||
<attribute name="action">app.on_telnet_show</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Logs</attribute>
|
||||
<attribute name="action">app.on_logs_show</attribute>
|
||||
</item>
|
||||
</section>
|
||||
</submenu>
|
||||
<submenu>
|
||||
@@ -333,6 +337,10 @@
|
||||
<attribute name="label" translatable="yes">Telnet</attribute>
|
||||
<attribute name="action">app.on_telnet_show</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Logs</attribute>
|
||||
<attribute name="action">app.on_logs_show</attribute>
|
||||
</item>
|
||||
</section>
|
||||
</submenu>
|
||||
<submenu>
|
||||
|
||||
125
app/ui/logs.glade
Normal file
125
app/ui/logs.glade
Normal file
@@ -0,0 +1,125 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.22.2
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018-2021 Dmitriy Yefremov
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
Author: Dmitriy Yefremov
|
||||
|
||||
-->
|
||||
<interface domain="demon-editor">
|
||||
<requires lib="gtk+" version="3.18"/>
|
||||
<!-- interface-css-provider-path style.css -->
|
||||
<!-- interface-license-type mit -->
|
||||
<!-- interface-name DemonEditor -->
|
||||
<!-- interface-description Enigma2 channel and satellite list editor. -->
|
||||
<!-- interface-copyright 2018-2021 Dmitriy Yefremov -->
|
||||
<!-- interface-authors Dmitriy Yefremov -->
|
||||
<object class="GtkFrame" id="log_frame">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label_xalign">0.49000000953674316</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="main_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">5</property>
|
||||
<property name="margin_right">5</property>
|
||||
<property name="margin_bottom">5</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="header_box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">5</property>
|
||||
<property name="margin_right">5</property>
|
||||
<property name="margin_bottom">2</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="clear_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Clear</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<signal name="clicked" handler="on_clear" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkImage" id="clear_button_image">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-clear</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="scrolled_window">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkTextView" id="log_view">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="editable">False</property>
|
||||
<property name="left_margin">5</property>
|
||||
<property name="right_margin">5</property>
|
||||
<property name="top_margin">5</property>
|
||||
<property name="bottom_margin">5</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="label">
|
||||
<object class="GtkLabel" id="log_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Logs</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
66
app/ui/logs.py
Normal file
66
app/ui/logs.py
Normal file
@@ -0,0 +1,66 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright (c) 2018-2021 Dmitriy Yefremov
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
#
|
||||
# Author: Dmitriy Yefremov
|
||||
#
|
||||
|
||||
|
||||
import logging
|
||||
|
||||
from gi.repository import GLib
|
||||
|
||||
from app.commons import LOGGER_NAME
|
||||
from app.ui.dialogs import get_builder
|
||||
from app.ui.main_helper import append_text_to_tview
|
||||
from app.ui.uicommons import Gtk, UI_RESOURCES_PATH
|
||||
|
||||
|
||||
class LogsClient(Gtk.Box):
|
||||
""" Logger GUI client. """
|
||||
|
||||
class LogHandler(logging.Handler):
|
||||
def __init__(self, view):
|
||||
logging.Handler.__init__(self)
|
||||
self._view = view
|
||||
|
||||
def handle(self, rec):
|
||||
GLib.idle_add(append_text_to_tview, f"{rec.msg}\n", self._view)
|
||||
|
||||
def __init__(self, app, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self._app = app
|
||||
|
||||
handlers = {"on_clear": self.on_clear}
|
||||
builder = get_builder(UI_RESOURCES_PATH + "logs.glade", handlers)
|
||||
|
||||
self._log_view = builder.get_object("log_view")
|
||||
self.pack_start(builder.get_object("log_frame"), True, True, 0)
|
||||
|
||||
logger = logging.getLogger(LOGGER_NAME)
|
||||
logger.addHandler(LogsClient.LogHandler(self._log_view))
|
||||
|
||||
self.show()
|
||||
|
||||
def on_clear(self, button):
|
||||
GLib.idle_add(self._log_view.get_buffer().set_text, "")
|
||||
3686
app/ui/main.glade
3686
app/ui/main.glade
File diff suppressed because it is too large
Load Diff
@@ -51,6 +51,7 @@ from app.tools.media import Recorder
|
||||
from app.ui.control import ControlTool, EpgTool, TimerTool, RecordingsTool
|
||||
from app.ui.epg import EpgDialog
|
||||
from app.ui.ftp import FtpClientBox
|
||||
from app.ui.logs import LogsClient
|
||||
from app.ui.playback import PlayerBox
|
||||
from app.ui.telnet import TelnetClient
|
||||
from app.ui.transmitter import LinksTransmitter
|
||||
@@ -194,7 +195,8 @@ class Application(Gtk.Application):
|
||||
"on_recordings_realize": self.on_recordings_realize,
|
||||
"on_control_realize": self.on_control_realize,
|
||||
"on_ftp_realize": self.on_ftp_realize,
|
||||
"on_telnet_relize": self.on_telnet_relize,
|
||||
"on_telnet_realize": self.on_telnet_realize,
|
||||
"on_logs_realize": self.on_logs_realize,
|
||||
"on_visible_page": self.on_visible_page,
|
||||
"on_data_paned_realize": self.init_main_paned_position}
|
||||
|
||||
@@ -386,8 +388,11 @@ class Application(Gtk.Application):
|
||||
self._stack_recordings_box = builder.get_object("recordings_box")
|
||||
self._stack_ftp_box = builder.get_object("ftp_box")
|
||||
self._stack_control_box = builder.get_object("control_box")
|
||||
self._telnet_box = builder.get_object("telnet_box")
|
||||
self.connect("change-page", self.on_page_change)
|
||||
# Extra tools.
|
||||
self._telnet_box = builder.get_object("telnet_box")
|
||||
self._logs_box = builder.get_object("logs_box")
|
||||
self._bottom_paned = builder.get_object("bottom_paned")
|
||||
# Header bar.
|
||||
profile_box = builder.get_object("profile_combo_box")
|
||||
toolbar_box = builder.get_object("toolbar_main_box")
|
||||
@@ -464,6 +469,7 @@ class Application(Gtk.Application):
|
||||
self.set_action("on_about_app", self.on_about_app)
|
||||
self.set_action("on_close_app", self.on_close_app)
|
||||
self.set_state_action("on_telnet_show", self.on_telnet_show, False)
|
||||
self.set_state_action("on_logs_show", self.on_logs_show, False)
|
||||
# Filter.
|
||||
filter_action = Gio.SimpleAction.new("filter", None)
|
||||
filter_action.connect("activate", lambda a, v: self.emit("filter-toggled", None))
|
||||
@@ -544,6 +550,7 @@ class Application(Gtk.Application):
|
||||
self.set_accels_for_action("app.on_close_app", ["<primary>q"])
|
||||
self.set_accels_for_action("app.on_edit", ["<primary>e"])
|
||||
self.set_accels_for_action("app.on_telnet_show", ["<primary>t"])
|
||||
self.set_accels_for_action("app.on_logs_show", ["<shift><primary>l"])
|
||||
self.set_accels_for_action("win.filter", ["<shift><primary>f"])
|
||||
|
||||
def do_activate(self):
|
||||
@@ -795,9 +802,11 @@ class Application(Gtk.Application):
|
||||
self._control_tool = ControlTool(self, self._http_api, self._settings)
|
||||
box.pack_start(self._control_tool, True, True, 0)
|
||||
|
||||
def on_telnet_relize(self, box):
|
||||
telnet_tool = TelnetClient(self, self._settings)
|
||||
box.pack_start(telnet_tool, True, True, 0)
|
||||
def on_telnet_realize(self, box):
|
||||
box.pack_start(TelnetClient(self), True, True, 0)
|
||||
|
||||
def on_logs_realize(self, box):
|
||||
box.pack_start(LogsClient(self), True, True, 0)
|
||||
|
||||
def on_visible_page(self, stack, param):
|
||||
self._page = Page(stack.get_visible_child_name())
|
||||
@@ -1209,6 +1218,9 @@ class Application(Gtk.Application):
|
||||
|
||||
def on_fav_view_query_tooltip(self, view, x, y, keyboard_mode, tooltip):
|
||||
""" Sets detailed info about service in the tooltip [fav view]. """
|
||||
if not self._main_window.is_active():
|
||||
return False
|
||||
|
||||
result = view.get_dest_row_at_pos(x, y)
|
||||
if not result or not self._settings.show_bq_hints:
|
||||
return False
|
||||
@@ -1217,6 +1229,9 @@ class Application(Gtk.Application):
|
||||
|
||||
def on_services_view_query_tooltip(self, view, x, y, keyboard_mode, tooltip):
|
||||
""" Sets short info about service in the tooltip [main services view]. """
|
||||
if not self._main_window.is_active():
|
||||
return False
|
||||
|
||||
result = view.get_dest_row_at_pos(x, y)
|
||||
if not result or not self._settings.show_srv_hints:
|
||||
return False
|
||||
@@ -2657,11 +2672,21 @@ class Application(Gtk.Application):
|
||||
""" Shows backup tool dialog """
|
||||
BackupDialog(self._main_window, self._settings, self.open_data).show()
|
||||
|
||||
# ***************** Telnet ******************** #
|
||||
# ***************** Extra tools ******************** #
|
||||
|
||||
def on_telnet_show(self, action, value=False):
|
||||
action.set_state(value)
|
||||
GLib.idle_add(self._telnet_box.set_visible, value)
|
||||
self._telnet_box.set_visible(value)
|
||||
self.update_tools_visibility()
|
||||
|
||||
def on_logs_show(self, action, value=False):
|
||||
action.set_state(value)
|
||||
self._logs_box.set_visible(value)
|
||||
self.update_tools_visibility()
|
||||
|
||||
@run_idle
|
||||
def update_tools_visibility(self):
|
||||
self._bottom_paned.set_visible(self._telnet_box.get_visible() or self._logs_box.get_visible())
|
||||
|
||||
# ************************* Streams ***************************** #
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ Author: Dmitriy Yefremov
|
||||
|
||||
-->
|
||||
<interface domain="demon-editor">
|
||||
<requires lib="gtk+" version="3.16"/>
|
||||
<requires lib="gtk+" version="3.18"/>
|
||||
<!-- interface-license-type mit -->
|
||||
<!-- interface-name DemonEditor -->
|
||||
<!-- interface-copyright 2018-2021 Dmitriy Yefremov -->
|
||||
@@ -46,16 +46,10 @@ Author: Dmitriy Yefremov
|
||||
<object class="GtkFrame" id="telnet_frame">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">5</property>
|
||||
<property name="margin_right">5</property>
|
||||
<property name="margin_top">5</property>
|
||||
<property name="margin_bottom">5</property>
|
||||
<property name="label_xalign">0.49000000953674316</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="telnet_main_box">
|
||||
<property name="width_request">480</property>
|
||||
<property name="height_request">180</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">5</property>
|
||||
|
||||
@@ -1,3 +1,31 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright (c) 2018-2021 Dmitriy Yefremov
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
#
|
||||
# Author: Dmitriy Yefremov
|
||||
#
|
||||
|
||||
|
||||
import re
|
||||
import selectors
|
||||
import socket
|
||||
@@ -44,7 +72,7 @@ class TelnetClient(Gtk.Box):
|
||||
_ALL_PATTERN = re.compile(r'(\x1b\[|\x9b)[0-?]*[@-~]')
|
||||
_NOT_SUPPORTED = {"mc", "mcedit", "vi", "nano"}
|
||||
|
||||
def __init__(self, app, settings, *args, **kwargs):
|
||||
def __init__(self, app, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self._app = app
|
||||
self._app.connect("profile-changed", self.on_profile_changed)
|
||||
|
||||
Reference in New Issue
Block a user