mirror of
https://github.com/Snigdha-OS/snigdhaos-kernel-switcher.git
synced 2025-09-20 21:04:55 +02:00
Btw Antora valo ache bhai??
This commit is contained in:
668
ui/FlowBox.py
Normal file
668
ui/FlowBox.py
Normal file
@@ -0,0 +1,668 @@
|
|||||||
|
import datetime
|
||||||
|
|
||||||
|
import gi
|
||||||
|
import os
|
||||||
|
import libs.functions as fn
|
||||||
|
from ui.ProgressWindow import ProgressWindow
|
||||||
|
from ui.MessageWindow import MessageWindow
|
||||||
|
|
||||||
|
gi.require_version("Gtk", "4.0")
|
||||||
|
from gi.repository import Gtk, Gio, GLib
|
||||||
|
|
||||||
|
base_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
||||||
|
|
||||||
|
|
||||||
|
class FlowBox(Gtk.FlowBox):
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
kernel,
|
||||||
|
active_kernel,
|
||||||
|
manager_gui,
|
||||||
|
source,
|
||||||
|
):
|
||||||
|
super(FlowBox, self).__init__()
|
||||||
|
|
||||||
|
self.manager_gui = manager_gui
|
||||||
|
|
||||||
|
# self.set_row_spacing(1)
|
||||||
|
# self.set_column_spacing(1)
|
||||||
|
# self.set_name("hbox_kernel")
|
||||||
|
# self.set_activate_on_single_click(True)
|
||||||
|
# self.connect("child-activated", self.on_child_activated)
|
||||||
|
self.set_valign(Gtk.Align.START)
|
||||||
|
|
||||||
|
self.set_selection_mode(Gtk.SelectionMode.NONE)
|
||||||
|
|
||||||
|
# self.set_homogeneous(True)
|
||||||
|
|
||||||
|
self.set_max_children_per_line(2)
|
||||||
|
self.set_min_children_per_line(2)
|
||||||
|
self.kernel_count = 0
|
||||||
|
|
||||||
|
self.active_kernel_found = False
|
||||||
|
self.kernels = []
|
||||||
|
|
||||||
|
self.kernel = kernel
|
||||||
|
self.source = source
|
||||||
|
|
||||||
|
if self.source == "official":
|
||||||
|
self.flowbox_official()
|
||||||
|
|
||||||
|
if self.source == "community":
|
||||||
|
self.flowbox_community()
|
||||||
|
|
||||||
|
def flowbox_community(self):
|
||||||
|
for community_kernel in self.kernel:
|
||||||
|
self.kernels.append(community_kernel)
|
||||||
|
self.kernel_count += 1
|
||||||
|
|
||||||
|
if len(self.kernels) > 0:
|
||||||
|
installed = False
|
||||||
|
|
||||||
|
for cache in self.kernels:
|
||||||
|
fb_child = Gtk.FlowBoxChild()
|
||||||
|
fb_child.set_name(
|
||||||
|
"%s %s %s" % (cache.name, cache.version, cache.repository)
|
||||||
|
)
|
||||||
|
|
||||||
|
vbox_kernel_widgets = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.VERTICAL, spacing=0
|
||||||
|
)
|
||||||
|
vbox_kernel_widgets.set_name("vbox_kernel_widgets")
|
||||||
|
vbox_kernel_widgets.set_homogeneous(True)
|
||||||
|
|
||||||
|
switch_kernel = Gtk.Switch()
|
||||||
|
switch_kernel.set_halign(Gtk.Align.START)
|
||||||
|
|
||||||
|
hbox_kernel_switch = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.HORIZONTAL, spacing=0
|
||||||
|
)
|
||||||
|
|
||||||
|
hbox_kernel_switch.append(switch_kernel)
|
||||||
|
|
||||||
|
label_kernel_size = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_kernel_size.set_name("label_kernel_flowbox")
|
||||||
|
|
||||||
|
label_kernel_name = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_kernel_name.set_name("label_kernel_version")
|
||||||
|
label_kernel_name.set_markup(
|
||||||
|
"<b>%s</b> %s <i>%s</i>"
|
||||||
|
% (cache.name, cache.version, cache.repository)
|
||||||
|
)
|
||||||
|
label_kernel_name.set_selectable(True)
|
||||||
|
|
||||||
|
vbox_kernel_widgets.append(label_kernel_name)
|
||||||
|
|
||||||
|
tux_icon = Gtk.Picture.new_for_file(
|
||||||
|
file=Gio.File.new_for_path(
|
||||||
|
os.path.join(base_dir, "images/48x48/akm-tux.png")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
tux_icon.set_can_shrink(True)
|
||||||
|
|
||||||
|
for installed_kernel in self.manager_gui.installed_kernels:
|
||||||
|
if "{}-{}".format(
|
||||||
|
installed_kernel.name, installed_kernel.version
|
||||||
|
) == "{}-{}".format(cache.name, cache.version):
|
||||||
|
installed = True
|
||||||
|
|
||||||
|
if cache.name == installed_kernel.name:
|
||||||
|
if (
|
||||||
|
cache.version > installed_kernel.version
|
||||||
|
or cache.version != installed_kernel.version
|
||||||
|
):
|
||||||
|
fn.logger.info(
|
||||||
|
"Kernel upgrade available - %s %s"
|
||||||
|
% (cache.name, cache.version)
|
||||||
|
)
|
||||||
|
|
||||||
|
tux_icon = Gtk.Picture.new_for_file(
|
||||||
|
file=Gio.File.new_for_path(
|
||||||
|
os.path.join(
|
||||||
|
base_dir, "images/48x48/akm-update.png"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
tux_icon.set_can_shrink(True)
|
||||||
|
|
||||||
|
label_kernel_name.set_markup(
|
||||||
|
"<b>*%s</b> %s <i>%s</i>"
|
||||||
|
% (cache.name, cache.version, cache.repository)
|
||||||
|
)
|
||||||
|
|
||||||
|
if installed is True:
|
||||||
|
switch_kernel.set_state(True)
|
||||||
|
switch_kernel.set_active(True)
|
||||||
|
|
||||||
|
else:
|
||||||
|
switch_kernel.set_state(False)
|
||||||
|
switch_kernel.set_active(False)
|
||||||
|
|
||||||
|
tux_icon.set_content_fit(content_fit=Gtk.ContentFit.SCALE_DOWN)
|
||||||
|
tux_icon.set_halign(Gtk.Align.START)
|
||||||
|
|
||||||
|
installed = False
|
||||||
|
switch_kernel.connect("state-set", self.kernel_toggle_state, cache)
|
||||||
|
|
||||||
|
hbox_kernel = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0)
|
||||||
|
hbox_kernel.set_name("hbox_kernel")
|
||||||
|
|
||||||
|
label_kernel_size.set_text("%sM" % str(cache.install_size))
|
||||||
|
|
||||||
|
vbox_kernel_widgets.append(label_kernel_size)
|
||||||
|
|
||||||
|
label_kernel_build_date = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_kernel_build_date.set_name("label_kernel_flowbox")
|
||||||
|
label_kernel_build_date.set_text(cache.build_date)
|
||||||
|
|
||||||
|
vbox_kernel_widgets.append(label_kernel_build_date)
|
||||||
|
|
||||||
|
vbox_kernel_widgets.append(hbox_kernel_switch)
|
||||||
|
|
||||||
|
hbox_kernel.append(tux_icon)
|
||||||
|
hbox_kernel.append(vbox_kernel_widgets)
|
||||||
|
|
||||||
|
fb_child.set_child(hbox_kernel)
|
||||||
|
|
||||||
|
self.append(fb_child)
|
||||||
|
|
||||||
|
def flowbox_official(self):
|
||||||
|
for official_kernel in self.manager_gui.official_kernels:
|
||||||
|
if official_kernel.name == self.kernel:
|
||||||
|
self.kernels.append(official_kernel)
|
||||||
|
self.kernel_count += 1
|
||||||
|
|
||||||
|
if len(self.kernels) > 0:
|
||||||
|
installed = False
|
||||||
|
|
||||||
|
latest = sorted(self.kernels)[:-1][0]
|
||||||
|
|
||||||
|
for cache in sorted(self.kernels):
|
||||||
|
fb_child = Gtk.FlowBoxChild()
|
||||||
|
fb_child.set_name("%s %s" % (cache.name, cache.version))
|
||||||
|
if cache == latest:
|
||||||
|
tux_icon = Gtk.Picture.new_for_file(
|
||||||
|
file=Gio.File.new_for_path(
|
||||||
|
os.path.join(base_dir, "images/48x48/akm-new.png")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
else:
|
||||||
|
tux_icon = Gtk.Picture.new_for_file(
|
||||||
|
file=Gio.File.new_for_path(
|
||||||
|
os.path.join(base_dir, "images/48x48/akm-tux.png")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
tux_icon.set_content_fit(content_fit=Gtk.ContentFit.SCALE_DOWN)
|
||||||
|
tux_icon.set_halign(Gtk.Align.START)
|
||||||
|
|
||||||
|
vbox_kernel_widgets = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.VERTICAL, spacing=0
|
||||||
|
)
|
||||||
|
vbox_kernel_widgets.set_homogeneous(True)
|
||||||
|
|
||||||
|
hbox_kernel_switch = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.HORIZONTAL, spacing=0
|
||||||
|
)
|
||||||
|
|
||||||
|
switch_kernel = Gtk.Switch()
|
||||||
|
switch_kernel.set_halign(Gtk.Align.START)
|
||||||
|
|
||||||
|
hbox_kernel_switch.append(switch_kernel)
|
||||||
|
|
||||||
|
label_kernel_version = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_kernel_version.set_name("label_kernel_version")
|
||||||
|
label_kernel_version.set_selectable(True)
|
||||||
|
|
||||||
|
label_kernel_size = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_kernel_size.set_name("label_kernel_flowbox")
|
||||||
|
|
||||||
|
if self.manager_gui.installed_kernels is None:
|
||||||
|
self.manager_gui.installed_kernels = fn.get_installed_kernels()
|
||||||
|
|
||||||
|
for installed_kernel in self.manager_gui.installed_kernels:
|
||||||
|
if (
|
||||||
|
"{}-{}".format(installed_kernel.name, installed_kernel.version)
|
||||||
|
== cache.version
|
||||||
|
):
|
||||||
|
installed = True
|
||||||
|
|
||||||
|
if installed is True:
|
||||||
|
switch_kernel.set_state(True)
|
||||||
|
switch_kernel.set_active(True)
|
||||||
|
|
||||||
|
else:
|
||||||
|
switch_kernel.set_state(False)
|
||||||
|
switch_kernel.set_active(False)
|
||||||
|
|
||||||
|
installed = False
|
||||||
|
switch_kernel.connect("state-set", self.kernel_toggle_state, cache)
|
||||||
|
|
||||||
|
label_kernel_version.set_markup("<b>%s</b>" % cache.version)
|
||||||
|
|
||||||
|
hbox_kernel = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0)
|
||||||
|
hbox_kernel.set_name("hbox_kernel")
|
||||||
|
|
||||||
|
label_kernel_size.set_text(cache.size)
|
||||||
|
|
||||||
|
vbox_kernel_widgets.append(label_kernel_version)
|
||||||
|
vbox_kernel_widgets.append(label_kernel_size)
|
||||||
|
|
||||||
|
label_kernel_modified = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_kernel_modified.set_name("label_kernel_flowbox")
|
||||||
|
label_kernel_modified.set_text(cache.last_modified)
|
||||||
|
|
||||||
|
vbox_kernel_widgets.append(label_kernel_modified)
|
||||||
|
|
||||||
|
vbox_kernel_widgets.append(hbox_kernel_switch)
|
||||||
|
|
||||||
|
hbox_kernel.append(tux_icon)
|
||||||
|
hbox_kernel.append(vbox_kernel_widgets)
|
||||||
|
|
||||||
|
fb_child.set_child(hbox_kernel)
|
||||||
|
|
||||||
|
self.append(fb_child)
|
||||||
|
|
||||||
|
else:
|
||||||
|
fn.logger.error("Failed to read in kernels.")
|
||||||
|
|
||||||
|
def kernel_toggle_state(self, switch, data, kernel):
|
||||||
|
fn.logger.debug(
|
||||||
|
"Switch toggled, kernel selected = %s %s" % (kernel.name, kernel.version)
|
||||||
|
)
|
||||||
|
message = None
|
||||||
|
title = None
|
||||||
|
downgrade = False
|
||||||
|
community_repo = False
|
||||||
|
|
||||||
|
if fn.check_pacman_lockfile() is False:
|
||||||
|
# switch widget is currently toggled off
|
||||||
|
if switch.get_state() is False: # and switch.get_active() is True:
|
||||||
|
for inst_kernel in fn.get_installed_kernels():
|
||||||
|
if inst_kernel.name == kernel.name:
|
||||||
|
if self.source == "official":
|
||||||
|
if (
|
||||||
|
inst_kernel.version
|
||||||
|
> kernel.version.split("%s-" % inst_kernel.name)[1]
|
||||||
|
):
|
||||||
|
downgrade = True
|
||||||
|
title = "Downgrading %s kernel" % kernel.name
|
||||||
|
else:
|
||||||
|
downgrade = False
|
||||||
|
title = "Upgrading %s kernel" % kernel.name
|
||||||
|
|
||||||
|
break
|
||||||
|
|
||||||
|
if title is None:
|
||||||
|
title = "Kernel installation"
|
||||||
|
|
||||||
|
if self.source == "community":
|
||||||
|
message = (
|
||||||
|
"<span foreground='orange'><b>Community kernel selected - this may break your system</b></span>\n"
|
||||||
|
"Confirm the install of <b>%s-%s</b>"
|
||||||
|
% (
|
||||||
|
kernel.name,
|
||||||
|
kernel.version,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# check if the community pacman repo is configured
|
||||||
|
if fn.check_pacman_repo(kernel.repository) is True:
|
||||||
|
community_repo = True
|
||||||
|
else:
|
||||||
|
community_repo = False
|
||||||
|
fn.logger.error(
|
||||||
|
"%s pacman repo is not configured" % kernel.repository
|
||||||
|
)
|
||||||
|
|
||||||
|
elif self.source == "official":
|
||||||
|
message = "Confirm the install of <b>%s-%s</b>" % (
|
||||||
|
kernel.name,
|
||||||
|
kernel.version,
|
||||||
|
)
|
||||||
|
|
||||||
|
if community_repo is False and self.source == "community":
|
||||||
|
mw = MessageWindow(
|
||||||
|
title="Cannot find %s pacman repo" % kernel.repository,
|
||||||
|
message="Enable the pacman repository then retry the installation",
|
||||||
|
transient_for=self.manager_gui,
|
||||||
|
detailed_message=False,
|
||||||
|
)
|
||||||
|
mw.present()
|
||||||
|
else:
|
||||||
|
message_window = FlowBoxMessageWindow(
|
||||||
|
title=title,
|
||||||
|
message=message,
|
||||||
|
action="install",
|
||||||
|
kernel=kernel,
|
||||||
|
transient_for=self.manager_gui,
|
||||||
|
textview=self.manager_gui.textview,
|
||||||
|
textbuffer=self.manager_gui.textbuffer,
|
||||||
|
switch=switch,
|
||||||
|
source=self.source,
|
||||||
|
manager_gui=self.manager_gui,
|
||||||
|
downgrade=downgrade,
|
||||||
|
)
|
||||||
|
message_window.present()
|
||||||
|
return True
|
||||||
|
|
||||||
|
# switch widget is currently toggled on
|
||||||
|
# if widget.get_state() == True and widget.get_active() == False:
|
||||||
|
if switch.get_state() is True:
|
||||||
|
# and switch.get_active() is False:
|
||||||
|
installed_kernels = fn.get_installed_kernels()
|
||||||
|
|
||||||
|
if len(installed_kernels) > 1:
|
||||||
|
|
||||||
|
if self.source == "community":
|
||||||
|
message = "Confirm the removal of <b>%s-%s</b>" % (
|
||||||
|
kernel.name,
|
||||||
|
kernel.version,
|
||||||
|
)
|
||||||
|
elif self.source == "official":
|
||||||
|
message = "Confirm the removal of <b>%s-%s</b>" % (
|
||||||
|
kernel.name,
|
||||||
|
kernel.version,
|
||||||
|
)
|
||||||
|
|
||||||
|
message_window = FlowBoxMessageWindow(
|
||||||
|
title="Kernel uninstallation",
|
||||||
|
message=message,
|
||||||
|
action="uninstall",
|
||||||
|
kernel=kernel,
|
||||||
|
transient_for=self.manager_gui,
|
||||||
|
textview=self.manager_gui.textview,
|
||||||
|
textbuffer=self.manager_gui.textbuffer,
|
||||||
|
switch=switch,
|
||||||
|
source=self.source,
|
||||||
|
manager_gui=self.manager_gui,
|
||||||
|
downgrade=downgrade,
|
||||||
|
)
|
||||||
|
message_window.present()
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
switch.set_state(True)
|
||||||
|
# switch.set_active(False)
|
||||||
|
fn.logger.warn(
|
||||||
|
"You only have 1 kernel installed, and %s-%s is currently running, uninstall aborted."
|
||||||
|
% (kernel.name, kernel.version)
|
||||||
|
)
|
||||||
|
msg_win = MessageWindow(
|
||||||
|
title="Warning: Uninstall aborted",
|
||||||
|
message=f"You only have 1 kernel installed\n"
|
||||||
|
f"<b>{kernel.name} {kernel.version}</b> is currently active\n",
|
||||||
|
transient_for=self.manager_gui,
|
||||||
|
detailed_message=False,
|
||||||
|
)
|
||||||
|
msg_win.present()
|
||||||
|
return True
|
||||||
|
|
||||||
|
else:
|
||||||
|
fn.logger.error(
|
||||||
|
"Pacman lockfile found, is another pacman process running ?"
|
||||||
|
)
|
||||||
|
|
||||||
|
msg_win = MessageWindow(
|
||||||
|
title="Warning",
|
||||||
|
message="Pacman lockfile found, which indicates another pacman process is running",
|
||||||
|
transient_for=self.manager_gui,
|
||||||
|
detailed_message=False,
|
||||||
|
)
|
||||||
|
msg_win.present()
|
||||||
|
return True
|
||||||
|
|
||||||
|
# while self.manager_gui.default_context.pending():
|
||||||
|
# self.manager_gui.default_context.iteration(True)
|
||||||
|
|
||||||
|
|
||||||
|
class FlowBoxInstalled(Gtk.FlowBox):
|
||||||
|
def __init__(self, installed_kernels, manager_gui, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
self.set_selection_mode(Gtk.SelectionMode.NONE)
|
||||||
|
|
||||||
|
self.set_homogeneous(True)
|
||||||
|
self.set_max_children_per_line(2)
|
||||||
|
self.set_min_children_per_line(2)
|
||||||
|
|
||||||
|
self.manager_gui = manager_gui
|
||||||
|
|
||||||
|
for installed_kernel in installed_kernels:
|
||||||
|
tux_icon = Gtk.Picture.new_for_file(
|
||||||
|
file=Gio.File.new_for_path(
|
||||||
|
os.path.join(base_dir, "images/48x48/akm-tux.png")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
fb_child = Gtk.FlowBoxChild()
|
||||||
|
fb_child.set_name(
|
||||||
|
"%s %s" % (installed_kernel.name, installed_kernel.version)
|
||||||
|
)
|
||||||
|
|
||||||
|
tux_icon.set_content_fit(content_fit=Gtk.ContentFit.SCALE_DOWN)
|
||||||
|
tux_icon.set_halign(Gtk.Align.START)
|
||||||
|
|
||||||
|
label_installed_kernel_version = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_installed_kernel_version.set_name("label_kernel_version")
|
||||||
|
label_installed_kernel_version.set_markup(
|
||||||
|
"<b>%s</b> %s" % (installed_kernel.name, installed_kernel.version)
|
||||||
|
)
|
||||||
|
label_installed_kernel_version.set_selectable(True)
|
||||||
|
|
||||||
|
hbox_installed_version = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.HORIZONTAL, spacing=0
|
||||||
|
)
|
||||||
|
|
||||||
|
hbox_installed_version.append(label_installed_kernel_version)
|
||||||
|
|
||||||
|
label_installed_kernel_size = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_installed_kernel_size.set_name("label_kernel_flowbox")
|
||||||
|
label_installed_kernel_size.set_text("%sM" % str(installed_kernel.size))
|
||||||
|
|
||||||
|
label_installed_kernel_date = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_installed_kernel_date.set_name("label_kernel_flowbox")
|
||||||
|
label_installed_kernel_date.set_text("%s" % installed_kernel.date)
|
||||||
|
|
||||||
|
btn_uninstall_kernel = Gtk.Button.new_with_label("Remove")
|
||||||
|
|
||||||
|
btn_context = btn_uninstall_kernel.get_style_context()
|
||||||
|
btn_context.add_class("destructive-action")
|
||||||
|
|
||||||
|
vbox_uninstall_button = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.HORIZONTAL, spacing=0
|
||||||
|
)
|
||||||
|
vbox_uninstall_button.set_name("box_padding_left")
|
||||||
|
|
||||||
|
btn_uninstall_kernel.set_hexpand(False)
|
||||||
|
btn_uninstall_kernel.set_halign(Gtk.Align.CENTER)
|
||||||
|
btn_uninstall_kernel.set_vexpand(False)
|
||||||
|
btn_uninstall_kernel.set_valign(Gtk.Align.CENTER)
|
||||||
|
|
||||||
|
vbox_uninstall_button.append(btn_uninstall_kernel)
|
||||||
|
|
||||||
|
btn_uninstall_kernel.connect(
|
||||||
|
"clicked", self.button_uninstall_kernel, installed_kernel
|
||||||
|
)
|
||||||
|
|
||||||
|
vbox_kernel_widgets = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.VERTICAL, spacing=0
|
||||||
|
)
|
||||||
|
|
||||||
|
vbox_kernel_widgets.append(hbox_installed_version)
|
||||||
|
vbox_kernel_widgets.append(label_installed_kernel_size)
|
||||||
|
vbox_kernel_widgets.append(label_installed_kernel_date)
|
||||||
|
vbox_kernel_widgets.append(vbox_uninstall_button)
|
||||||
|
|
||||||
|
hbox_kernel = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0)
|
||||||
|
hbox_kernel.set_name("hbox_kernel")
|
||||||
|
|
||||||
|
hbox_kernel.append(tux_icon)
|
||||||
|
hbox_kernel.append(vbox_kernel_widgets)
|
||||||
|
|
||||||
|
fb_child.set_child(hbox_kernel)
|
||||||
|
|
||||||
|
self.append(fb_child)
|
||||||
|
|
||||||
|
def button_uninstall_kernel(self, button, installed_kernel):
|
||||||
|
installed_kernels = fn.get_installed_kernels()
|
||||||
|
|
||||||
|
if len(installed_kernels) > 1:
|
||||||
|
fn.logger.info(
|
||||||
|
"Selected kernel to remove = %s %s"
|
||||||
|
% (installed_kernel.name, installed_kernel.version)
|
||||||
|
)
|
||||||
|
|
||||||
|
message_window = FlowBoxMessageWindow(
|
||||||
|
title="Kernel uninstall",
|
||||||
|
message="This will remove <b>%s-%s</b> - Is this ok ?"
|
||||||
|
% (installed_kernel.name, installed_kernel.version),
|
||||||
|
action="uninstall",
|
||||||
|
kernel=installed_kernel,
|
||||||
|
transient_for=self.manager_gui,
|
||||||
|
textview=self.manager_gui.textview,
|
||||||
|
textbuffer=self.manager_gui.textbuffer,
|
||||||
|
switch=None,
|
||||||
|
source=None,
|
||||||
|
manager_gui=self.manager_gui,
|
||||||
|
downgrade=None,
|
||||||
|
)
|
||||||
|
message_window.present()
|
||||||
|
else:
|
||||||
|
fn.logger.warn(
|
||||||
|
"You only have 1 kernel installed %s %s, uninstall aborted."
|
||||||
|
% (installed_kernel.name, installed_kernel.version)
|
||||||
|
)
|
||||||
|
msg_win = MessageWindow(
|
||||||
|
title="Warning: Uninstall aborted",
|
||||||
|
message=f"You only have 1 kernel installed\n"
|
||||||
|
f"<b>{installed_kernel.name} {installed_kernel.version}</b>\n",
|
||||||
|
transient_for=self.manager_gui,
|
||||||
|
detailed_message=False,
|
||||||
|
)
|
||||||
|
msg_win.present()
|
||||||
|
|
||||||
|
|
||||||
|
class FlowBoxMessageWindow(Gtk.Window):
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
title,
|
||||||
|
message,
|
||||||
|
action,
|
||||||
|
kernel,
|
||||||
|
textview,
|
||||||
|
textbuffer,
|
||||||
|
switch,
|
||||||
|
source,
|
||||||
|
manager_gui,
|
||||||
|
downgrade,
|
||||||
|
**kwargs,
|
||||||
|
):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
self.set_title(title=title)
|
||||||
|
self.set_modal(modal=True)
|
||||||
|
self.set_resizable(False)
|
||||||
|
self.set_icon_name("archlinux-kernel-manager-tux")
|
||||||
|
|
||||||
|
header_bar = Gtk.HeaderBar()
|
||||||
|
header_bar.set_show_title_buttons(False)
|
||||||
|
|
||||||
|
label_title = Gtk.Label(xalign=0.5, yalign=0.5)
|
||||||
|
label_title.set_markup("<b>%s</b>" % title)
|
||||||
|
|
||||||
|
self.set_titlebar(header_bar)
|
||||||
|
|
||||||
|
header_bar.set_title_widget(label_title)
|
||||||
|
|
||||||
|
self.textview = textview
|
||||||
|
self.textbuffer = textbuffer
|
||||||
|
self.manager_gui = manager_gui
|
||||||
|
self.kernel = kernel
|
||||||
|
self.action = action
|
||||||
|
self.switch = switch
|
||||||
|
self.source = source
|
||||||
|
self.downgrade = downgrade
|
||||||
|
|
||||||
|
vbox_flowbox_message = Gtk.Box.new(
|
||||||
|
orientation=Gtk.Orientation.VERTICAL, spacing=10
|
||||||
|
)
|
||||||
|
vbox_flowbox_message.set_name("vbox_flowbox_message")
|
||||||
|
|
||||||
|
self.set_child(child=vbox_flowbox_message)
|
||||||
|
|
||||||
|
label_flowbox_message = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_flowbox_message.set_markup("%s" % message)
|
||||||
|
label_flowbox_message.set_name("label_flowbox_message")
|
||||||
|
|
||||||
|
vbox_flowbox_message.set_halign(Gtk.Align.CENTER)
|
||||||
|
|
||||||
|
# Widgets.
|
||||||
|
button_yes = Gtk.Button.new_with_label("Yes")
|
||||||
|
button_yes.set_size_request(100, 30)
|
||||||
|
button_yes.set_halign(Gtk.Align.END)
|
||||||
|
button_yes_context = button_yes.get_style_context()
|
||||||
|
button_yes_context.add_class("destructive-action")
|
||||||
|
button_yes.connect("clicked", self.on_button_yes_clicked)
|
||||||
|
|
||||||
|
button_no = Gtk.Button.new_with_label("No")
|
||||||
|
button_no.set_size_request(100, 30)
|
||||||
|
button_no.set_halign(Gtk.Align.END)
|
||||||
|
button_no.connect("clicked", self.on_button_no_clicked)
|
||||||
|
|
||||||
|
hbox_buttons = Gtk.Box.new(orientation=Gtk.Orientation.HORIZONTAL, spacing=15)
|
||||||
|
hbox_buttons.set_halign(Gtk.Align.CENTER)
|
||||||
|
hbox_buttons.append(button_yes)
|
||||||
|
hbox_buttons.append(button_no)
|
||||||
|
|
||||||
|
vbox_flowbox_message.append(label_flowbox_message)
|
||||||
|
vbox_flowbox_message.append(hbox_buttons)
|
||||||
|
|
||||||
|
def on_button_yes_clicked(self, button):
|
||||||
|
self.hide()
|
||||||
|
self.destroy()
|
||||||
|
progress_window = None
|
||||||
|
if fn.check_pacman_lockfile() is False:
|
||||||
|
if self.action == "uninstall":
|
||||||
|
progress_window = ProgressWindow(
|
||||||
|
title="Removing kernel",
|
||||||
|
action="uninstall",
|
||||||
|
textview=self.textview,
|
||||||
|
textbuffer=self.textbuffer,
|
||||||
|
kernel=self.kernel,
|
||||||
|
switch=self.switch,
|
||||||
|
source=self.source,
|
||||||
|
manager_gui=self.manager_gui,
|
||||||
|
transient_for=self.manager_gui,
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.action == "install":
|
||||||
|
progress_window = ProgressWindow(
|
||||||
|
title="Installing kernel",
|
||||||
|
action="install",
|
||||||
|
textview=self.textview,
|
||||||
|
textbuffer=self.textbuffer,
|
||||||
|
kernel=self.kernel,
|
||||||
|
switch=self.switch,
|
||||||
|
source=self.source,
|
||||||
|
manager_gui=self.manager_gui,
|
||||||
|
transient_for=self.manager_gui,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
fn.logger.error(
|
||||||
|
"Pacman lockfile found, is another pacman process running ?"
|
||||||
|
)
|
||||||
|
|
||||||
|
def on_button_no_clicked(self, button):
|
||||||
|
if self.action == "uninstall":
|
||||||
|
if self.switch is not None:
|
||||||
|
self.switch.set_state(True)
|
||||||
|
|
||||||
|
elif self.action == "install":
|
||||||
|
if self.switch is not None:
|
||||||
|
self.switch.set_state(False)
|
||||||
|
|
||||||
|
self.hide()
|
||||||
|
self.destroy()
|
||||||
|
|
||||||
|
return True
|
657
ui/KernelStack.py
Normal file
657
ui/KernelStack.py
Normal file
@@ -0,0 +1,657 @@
|
|||||||
|
import gi
|
||||||
|
import os
|
||||||
|
import libs.functions as fn
|
||||||
|
from ui.FlowBox import FlowBox, FlowBoxInstalled
|
||||||
|
from ui.Stack import Stack
|
||||||
|
from libs.Kernel import Kernel, InstalledKernel, CommunityKernel
|
||||||
|
|
||||||
|
gi.require_version("Gtk", "4.0")
|
||||||
|
from gi.repository import Gtk, Gio, Gdk
|
||||||
|
|
||||||
|
base_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
||||||
|
|
||||||
|
|
||||||
|
class KernelStack:
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
manager_gui,
|
||||||
|
**kwargs,
|
||||||
|
):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
self.manager_gui = manager_gui
|
||||||
|
self.flowbox_stacks = []
|
||||||
|
self.search_entries = []
|
||||||
|
|
||||||
|
def add_installed_kernels_to_stack(self, reload):
|
||||||
|
vbox_header = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
|
||||||
|
vbox_header.set_name("vbox_header")
|
||||||
|
|
||||||
|
lbl_heading = Gtk.Label(xalign=0.5, yalign=0.5)
|
||||||
|
lbl_heading.set_name("label_flowbox_message")
|
||||||
|
lbl_heading.set_text("%s" % "Installed kernels".upper())
|
||||||
|
|
||||||
|
lbl_padding = Gtk.Label(xalign=0.0, yalign=0.0)
|
||||||
|
lbl_padding.set_text(" ")
|
||||||
|
|
||||||
|
grid_banner_img = Gtk.Grid()
|
||||||
|
|
||||||
|
image_settings = Gtk.Image.new_from_file(
|
||||||
|
os.path.join(base_dir, "images/48x48/akm-install.png")
|
||||||
|
)
|
||||||
|
|
||||||
|
image_settings.set_icon_size(Gtk.IconSize.LARGE)
|
||||||
|
image_settings.set_halign(Gtk.Align.START)
|
||||||
|
|
||||||
|
grid_banner_img.attach(image_settings, 0, 1, 1, 1)
|
||||||
|
grid_banner_img.attach_next_to(
|
||||||
|
lbl_padding,
|
||||||
|
image_settings,
|
||||||
|
Gtk.PositionType.RIGHT,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
|
||||||
|
grid_banner_img.attach_next_to(
|
||||||
|
lbl_heading,
|
||||||
|
lbl_padding,
|
||||||
|
Gtk.PositionType.RIGHT,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
|
||||||
|
vbox_header.append(grid_banner_img)
|
||||||
|
|
||||||
|
label_installed_desc = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_installed_desc.set_text("Installed Linux kernel and modules")
|
||||||
|
label_installed_desc.set_name("label_stack_desc")
|
||||||
|
|
||||||
|
label_installed_count = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
|
||||||
|
label_installed_count.set_name("label_stack_count")
|
||||||
|
|
||||||
|
vbox_search_entry = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
|
||||||
|
|
||||||
|
search_entry_installed = Gtk.SearchEntry()
|
||||||
|
search_entry_installed.set_name("search_entry_installed")
|
||||||
|
search_entry_installed.set_placeholder_text("Search installed kernels...")
|
||||||
|
search_entry_installed.connect("search_changed", self.flowbox_filter_installed)
|
||||||
|
|
||||||
|
vbox_search_entry.append(search_entry_installed)
|
||||||
|
|
||||||
|
if reload is True:
|
||||||
|
if self.manager_gui.vbox_installed_kernels is not None:
|
||||||
|
for widget in self.manager_gui.vbox_installed_kernels:
|
||||||
|
if widget.get_name() == "label_stack_count":
|
||||||
|
widget.set_markup(
|
||||||
|
"<i>%s Installed kernels</i>"
|
||||||
|
% len(self.manager_gui.installed_kernels)
|
||||||
|
)
|
||||||
|
|
||||||
|
if widget.get_name() == "scrolled_window_installed":
|
||||||
|
self.manager_gui.vbox_installed_kernels.remove(widget)
|
||||||
|
|
||||||
|
scrolled_window_installed = Gtk.ScrolledWindow()
|
||||||
|
scrolled_window_installed.set_name("scrolled_window_installed")
|
||||||
|
scrolled_window_installed.set_policy(
|
||||||
|
Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC
|
||||||
|
)
|
||||||
|
scrolled_window_installed.set_propagate_natural_height(True)
|
||||||
|
scrolled_window_installed.set_propagate_natural_width(True)
|
||||||
|
|
||||||
|
self.flowbox_installed = FlowBoxInstalled(
|
||||||
|
installed_kernels=self.manager_gui.installed_kernels,
|
||||||
|
manager_gui=self.manager_gui,
|
||||||
|
)
|
||||||
|
vbox_installed_flowbox = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.VERTICAL, spacing=12
|
||||||
|
)
|
||||||
|
|
||||||
|
# vbox_installed_flowbox.set_halign(align=Gtk.Align.FILL)
|
||||||
|
|
||||||
|
vbox_installed_flowbox.append(self.flowbox_installed)
|
||||||
|
|
||||||
|
scrolled_window_installed.set_child(vbox_installed_flowbox)
|
||||||
|
|
||||||
|
self.manager_gui.vbox_installed_kernels.append(scrolled_window_installed)
|
||||||
|
|
||||||
|
if self.manager_gui.vbox_active_installed_kernel is not None:
|
||||||
|
self.manager_gui.vbox_installed_kernels.reorder_child_after(
|
||||||
|
self.manager_gui.vbox_active_installed_kernel,
|
||||||
|
scrolled_window_installed,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.manager_gui.vbox_installed_kernels = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.VERTICAL, spacing=5
|
||||||
|
)
|
||||||
|
self.manager_gui.vbox_installed_kernels.set_name("vbox_installed_kernels")
|
||||||
|
|
||||||
|
self.manager_gui.vbox_active_installed_kernel = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.HORIZONTAL, spacing=5
|
||||||
|
)
|
||||||
|
self.manager_gui.vbox_active_installed_kernel.set_name("vbox_active_kernel")
|
||||||
|
|
||||||
|
label_active_installed_kernel = Gtk.Label(xalign=0.5, yalign=0.5)
|
||||||
|
label_active_installed_kernel.set_name("label_active_kernel")
|
||||||
|
label_active_installed_kernel.set_selectable(True)
|
||||||
|
|
||||||
|
label_active_installed_kernel.set_markup(
|
||||||
|
"Active kernel: <b>%s</b>" % self.manager_gui.active_kernel
|
||||||
|
)
|
||||||
|
label_active_installed_kernel.set_halign(Gtk.Align.START)
|
||||||
|
self.manager_gui.vbox_active_installed_kernel.append(
|
||||||
|
label_active_installed_kernel
|
||||||
|
)
|
||||||
|
|
||||||
|
scrolled_window_installed = Gtk.ScrolledWindow()
|
||||||
|
scrolled_window_installed.set_name("scrolled_window_installed")
|
||||||
|
scrolled_window_installed.set_policy(
|
||||||
|
Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC
|
||||||
|
)
|
||||||
|
scrolled_window_installed.set_propagate_natural_height(True)
|
||||||
|
scrolled_window_installed.set_propagate_natural_width(True)
|
||||||
|
|
||||||
|
label_installed_count.set_markup(
|
||||||
|
"<i>%s Installed kernels</i>" % len(self.manager_gui.installed_kernels)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.flowbox_installed = FlowBoxInstalled(
|
||||||
|
installed_kernels=self.manager_gui.installed_kernels,
|
||||||
|
manager_gui=self.manager_gui,
|
||||||
|
)
|
||||||
|
vbox_installed_flowbox = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.VERTICAL, spacing=12
|
||||||
|
)
|
||||||
|
|
||||||
|
# vbox_installed_flowbox.set_halign(align=Gtk.Align.FILL)
|
||||||
|
|
||||||
|
vbox_installed_flowbox.append(self.flowbox_installed)
|
||||||
|
|
||||||
|
scrolled_window_installed.set_child(vbox_installed_flowbox)
|
||||||
|
|
||||||
|
# self.manager_gui.vbox_installed_kernels.append(label_installed_title)
|
||||||
|
self.manager_gui.vbox_installed_kernels.append(vbox_header)
|
||||||
|
self.manager_gui.vbox_installed_kernels.append(label_installed_desc)
|
||||||
|
self.manager_gui.vbox_installed_kernels.append(label_installed_count)
|
||||||
|
self.manager_gui.vbox_installed_kernels.append(vbox_search_entry)
|
||||||
|
self.manager_gui.vbox_installed_kernels.append(scrolled_window_installed)
|
||||||
|
self.manager_gui.vbox_installed_kernels.append(
|
||||||
|
self.manager_gui.vbox_active_installed_kernel
|
||||||
|
)
|
||||||
|
|
||||||
|
self.manager_gui.stack.add_titled(
|
||||||
|
self.manager_gui.vbox_installed_kernels, "Installed", "Installed"
|
||||||
|
)
|
||||||
|
|
||||||
|
def add_official_kernels_to_stack(self, reload):
|
||||||
|
if reload is True:
|
||||||
|
self.flowbox_stacks.clear()
|
||||||
|
for kernel in fn.supported_kernels_dict:
|
||||||
|
vbox_flowbox = None
|
||||||
|
stack_child = self.manager_gui.stack.get_child_by_name(kernel)
|
||||||
|
|
||||||
|
if stack_child is not None:
|
||||||
|
for stack_widget in stack_child:
|
||||||
|
if stack_widget.get_name() == "scrolled_window_official":
|
||||||
|
scrolled_window_official = stack_widget
|
||||||
|
vbox_flowbox = (
|
||||||
|
scrolled_window_official.get_child().get_child()
|
||||||
|
)
|
||||||
|
|
||||||
|
for widget in vbox_flowbox:
|
||||||
|
widget.remove_all()
|
||||||
|
|
||||||
|
self.flowbox_official_kernel = FlowBox(
|
||||||
|
kernel,
|
||||||
|
self.manager_gui.active_kernel,
|
||||||
|
self.manager_gui,
|
||||||
|
"official",
|
||||||
|
)
|
||||||
|
self.flowbox_stacks.append(self.flowbox_official_kernel)
|
||||||
|
|
||||||
|
vbox_flowbox.append(self.flowbox_official_kernel)
|
||||||
|
|
||||||
|
# while self.manager_gui.default_context.pending():
|
||||||
|
# self.manager_gui.default_context.iteration(True)
|
||||||
|
else:
|
||||||
|
for kernel in fn.supported_kernels_dict:
|
||||||
|
self.manager_gui.vbox_kernels = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.VERTICAL, spacing=5
|
||||||
|
)
|
||||||
|
|
||||||
|
self.manager_gui.vbox_kernels.set_name("stack_%s" % kernel)
|
||||||
|
|
||||||
|
hbox_sep_kernels = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.VERTICAL, spacing=10
|
||||||
|
)
|
||||||
|
|
||||||
|
hsep_kernels = Gtk.Separator(orientation=Gtk.Orientation.VERTICAL)
|
||||||
|
|
||||||
|
vbox_active_kernel = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.HORIZONTAL, spacing=5
|
||||||
|
)
|
||||||
|
vbox_active_kernel.set_name("vbox_active_kernel")
|
||||||
|
|
||||||
|
label_active_kernel = Gtk.Label(xalign=0.5, yalign=0.5)
|
||||||
|
label_active_kernel.set_name("label_active_kernel")
|
||||||
|
label_active_kernel.set_selectable(True)
|
||||||
|
label_active_kernel.set_markup(
|
||||||
|
"Active kernel: <b>%s</b>" % self.manager_gui.active_kernel
|
||||||
|
)
|
||||||
|
label_active_kernel.set_halign(Gtk.Align.START)
|
||||||
|
|
||||||
|
label_bottom_padding = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_bottom_padding.set_text(" ")
|
||||||
|
|
||||||
|
hbox_sep_kernels.append(hsep_kernels)
|
||||||
|
|
||||||
|
self.flowbox_official_kernel = FlowBox(
|
||||||
|
kernel, self.manager_gui.active_kernel, self.manager_gui, "official"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.flowbox_stacks.append(self.flowbox_official_kernel)
|
||||||
|
|
||||||
|
vbox_flowbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
|
||||||
|
vbox_flowbox.set_name("vbox_flowbox_%s" % kernel)
|
||||||
|
# vbox_flowbox.set_halign(align=Gtk.Align.FILL)
|
||||||
|
vbox_flowbox.append(self.flowbox_official_kernel)
|
||||||
|
|
||||||
|
scrolled_window_official = Gtk.ScrolledWindow()
|
||||||
|
scrolled_window_official.set_name("scrolled_window_official")
|
||||||
|
scrolled_window_official.set_policy(
|
||||||
|
Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC
|
||||||
|
)
|
||||||
|
scrolled_window_official.set_propagate_natural_height(True)
|
||||||
|
scrolled_window_official.set_propagate_natural_width(True)
|
||||||
|
|
||||||
|
label_title = Gtk.Label(xalign=0.5, yalign=0.5)
|
||||||
|
label_title.set_text(kernel.upper())
|
||||||
|
label_title.set_name("label_stack_kernel")
|
||||||
|
|
||||||
|
label_desc = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_desc.set_text(fn.supported_kernels_dict[kernel][0])
|
||||||
|
label_desc.set_name("label_stack_desc")
|
||||||
|
|
||||||
|
label_count = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_count.set_markup(
|
||||||
|
"<i>%s Available kernels</i>"
|
||||||
|
% self.flowbox_official_kernel.kernel_count
|
||||||
|
)
|
||||||
|
|
||||||
|
label_count.set_name("label_stack_count")
|
||||||
|
|
||||||
|
vbox_search_entry = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.VERTICAL, spacing=5
|
||||||
|
)
|
||||||
|
|
||||||
|
search_entry_official = Gtk.SearchEntry()
|
||||||
|
search_entry_official.set_name(kernel)
|
||||||
|
search_entry_official.set_placeholder_text(
|
||||||
|
"Search %s kernels..." % kernel
|
||||||
|
)
|
||||||
|
search_entry_official.connect(
|
||||||
|
"search_changed", self.flowbox_filter_official
|
||||||
|
)
|
||||||
|
|
||||||
|
self.search_entries.append(search_entry_official)
|
||||||
|
|
||||||
|
vbox_search_entry.append(search_entry_official)
|
||||||
|
|
||||||
|
vbox_active_kernel.append(label_active_kernel)
|
||||||
|
|
||||||
|
vbox_header = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
|
||||||
|
vbox_header.set_name("vbox_header")
|
||||||
|
|
||||||
|
lbl_heading = Gtk.Label(xalign=0.5, yalign=0.5)
|
||||||
|
lbl_heading.set_name("label_flowbox_message")
|
||||||
|
lbl_heading.set_text(
|
||||||
|
"%s - Verified and official kernels" % kernel.upper()
|
||||||
|
)
|
||||||
|
|
||||||
|
lbl_padding = Gtk.Label(xalign=0.0, yalign=0.0)
|
||||||
|
lbl_padding.set_text(" ")
|
||||||
|
|
||||||
|
grid_banner_img = Gtk.Grid()
|
||||||
|
|
||||||
|
image_settings = Gtk.Image.new_from_file(
|
||||||
|
os.path.join(base_dir, "images/48x48/akm-verified.png")
|
||||||
|
)
|
||||||
|
|
||||||
|
image_settings.set_icon_size(Gtk.IconSize.LARGE)
|
||||||
|
image_settings.set_halign(Gtk.Align.START)
|
||||||
|
|
||||||
|
grid_banner_img.attach(image_settings, 0, 1, 1, 1)
|
||||||
|
grid_banner_img.attach_next_to(
|
||||||
|
lbl_padding,
|
||||||
|
image_settings,
|
||||||
|
Gtk.PositionType.RIGHT,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
|
||||||
|
grid_banner_img.attach_next_to(
|
||||||
|
lbl_heading,
|
||||||
|
lbl_padding,
|
||||||
|
Gtk.PositionType.RIGHT,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
|
||||||
|
vbox_header.append(grid_banner_img)
|
||||||
|
|
||||||
|
# vbox_kernels.append(label_title)
|
||||||
|
self.manager_gui.vbox_kernels.append(vbox_header)
|
||||||
|
# self.manager_gui.vbox_kernels.append(label_title)
|
||||||
|
self.manager_gui.vbox_kernels.append(label_desc)
|
||||||
|
self.manager_gui.vbox_kernels.append(label_count)
|
||||||
|
self.manager_gui.vbox_kernels.append(vbox_search_entry)
|
||||||
|
self.manager_gui.vbox_kernels.append(hbox_sep_kernels)
|
||||||
|
|
||||||
|
scrolled_window_official.set_child(vbox_flowbox)
|
||||||
|
self.manager_gui.vbox_kernels.append(scrolled_window_official)
|
||||||
|
self.manager_gui.vbox_kernels.append(vbox_active_kernel)
|
||||||
|
|
||||||
|
kernel_sidebar_title = None
|
||||||
|
|
||||||
|
if kernel == "linux":
|
||||||
|
kernel_sidebar_title = "Linux"
|
||||||
|
elif kernel == "linux-lts":
|
||||||
|
kernel_sidebar_title = "Linux-LTS"
|
||||||
|
elif kernel == "linux-zen":
|
||||||
|
kernel_sidebar_title = "Linux-ZEN"
|
||||||
|
elif kernel == "linux-hardened":
|
||||||
|
kernel_sidebar_title = "Linux-Hardened"
|
||||||
|
elif kernel == "linux-rt":
|
||||||
|
kernel_sidebar_title = "Linux-RT"
|
||||||
|
elif kernel == "linux-rt-lts":
|
||||||
|
kernel_sidebar_title = "Linux-RT-LTS"
|
||||||
|
|
||||||
|
self.manager_gui.stack.add_titled(
|
||||||
|
self.manager_gui.vbox_kernels, kernel, kernel_sidebar_title
|
||||||
|
)
|
||||||
|
|
||||||
|
def flowbox_filter_official(self, search_entry):
|
||||||
|
def filter_func(fb_child, text):
|
||||||
|
if search_entry.get_name() == fb_child.get_name().split(" ")[0]:
|
||||||
|
if text in fb_child.get_name():
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
text = search_entry.get_text()
|
||||||
|
|
||||||
|
for flowbox in self.flowbox_stacks:
|
||||||
|
flowbox.set_filter_func(filter_func, text)
|
||||||
|
|
||||||
|
def flowbox_filter_community(self, search_entry):
|
||||||
|
def filter_func(fb_child, text):
|
||||||
|
if search_entry.get_name() == "search_entry_community":
|
||||||
|
if text in fb_child.get_name():
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
text = search_entry.get_text()
|
||||||
|
|
||||||
|
self.flowbox_community.set_filter_func(filter_func, text)
|
||||||
|
|
||||||
|
def flowbox_filter_installed(self, search_entry):
|
||||||
|
def filter_func(fb_child, text):
|
||||||
|
if search_entry.get_name() == "search_entry_installed":
|
||||||
|
if text in fb_child.get_name():
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
text = search_entry.get_text()
|
||||||
|
|
||||||
|
self.flowbox_installed.set_filter_func(filter_func, text)
|
||||||
|
|
||||||
|
def add_community_kernels_to_stack(self, reload):
|
||||||
|
vbox_active_kernel = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5)
|
||||||
|
vbox_active_kernel.set_name("vbox_active_kernel")
|
||||||
|
vbox_kernels = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
|
||||||
|
hbox_sep_kernels = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
|
||||||
|
hsep_kernels = Gtk.Separator(orientation=Gtk.Orientation.VERTICAL)
|
||||||
|
hbox_sep_kernels.append(hsep_kernels)
|
||||||
|
|
||||||
|
label_active_kernel = Gtk.Label(xalign=0.5, yalign=0.5)
|
||||||
|
label_active_kernel.set_name("label_active_kernel")
|
||||||
|
label_active_kernel.set_selectable(True)
|
||||||
|
label_active_kernel.set_markup(
|
||||||
|
"Active kernel: <b>%s</b>" % self.manager_gui.active_kernel
|
||||||
|
)
|
||||||
|
label_active_kernel.set_halign(Gtk.Align.START)
|
||||||
|
|
||||||
|
label_count = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_count.set_name("label_stack_count")
|
||||||
|
|
||||||
|
vbox_search_entry = None
|
||||||
|
|
||||||
|
search_entry_community = Gtk.SearchEntry()
|
||||||
|
search_entry_community.set_name("search_entry_community")
|
||||||
|
search_entry_community.set_placeholder_text(
|
||||||
|
"Search %s kernels..." % "community based"
|
||||||
|
)
|
||||||
|
search_entry_community.connect("search_changed", self.flowbox_filter_community)
|
||||||
|
|
||||||
|
hbox_warning_message = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.HORIZONTAL, spacing=5
|
||||||
|
)
|
||||||
|
hbox_warning_message.set_name("hbox_warning_message")
|
||||||
|
|
||||||
|
label_pacman_warning = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_pacman_warning.set_name("label_community_warning")
|
||||||
|
|
||||||
|
image_warning = Gtk.Image.new_from_file(
|
||||||
|
os.path.join(base_dir, "images/48x48/akm-warning.png")
|
||||||
|
)
|
||||||
|
image_warning.set_name("image_warning")
|
||||||
|
|
||||||
|
image_warning.set_icon_size(Gtk.IconSize.LARGE)
|
||||||
|
image_warning.set_halign(Gtk.Align.CENTER)
|
||||||
|
|
||||||
|
hbox_warning = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5)
|
||||||
|
hbox_warning.set_name("hbox_warning")
|
||||||
|
|
||||||
|
hbox_warning.append(image_warning)
|
||||||
|
# hbox_warning.append(label_pacman_warning)
|
||||||
|
|
||||||
|
label_warning = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_warning.set_name("label_community_warning")
|
||||||
|
|
||||||
|
if (
|
||||||
|
self.manager_gui.community_kernels is not None
|
||||||
|
and len(self.manager_gui.community_kernels) == 0
|
||||||
|
):
|
||||||
|
label_warning.set_markup(
|
||||||
|
f"<b>Cannot find any supported unofficial pacman repository's</b>\n"
|
||||||
|
f"<b>Add the Chaotic-AUR pacman repository to access Community based kernels</b>"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
label_warning.set_markup(
|
||||||
|
f"These kernels are user produced content\n"
|
||||||
|
f"These kernels may not work on your hardware\n"
|
||||||
|
f"<b>Any use of the provided files is at your own risk</b>"
|
||||||
|
)
|
||||||
|
|
||||||
|
hbox_warning.append(label_warning)
|
||||||
|
|
||||||
|
if reload is True:
|
||||||
|
vbox_flowbox = None
|
||||||
|
stack_child = self.manager_gui.stack.get_child_by_name("Community Kernels")
|
||||||
|
|
||||||
|
if stack_child is not None:
|
||||||
|
for stack_widget in stack_child:
|
||||||
|
if stack_widget.get_name() == "hbox_warning":
|
||||||
|
for w in stack_widget:
|
||||||
|
if w.get_name() == "label_community_warning":
|
||||||
|
if len(self.manager_gui.community_kernels) == 0:
|
||||||
|
w.set_markup(
|
||||||
|
f"<b>Cannot find any supported unofficial pacman repository's</b>\n"
|
||||||
|
f"<b>Add the Chaotic-AUR pacman repository to access Community based kernels</b>"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
w.set_markup(
|
||||||
|
f"These kernels are user produced content\n"
|
||||||
|
f"These kernels may not work on your hardware\n"
|
||||||
|
f"<b>Any use of the provided files is at your own risk</b>"
|
||||||
|
)
|
||||||
|
break
|
||||||
|
if stack_widget.get_name() == "label_stack_count":
|
||||||
|
stack_widget.set_markup(
|
||||||
|
"<i>%s Available kernels</i>"
|
||||||
|
% len(self.manager_gui.community_kernels)
|
||||||
|
)
|
||||||
|
if stack_widget.get_name() == "vbox_search_entry":
|
||||||
|
if len(self.manager_gui.community_kernels) == 0:
|
||||||
|
for search_entry in stack_widget:
|
||||||
|
search_entry.set_visible(False)
|
||||||
|
else:
|
||||||
|
for search_entry in stack_widget:
|
||||||
|
search_entry.set_visible(True)
|
||||||
|
|
||||||
|
if stack_widget.get_name() == "scrolled_window_community":
|
||||||
|
scrolled_window_community = stack_widget
|
||||||
|
vbox_flowbox = scrolled_window_community.get_child().get_child()
|
||||||
|
|
||||||
|
for widget in vbox_flowbox:
|
||||||
|
widget.remove_all()
|
||||||
|
|
||||||
|
# scrolled_window_community.hide()
|
||||||
|
|
||||||
|
# vbox_search_entry = Gtk.Box(
|
||||||
|
# orientation=Gtk.Orientation.VERTICAL, spacing=5
|
||||||
|
# )
|
||||||
|
#
|
||||||
|
# vbox_search_entry.append(search_entry_community)
|
||||||
|
# widget.append(vbox_search_entry)
|
||||||
|
|
||||||
|
if (
|
||||||
|
self.manager_gui.community_kernels is not None
|
||||||
|
and len(self.manager_gui.community_kernels) > 0
|
||||||
|
):
|
||||||
|
self.flowbox_community = FlowBox(
|
||||||
|
self.manager_gui.community_kernels,
|
||||||
|
self.manager_gui.active_kernel,
|
||||||
|
self.manager_gui,
|
||||||
|
"community",
|
||||||
|
)
|
||||||
|
vbox_flowbox.append(self.flowbox_community)
|
||||||
|
|
||||||
|
# while self.manager_gui.default_context.pending():
|
||||||
|
# # fn.time.sleep(0.1)
|
||||||
|
# self.manager_gui.default_context.iteration(True)
|
||||||
|
else:
|
||||||
|
self.flowbox_community = None
|
||||||
|
|
||||||
|
vbox_flowbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
|
||||||
|
# vbox_flowbox.set_halign(align=Gtk.Align.FILL)
|
||||||
|
|
||||||
|
if len(self.manager_gui.community_kernels) == 0:
|
||||||
|
label_count.set_markup("<i>%s Available kernels</i>" % 0)
|
||||||
|
else:
|
||||||
|
self.flowbox_community = FlowBox(
|
||||||
|
self.manager_gui.community_kernels,
|
||||||
|
self.manager_gui.active_kernel,
|
||||||
|
self.manager_gui,
|
||||||
|
"community",
|
||||||
|
)
|
||||||
|
|
||||||
|
vbox_flowbox.append(self.flowbox_community)
|
||||||
|
|
||||||
|
label_count.set_markup(
|
||||||
|
"<i>%s Available kernels</i>" % self.flowbox_community.kernel_count
|
||||||
|
)
|
||||||
|
|
||||||
|
vbox_search_entry = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.VERTICAL, spacing=5
|
||||||
|
)
|
||||||
|
|
||||||
|
vbox_search_entry.set_name("vbox_search_entry")
|
||||||
|
|
||||||
|
vbox_search_entry.append(search_entry_community)
|
||||||
|
|
||||||
|
if reload is False:
|
||||||
|
scrolled_window_community = Gtk.ScrolledWindow()
|
||||||
|
scrolled_window_community.set_name("scrolled_window_community")
|
||||||
|
scrolled_window_community.set_policy(
|
||||||
|
Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC
|
||||||
|
)
|
||||||
|
scrolled_window_community.set_propagate_natural_height(True)
|
||||||
|
scrolled_window_community.set_propagate_natural_width(True)
|
||||||
|
|
||||||
|
label_title = Gtk.Label(xalign=0.5, yalign=0.5)
|
||||||
|
label_title.set_text("Community Kernels")
|
||||||
|
label_title.set_name("label_stack_kernel")
|
||||||
|
|
||||||
|
label_desc = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_desc.set_text("Community Linux kernel and modules")
|
||||||
|
label_desc.set_name("label_stack_desc")
|
||||||
|
|
||||||
|
vbox_active_kernel.append(label_active_kernel)
|
||||||
|
|
||||||
|
vbox_header = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
|
||||||
|
vbox_header.set_name("vbox_header")
|
||||||
|
|
||||||
|
lbl_heading = Gtk.Label(xalign=0.5, yalign=0.5)
|
||||||
|
lbl_heading.set_name("label_flowbox_message")
|
||||||
|
|
||||||
|
lbl_heading.set_text(
|
||||||
|
"%s - Unofficial kernels" % "Community based".upper()
|
||||||
|
)
|
||||||
|
|
||||||
|
lbl_padding = Gtk.Label(xalign=0.0, yalign=0.0)
|
||||||
|
lbl_padding.set_text(" ")
|
||||||
|
|
||||||
|
grid_banner_img = Gtk.Grid()
|
||||||
|
|
||||||
|
image_settings = Gtk.Image.new_from_file(
|
||||||
|
os.path.join(base_dir, "images/48x48/akm-community.png")
|
||||||
|
)
|
||||||
|
|
||||||
|
image_settings.set_icon_size(Gtk.IconSize.LARGE)
|
||||||
|
image_settings.set_halign(Gtk.Align.START)
|
||||||
|
|
||||||
|
grid_banner_img.attach(image_settings, 0, 1, 1, 1)
|
||||||
|
grid_banner_img.attach_next_to(
|
||||||
|
lbl_padding,
|
||||||
|
image_settings,
|
||||||
|
Gtk.PositionType.RIGHT,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
|
||||||
|
grid_banner_img.attach_next_to(
|
||||||
|
lbl_heading,
|
||||||
|
lbl_padding,
|
||||||
|
Gtk.PositionType.RIGHT,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
|
||||||
|
vbox_header.append(grid_banner_img)
|
||||||
|
|
||||||
|
vbox_kernels.append(vbox_header)
|
||||||
|
vbox_kernels.append(label_desc)
|
||||||
|
vbox_kernels.append(hbox_warning)
|
||||||
|
vbox_kernels.append(label_count)
|
||||||
|
|
||||||
|
if vbox_search_entry is not None:
|
||||||
|
vbox_kernels.append(vbox_search_entry)
|
||||||
|
|
||||||
|
vbox_kernels.append(hbox_sep_kernels)
|
||||||
|
|
||||||
|
scrolled_window_community.set_child(vbox_flowbox)
|
||||||
|
|
||||||
|
vbox_kernels.append(scrolled_window_community)
|
||||||
|
vbox_kernels.append(vbox_active_kernel)
|
||||||
|
|
||||||
|
self.manager_gui.stack.add_titled(
|
||||||
|
vbox_kernels, "Community Kernels", "Community"
|
||||||
|
)
|
573
ui/ManagerGUI.py
Normal file
573
ui/ManagerGUI.py
Normal file
@@ -0,0 +1,573 @@
|
|||||||
|
import gi
|
||||||
|
import os
|
||||||
|
from ui.MenuButton import MenuButton
|
||||||
|
from ui.Stack import Stack
|
||||||
|
from ui.KernelStack import KernelStack
|
||||||
|
from ui.FlowBox import FlowBox, FlowBoxInstalled
|
||||||
|
from ui.AboutDialog import AboutDialog
|
||||||
|
from ui.SplashScreen import SplashScreen
|
||||||
|
from ui.MessageWindow import MessageWindow
|
||||||
|
from ui.SettingsWindow import SettingsWindow
|
||||||
|
import libs.functions as fn
|
||||||
|
|
||||||
|
gi.require_version("Gtk", "4.0")
|
||||||
|
from gi.repository import Gtk, Gio, Gdk, GLib
|
||||||
|
|
||||||
|
|
||||||
|
base_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
||||||
|
|
||||||
|
|
||||||
|
class ManagerGUI(Gtk.ApplicationWindow):
|
||||||
|
def __init__(self, app_name, default_context, app_version, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
self.default_context = default_context
|
||||||
|
|
||||||
|
self.app_version = app_version
|
||||||
|
|
||||||
|
if self.app_version == "${app_version}":
|
||||||
|
self.app_version = "dev"
|
||||||
|
|
||||||
|
self.set_title(app_name)
|
||||||
|
self.set_resizable(True)
|
||||||
|
self.set_default_size(950, 650)
|
||||||
|
|
||||||
|
# get list of kernels from the arch archive website, aur, then cache
|
||||||
|
self.official_kernels = []
|
||||||
|
self.community_kernels = []
|
||||||
|
|
||||||
|
# splashscreen queue for threading
|
||||||
|
self.queue_load_progress = fn.Queue()
|
||||||
|
|
||||||
|
# official kernels queue for threading
|
||||||
|
self.queue_kernels = fn.Queue()
|
||||||
|
|
||||||
|
# community kernels queue for threading
|
||||||
|
self.queue_community_kernels = fn.Queue()
|
||||||
|
|
||||||
|
self.splash_screen = SplashScreen(app_name)
|
||||||
|
|
||||||
|
try:
|
||||||
|
fn.Thread(
|
||||||
|
target=self.wait_for_gui_load,
|
||||||
|
daemon=True,
|
||||||
|
).start()
|
||||||
|
except Exception as e:
|
||||||
|
fn.logger.error(e)
|
||||||
|
|
||||||
|
while self.default_context.pending():
|
||||||
|
fn.time.sleep(0.1)
|
||||||
|
self.default_context.iteration(True)
|
||||||
|
|
||||||
|
hbox_notify_revealer = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.HORIZONTAL, spacing=20
|
||||||
|
)
|
||||||
|
hbox_notify_revealer.set_name("hbox_notify_revealer")
|
||||||
|
hbox_notify_revealer.set_halign(Gtk.Align.CENTER)
|
||||||
|
|
||||||
|
self.notify_revealer = Gtk.Revealer()
|
||||||
|
self.notify_revealer.set_reveal_child(False)
|
||||||
|
self.label_notify_revealer = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
self.label_notify_revealer.set_name("label_notify_revealer")
|
||||||
|
|
||||||
|
self.notify_revealer.set_child(hbox_notify_revealer)
|
||||||
|
|
||||||
|
hbox_notify_revealer.append(self.label_notify_revealer)
|
||||||
|
|
||||||
|
# while self.default_context.pending():
|
||||||
|
# fn.time.sleep(0.1)
|
||||||
|
# self.default_context.iteration(True)
|
||||||
|
|
||||||
|
self.bootloader = None
|
||||||
|
self.bootloader_grub_cfg = None
|
||||||
|
|
||||||
|
# self.bootloader = fn.get_boot_loader()
|
||||||
|
|
||||||
|
config_data = fn.setup_config(self)
|
||||||
|
|
||||||
|
fn.logger.info("Version = %s" % self.app_version)
|
||||||
|
fn.logger.info("Distro = %s" % fn.distro.id())
|
||||||
|
|
||||||
|
if "bootloader" in config_data.keys():
|
||||||
|
if config_data["bootloader"]["name"] is not None:
|
||||||
|
self.bootloader = config_data["bootloader"]["name"].lower()
|
||||||
|
|
||||||
|
if self.bootloader == "grub":
|
||||||
|
if config_data["bootloader"]["grub_config"] is not None:
|
||||||
|
self.bootloader_grub_cfg = config_data["bootloader"][
|
||||||
|
"grub_config"
|
||||||
|
]
|
||||||
|
elif self.bootloader != "systemd-boot" or self.bootloader != "grub":
|
||||||
|
fn.logger.warning(
|
||||||
|
"Invalid bootloader config found it should only be systemd-boot or grub"
|
||||||
|
)
|
||||||
|
|
||||||
|
fn.logger.warning("Using bootctl to determine current bootloader")
|
||||||
|
self.bootloader = None
|
||||||
|
|
||||||
|
if self.bootloader is not None or self.bootloader_grub_cfg is not None:
|
||||||
|
fn.logger.info("User provided bootloader options read from config file")
|
||||||
|
fn.logger.info("User bootloader option = %s " % self.bootloader)
|
||||||
|
if self.bootloader_grub_cfg is not None:
|
||||||
|
fn.logger.info(
|
||||||
|
"User bootloader Grub config = %s " % self.bootloader_grub_cfg
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# no config setting found for bootloader use default method
|
||||||
|
self.bootloader = fn.get_boot_loader()
|
||||||
|
if self.bootloader == "grub":
|
||||||
|
self.bootloader_grub_cfg = "/boot/grub/grub.cfg"
|
||||||
|
|
||||||
|
if self.bootloader is not None:
|
||||||
|
fn.create_cache_dir()
|
||||||
|
fn.create_log_dir()
|
||||||
|
fn.get_pacman_repos()
|
||||||
|
|
||||||
|
self.stack = Stack(transition_type="OVER_DOWN")
|
||||||
|
self.kernel_stack = KernelStack(self)
|
||||||
|
|
||||||
|
header_bar = Gtk.HeaderBar()
|
||||||
|
|
||||||
|
label_title = Gtk.Label(xalign=0.5, yalign=0.5)
|
||||||
|
label_title.set_markup("<b>%s</b>" % app_name)
|
||||||
|
|
||||||
|
header_bar.set_title_widget(label_title)
|
||||||
|
header_bar.set_show_title_buttons(True)
|
||||||
|
|
||||||
|
self.set_titlebar(header_bar)
|
||||||
|
|
||||||
|
menu_outerbox = Gtk.Box(spacing=6, orientation=Gtk.Orientation.VERTICAL)
|
||||||
|
header_bar.pack_end(menu_outerbox)
|
||||||
|
|
||||||
|
menu_outerbox.show()
|
||||||
|
|
||||||
|
menubutton = MenuButton()
|
||||||
|
|
||||||
|
menu_outerbox.append(menubutton)
|
||||||
|
|
||||||
|
menubutton.show()
|
||||||
|
|
||||||
|
action_about = Gio.SimpleAction(name="about")
|
||||||
|
action_about.connect("activate", self.on_about)
|
||||||
|
|
||||||
|
action_settings = Gio.SimpleAction(name="settings")
|
||||||
|
action_settings.connect("activate", self.on_settings, fn)
|
||||||
|
|
||||||
|
self.add_action(action_settings)
|
||||||
|
|
||||||
|
self.add_action(action_about)
|
||||||
|
|
||||||
|
action_refresh = Gio.SimpleAction(name="refresh")
|
||||||
|
action_refresh.connect("activate", self.on_refresh)
|
||||||
|
|
||||||
|
self.add_action(action_refresh)
|
||||||
|
|
||||||
|
action_quit = Gio.SimpleAction(name="quit")
|
||||||
|
action_quit.connect("activate", self.on_quit)
|
||||||
|
|
||||||
|
self.add_action(action_quit)
|
||||||
|
|
||||||
|
# add shortcut keys
|
||||||
|
|
||||||
|
event_controller_key = Gtk.EventControllerKey.new()
|
||||||
|
event_controller_key.connect("key-pressed", self.key_pressed)
|
||||||
|
|
||||||
|
self.add_controller(event_controller_key)
|
||||||
|
|
||||||
|
# overlay = Gtk.Overlay()
|
||||||
|
# self.set_child(child=overlay)
|
||||||
|
|
||||||
|
self.vbox = Gtk.Box.new(orientation=Gtk.Orientation.VERTICAL, spacing=10)
|
||||||
|
self.vbox.set_name("main")
|
||||||
|
|
||||||
|
self.set_child(child=self.vbox)
|
||||||
|
|
||||||
|
self.vbox.append(self.notify_revealer)
|
||||||
|
|
||||||
|
self.installed_kernels = fn.get_installed_kernels()
|
||||||
|
if self.installed_kernels is not None:
|
||||||
|
fn.logger.info("Installed kernels = %s" % len(self.installed_kernels))
|
||||||
|
|
||||||
|
self.active_kernel = fn.get_active_kernel()
|
||||||
|
|
||||||
|
self.refresh_cache = False
|
||||||
|
|
||||||
|
self.refresh_cache = fn.get_latest_kernel_updates(self)
|
||||||
|
|
||||||
|
self.start_get_kernels_threads()
|
||||||
|
|
||||||
|
self.load_kernels_gui()
|
||||||
|
|
||||||
|
# validate bootloader
|
||||||
|
if self.bootloader_grub_cfg and not os.path.exists(
|
||||||
|
self.bootloader_grub_cfg
|
||||||
|
):
|
||||||
|
mw = MessageWindow(
|
||||||
|
title="Grub config file not found",
|
||||||
|
message=f"The specified Grub config file: {self.bootloader_grub_cfg} does not exist\n"
|
||||||
|
f"This will cause an issue when updating the bootloader\n"
|
||||||
|
f"Update the configuration file/use the Advanced Settings to change this\n",
|
||||||
|
detailed_message=False,
|
||||||
|
transient_for=self,
|
||||||
|
)
|
||||||
|
|
||||||
|
mw.present()
|
||||||
|
if self.bootloader == "systemd-boot":
|
||||||
|
if not os.path.exists(
|
||||||
|
"/sys/firmware/efi/fw_platform_size"
|
||||||
|
) or not os.path.exists("/sys/firmware/efi/efivars"):
|
||||||
|
mw = MessageWindow(
|
||||||
|
title="Legacy boot detected",
|
||||||
|
message=f"Cannot select systemd-boot, UEFI boot mode is not available\n"
|
||||||
|
f"Update the configuration file\n"
|
||||||
|
f"Or use the Advanced Settings to change this\n",
|
||||||
|
detailed_message=False,
|
||||||
|
transient_for=self,
|
||||||
|
)
|
||||||
|
|
||||||
|
mw.present()
|
||||||
|
|
||||||
|
else:
|
||||||
|
fn.logger.error("Failed to set bootloader, application closing")
|
||||||
|
fn.sys.exit(1)
|
||||||
|
|
||||||
|
def key_pressed(self, keyval, keycode, state, userdata):
|
||||||
|
shortcut = Gtk.accelerator_get_label(
|
||||||
|
keycode, keyval.get_current_event().get_modifier_state()
|
||||||
|
)
|
||||||
|
|
||||||
|
# quit application
|
||||||
|
if shortcut in ("Ctrl+Q", "Ctrl+Mod2+Q"):
|
||||||
|
self.destroy()
|
||||||
|
|
||||||
|
def open_settings(self, fn):
|
||||||
|
settings_win = SettingsWindow(fn, self)
|
||||||
|
settings_win.present()
|
||||||
|
|
||||||
|
def timeout(self):
|
||||||
|
self.hide_notify()
|
||||||
|
|
||||||
|
def hide_notify(self):
|
||||||
|
self.notify_revealer.set_reveal_child(False)
|
||||||
|
if self.timeout_id is not None:
|
||||||
|
GLib.source_remove(self.timeout_id)
|
||||||
|
self.timeout_id = None
|
||||||
|
|
||||||
|
def reveal_notify(self):
|
||||||
|
# reveal = self.notify_revealer.get_reveal_child()
|
||||||
|
self.notify_revealer.set_reveal_child(True)
|
||||||
|
self.timeout_id = GLib.timeout_add(3000, self.timeout)
|
||||||
|
|
||||||
|
def start_get_kernels_threads(self):
|
||||||
|
if self.refresh_cache is False:
|
||||||
|
fn.logger.info("Starting get official Linux kernels thread")
|
||||||
|
try:
|
||||||
|
fn.Thread(
|
||||||
|
name=fn.thread_get_kernels,
|
||||||
|
target=fn.get_official_kernels,
|
||||||
|
daemon=True,
|
||||||
|
args=(self,),
|
||||||
|
).start()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
fn.logger.error("Exception in thread fn.get_official_kernels(): %s" % e)
|
||||||
|
finally:
|
||||||
|
self.official_kernels = self.queue_kernels.get()
|
||||||
|
self.queue_kernels.task_done()
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.official_kernels = self.queue_kernels.get()
|
||||||
|
self.queue_kernels.task_done()
|
||||||
|
|
||||||
|
# =====================================================
|
||||||
|
# PACMAN DB SYNC
|
||||||
|
# =====================================================
|
||||||
|
|
||||||
|
def pacman_db_sync(self):
|
||||||
|
sync_err = fn.sync_package_db()
|
||||||
|
|
||||||
|
if sync_err is not None:
|
||||||
|
# fn.logger.error("Pacman db synchronization failed")
|
||||||
|
|
||||||
|
GLib.idle_add(
|
||||||
|
self.show_sync_window,
|
||||||
|
sync_err,
|
||||||
|
priority=GLib.PRIORITY_DEFAULT,
|
||||||
|
)
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
else:
|
||||||
|
fn.logger.info("Pacman DB synchronization completed")
|
||||||
|
return True
|
||||||
|
|
||||||
|
def show_sync_window(self, sync_err):
|
||||||
|
mw = MessageWindow(
|
||||||
|
title="Error - Pacman db synchronization",
|
||||||
|
message=f"Pacman db synchronization failed\n"
|
||||||
|
f"Failed to run 'pacman -Syu'\n"
|
||||||
|
f"{sync_err}\n",
|
||||||
|
transient_for=self,
|
||||||
|
detailed_message=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
mw.present()
|
||||||
|
|
||||||
|
# keep splash screen open, until main gui is loaded
|
||||||
|
def wait_for_gui_load(self):
|
||||||
|
while True:
|
||||||
|
if fn.logger.getEffectiveLevel() == 10:
|
||||||
|
fn.logger.debug("Waiting for GUI to load ..")
|
||||||
|
|
||||||
|
# fn.time.sleep(0.2)
|
||||||
|
status = self.queue_load_progress.get()
|
||||||
|
try:
|
||||||
|
|
||||||
|
if fn.logger.getEffectiveLevel() == 10:
|
||||||
|
fn.logger.debug("Status = %s" % status)
|
||||||
|
|
||||||
|
if status == 1:
|
||||||
|
if fn.logger.getEffectiveLevel() == 10:
|
||||||
|
fn.logger.debug("Destroying splashscreen")
|
||||||
|
|
||||||
|
GLib.idle_add(
|
||||||
|
self.splash_screen.destroy,
|
||||||
|
priority=GLib.PRIORITY_DEFAULT,
|
||||||
|
)
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
fn.logger.error("Exception in wait_for_gui_load(): %s" % e)
|
||||||
|
finally:
|
||||||
|
self.queue_load_progress.task_done()
|
||||||
|
|
||||||
|
def on_settings(self, action, param, fn):
|
||||||
|
self.open_settings(fn)
|
||||||
|
|
||||||
|
def on_about(self, action, param):
|
||||||
|
about_dialog = AboutDialog(self)
|
||||||
|
about_dialog.present()
|
||||||
|
|
||||||
|
def on_refresh(self, action, param):
|
||||||
|
if not fn.is_thread_alive(fn.thread_refresh_ui):
|
||||||
|
fn.Thread(
|
||||||
|
name=fn.thread_refresh_ui,
|
||||||
|
target=self.refresh_ui,
|
||||||
|
daemon=True,
|
||||||
|
).start()
|
||||||
|
|
||||||
|
def refresh_ui(self):
|
||||||
|
if fn.logger.getEffectiveLevel() == 10:
|
||||||
|
fn.logger.debug("Refreshing UI")
|
||||||
|
|
||||||
|
self.label_notify_revealer.set_text("Refreshing UI started")
|
||||||
|
GLib.idle_add(
|
||||||
|
self.reveal_notify,
|
||||||
|
priority=GLib.PRIORITY_DEFAULT,
|
||||||
|
)
|
||||||
|
fn.pacman_repos_list = []
|
||||||
|
fn.get_pacman_repos()
|
||||||
|
|
||||||
|
fn.cached_kernels_list = []
|
||||||
|
fn.community_kernels_list = []
|
||||||
|
|
||||||
|
self.official_kernels = None
|
||||||
|
|
||||||
|
self.community_kernels = None
|
||||||
|
|
||||||
|
self.installed_kernels = None
|
||||||
|
|
||||||
|
self.start_get_kernels_threads()
|
||||||
|
|
||||||
|
if self.pacman_db_sync() is False:
|
||||||
|
fn.logger.error("Pacman DB synchronization failed")
|
||||||
|
else:
|
||||||
|
if fn.logger.getEffectiveLevel() == 10:
|
||||||
|
fn.logger.debug("Adding community kernels to UI")
|
||||||
|
|
||||||
|
try:
|
||||||
|
thread_get_community_kernels = fn.Thread(
|
||||||
|
name=fn.thread_get_community_kernels,
|
||||||
|
target=fn.get_community_kernels,
|
||||||
|
daemon=True,
|
||||||
|
args=(self,),
|
||||||
|
)
|
||||||
|
|
||||||
|
thread_get_community_kernels.start()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
fn.logger.error("Exception in thread_get_community_kernels: %s" % e)
|
||||||
|
finally:
|
||||||
|
self.community_kernels = self.queue_community_kernels.get()
|
||||||
|
self.queue_community_kernels.task_done()
|
||||||
|
|
||||||
|
self.installed_kernels = fn.get_installed_kernels()
|
||||||
|
|
||||||
|
self.label_notify_revealer.set_text("Refreshing official kernels")
|
||||||
|
GLib.idle_add(
|
||||||
|
self.reveal_notify,
|
||||||
|
priority=GLib.PRIORITY_DEFAULT,
|
||||||
|
)
|
||||||
|
|
||||||
|
GLib.idle_add(
|
||||||
|
self.kernel_stack.add_official_kernels_to_stack,
|
||||||
|
True,
|
||||||
|
priority=GLib.PRIORITY_DEFAULT,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.label_notify_revealer.set_text("Refreshing community kernels")
|
||||||
|
GLib.idle_add(
|
||||||
|
self.reveal_notify,
|
||||||
|
priority=GLib.PRIORITY_DEFAULT,
|
||||||
|
)
|
||||||
|
|
||||||
|
GLib.idle_add(
|
||||||
|
self.kernel_stack.add_community_kernels_to_stack,
|
||||||
|
True,
|
||||||
|
priority=GLib.PRIORITY_DEFAULT,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.label_notify_revealer.set_text("Refreshing installed kernels")
|
||||||
|
GLib.idle_add(
|
||||||
|
self.reveal_notify,
|
||||||
|
priority=GLib.PRIORITY_DEFAULT,
|
||||||
|
)
|
||||||
|
|
||||||
|
GLib.idle_add(
|
||||||
|
self.kernel_stack.add_installed_kernels_to_stack,
|
||||||
|
True,
|
||||||
|
priority=GLib.PRIORITY_DEFAULT,
|
||||||
|
)
|
||||||
|
|
||||||
|
while self.default_context.pending():
|
||||||
|
if fn.logger.getEffectiveLevel() == 10:
|
||||||
|
fn.logger.debug("Waiting for UI loop")
|
||||||
|
fn.time.sleep(0.3)
|
||||||
|
self.default_context.iteration(False)
|
||||||
|
|
||||||
|
# fn.time.sleep(0.5)
|
||||||
|
if fn.logger.getEffectiveLevel() == 10:
|
||||||
|
fn.logger.debug("Refresh UI completed")
|
||||||
|
|
||||||
|
self.label_notify_revealer.set_text("Refreshing UI completed")
|
||||||
|
GLib.idle_add(
|
||||||
|
self.reveal_notify,
|
||||||
|
priority=GLib.PRIORITY_DEFAULT,
|
||||||
|
)
|
||||||
|
|
||||||
|
def on_quit(self, action, param):
|
||||||
|
self.destroy()
|
||||||
|
fn.logger.info("Application quit")
|
||||||
|
|
||||||
|
def on_button_quit_response(self, widget):
|
||||||
|
self.destroy()
|
||||||
|
fn.logger.info("Application quit")
|
||||||
|
|
||||||
|
def load_kernels_gui(self):
|
||||||
|
self.queue_load_progress.put(0)
|
||||||
|
hbox_sep = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
|
||||||
|
hsep = Gtk.Separator(orientation=Gtk.Orientation.VERTICAL)
|
||||||
|
hbox_sep.append(hsep)
|
||||||
|
|
||||||
|
# handle error here with message
|
||||||
|
if self.official_kernels is None:
|
||||||
|
fn.logger.error("Failed to retrieve kernel list")
|
||||||
|
self.queue_load_progress.put(1)
|
||||||
|
|
||||||
|
stack_sidebar = Gtk.StackSidebar()
|
||||||
|
stack_sidebar.set_name("stack_sidebar")
|
||||||
|
stack_sidebar.set_stack(self.stack)
|
||||||
|
|
||||||
|
hbox_stack_sidebar = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
|
||||||
|
hbox_stack_sidebar.set_name("hbox_stack_sidebar")
|
||||||
|
hbox_stack_sidebar.append(stack_sidebar)
|
||||||
|
hbox_stack_sidebar.append(self.stack)
|
||||||
|
|
||||||
|
self.vbox.append(hbox_stack_sidebar)
|
||||||
|
|
||||||
|
button_quit = Gtk.Button.new_with_label("Quit")
|
||||||
|
# button_quit.set_size_request(100, 30)
|
||||||
|
button_quit.connect(
|
||||||
|
"clicked",
|
||||||
|
self.on_button_quit_response,
|
||||||
|
)
|
||||||
|
|
||||||
|
btn_context = button_quit.get_style_context()
|
||||||
|
btn_context.add_class("destructive-action")
|
||||||
|
|
||||||
|
grid_bottom_panel = Gtk.Grid()
|
||||||
|
grid_bottom_panel.set_halign(Gtk.Align.END)
|
||||||
|
grid_bottom_panel.set_row_homogeneous(True)
|
||||||
|
|
||||||
|
grid_bottom_panel.attach(button_quit, 0, 1, 1, 1)
|
||||||
|
|
||||||
|
self.vbox.append(grid_bottom_panel)
|
||||||
|
|
||||||
|
self.textbuffer = Gtk.TextBuffer()
|
||||||
|
|
||||||
|
self.textview = Gtk.TextView()
|
||||||
|
self.textview.set_property("editable", False)
|
||||||
|
self.textview.set_property("monospace", True)
|
||||||
|
|
||||||
|
self.textview.set_vexpand(True)
|
||||||
|
self.textview.set_hexpand(True)
|
||||||
|
|
||||||
|
self.textview.set_buffer(self.textbuffer)
|
||||||
|
|
||||||
|
fn.logger.info("Creating kernel UI")
|
||||||
|
|
||||||
|
# add official kernel flowbox
|
||||||
|
if fn.logger.getEffectiveLevel() == 10:
|
||||||
|
fn.logger.debug("Adding official kernels to UI")
|
||||||
|
|
||||||
|
self.queue_load_progress.put(0)
|
||||||
|
|
||||||
|
self.kernel_stack.add_official_kernels_to_stack(reload=False)
|
||||||
|
|
||||||
|
# fn.logger.debug("Adding community kernels to UI")
|
||||||
|
# self.kernel_stack.add_community_kernels_to_stack(reload=False)
|
||||||
|
|
||||||
|
fn.logger.info("Starting pacman db synchronization")
|
||||||
|
|
||||||
|
if self.pacman_db_sync() is False:
|
||||||
|
fn.logger.error("Pacman DB synchronization failed")
|
||||||
|
|
||||||
|
else:
|
||||||
|
if fn.logger.getEffectiveLevel() == 10:
|
||||||
|
fn.logger.debug("Adding community kernels to UI")
|
||||||
|
|
||||||
|
try:
|
||||||
|
thread_get_community_kernels = fn.Thread(
|
||||||
|
name=fn.thread_get_community_kernels,
|
||||||
|
target=fn.get_community_kernels,
|
||||||
|
daemon=True,
|
||||||
|
args=(self,),
|
||||||
|
)
|
||||||
|
|
||||||
|
thread_get_community_kernels.start()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
fn.logger.error("Exception in thread_get_community_kernels: %s" % e)
|
||||||
|
finally:
|
||||||
|
self.community_kernels = self.queue_community_kernels.get()
|
||||||
|
self.queue_community_kernels.task_done()
|
||||||
|
|
||||||
|
self.kernel_stack.add_community_kernels_to_stack(reload=False)
|
||||||
|
|
||||||
|
if fn.logger.getEffectiveLevel() == 10:
|
||||||
|
fn.logger.debug("Sending signal to destroy splashscreen")
|
||||||
|
|
||||||
|
# signal to destroy splash screen
|
||||||
|
self.queue_load_progress.put(1)
|
||||||
|
|
||||||
|
if fn.logger.getEffectiveLevel() == 10:
|
||||||
|
fn.logger.debug("Adding installed kernels to UI")
|
||||||
|
|
||||||
|
self.kernel_stack.add_installed_kernels_to_stack(reload=False)
|
||||||
|
|
||||||
|
fn.logger.info("Application started")
|
||||||
|
|
||||||
|
# while self.default_context.pending():
|
||||||
|
# if fn.logger.getEffectiveLevel() == 10:
|
||||||
|
# fn.logger.debug("Waiting for UI loop")
|
||||||
|
# self.default_context.iteration(False)
|
||||||
|
# fn.time.sleep(0.3)
|
45
ui/MenuButton.py
Normal file
45
ui/MenuButton.py
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import gi
|
||||||
|
|
||||||
|
gi.require_version("Gtk", "4.0")
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
# Gtk.Builder xml for the application menu
|
||||||
|
APP_MENU = """
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<menu id='app-menu'>
|
||||||
|
<section>
|
||||||
|
<item>
|
||||||
|
<attribute name='label' translatable='yes'>_About</attribute>
|
||||||
|
<attribute name='action'>win.about</attribute>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<attribute name='label' translatable='yes'>_Settings</attribute>
|
||||||
|
<attribute name='action'>win.settings</attribute>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<attribute name='label' translatable='yes'>_Refresh</attribute>
|
||||||
|
<attribute name='action'>win.refresh</attribute>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<attribute name='label' translatable='yes'>_Quit</attribute>
|
||||||
|
<attribute name='action'>win.quit</attribute>
|
||||||
|
</item>
|
||||||
|
</section>
|
||||||
|
</menu>
|
||||||
|
</interface>
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class MenuButton(Gtk.MenuButton):
|
||||||
|
"""
|
||||||
|
Wrapper class for at Gtk.Menubutton with a menu defined
|
||||||
|
in a Gtk.Builder xml string
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, icon_name="open-menu-symbolic"):
|
||||||
|
super(MenuButton, self).__init__()
|
||||||
|
builder = Gtk.Builder.new_from_string(APP_MENU, -1)
|
||||||
|
menu = builder.get_object("app-menu")
|
||||||
|
self.set_menu_model(menu)
|
||||||
|
self.set_icon_name(icon_name)
|
87
ui/MessageWindow.py
Normal file
87
ui/MessageWindow.py
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
import gi
|
||||||
|
import os
|
||||||
|
import libs.functions as fn
|
||||||
|
|
||||||
|
gi.require_version("Gtk", "4.0")
|
||||||
|
from gi.repository import Gtk, Gio, GLib
|
||||||
|
|
||||||
|
base_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
||||||
|
|
||||||
|
|
||||||
|
class MessageWindow(Gtk.Window):
|
||||||
|
def __init__(self, title, message, detailed_message, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
self.set_title(title=title)
|
||||||
|
self.set_modal(modal=True)
|
||||||
|
self.set_resizable(False)
|
||||||
|
icon_name = "akm-tux"
|
||||||
|
self.set_icon_name(icon_name)
|
||||||
|
|
||||||
|
header_bar = Gtk.HeaderBar()
|
||||||
|
header_bar.set_show_title_buttons(True)
|
||||||
|
|
||||||
|
hbox_title = Gtk.Box.new(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
|
||||||
|
|
||||||
|
label_title = Gtk.Label(xalign=0.5, yalign=0.5)
|
||||||
|
label_title.set_markup("<b>%s</b>" % title)
|
||||||
|
|
||||||
|
hbox_title.append(label_title)
|
||||||
|
header_bar.set_title_widget(hbox_title)
|
||||||
|
|
||||||
|
self.set_titlebar(header_bar)
|
||||||
|
|
||||||
|
vbox_message = Gtk.Box.new(orientation=Gtk.Orientation.VERTICAL, spacing=10)
|
||||||
|
vbox_message.set_name("vbox_flowbox_message")
|
||||||
|
|
||||||
|
hbox_message = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5)
|
||||||
|
|
||||||
|
self.set_child(child=vbox_message)
|
||||||
|
|
||||||
|
if detailed_message is True:
|
||||||
|
scrolled_window = Gtk.ScrolledWindow()
|
||||||
|
|
||||||
|
textview = Gtk.TextView()
|
||||||
|
textview.set_property("editable", False)
|
||||||
|
textview.set_property("monospace", True)
|
||||||
|
|
||||||
|
textview.set_vexpand(True)
|
||||||
|
textview.set_hexpand(True)
|
||||||
|
|
||||||
|
msg_buffer = textview.get_buffer()
|
||||||
|
msg_buffer.insert(
|
||||||
|
msg_buffer.get_end_iter(),
|
||||||
|
"Event timestamp = %s\n"
|
||||||
|
% fn.datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||||
|
)
|
||||||
|
msg_buffer.insert(msg_buffer.get_end_iter(), "%s\n" % message)
|
||||||
|
|
||||||
|
scrolled_window.set_child(textview)
|
||||||
|
|
||||||
|
hbox_message.append(scrolled_window)
|
||||||
|
|
||||||
|
self.set_size_request(700, 500)
|
||||||
|
self.set_resizable(True)
|
||||||
|
else:
|
||||||
|
label_message = Gtk.Label(xalign=0.5, yalign=0.5)
|
||||||
|
label_message.set_markup("%s" % message)
|
||||||
|
label_message.set_name("label_flowbox_message")
|
||||||
|
|
||||||
|
hbox_message.append(label_message)
|
||||||
|
|
||||||
|
vbox_message.append(hbox_message)
|
||||||
|
|
||||||
|
button_ok = Gtk.Button.new_with_label("OK")
|
||||||
|
button_ok.set_size_request(100, 30)
|
||||||
|
button_ok.set_halign(Gtk.Align.END)
|
||||||
|
button_ok.connect("clicked", self.on_button_ok_clicked)
|
||||||
|
|
||||||
|
hbox_buttons = Gtk.Box.new(orientation=Gtk.Orientation.HORIZONTAL, spacing=50)
|
||||||
|
hbox_buttons.set_halign(Gtk.Align.END)
|
||||||
|
hbox_buttons.append(button_ok)
|
||||||
|
|
||||||
|
vbox_message.append(hbox_buttons)
|
||||||
|
|
||||||
|
def on_button_ok_clicked(self, button):
|
||||||
|
self.hide()
|
||||||
|
self.destroy()
|
703
ui/SettingsWindow.py
Normal file
703
ui/SettingsWindow.py
Normal file
@@ -0,0 +1,703 @@
|
|||||||
|
import gi
|
||||||
|
import os
|
||||||
|
from ui.Stack import Stack
|
||||||
|
from ui.MessageWindow import MessageWindow
|
||||||
|
import libs.functions as fn
|
||||||
|
from gi.repository import Gtk, Gio, GLib, GObject
|
||||||
|
|
||||||
|
base_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
||||||
|
|
||||||
|
|
||||||
|
class SettingsWindow(Gtk.Window):
|
||||||
|
def __init__(self, fn, manager_gui, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
self.set_title("Arch Linux Kernel Manager - Settings")
|
||||||
|
self.set_resizable(False)
|
||||||
|
self.set_size_request(600, 600)
|
||||||
|
stack = Stack(transition_type="CROSSFADE")
|
||||||
|
|
||||||
|
self.set_icon_name("akm-tux")
|
||||||
|
self.manager_gui = manager_gui
|
||||||
|
self.set_modal(True)
|
||||||
|
self.set_transient_for(self.manager_gui)
|
||||||
|
|
||||||
|
self.queue_kernels = self.manager_gui.queue_kernels
|
||||||
|
|
||||||
|
header_bar = Gtk.HeaderBar()
|
||||||
|
|
||||||
|
header_bar.set_show_title_buttons(True)
|
||||||
|
|
||||||
|
self.set_titlebar(header_bar)
|
||||||
|
|
||||||
|
hbox_main = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
|
||||||
|
hbox_main.set_name("box")
|
||||||
|
self.set_child(child=hbox_main)
|
||||||
|
|
||||||
|
vbox_header = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
|
||||||
|
vbox_header.set_name("vbox_header")
|
||||||
|
|
||||||
|
lbl_heading = Gtk.Label(xalign=0.5, yalign=0.5)
|
||||||
|
lbl_heading.set_name("label_flowbox_message")
|
||||||
|
lbl_heading.set_text("Preferences")
|
||||||
|
|
||||||
|
lbl_padding = Gtk.Label(xalign=0.0, yalign=0.0)
|
||||||
|
lbl_padding.set_text(" ")
|
||||||
|
|
||||||
|
grid_banner_img = Gtk.Grid()
|
||||||
|
|
||||||
|
image_settings = Gtk.Image.new_from_file(
|
||||||
|
os.path.join(base_dir, "images/48x48/akm-settings.png")
|
||||||
|
)
|
||||||
|
|
||||||
|
image_settings.set_icon_size(Gtk.IconSize.LARGE)
|
||||||
|
image_settings.set_halign(Gtk.Align.START)
|
||||||
|
|
||||||
|
grid_banner_img.attach(image_settings, 0, 1, 1, 1)
|
||||||
|
grid_banner_img.attach_next_to(
|
||||||
|
lbl_padding,
|
||||||
|
image_settings,
|
||||||
|
Gtk.PositionType.RIGHT,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
|
||||||
|
grid_banner_img.attach_next_to(
|
||||||
|
lbl_heading,
|
||||||
|
lbl_padding,
|
||||||
|
Gtk.PositionType.RIGHT,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
|
||||||
|
vbox_header.append(grid_banner_img)
|
||||||
|
|
||||||
|
hbox_main.append(vbox_header)
|
||||||
|
|
||||||
|
stack_switcher = Gtk.StackSwitcher()
|
||||||
|
stack_switcher.set_orientation(Gtk.Orientation.HORIZONTAL)
|
||||||
|
stack_switcher.set_stack(stack)
|
||||||
|
|
||||||
|
button_close = Gtk.Button(label="Close")
|
||||||
|
button_close.connect("clicked", self.on_close_clicked)
|
||||||
|
|
||||||
|
hbox_stack_sidebar = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
|
||||||
|
hbox_stack_sidebar.set_name("box")
|
||||||
|
|
||||||
|
hbox_stack_sidebar.append(stack_switcher)
|
||||||
|
hbox_stack_sidebar.append(stack)
|
||||||
|
|
||||||
|
hbox_main.append(hbox_stack_sidebar)
|
||||||
|
|
||||||
|
vbox_button = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
|
||||||
|
vbox_button.set_halign(Gtk.Align.END)
|
||||||
|
vbox_button.set_name("box")
|
||||||
|
|
||||||
|
vbox_button.append(button_close)
|
||||||
|
|
||||||
|
hbox_stack_sidebar.append(vbox_button)
|
||||||
|
|
||||||
|
vbox_settings = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
|
||||||
|
vbox_settings.set_name("box")
|
||||||
|
|
||||||
|
label_official_kernels = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_official_kernels.set_markup(
|
||||||
|
"<b>Latest Official kernels (%s)</b>" % len(fn.supported_kernels_dict)
|
||||||
|
)
|
||||||
|
|
||||||
|
label_community_kernels = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_community_kernels.set_markup(
|
||||||
|
"<b>Latest Community based kernels (%s)</b>"
|
||||||
|
% len(self.manager_gui.community_kernels)
|
||||||
|
)
|
||||||
|
|
||||||
|
vbox_settings_listbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
|
||||||
|
|
||||||
|
self.listbox_official_kernels = Gtk.ListBox()
|
||||||
|
self.listbox_official_kernels.set_selection_mode(Gtk.SelectionMode.NONE)
|
||||||
|
|
||||||
|
self.label_loading_kernels = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
self.label_loading_kernels.set_text("Loading ...")
|
||||||
|
|
||||||
|
self.listbox_official_kernels.append(self.label_loading_kernels)
|
||||||
|
|
||||||
|
listbox_community_kernels = Gtk.ListBox()
|
||||||
|
listbox_community_kernels.set_selection_mode(Gtk.SelectionMode.NONE)
|
||||||
|
|
||||||
|
scrolled_window_community = Gtk.ScrolledWindow()
|
||||||
|
scrolled_window_official = Gtk.ScrolledWindow()
|
||||||
|
|
||||||
|
scrolled_window_community.set_policy(
|
||||||
|
Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC
|
||||||
|
)
|
||||||
|
|
||||||
|
scrolled_window_official.set_policy(
|
||||||
|
Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC
|
||||||
|
)
|
||||||
|
|
||||||
|
scrolled_window_community.set_size_request(0, 150)
|
||||||
|
scrolled_window_official.set_size_request(0, 150)
|
||||||
|
|
||||||
|
scrolled_window_official.set_child(self.listbox_official_kernels)
|
||||||
|
vbox_community_warning = None
|
||||||
|
|
||||||
|
self.kernel_versions_queue = fn.Queue()
|
||||||
|
fn.Thread(
|
||||||
|
target=fn.get_latest_versions,
|
||||||
|
args=(self,),
|
||||||
|
daemon=True,
|
||||||
|
).start()
|
||||||
|
|
||||||
|
fn.Thread(target=self.check_official_version_queue, daemon=True).start()
|
||||||
|
|
||||||
|
if len(self.manager_gui.community_kernels) > 0:
|
||||||
|
for community_kernel in self.manager_gui.community_kernels:
|
||||||
|
row_community_kernel = Gtk.ListBoxRow()
|
||||||
|
hbox_community_kernel = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.VERTICAL, spacing=5
|
||||||
|
)
|
||||||
|
hbox_community_kernel.set_name("box_row")
|
||||||
|
|
||||||
|
hbox_row_official_kernel_row = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.HORIZONTAL, spacing=10
|
||||||
|
)
|
||||||
|
|
||||||
|
label_community_kernel = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_community_kernel.set_text("%s" % community_kernel.name)
|
||||||
|
|
||||||
|
label_community_kernel_version = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_community_kernel_version.set_text("%s" % community_kernel.version)
|
||||||
|
|
||||||
|
hbox_row_official_kernel_row.append(label_community_kernel)
|
||||||
|
hbox_row_official_kernel_row.append(label_community_kernel_version)
|
||||||
|
|
||||||
|
hbox_community_kernel.append(hbox_row_official_kernel_row)
|
||||||
|
|
||||||
|
row_community_kernel.set_child(hbox_community_kernel)
|
||||||
|
listbox_community_kernels.append(row_community_kernel)
|
||||||
|
scrolled_window_community.set_child(listbox_community_kernels)
|
||||||
|
else:
|
||||||
|
vbox_community_warning = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.VERTICAL, spacing=10
|
||||||
|
)
|
||||||
|
image_warning = Gtk.Image.new_from_file(
|
||||||
|
os.path.join(base_dir, "images/48x48/akm-warning.png")
|
||||||
|
)
|
||||||
|
|
||||||
|
image_warning.set_icon_size(Gtk.IconSize.LARGE)
|
||||||
|
image_warning.set_halign(Gtk.Align.START)
|
||||||
|
|
||||||
|
hbox_warning = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5)
|
||||||
|
hbox_warning.set_name("hbox_warning")
|
||||||
|
|
||||||
|
hbox_warning.append(image_warning)
|
||||||
|
|
||||||
|
label_pacman_no_community = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_pacman_no_community.set_name("label_community_warning")
|
||||||
|
label_pacman_no_community.set_markup(
|
||||||
|
f"<b>Cannot find any supported unofficial pacman repository's</b>\n"
|
||||||
|
f"<b>Add the Chaotic-AUR pacman repository to access Community based kernels</b>"
|
||||||
|
)
|
||||||
|
|
||||||
|
hbox_warning.append(label_pacman_no_community)
|
||||||
|
|
||||||
|
vbox_community_warning.append(hbox_warning)
|
||||||
|
|
||||||
|
vbox_settings_listbox.append(label_official_kernels)
|
||||||
|
vbox_settings_listbox.append(scrolled_window_official)
|
||||||
|
vbox_settings_listbox.append(label_community_kernels)
|
||||||
|
|
||||||
|
if len(self.manager_gui.community_kernels) > 0:
|
||||||
|
vbox_settings_listbox.append(scrolled_window_community)
|
||||||
|
else:
|
||||||
|
vbox_settings_listbox.append(vbox_community_warning)
|
||||||
|
|
||||||
|
vbox_settings.append(vbox_settings_listbox)
|
||||||
|
|
||||||
|
vbox_settings_adv = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
|
||||||
|
|
||||||
|
vbox_settings_adv.set_name("box")
|
||||||
|
|
||||||
|
self.listbox_settings_adv = Gtk.ListBox()
|
||||||
|
self.listbox_settings_adv.set_selection_mode(Gtk.SelectionMode.NONE)
|
||||||
|
|
||||||
|
row_settings_adv = Gtk.ListBoxRow()
|
||||||
|
self.listbox_settings_adv.append(row_settings_adv)
|
||||||
|
|
||||||
|
hbox_bootloader_row = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5)
|
||||||
|
hbox_bootloader_row.set_name("box_row")
|
||||||
|
hbox_bootloader_row.set_halign(Gtk.Align.START)
|
||||||
|
|
||||||
|
self.hbox_bootloader_grub_row = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.HORIZONTAL, spacing=5
|
||||||
|
)
|
||||||
|
self.hbox_bootloader_grub_row.set_name("box_row")
|
||||||
|
self.hbox_bootloader_grub_row.set_halign(Gtk.Align.START)
|
||||||
|
|
||||||
|
self.text_entry_bootloader_file = Gtk.Entry()
|
||||||
|
|
||||||
|
hbox_switch_row = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5)
|
||||||
|
hbox_switch_row.set_name("box_row")
|
||||||
|
hbox_switch_row.set_halign(Gtk.Align.START)
|
||||||
|
|
||||||
|
hbox_log_row = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5)
|
||||||
|
hbox_log_row.set_name("box_row")
|
||||||
|
hbox_log_row.set_halign(Gtk.Align.START)
|
||||||
|
|
||||||
|
label_bootloader = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_bootloader.set_markup("<b>Bootloader</b>")
|
||||||
|
|
||||||
|
hbox_warning = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5)
|
||||||
|
hbox_warning.set_name("hbox_warning")
|
||||||
|
|
||||||
|
label_bootloader_warning = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_bootloader_warning.set_markup(
|
||||||
|
f"Only change this setting if you know what you are doing\n"
|
||||||
|
f"The selected Grub/Systemd-boot bootloader entry will be updated\n"
|
||||||
|
f"<b>This may break your system</b>"
|
||||||
|
)
|
||||||
|
|
||||||
|
hbox_warning.append(label_bootloader_warning)
|
||||||
|
|
||||||
|
label_settings_bootloader_title = Gtk.Label(xalign=0.5, yalign=0.5)
|
||||||
|
label_settings_bootloader_title.set_markup("Current Bootloader")
|
||||||
|
|
||||||
|
self.label_settings_bootloader_file = Gtk.Label(xalign=0.5, yalign=0.5)
|
||||||
|
self.label_settings_bootloader_file.set_text("GRUB config file")
|
||||||
|
|
||||||
|
self.button_override_bootloader = Gtk.Button(
|
||||||
|
label="Override bootloader settings"
|
||||||
|
)
|
||||||
|
self.button_override_bootloader.connect("clicked", self.on_override_clicked)
|
||||||
|
self.hbox_bootloader_override_row = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.HORIZONTAL, spacing=20
|
||||||
|
)
|
||||||
|
self.hbox_bootloader_override_row.set_name("box_row")
|
||||||
|
self.hbox_bootloader_override_row.append(self.button_override_bootloader)
|
||||||
|
|
||||||
|
boot_loaders = {0: "grub", 1: "systemd-boot"}
|
||||||
|
|
||||||
|
# Set up the factory
|
||||||
|
factory = Gtk.SignalListItemFactory()
|
||||||
|
factory.connect("setup", self._on_factory_setup)
|
||||||
|
factory.connect("bind", self._on_factory_bind)
|
||||||
|
|
||||||
|
self.model = Gio.ListStore(item_type=Bootloader)
|
||||||
|
for bootloader_id in boot_loaders.keys():
|
||||||
|
self.model.append(
|
||||||
|
Bootloader(
|
||||||
|
id=bootloader_id,
|
||||||
|
name=boot_loaders[bootloader_id],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.dropdown_bootloader = Gtk.DropDown(
|
||||||
|
model=self.model, factory=factory, hexpand=True
|
||||||
|
)
|
||||||
|
|
||||||
|
self.dropdown_bootloader.set_sensitive(False)
|
||||||
|
|
||||||
|
self.selected_bootloader = None
|
||||||
|
|
||||||
|
self._bootloader_grub_config = "/boot/grub/grub.cfg"
|
||||||
|
|
||||||
|
row_settings_override_grub = Gtk.ListBoxRow()
|
||||||
|
row_settings_grub = Gtk.ListBoxRow()
|
||||||
|
self.listbox_settings_adv.append(row_settings_grub)
|
||||||
|
|
||||||
|
self.listbox_settings_adv.append(row_settings_override_grub)
|
||||||
|
|
||||||
|
self.text_entry_bootloader_file.connect("changed", self.on_entry_changed)
|
||||||
|
self.text_entry_bootloader_file.props.editable = False
|
||||||
|
text_entry_buffer_file = Gtk.EntryBuffer()
|
||||||
|
|
||||||
|
if self.manager_gui.bootloader_grub_cfg is not None:
|
||||||
|
text_entry_buffer_file.set_text(
|
||||||
|
self.manager_gui.bootloader_grub_cfg,
|
||||||
|
len(self.manager_gui.bootloader_grub_cfg),
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
text_entry_buffer_file.set_text(
|
||||||
|
self._bootloader_grub_config,
|
||||||
|
len(self._bootloader_grub_config),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.text_entry_bootloader_file.set_buffer(text_entry_buffer_file)
|
||||||
|
self.text_entry_bootloader_file.set_halign(Gtk.Align.END)
|
||||||
|
self.text_entry_bootloader_file.set_sensitive(False)
|
||||||
|
|
||||||
|
label_grub_file_path = Gtk.Label(xalign=0.5, yalign=0.5)
|
||||||
|
label_grub_file_path.set_markup("Grub file path")
|
||||||
|
|
||||||
|
self.hbox_bootloader_grub_row.append(label_grub_file_path)
|
||||||
|
self.hbox_bootloader_grub_row.append(self.text_entry_bootloader_file)
|
||||||
|
|
||||||
|
row_settings_grub.set_child(self.hbox_bootloader_grub_row)
|
||||||
|
|
||||||
|
if manager_gui.bootloader == "grub":
|
||||||
|
self.dropdown_bootloader.set_selected(0)
|
||||||
|
self.selected_bootloader = 0
|
||||||
|
self.hbox_bootloader_grub_row.set_visible(True)
|
||||||
|
|
||||||
|
row_settings_override_grub.set_child(self.hbox_bootloader_override_row)
|
||||||
|
|
||||||
|
if manager_gui.bootloader == "systemd-boot":
|
||||||
|
|
||||||
|
self.selected_bootloader = 1
|
||||||
|
|
||||||
|
self.dropdown_bootloader.set_selected(1)
|
||||||
|
row_settings_override_systemd = Gtk.ListBoxRow()
|
||||||
|
self.listbox_settings_adv.append(row_settings_override_systemd)
|
||||||
|
row_settings_override_systemd.set_child(self.hbox_bootloader_override_row)
|
||||||
|
|
||||||
|
self.hbox_bootloader_grub_row.set_visible(False)
|
||||||
|
|
||||||
|
self.dropdown_bootloader.connect(
|
||||||
|
"notify::selected-item", self._on_selected_item_notify
|
||||||
|
)
|
||||||
|
|
||||||
|
hbox_bootloader_row.append(label_settings_bootloader_title)
|
||||||
|
hbox_bootloader_row.append(self.dropdown_bootloader)
|
||||||
|
|
||||||
|
row_settings_adv.set_child(hbox_bootloader_row)
|
||||||
|
|
||||||
|
vbox_settings_adv.append(label_bootloader)
|
||||||
|
vbox_settings_adv.append(hbox_warning)
|
||||||
|
vbox_settings_adv.append(self.listbox_settings_adv)
|
||||||
|
|
||||||
|
listbox_settings_cache = Gtk.ListBox()
|
||||||
|
listbox_settings_cache.set_selection_mode(Gtk.SelectionMode.NONE)
|
||||||
|
|
||||||
|
row_settings_cache = Gtk.ListBoxRow()
|
||||||
|
listbox_settings_cache.append(row_settings_cache)
|
||||||
|
|
||||||
|
label_cache = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_cache.set_markup("<b>Refresh data from Arch Linux Archive</b>")
|
||||||
|
|
||||||
|
label_cache_update = Gtk.Label(xalign=0.5, yalign=0.5)
|
||||||
|
label_cache_update.set_text("Update (this will take some time)")
|
||||||
|
|
||||||
|
self.label_cache_update_status = Gtk.Label(xalign=0.5, yalign=0.5)
|
||||||
|
|
||||||
|
switch_refresh_cache = Gtk.Switch()
|
||||||
|
switch_refresh_cache.connect("state-set", self.refresh_toggle)
|
||||||
|
|
||||||
|
label_cache_file = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_cache_file.set_text(fn.cache_file)
|
||||||
|
label_cache_file.set_selectable(True)
|
||||||
|
|
||||||
|
self.label_cache_lastmodified = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
self.label_cache_lastmodified.set_markup(
|
||||||
|
"Last modified date: <b>%s</b>" % fn.get_cache_last_modified()
|
||||||
|
)
|
||||||
|
|
||||||
|
hbox_switch_row.append(label_cache_update)
|
||||||
|
hbox_switch_row.append(switch_refresh_cache)
|
||||||
|
hbox_switch_row.append(self.label_cache_update_status)
|
||||||
|
|
||||||
|
row_settings_cache.set_child(hbox_switch_row)
|
||||||
|
|
||||||
|
label_logfile = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_logfile.set_markup("<b>Log file</b>")
|
||||||
|
|
||||||
|
button_logfile = Gtk.Button(label="Open event log file")
|
||||||
|
button_logfile.connect("clicked", self.on_button_logfile_clicked)
|
||||||
|
|
||||||
|
label_logfile_location = Gtk.Label(xalign=0.5, yalign=0.5)
|
||||||
|
label_logfile_location.set_text(fn.event_log_file)
|
||||||
|
label_logfile_location.set_selectable(True)
|
||||||
|
hbox_log_row.append(button_logfile)
|
||||||
|
hbox_log_row.append(label_logfile_location)
|
||||||
|
|
||||||
|
listbox_settings_log = Gtk.ListBox()
|
||||||
|
listbox_settings_log.set_selection_mode(Gtk.SelectionMode.NONE)
|
||||||
|
|
||||||
|
row_settings_log = Gtk.ListBoxRow()
|
||||||
|
listbox_settings_log.append(row_settings_log)
|
||||||
|
|
||||||
|
row_settings_log.set_child(hbox_log_row)
|
||||||
|
|
||||||
|
vbox_settings_adv.append(label_cache)
|
||||||
|
vbox_settings_adv.append(self.label_cache_lastmodified)
|
||||||
|
vbox_settings_adv.append(label_cache_file)
|
||||||
|
vbox_settings_adv.append(listbox_settings_cache)
|
||||||
|
vbox_settings_adv.append(label_logfile)
|
||||||
|
vbox_settings_adv.append(listbox_settings_log)
|
||||||
|
|
||||||
|
stack.add_titled(vbox_settings_adv, "Advanced Settings", "Advanced")
|
||||||
|
stack.add_titled(vbox_settings, "Kernels", "Kernel versions")
|
||||||
|
|
||||||
|
def populate_official_kernels(self):
|
||||||
|
self.label_loading_kernels.hide()
|
||||||
|
for official_kernel in fn.supported_kernels_dict:
|
||||||
|
row_official_kernel = Gtk.ListBoxRow()
|
||||||
|
hbox_row_official = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
|
||||||
|
|
||||||
|
hbox_row_official_kernel_row = Gtk.Box(
|
||||||
|
orientation=Gtk.Orientation.HORIZONTAL, spacing=10
|
||||||
|
)
|
||||||
|
|
||||||
|
hbox_row_official.set_name("box_row")
|
||||||
|
|
||||||
|
label_kernel = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_kernel.set_text("%s" % official_kernel)
|
||||||
|
|
||||||
|
label_kernel_version = Gtk.Label(xalign=0, yalign=0)
|
||||||
|
label_kernel_version.set_text("%s" % self.kernel_versions[official_kernel])
|
||||||
|
|
||||||
|
hbox_row_official_kernel_row.append(label_kernel)
|
||||||
|
hbox_row_official_kernel_row.append(label_kernel_version)
|
||||||
|
|
||||||
|
hbox_row_official.append(hbox_row_official_kernel_row)
|
||||||
|
|
||||||
|
row_official_kernel.set_child(hbox_row_official)
|
||||||
|
|
||||||
|
self.listbox_official_kernels.append(row_official_kernel)
|
||||||
|
|
||||||
|
def check_official_version_queue(self):
|
||||||
|
while True:
|
||||||
|
self.kernel_versions = self.kernel_versions_queue.get()
|
||||||
|
|
||||||
|
if self.kernel_versions is not None and len(self.kernel_versions) > 0:
|
||||||
|
break
|
||||||
|
|
||||||
|
self.kernel_versions_queue.task_done()
|
||||||
|
|
||||||
|
GLib.idle_add(self.populate_official_kernels, priority=GLib.PRIORITY_DEFAULT)
|
||||||
|
|
||||||
|
def on_entry_changed(self, entry):
|
||||||
|
if (
|
||||||
|
len(entry.get_text()) > 0
|
||||||
|
and entry.get_text() != self.manager_gui.bootloader_grub_cfg
|
||||||
|
):
|
||||||
|
self.button_override_bootloader.get_child().set_text("Apply changes")
|
||||||
|
|
||||||
|
def _on_factory_setup(self, factory, list_item):
|
||||||
|
label = Gtk.Label()
|
||||||
|
list_item.set_child(label)
|
||||||
|
|
||||||
|
def _on_factory_bind(self, factory, list_item):
|
||||||
|
label = list_item.get_child()
|
||||||
|
bootloader = list_item.get_item()
|
||||||
|
label.set_text(bootloader.name)
|
||||||
|
|
||||||
|
def on_override_clicked(self, widget):
|
||||||
|
if self.button_override_bootloader.get_child().get_text() == "Apply changes":
|
||||||
|
# validate bootloader
|
||||||
|
if self.dropdown_bootloader.get_selected() == 1:
|
||||||
|
if not os.path.exists(
|
||||||
|
"/sys/firmware/efi/fw_platform_size"
|
||||||
|
) or not os.path.exists("/sys/firmware/efi/efivars"):
|
||||||
|
mw = MessageWindow(
|
||||||
|
title="Legacy boot detected",
|
||||||
|
message="Cannot select systemd-boot, UEFI boot mode is not available",
|
||||||
|
transient_for=self,
|
||||||
|
detailed_message=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
mw.present()
|
||||||
|
self.dropdown_bootloader.set_selected(0)
|
||||||
|
return
|
||||||
|
|
||||||
|
config_data = fn.read_config(self)
|
||||||
|
|
||||||
|
if config_data is not None:
|
||||||
|
# grub
|
||||||
|
|
||||||
|
if (
|
||||||
|
self.dropdown_bootloader.get_selected() == 0
|
||||||
|
and len(
|
||||||
|
self.text_entry_bootloader_file.get_buffer().get_text().strip()
|
||||||
|
)
|
||||||
|
> 0
|
||||||
|
):
|
||||||
|
if fn.os.path.exists(
|
||||||
|
self.text_entry_bootloader_file.get_buffer().get_text().strip()
|
||||||
|
):
|
||||||
|
if "bootloader" in config_data.keys():
|
||||||
|
config_data.remove("bootloader")
|
||||||
|
|
||||||
|
bootloader = fn.tomlkit.table(True)
|
||||||
|
bootloader.update({"name": "grub"})
|
||||||
|
bootloader.update(
|
||||||
|
{
|
||||||
|
"grub_config": self.text_entry_bootloader_file.get_buffer()
|
||||||
|
.get_text()
|
||||||
|
.strip()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
config_data.append("bootloader", bootloader)
|
||||||
|
|
||||||
|
if fn.update_config(config_data, "grub") is True:
|
||||||
|
self.manager_gui.bootloader = "grub"
|
||||||
|
self.manager_gui.bootloader_grub_cfg = (
|
||||||
|
self.text_entry_bootloader_file.get_buffer()
|
||||||
|
.get_text()
|
||||||
|
.strip()
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
mw = MessageWindow(
|
||||||
|
title="Grub config file",
|
||||||
|
message="The specified Grub config file %s does not exist"
|
||||||
|
% self.text_entry_bootloader_file.get_buffer()
|
||||||
|
.get_text()
|
||||||
|
.strip(),
|
||||||
|
transient_for=self,
|
||||||
|
detailed_message=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
mw.present()
|
||||||
|
self.button_override_bootloader.get_child().set_text(
|
||||||
|
"Override bootloader settings"
|
||||||
|
)
|
||||||
|
|
||||||
|
elif (
|
||||||
|
self.dropdown_bootloader.get_selected() == 1
|
||||||
|
and self.selected_bootloader
|
||||||
|
!= self.dropdown_bootloader.get_selected()
|
||||||
|
):
|
||||||
|
if "bootloader" in config_data.keys():
|
||||||
|
config_data.remove("bootloader")
|
||||||
|
|
||||||
|
self.hbox_bootloader_grub_row.set_visible(True)
|
||||||
|
|
||||||
|
bootloader = fn.tomlkit.table(True)
|
||||||
|
bootloader.update({"name": "systemd-boot"})
|
||||||
|
|
||||||
|
config_data.append("bootloader", bootloader)
|
||||||
|
|
||||||
|
if fn.update_config(config_data, "systemd-boot") is True:
|
||||||
|
self.manager_gui.bootloader = "systemd-boot"
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.dropdown_bootloader.set_sensitive(True)
|
||||||
|
|
||||||
|
if self.dropdown_bootloader.get_selected() == 0:
|
||||||
|
self.hbox_bootloader_grub_row.set_visible(True)
|
||||||
|
self.text_entry_bootloader_file.set_sensitive(True)
|
||||||
|
self.text_entry_bootloader_file.props.editable = True
|
||||||
|
elif self.dropdown_bootloader.get_selected() == 1:
|
||||||
|
self.hbox_bootloader_grub_row.set_visible(False)
|
||||||
|
|
||||||
|
def _on_selected_item_notify(self, dd, _):
|
||||||
|
if self.dropdown_bootloader.get_selected() != self.selected_bootloader:
|
||||||
|
self.button_override_bootloader.get_child().set_text("Apply changes")
|
||||||
|
else:
|
||||||
|
self.button_override_bootloader.get_child().set_text(
|
||||||
|
"Override bootloader settings"
|
||||||
|
)
|
||||||
|
if dd.get_selected() == 1:
|
||||||
|
if self.text_entry_bootloader_file is not None:
|
||||||
|
self.hbox_bootloader_grub_row.set_visible(False)
|
||||||
|
elif dd.get_selected() == 0:
|
||||||
|
if self.text_entry_bootloader_file is not None:
|
||||||
|
self.hbox_bootloader_grub_row.set_visible(True)
|
||||||
|
self.text_entry_bootloader_file.set_sensitive(True)
|
||||||
|
self.text_entry_bootloader_file.props.editable = True
|
||||||
|
|
||||||
|
def monitor_kernels_queue(self, switch):
|
||||||
|
while True:
|
||||||
|
if len(fn.fetched_kernels_dict) > 0:
|
||||||
|
self.manager_gui.official_kernels = self.queue_kernels.get()
|
||||||
|
|
||||||
|
self.queue_kernels.task_done()
|
||||||
|
self.refreshed = True
|
||||||
|
if self.manager_gui.official_kernels is not None:
|
||||||
|
switch.set_sensitive(False)
|
||||||
|
|
||||||
|
self.update_official_list()
|
||||||
|
self.update_timestamp()
|
||||||
|
self.label_cache_update_status.set_markup(
|
||||||
|
"<b>Cache refresh completed</b>"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.label_cache_update_status.set_markup(
|
||||||
|
"<b>Cache refresh failed</b>"
|
||||||
|
)
|
||||||
|
self.refreshed = False
|
||||||
|
self.update_timestamp()
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
self.label_cache_update_status.set_markup(
|
||||||
|
"<b>Cache refresh in progress</b>"
|
||||||
|
)
|
||||||
|
# fn.time.sleep(0.3)
|
||||||
|
|
||||||
|
def refresh_toggle(self, switch, data):
|
||||||
|
if switch.get_active() is True:
|
||||||
|
# refresh cache
|
||||||
|
fn.logger.info("Refreshing cache file %s" % fn.cache_file)
|
||||||
|
switch.set_sensitive(False)
|
||||||
|
|
||||||
|
try:
|
||||||
|
th_refresh_cache = fn.Thread(
|
||||||
|
name=fn.thread_refresh_cache,
|
||||||
|
target=fn.refresh_cache,
|
||||||
|
args=(self,),
|
||||||
|
daemon=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
th_refresh_cache.start()
|
||||||
|
|
||||||
|
# monitor queue
|
||||||
|
fn.Thread(
|
||||||
|
target=self.monitor_kernels_queue, daemon=True, args=(switch,)
|
||||||
|
).start()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
fn.logger.error("Exception in refresh_toggle(): %s" % e)
|
||||||
|
self.label_cache_update_status.set_markup("<b>Cache refresh failed</b>")
|
||||||
|
|
||||||
|
def update_timestamp(self):
|
||||||
|
if self.refreshed is True:
|
||||||
|
self.label_cache_lastmodified.set_markup(
|
||||||
|
"Last modified date: <span foreground='orange'><b>%s</b></span>"
|
||||||
|
% fn.get_cache_last_modified()
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.label_cache_lastmodified.set_markup(
|
||||||
|
"Last modified date: <span foreground='orange'><b>%s</b></span>"
|
||||||
|
% "Refresh failed"
|
||||||
|
)
|
||||||
|
|
||||||
|
def update_official_list(self):
|
||||||
|
self.manager_gui.installed_kernels = fn.get_installed_kernels()
|
||||||
|
GLib.idle_add(
|
||||||
|
self.manager_gui.kernel_stack.add_official_kernels_to_stack,
|
||||||
|
True,
|
||||||
|
)
|
||||||
|
|
||||||
|
def on_close_clicked(self, widget):
|
||||||
|
self.destroy()
|
||||||
|
|
||||||
|
def on_button_logfile_clicked(self, widget):
|
||||||
|
try:
|
||||||
|
cmd = ["sudo", "-u", fn.sudo_username, "xdg-open", fn.event_log_file]
|
||||||
|
fn.subprocess.Popen(
|
||||||
|
cmd,
|
||||||
|
shell=False,
|
||||||
|
stdout=fn.subprocess.PIPE,
|
||||||
|
stderr=fn.subprocess.STDOUT,
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
fn.logger.error("Exception in on_button_logfile_clicked(): %s" % e)
|
||||||
|
|
||||||
|
|
||||||
|
class Bootloader(GObject.Object):
|
||||||
|
__gtype_name__ = "Bootloader"
|
||||||
|
|
||||||
|
def __init__(self, id, name):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.id = id
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
@GObject.Property
|
||||||
|
def bootloader_id(self):
|
||||||
|
return self.id
|
||||||
|
|
||||||
|
@GObject.Property
|
||||||
|
def bootloader_name(self):
|
||||||
|
return self.name
|
30
ui/SplashScreen.py
Normal file
30
ui/SplashScreen.py
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import gi
|
||||||
|
import libs.functions as fn
|
||||||
|
|
||||||
|
gi.require_version("Gtk", "4.0")
|
||||||
|
from gi.repository import Gtk, Gio
|
||||||
|
|
||||||
|
base_dir = fn.os.path.abspath(fn.os.path.join(fn.os.path.dirname(__file__), ".."))
|
||||||
|
|
||||||
|
|
||||||
|
class SplashScreen(Gtk.Window):
|
||||||
|
def __init__(self, app_name, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
self.set_decorated(False)
|
||||||
|
self.set_resizable(False)
|
||||||
|
self.set_default_size(600, 400)
|
||||||
|
|
||||||
|
self.set_modal(True)
|
||||||
|
self.set_title(app_name)
|
||||||
|
self.set_icon_name("archlinux-kernel-manager-tux")
|
||||||
|
|
||||||
|
tux_icon = Gtk.Picture.new_for_file(
|
||||||
|
file=Gio.File.new_for_path(
|
||||||
|
fn.os.path.join(base_dir, "images/600x400/akm-tux-splash.png")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
tux_icon.set_content_fit(content_fit=Gtk.ContentFit.FILL)
|
||||||
|
|
||||||
|
self.set_child(child=tux_icon)
|
||||||
|
self.present()
|
30
ui/Stack.py
Normal file
30
ui/Stack.py
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import gi
|
||||||
|
|
||||||
|
gi.require_version("Gtk", "4.0")
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
|
||||||
|
class Stack(Gtk.Stack):
|
||||||
|
def __init__(self, transition_type):
|
||||||
|
super(Stack, self).__init__()
|
||||||
|
|
||||||
|
# self.set_transition_type(Gtk.StackTransitionType.ROTATE_LEFT)
|
||||||
|
if transition_type == "ROTATE_LEFT":
|
||||||
|
transition_type = Gtk.StackTransitionType.ROTATE_LEFT
|
||||||
|
if transition_type == "ROTATE_RIGHT":
|
||||||
|
transition_type = Gtk.StackTransitionType.ROTATE_RIGHT
|
||||||
|
if transition_type == "CROSSFADE":
|
||||||
|
transition_type = Gtk.StackTransitionType.CROSSFADE
|
||||||
|
if transition_type == "SLIDE_UP":
|
||||||
|
transition_type = Gtk.StackTransitionType.SLIDE_UP
|
||||||
|
if transition_type == "SLIDE_DOWN":
|
||||||
|
transition_type = Gtk.StackTransitionType.SLIDE_DOWN
|
||||||
|
if transition_type == "OVER_DOWN":
|
||||||
|
transition_type = Gtk.StackTransitionType.OVER_DOWN
|
||||||
|
|
||||||
|
self.set_transition_type(transition_type)
|
||||||
|
self.set_hexpand(True)
|
||||||
|
self.set_vexpand(True)
|
||||||
|
self.set_transition_duration(250)
|
||||||
|
self.set_hhomogeneous(False)
|
||||||
|
self.set_vhomogeneous(False)
|
Reference in New Issue
Block a user