Add update manager capability and revamp system panel to show all moonraker update clients
This commit is contained in:
parent
23832e8ad6
commit
867ded34d9
@ -185,23 +185,20 @@ class KlippyGtk:
|
||||
dialog.connect("response", callback, *args)
|
||||
dialog.get_style_context().add_class("dialog")
|
||||
|
||||
grid = Gtk.Grid()
|
||||
grid.set_size_request(screen.width - 60, -1)
|
||||
grid.set_vexpand(True)
|
||||
grid.set_halign(Gtk.Align.CENTER)
|
||||
grid.set_valign(Gtk.Align.CENTER)
|
||||
grid.add(content)
|
||||
box = Gtk.Box()
|
||||
box.set_size_request(screen.width - 60, 0)
|
||||
box.set_vexpand(True)
|
||||
|
||||
content_area = dialog.get_content_area()
|
||||
content_area.set_margin_start(15)
|
||||
content_area.set_margin_end(15)
|
||||
content_area.set_margin_top(15)
|
||||
content_area.set_margin_bottom(15)
|
||||
content_area.add(grid)
|
||||
content_area.add(content)
|
||||
|
||||
dialog.show_all()
|
||||
|
||||
return dialog, grid
|
||||
return dialog
|
||||
|
||||
|
||||
def ToggleButtonImage(self, image_name, label, style=False, width_scale=1, height_scale=1):
|
||||
|
@ -21,8 +21,9 @@ class Printer:
|
||||
}
|
||||
tools = []
|
||||
|
||||
def __init__(self, printer_info, data):
|
||||
def __init__(self, printer_info, data, state_execute_cb):
|
||||
self.state = "disconnected"
|
||||
self.state_cb = state_execute_cb
|
||||
self.power_devices = {}
|
||||
|
||||
def reinit(self, printer_info, data):
|
||||
@ -145,6 +146,7 @@ class Printer:
|
||||
logging.debug("Adding callback for state: %s" % state)
|
||||
Gdk.threads_add_idle(
|
||||
GLib.PRIORITY_HIGH_IDLE,
|
||||
self.state_cb,
|
||||
self.state_callbacks[state],
|
||||
prev_state
|
||||
)
|
||||
|
212
panels/system.py
212
panels/system.py
@ -4,6 +4,7 @@ import os
|
||||
|
||||
gi.require_version("Gtk", "3.0")
|
||||
from gi.repository import Gtk, Gdk, GLib
|
||||
from datetime import datetime
|
||||
|
||||
from ks_includes.KlippyGcodes import KlippyGcodes
|
||||
from ks_includes.screen_panel import ScreenPanel
|
||||
@ -20,27 +21,30 @@ class SystemPanel(ScreenPanel):
|
||||
|
||||
restart = self._gtk.ButtonImage('refresh',"\n".join(_('Klipper Restart').split(' ')),'color1')
|
||||
restart.connect("clicked", self.restart_klippy)
|
||||
restart.set_vexpand(False)
|
||||
firmrestart = self._gtk.ButtonImage('refresh',"\n".join(_('Firmware Restart').split(' ')),'color2')
|
||||
firmrestart.connect("clicked", self.restart_klippy, "firmware")
|
||||
firmrestart.set_vexpand(False)
|
||||
|
||||
ks_restart = self._gtk.ButtonImage('refresh',"\n".join(_('Restart Klipper Screen').split(' ')))
|
||||
ks_restart.set_vexpand(False)
|
||||
ks_restart.connect("clicked", self.restart_ks)
|
||||
|
||||
reboot = self._gtk.ButtonImage('refresh',_('System\nRestart'),'color3')
|
||||
reboot.connect("clicked", self._screen._confirm_send_action,
|
||||
_("Are you sure you wish to reboot the system?"), "machine.reboot")
|
||||
reboot.set_vexpand(False)
|
||||
shutdown = self._gtk.ButtonImage('shutdown',_('System\nShutdown'),'color4')
|
||||
shutdown.connect("clicked", self._screen._confirm_send_action,
|
||||
_("Are you sure you wish to shutdown the system?"), "machine.shutdown")
|
||||
shutdown.set_vexpand(False)
|
||||
|
||||
info = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
|
||||
info.set_vexpand(True)
|
||||
info.set_valign(Gtk.Align.CENTER)
|
||||
|
||||
self.labels['loadavg'] = Gtk.Label("temp")
|
||||
self.update_system_load()
|
||||
|
||||
self.system_timeout = GLib.timeout_add(1000, self.update_system_load)
|
||||
#self.system_timeout = GLib.timeout_add(1000, self.update_system_load)
|
||||
|
||||
self.labels['klipper_version'] = Gtk.Label(_("Klipper Version") +
|
||||
(": %s" % self._screen.printer.get_klipper_version()))
|
||||
@ -53,8 +57,47 @@ class SystemPanel(ScreenPanel):
|
||||
info.add(self.labels['klipper_version'])
|
||||
info.add(self.labels['ks_version'])
|
||||
|
||||
scroll = Gtk.ScrolledWindow()
|
||||
scroll.set_property("overlay-scrolling", False)
|
||||
scroll.set_vexpand(True)
|
||||
|
||||
grid.attach(info, 0, 0, 5, 2)
|
||||
infogrid = Gtk.Grid()
|
||||
infogrid.get_style_context().add_class("system-program-grid")
|
||||
update_resp = self._screen.apiclient.send_request("machine/update/status")
|
||||
self.update_status = False
|
||||
|
||||
if update_resp == False:
|
||||
logging.info("No update manager configured")
|
||||
else:
|
||||
self.update_status = update_resp['result']
|
||||
vi = update_resp['result']['version_info']
|
||||
items = sorted(list(vi))
|
||||
i = 0
|
||||
for prog in items:
|
||||
self.labels[prog] = Gtk.Label("")
|
||||
self.labels[prog].set_hexpand(True)
|
||||
self.labels[prog].set_halign(Gtk.Align.START)
|
||||
|
||||
self.labels["%s_status" % prog] = self._gtk.Button()
|
||||
self.labels["%s_status" % prog].set_hexpand(False)
|
||||
self.labels["%s_status" % prog].connect("clicked", self.update_program, prog)
|
||||
self.labels["%s_box" % prog] = Gtk.Box()
|
||||
self.labels["%s_box" % prog].set_hexpand(False)
|
||||
self.labels["%s_info" % prog] = self._gtk.ButtonImage("information",None, None, .7, .7)
|
||||
self.labels["%s_info" % prog].connect("clicked", self.show_commit_history, prog)
|
||||
|
||||
self.labels["%s_box" % prog].pack_end(self.labels["%s_status" % prog], True, 0, 0)
|
||||
logging.info("Updating program: %s " % prog)
|
||||
self.update_program_info(prog)
|
||||
|
||||
|
||||
infogrid.attach(self.labels["%s_box" % prog], 1, i, 1, 1)
|
||||
infogrid.attach(self.labels[prog], 0, i, 1, 1)
|
||||
i = i + 1
|
||||
|
||||
scroll.add(infogrid)
|
||||
|
||||
grid.attach(scroll, 0, 0, 5, 2)
|
||||
grid.attach(restart, 0, 2, 1, 1)
|
||||
grid.attach(firmrestart, 1, 2, 1, 1)
|
||||
grid.attach(ks_restart, 2, 2, 1, 1)
|
||||
@ -62,16 +105,163 @@ class SystemPanel(ScreenPanel):
|
||||
grid.attach(shutdown, 4, 2, 1, 1)
|
||||
|
||||
self.content.add(grid)
|
||||
self._screen.add_subscription(panel_name)
|
||||
|
||||
def update_system_load(self):
|
||||
def activate(self):
|
||||
self.get_updates()
|
||||
|
||||
def destroy_widget(self, widget, response_id):
|
||||
widget.destroy()
|
||||
|
||||
def finish_updating(self, widget, response_id):
|
||||
widget.destroy()
|
||||
self._screen.set_updating(False)
|
||||
self.get_updates()
|
||||
|
||||
def get_updates(self):
|
||||
update_resp = self._screen.apiclient.send_request("machine/update/status")
|
||||
if update_resp == False:
|
||||
logging.info("No update manager configured")
|
||||
else:
|
||||
self.update_status = update_resp['result']
|
||||
vi = update_resp['result']['version_info']
|
||||
items = sorted(list(vi))
|
||||
for prog in items:
|
||||
self.update_program_info(prog)
|
||||
|
||||
def process_update(self, action, data):
|
||||
if action == "notify_update_response":
|
||||
logging.info("Update: %s" % data)
|
||||
if 'application' in data and data['application'] == self.update_prog:
|
||||
self.labels['update_progress'].set_text(self.labels['update_progress'].get_text().strip() + "\n" +
|
||||
data['message'] + "\n")
|
||||
adjustment = self.labels['update_scroll'].get_vadjustment()
|
||||
adjustment.set_value( adjustment.get_upper() - adjustment.get_page_size() )
|
||||
adjustment = self.labels['update_scroll'].show_all()
|
||||
|
||||
if data['complete'] == True:
|
||||
self.update_dialog.set_response_sensitive(Gtk.ResponseType.CANCEL, True)
|
||||
|
||||
def show_commit_history(self, widget, program):
|
||||
_ = self.lang.gettext
|
||||
lavg = os.getloadavg()
|
||||
self.labels['loadavg'].set_text(
|
||||
_("Load Average") + (": %.2f %.2f %.2f" % (lavg[0], lavg[1], lavg[2]))
|
||||
)
|
||||
|
||||
#TODO: Shouldn't need this
|
||||
self.system_timeout = GLib.timeout_add(1000, self.update_system_load)
|
||||
if self.update_status == False or program not in self.update_status['version_info']:
|
||||
return
|
||||
|
||||
info = self.update_status['version_info'][program]
|
||||
if info['version'] == info['remote_version']:
|
||||
return
|
||||
|
||||
buttons = [
|
||||
{"name":_("Go Back"), "response": Gtk.ResponseType.CANCEL}
|
||||
]
|
||||
|
||||
scroll = Gtk.ScrolledWindow()
|
||||
scroll.set_hexpand(True)
|
||||
scroll.set_vexpand(True)
|
||||
|
||||
grid = Gtk.Grid()
|
||||
grid.set_halign(Gtk.Align.START)
|
||||
i = 0
|
||||
date = ""
|
||||
for c in info['commits_behind']:
|
||||
ndate = datetime.fromtimestamp(int(c['date'])).strftime("%b %d")
|
||||
if date != ndate:
|
||||
date = ndate
|
||||
label = Gtk.Label("")
|
||||
label.set_markup("<b>%s</b>\n" % date)
|
||||
grid.attach(label, 0, i, 1, 1)
|
||||
i = i + 1
|
||||
|
||||
label = Gtk.Label()
|
||||
label.set_markup("%s\n<i>%s</i> %s %s\n" % (c['subject'], c['author'], _("Commited"),"2 days ago"))
|
||||
label.set_hexpand(True)
|
||||
label.set_halign(Gtk.Align.START)
|
||||
grid.attach(label, 0, i, 1, 1)
|
||||
i = i + 1
|
||||
|
||||
scroll.add(grid)
|
||||
|
||||
dialog = self._gtk.Dialog(self._screen, buttons, scroll, self.destroy_widget)
|
||||
|
||||
def update_program(self, widget, program):
|
||||
if self._screen.is_updating():
|
||||
return
|
||||
|
||||
_ = self.lang.gettext
|
||||
|
||||
if self.update_status == False or program not in self.update_status['version_info']:
|
||||
return
|
||||
|
||||
info = self.update_status['version_info'][program]
|
||||
logging.info("program: %s" % info)
|
||||
if "package_count" in info:
|
||||
if info['package_count'] == 0:
|
||||
return
|
||||
else:
|
||||
if info['version'] == info['remote_version']:
|
||||
return
|
||||
|
||||
buttons = [
|
||||
{"name":_("Finish"), "response": Gtk.ResponseType.CANCEL}
|
||||
]
|
||||
|
||||
scroll = Gtk.ScrolledWindow()
|
||||
scroll.set_hexpand(True)
|
||||
scroll.set_vexpand(True)
|
||||
|
||||
self.labels['update_progress'] = Gtk.Label("%s %s%s" % (_("Starting update for"), program, _("...")))
|
||||
self.labels['update_progress'].set_halign(Gtk.Align.START)
|
||||
self.labels['update_progress'].set_valign(Gtk.Align.START)
|
||||
scroll.add(self.labels['update_progress'])
|
||||
self.labels['update_scroll'] = scroll
|
||||
|
||||
dialog = self._gtk.Dialog(self._screen, buttons, scroll, self.finish_updating)
|
||||
dialog.set_response_sensitive(Gtk.ResponseType.CANCEL, False)
|
||||
|
||||
self.update_prog = program
|
||||
self.update_dialog = dialog
|
||||
|
||||
if program in ['klipper','moonraker','system']:
|
||||
logging.info("Sending machine.update.%s" % program)
|
||||
self._screen._ws.send_method("machine.update.%s" % program)
|
||||
else:
|
||||
logging.info("Sending machine.update.client name: %s" % program)
|
||||
self._screen._ws.send_method("machine.update.client", {"name": program})
|
||||
self._screen.set_updating(True)
|
||||
|
||||
def update_program_info(self, p):
|
||||
_ = self.lang.gettext
|
||||
|
||||
logging.info("Updating program: %s " % p)
|
||||
if 'version_info' not in self.update_status or p not in self.update_status['version_info']:
|
||||
return
|
||||
|
||||
info = self.update_status['version_info'][p]
|
||||
logging.info("%s: %s" % (p, info))
|
||||
if p != "system":
|
||||
version = (info['full_version_string'] if "full_version_string" in info else info['version'])
|
||||
|
||||
if info['version'] == info['remote_version']:
|
||||
self.labels[p].set_markup("<b>%s</b>\n%s" % (p, version))
|
||||
self.labels["%s_status" % p].set_label(_("Up To Date"))
|
||||
self.labels["%s_status" % p].set_sensitive(False)
|
||||
if self.labels["%s_info" % p] in self.labels["%s_box" % p].get_children():
|
||||
self.labels["%s_box" % p].remove(self.labels["%s_info" % p])
|
||||
else:
|
||||
self.labels[p].set_markup("<b>%s</b>\n%s -> %s" % (p, version, info['remote_version']))
|
||||
self.labels["%s_status" % p].set_label(_("Update"))
|
||||
self.labels["%s_status" % p].set_sensitive(True)
|
||||
if not self.labels["%s_info" % p] in self.labels["%s_box" % p].get_children():
|
||||
self.labels["%s_box" % p].pack_start(self.labels["%s_info" % p], True, 0, 0)
|
||||
else:
|
||||
self.labels[p].set_markup("<b>System</b>")
|
||||
if info['package_count'] == 0:
|
||||
self.labels["%s_status" % p].set_label(_("Up To Date"))
|
||||
self.labels["%s_status" % p].set_sensitive(False)
|
||||
else:
|
||||
self.labels["%s_status" % p].set_label(_("Update"))
|
||||
self.labels["%s_status" % p].set_sensitive(True)
|
||||
|
||||
def restart_klippy(self, widget, type=None):
|
||||
if type == "firmware":
|
||||
|
26
screen.py
26
screen.py
@ -79,6 +79,8 @@ class KlipperScreen(Gtk.Window):
|
||||
rtl_languages = ['he_il']
|
||||
subscriptions = []
|
||||
shutdown = True
|
||||
updating = False
|
||||
update_queue = []
|
||||
_ws = None
|
||||
|
||||
def __init__(self, args, version):
|
||||
@ -193,7 +195,7 @@ class KlipperScreen(Gtk.Window):
|
||||
'virtual_sdcard': {
|
||||
'is_active': False
|
||||
}
|
||||
})
|
||||
}, self.state_execute)
|
||||
|
||||
self._remove_all_panels()
|
||||
panels = list(self.panels)
|
||||
@ -439,6 +441,9 @@ class KlipperScreen(Gtk.Window):
|
||||
def is_printing(self):
|
||||
return self.printer.get_state() == "printing"
|
||||
|
||||
def is_updating(self):
|
||||
return self.updating
|
||||
|
||||
def _go_to_submenu(self, widget, name):
|
||||
logging.info("#### Go to submenu " + str(name))
|
||||
#self._remove_current_panel(False)
|
||||
@ -540,11 +545,26 @@ class KlipperScreen(Gtk.Window):
|
||||
if self.dpms_timeout == None and functions.dpms_loaded == True:
|
||||
self.dpms_timeout = GLib.timeout_add(1000, self.check_dpms_state)
|
||||
|
||||
def set_updating(self, updating=False):
|
||||
if self.updating == True and updating == False:
|
||||
if len(self.update_queue) > 0:
|
||||
i = self.update_queue.pop()
|
||||
self.update_queue = []
|
||||
i[0](i[1])
|
||||
|
||||
self.updating = updating
|
||||
|
||||
def show_printer_select(self, widget=None):
|
||||
logging.debug("Saving panel: %s" % self._cur_panels[0])
|
||||
self.printer_select_prepanel = self._cur_panels[0]
|
||||
self.show_panel("printer_select","printer_select","Printer Select", 2)
|
||||
|
||||
def state_execute(self, callback, prev_state):
|
||||
if self.is_updating():
|
||||
self.update_queue.append([callback, prev_state])
|
||||
else:
|
||||
callback(prev_state)
|
||||
|
||||
def state_disconnected(self, prev_state):
|
||||
if "printer_select" in self._cur_panels:
|
||||
self.printer_select_callbacks = [self.state_disconnected]
|
||||
@ -557,7 +577,7 @@ class KlipperScreen(Gtk.Window):
|
||||
for panel in list(self.panels):
|
||||
if panel in ["printer_select","splash_screen"]:
|
||||
continue
|
||||
del self.panels[panel]
|
||||
#del self.panels[panel]
|
||||
|
||||
def state_error(self, prev_state):
|
||||
if "printer_select" in self._cur_panels:
|
||||
@ -650,6 +670,8 @@ class KlipperScreen(Gtk.Window):
|
||||
self.files.process_update(data)
|
||||
elif action == "notify_metadata_update":
|
||||
self.files.request_metadata(data['filename'])
|
||||
elif action == "notify_update_response":
|
||||
logging.info("%s: %s" % (action,data))
|
||||
elif action == "notify_power_changed":
|
||||
logging.debug("Power status changed: %s", data)
|
||||
self.printer.process_power_update(data)
|
||||
|
14
styles/z-bolt/images/information.svg
Normal file
14
styles/z-bolt/images/information.svg
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 330 330" style="enable-background:new 0 0 330 330;" xml:space="preserve">
|
||||
<g>
|
||||
<path style="fill: #ffffff;" d="M165,0C74.019,0,0,74.02,0,165.001C0,255.982,74.019,330,165,330s165-74.018,165-164.999C330,74.02,255.981,0,165,0z
|
||||
M165,300c-74.44,0-135-60.56-135-134.999C30,90.562,90.56,30,165,30s135,60.562,135,135.001C300,239.44,239.439,300,165,300z"/>
|
||||
<path style="fill: #ffffff;" d="M164.998,70c-11.026,0-19.996,8.976-19.996,20.009c0,11.023,8.97,19.991,19.996,19.991
|
||||
c11.026,0,19.996-8.968,19.996-19.991C184.994,78.976,176.024,70,164.998,70z"/>
|
||||
<path style="fill: #ffffff;" d="M165,140c-8.284,0-15,6.716-15,15v90c0,8.284,6.716,15,15,15c8.284,0,15-6.716,15-15v-90C180,146.716,173.284,140,165,140z
|
||||
"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
@ -330,6 +330,8 @@ trough {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.system-program-grid
|
||||
|
||||
.warning {
|
||||
background-color: rgba(30, 204, 39, 0.7);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user