update
1
usr/bin/akm
Symbolic link
|
@ -0,0 +1 @@
|
|||
archlinux-kernel-manager
|
52
usr/bin/archlinux-kernel-manager
Executable file
|
@ -0,0 +1,52 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# this script should not be run as root
|
||||
# the polkit agent running on the desktop environment should prompt for root password
|
||||
|
||||
echo "---------------------------------------------------------------------------"
|
||||
echo "[INFO] Checking session"
|
||||
test $(whoami) == "root" && echo "[ERROR] Do not run this script as root." && exit 1
|
||||
test -z $DISPLAY && echo "[ERROR] DISPLAY variable is not set." && exit 1
|
||||
|
||||
# check session is either one of X11, Wayland or TTY
|
||||
session=$(loginctl show-session $(loginctl|grep $(whoami) | awk '{print $1}') -p Type | awk -F= '{print $2}' | grep "x11\|wayland\|tty")
|
||||
|
||||
test -z "$session" && echo "[ERROR] Failed to verify session for user." && exit 1
|
||||
|
||||
xauth_file=$(xauth info | awk -F"Authority file:" '{print $2}' | tr -d ' ')
|
||||
test -s "$xauth_file" || touch "$xauth_file"
|
||||
|
||||
case "$session" in
|
||||
"wayland")
|
||||
# Wayland session, generate Xauth session cookie for $DISPLAY
|
||||
xauth gen $DISPLAY &> /dev/null
|
||||
echo "[INFO] Display = $DISPLAY"
|
||||
echo "[INFO] Session = $session"
|
||||
|
||||
test -z "$(xauth list)" || echo "[INFO] Xauth session = OK"
|
||||
;;
|
||||
"x11")
|
||||
# X11 session, don't do anything here
|
||||
echo "[INFO] Display = $DISPLAY"
|
||||
echo "[INFO] Session = $session"
|
||||
|
||||
# just show msg on whether the Xauth session cookie is setup
|
||||
test -z "$(xauth list)" || echo "[INFO] Xauth session = OK"
|
||||
;;
|
||||
"tty")
|
||||
# TTY session, as user may not use a display manager
|
||||
echo "[INFO] Display = $DISPLAY"
|
||||
echo "[INFO] Session = $session"
|
||||
|
||||
test -z "$(xauth list)" || echo "[INFO] Xauth session = OK"
|
||||
;;
|
||||
*)
|
||||
# anything here is an unknown session, most likely AKM will fail to load
|
||||
echo "[WARN] Continuing, but cannot verify session for user."
|
||||
;;
|
||||
esac
|
||||
echo "---------------------------------------------------------------------------"
|
||||
|
||||
echo "[INFO] Starting Arch Linux Kernel Manager"
|
||||
pkexec '/usr/share/archlinux-kernel-manager/archlinux-kernel-manager.py'
|
||||
|
12
usr/share/applications/archlinux-kernel-manager.desktop
Normal file
|
@ -0,0 +1,12 @@
|
|||
[Desktop Entry]
|
||||
Name=Arch Linux Kernel Manager
|
||||
GenericName=Arch Linux Kernel Manager
|
||||
X-GNOME-FullName=Arch Linux Kernel Manager
|
||||
Comment=Arch Linux Kernel Manager - Add/Remove Linux kernels
|
||||
Exec=/usr/bin/archlinux-kernel-manager
|
||||
Icon=archlinux-kernel-manager-tux
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=GTK;GNOME;Utility;Settings;X-GNOME-Settings-Panel;X-GNOME-SystemSettings;X-Unity-Settings-Panel;X-XFCE-SettingsDialog;X-XFCE-SystemSettings;
|
||||
Keywords=kernel;tool;system
|
||||
StartupNotify=true
|
176
usr/share/archlinux-kernel-manager/akm.css
Normal file
|
@ -0,0 +1,176 @@
|
|||
box#box{
|
||||
padding: 5px 5px 5px 5px;
|
||||
}
|
||||
|
||||
box#main{
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
padding-bottom: 20px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
box#box_padding_left{
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
box#vbox_flowbox_message {
|
||||
padding: 10px 10px 10px 10px;
|
||||
}
|
||||
|
||||
box#vbox_active_kernel{
|
||||
padding: 5px 5px 5px 5px;
|
||||
}
|
||||
|
||||
box#hbox_notify_revealer{
|
||||
padding: 10px 10px 10px 10px;
|
||||
border-radius: 10px;
|
||||
border-spacing: 5px;
|
||||
background-color: #3fe1b0;
|
||||
color: #0e1313;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
box#box_row{
|
||||
padding-left: 20px;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
box#hbox_kernel{
|
||||
background-color: @theme_base_color;
|
||||
padding-bottom: 8px;
|
||||
box-shadow: -6px 8px 10px rgba(81,41,10,0.1),0px 2px 2px rgba(81,41,10,0.2);
|
||||
}
|
||||
|
||||
box#vbox_header{
|
||||
background-color: @theme_base_color;
|
||||
border-top: 1px solid @borders;
|
||||
border-bottom: 1px solid @borders;
|
||||
border-left: 1px solid @borders;
|
||||
border-right: 1px solid @borders;
|
||||
padding: 5px 5px 5px 5px;
|
||||
border-radius: 100px;
|
||||
border-spacing: 5px;
|
||||
font-weight: bold;
|
||||
font-family: 'Noto Sans', 'Helvetica', sans-serif;
|
||||
box-shadow: -6px 8px 10px rgba(81,41,10,0.1),0px 2px 2px rgba(81,41,10,0.2);
|
||||
}
|
||||
|
||||
box#hbox_warning{
|
||||
background-color: #4c8bf5;
|
||||
color: white;
|
||||
font-family: 'Noto Sans', 'Helvetica', sans-serif;
|
||||
padding: 5px 5px 5px 5px;
|
||||
}
|
||||
|
||||
label#label_notify_revealer{
|
||||
background-color: #3fe1b0;
|
||||
color: #0e1313;
|
||||
font-family: 'Noto Sans', 'Helvetica', sans-serif;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
label#label_active_kernel {
|
||||
font-family: 'Noto Sans', 'Helvetica', sans-serif;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
label#label_stack_kernel {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
border-top: 1px solid @borders;
|
||||
border-bottom: 1px solid @borders;
|
||||
border-left: 1px solid @borders;
|
||||
border-right: 1px solid @borders;
|
||||
padding: 5px 5px 5px 5px;
|
||||
border-radius: 100px;
|
||||
border-spacing: 5px;
|
||||
font-family: 'Noto Sans', 'Helvetica', sans-serif;
|
||||
color: #fcfcfc;
|
||||
background-color: @theme_base_color;
|
||||
}
|
||||
|
||||
label#label_stack_desc {
|
||||
font-size: 12.5px;
|
||||
font-weight: 600;
|
||||
padding: 5px 5px 5px 5px;
|
||||
font-style: italic;
|
||||
font-family: 'Noto Sans', 'Helvetica', sans-serif;
|
||||
}
|
||||
|
||||
label#label_community_warning {
|
||||
font-size: 12.5px;
|
||||
padding: 5px 5px 5px 5px;
|
||||
font-family: 'Noto Sans', 'Helvetica', sans-serif;
|
||||
}
|
||||
|
||||
label#label_error{
|
||||
font-size: 12.5px;
|
||||
font-weight: 600;
|
||||
padding: 5px 5px 5px 5px;
|
||||
color: #fcfcfc;
|
||||
background-color: #E42217;
|
||||
font-family: 'Noto Sans', 'Helvetica', sans-serif;
|
||||
border-top: 1px solid @borders;
|
||||
border-bottom: 1px solid @borders;
|
||||
border-left: 1px solid @borders;
|
||||
border-right: 1px solid @borders;
|
||||
padding: 5px 5px 5px 5px;
|
||||
border-radius: 10px;
|
||||
border-spacing: 5px;
|
||||
}
|
||||
|
||||
label#label_stack_count {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
padding: 5px 5px 5px 5px;
|
||||
font-style: italic;
|
||||
font-family: 'Noto Sans', 'Helvetica', sans-serif;
|
||||
}
|
||||
|
||||
label#label_kernel_version {
|
||||
padding: 5px 5px 5px 5px;
|
||||
font-size: 12px;
|
||||
font-family: 'Noto Sans', 'Helvetica', sans-serif;
|
||||
}
|
||||
|
||||
label#label_kernel_flowbox {
|
||||
padding: 5px 5px 5px 5px;
|
||||
font-size: 11px;
|
||||
font-family: 'Noto Sans', 'Helvetica', sans-serif;
|
||||
}
|
||||
|
||||
label#label_about {
|
||||
padding: 5px 5px 5px 5px;
|
||||
font-size: 11px;
|
||||
font-family: 'Noto Sans', 'Helvetica', sans-serif;
|
||||
}
|
||||
|
||||
button#button_uninstall_kernel{
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.sidebar label{
|
||||
font-size: 12.5px;
|
||||
font-weight: 500;
|
||||
padding: 10px 10px 10px 10px;
|
||||
}
|
||||
|
||||
.sidebar label:hover,
|
||||
.sidebar label:focus{
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#hbox_stack_sidebar{
|
||||
box-shadow: rgba(33, 35, 38, 0.1) 0px 10px 10px -10px;
|
||||
}
|
||||
|
||||
#textview_log text{
|
||||
background-color: #232627;
|
||||
color: #fcfcfc;
|
||||
font-family: 'Noto Sans', 'Helvetica', sans-serif;
|
||||
border-top: 1px solid @borders;
|
||||
border-bottom: 1px solid @borders;
|
||||
border-left: 1px solid @borders;
|
||||
border-right: 1px solid @borders;
|
||||
}
|
115
usr/share/archlinux-kernel-manager/archlinux-kernel-manager.py
Executable file
|
@ -0,0 +1,115 @@
|
|||
#!/usr/bin/env python3
|
||||
import os
|
||||
|
||||
import gi
|
||||
import signal
|
||||
import libs.functions as fn
|
||||
|
||||
from ui.ManagerGUI import ManagerGUI
|
||||
|
||||
gi.require_version("Gtk", "4.0")
|
||||
|
||||
from gi.repository import Gtk, Gio, GLib, Gdk
|
||||
|
||||
base_dir = fn.os.path.dirname(fn.os.path.realpath(__file__))
|
||||
|
||||
|
||||
app_name = "Arch Linux Kernel Manager"
|
||||
app_version = "${app_version}"
|
||||
app_name_dir = "archlinux-kernel-manager"
|
||||
app_id = "com.deltacopy.kernelmanager"
|
||||
lock_file = "/tmp/akm.lock"
|
||||
pid_file = "/tmp/akm.pid"
|
||||
|
||||
|
||||
class Main(Gtk.Application):
|
||||
def __init__(self):
|
||||
super().__init__(application_id=app_id, flags=Gio.ApplicationFlags.FLAGS_NONE)
|
||||
|
||||
def do_activate(self):
|
||||
default_context = GLib.MainContext.default()
|
||||
|
||||
win = self.props.active_window
|
||||
if not win:
|
||||
win = ManagerGUI(
|
||||
application=self,
|
||||
app_name=app_name,
|
||||
default_context=default_context,
|
||||
app_version=app_version,
|
||||
)
|
||||
|
||||
display = Gtk.Widget.get_display(win)
|
||||
|
||||
# sourced from /usr/share/icons/hicolor/scalable/apps
|
||||
win.set_icon_name("archlinux-kernel-manager-tux")
|
||||
|
||||
provider = Gtk.CssProvider.new()
|
||||
css_file = Gio.file_new_for_path(base_dir + "/akm.css")
|
||||
provider.load_from_file(css_file)
|
||||
Gtk.StyleContext.add_provider_for_display(
|
||||
display, provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
||||
)
|
||||
|
||||
win.present()
|
||||
|
||||
def do_startup(self):
|
||||
Gtk.Application.do_startup(self)
|
||||
|
||||
def do_shutdown(self):
|
||||
Gtk.Application.do_shutdown(self)
|
||||
if os.path.exists(lock_file):
|
||||
os.remove(lock_file)
|
||||
if os.path.exists(pid_file):
|
||||
os.remove(pid_file)
|
||||
|
||||
|
||||
def signal_handler(sig, frame):
|
||||
Gtk.main_quit(0)
|
||||
|
||||
|
||||
# These should be kept as it ensures that multiple installation instances can't be run concurrently.
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
# signal.signal(signal.SIGINT, signal_handler)
|
||||
|
||||
if not fn.os.path.isfile(lock_file):
|
||||
with open(pid_file, "w") as f:
|
||||
f.write(str(fn.os.getpid()))
|
||||
|
||||
# splash = SplashScreen()
|
||||
|
||||
app = Main()
|
||||
app.run(None)
|
||||
else:
|
||||
md = Gtk.MessageDialog(
|
||||
parent=Main(),
|
||||
flags=0,
|
||||
message_type=Gtk.MessageType.INFO,
|
||||
buttons=Gtk.ButtonsType.YES_NO,
|
||||
text="%s Lock File Found" % app_name,
|
||||
)
|
||||
md.format_secondary_markup(
|
||||
"A %s lock file has been found. This indicates there is already an instance of <b>%s</b> running.\n\
|
||||
Click 'Yes' to remove the lock file and try running again"
|
||||
% (lock_file, app_name)
|
||||
) # noqa
|
||||
|
||||
result = md.run()
|
||||
md.destroy()
|
||||
|
||||
if result in (Gtk.ResponseType.OK, Gtk.ResponseType.YES):
|
||||
pid = ""
|
||||
if fn.os.path.exists(pid_file):
|
||||
with open(pid_file, "r") as f:
|
||||
line = f.read()
|
||||
pid = line.rstrip().lstrip()
|
||||
|
||||
else:
|
||||
# in the rare event that the lock file is present, but the pid isn't
|
||||
fn.os.unlink(lock_file)
|
||||
fn.sys.exit(1)
|
||||
else:
|
||||
fn.sys.exit(1)
|
||||
except Exception as e:
|
||||
# fn.logger.error("Exception in __main__: %s" % e)
|
||||
print("Exception in __main__: %s" % e)
|
33
usr/share/archlinux-kernel-manager/defaults/config.toml
Normal file
|
@ -0,0 +1,33 @@
|
|||
title = "ArchLinux Kernel Manager Settings"
|
||||
|
||||
[kernels]
|
||||
|
||||
# Kernels which are sourced from https://archive.archlinux.org
|
||||
official = [
|
||||
{ name = "linux", description = "The Linux kernel and modules (Stable)", headers = "linux-headers" },
|
||||
{ name = "linux-lts", description = "The LTS Linux kernel and modules (Longterm)", headers = "linux-lts-headers" },
|
||||
{ name = "linux-zen", description = "The Linux ZEN kernel and modules (Zen)", headers = "linux-zen-headers" },
|
||||
{ name = "linux-hardened", description = "The Security-Hardened Linux kernel and modules (Hardened)", headers = "linux-hardened-headers" },
|
||||
{ name = "linux-rt", description = "The Linux RT kernel and modules (Realtime)", headers = "linux-rt-headers" },
|
||||
{ name = "linux-rt-lts", description = "The Linux RT LTS kernel and modules (Realtime Longterm)", headers = "linux-rt-lts-headers" },
|
||||
]
|
||||
|
||||
# Kernels which are sourced from unofficial repositories, these won't work if you haven't updated your pacman configuration
|
||||
# https://wiki.archlinux.org/title/Unofficial_user_repositories
|
||||
community = [
|
||||
{ name = "linux-xanmod", description = "The Linux kernel and modules with Xanmod patches", headers = "linux-xanmod-headers", repository = "chaotic-aur" },
|
||||
{ name = "linux-xanmod-lts", description = "The Linux kernel and modules with Xanmod patches", headers = "linux-xanmod-lts-headers", repository = "chaotic-aur" },
|
||||
{ name = "linux-amd", description = "Linux kernel aimed at the ZNVER4/MZEN4 AMD Ryzen CPU based hardware", headers = "linux-amd-headers", repository = "chaotic-aur" },
|
||||
{ name = "linux-cachyos", description = "The Linux EEVDF-BORE scheduler Kernel by CachyOS with other patches and improvements kernel and modules", headers = "linux-cachyos-headers", repository = "chaotic-aur" },
|
||||
{ name = "linux-ck", description = "The Linux kernel and modules with ck's hrtimer patches", headers = "linux-ck-headers", repository = "repo-ck" },
|
||||
{ name = "linux-clear", description = "The Clear Linux kernel and modules", headers = "linux-clear-headers", repository = "chaotic-aur" },
|
||||
{ name = "linux-lqx", description = "The Linux Liquorix kernel and modules", headers = "linux-lqx-headers", repository = "chaotic-aur" },
|
||||
{ name = "linux-nitrous", description = "Modified Linux kernel optimized for Skylake and newer, compiled using clang", headers = "linux-nitrous-headers", repository = "chaotic-aur" },
|
||||
]
|
||||
|
||||
# Custom bootloader example
|
||||
# Only systemd-boot or grub are valid names
|
||||
# When using grub also set grub_config
|
||||
#[bootloader]
|
||||
#name = "grub"
|
||||
#grub_config = "/boot/grub/grub.cfg"
|
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 2.7 KiB |
BIN
usr/share/archlinux-kernel-manager/images/48x48/akm-install.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
usr/share/archlinux-kernel-manager/images/48x48/akm-new.png
Normal file
After Width: | Height: | Size: 2 KiB |
BIN
usr/share/archlinux-kernel-manager/images/48x48/akm-progress.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
usr/share/archlinux-kernel-manager/images/48x48/akm-remove.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
usr/share/archlinux-kernel-manager/images/48x48/akm-settings.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
usr/share/archlinux-kernel-manager/images/48x48/akm-star.png
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
usr/share/archlinux-kernel-manager/images/48x48/akm-tux.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
usr/share/archlinux-kernel-manager/images/48x48/akm-update.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
usr/share/archlinux-kernel-manager/images/48x48/akm-verified.png
Normal file
After Width: | Height: | Size: 909 B |
BIN
usr/share/archlinux-kernel-manager/images/48x48/akm-warning.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
usr/share/archlinux-kernel-manager/images/96x96/akm-tux.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
51
usr/share/archlinux-kernel-manager/libs/Kernel.py
Normal file
|
@ -0,0 +1,51 @@
|
|||
# Store kernel data taken from
|
||||
import datetime
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class Kernel:
|
||||
def __init__(self, name, headers, version, size, last_modified, file_format):
|
||||
self.name = name
|
||||
self.headers = headers
|
||||
self.version = version
|
||||
self.size = size
|
||||
self.last_modified = last_modified
|
||||
self.file_format = file_format
|
||||
|
||||
def __gt__(self, other):
|
||||
datetime_value_self = (
|
||||
datetime.strptime(self.last_modified, "%d-%b-%Y %H:%M")
|
||||
.replace(tzinfo=None)
|
||||
.date()
|
||||
)
|
||||
|
||||
datetime_value_other = (
|
||||
datetime.strptime(other.last_modified, "%d-%b-%Y %H:%M")
|
||||
.replace(tzinfo=None)
|
||||
.date()
|
||||
)
|
||||
|
||||
if datetime_value_other > datetime_value_self:
|
||||
return datetime_value_other
|
||||
|
||||
|
||||
class CommunityKernel:
|
||||
def __init__(self, name, headers, repository, version, build_date, install_size):
|
||||
self.name = name
|
||||
self.headers = headers
|
||||
self.repository = repository
|
||||
self.version = version
|
||||
self.build_date = build_date
|
||||
self.install_size = install_size
|
||||
|
||||
def __gt__(self, other):
|
||||
if other.name > self.name:
|
||||
return other
|
||||
|
||||
|
||||
class InstalledKernel:
|
||||
def __init__(self, name, version, date, size):
|
||||
self.name = name
|
||||
self.version = version
|
||||
self.date = date
|
||||
self.size = size
|
1703
usr/share/archlinux-kernel-manager/libs/functions.py
Normal file
68
usr/share/archlinux-kernel-manager/ui/AboutDialog.py
Normal file
|
@ -0,0 +1,68 @@
|
|||
# This class stores static information about the app, and is displayed in the about window
|
||||
import os
|
||||
import gi
|
||||
import libs.functions as fn
|
||||
|
||||
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 AboutDialog(Gtk.AboutDialog):
|
||||
def __init__(self, manager_gui, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
website = "https://github.com/DeltaCopy/archlinux-kernel-manager"
|
||||
authors = ["fennec (DeltaCopy)"]
|
||||
program_name = "Arch Linux Kernel Manager"
|
||||
comments = (
|
||||
f"Add/Remove Officially supported Linux kernels on Arch based systems\n"
|
||||
f"Powered by the Arch Linux Archive (a.k.a ALA)\n"
|
||||
f"Community based Linux kernels are also supported\n"
|
||||
f"This application matches your system theme !\n"
|
||||
f"Developed in Python with GTK 4\n"
|
||||
)
|
||||
|
||||
icon_name = "akm-tux"
|
||||
|
||||
self.set_transient_for(manager_gui)
|
||||
self.set_modal(True)
|
||||
self.set_authors(authors)
|
||||
self.set_program_name(program_name)
|
||||
self.set_comments(comments)
|
||||
self.set_website(website)
|
||||
|
||||
self.set_logo_icon_name(icon_name)
|
||||
self.set_version("Version %s" % manager_gui.app_version)
|
||||
|
||||
self.connect("activate-link", self.on_activate_link)
|
||||
|
||||
tux_icon = Gdk.Texture.new_from_file(
|
||||
file=Gio.File.new_for_path(
|
||||
os.path.join(base_dir, "images/364x408/akm-tux-splash.png")
|
||||
)
|
||||
)
|
||||
|
||||
self.set_logo(tux_icon)
|
||||
|
||||
def on_activate_link(self, about_dialog, uri):
|
||||
try:
|
||||
cmd = ["sudo", "-u", fn.sudo_username, "xdg-open", uri]
|
||||
|
||||
proc = fn.subprocess.Popen(
|
||||
cmd,
|
||||
shell=False,
|
||||
stdout=fn.subprocess.PIPE,
|
||||
stderr=fn.subprocess.STDOUT,
|
||||
universal_newlines=True,
|
||||
)
|
||||
|
||||
out, err = proc.communicate(timeout=50)
|
||||
|
||||
fn.logger.warning(out)
|
||||
|
||||
except Exception as e:
|
||||
fn.logger.error("Exception in activate_link(): %s" % e)
|
||||
|
||||
return True
|
635
usr/share/archlinux-kernel-manager/ui/FlowBox.py
Normal file
|
@ -0,0 +1,635 @@
|
|||
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
|
||||
and 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
|
||||
|
||||
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]
|
||||
):
|
||||
title = "Downgrading %s kernel" % kernel.name
|
||||
else:
|
||||
title = "Upgrading %s kernel" % kernel.name
|
||||
|
||||
break
|
||||
|
||||
if title is None:
|
||||
title = "Kernel install"
|
||||
|
||||
if self.source == "community":
|
||||
message = "This will install <b>%s-%s</b> - Is this ok ?" % (
|
||||
kernel.name,
|
||||
kernel.version,
|
||||
)
|
||||
elif self.source == "official":
|
||||
message = (
|
||||
"This will install <b>%s</b> - Is this ok ?" % kernel.version
|
||||
)
|
||||
|
||||
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,
|
||||
)
|
||||
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 = "This will remove <b>%s-%s</b> - Is this ok ?" % (
|
||||
kernel.name,
|
||||
kernel.version,
|
||||
)
|
||||
elif self.source == "official":
|
||||
message = (
|
||||
"This will remove <b>%s</b> - Is this ok ?" % kernel.version
|
||||
)
|
||||
|
||||
message_window = FlowBoxMessageWindow(
|
||||
title="Kernel uninstall",
|
||||
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,
|
||||
)
|
||||
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",
|
||||
image_path="images/48x48/akm-remove.png",
|
||||
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,
|
||||
image_path="images/48x48/akm-warning.png",
|
||||
)
|
||||
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,
|
||||
)
|
||||
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",
|
||||
image_path="images/48x48/akm-remove.png",
|
||||
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,
|
||||
**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
|
||||
|
||||
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
|
631
usr/share/archlinux-kernel-manager/ui/KernelStack.py
Normal file
|
@ -0,0 +1,631 @@
|
|||
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(
|
||||
"<b>Active kernel:</b> %s" % 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(
|
||||
"<b>Active kernel:</b> %s" % 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=12)
|
||||
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(
|
||||
"<b>Active kernel:</b> %s" % 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")
|
||||
label_warning.set_markup(
|
||||
f"These are user produced content\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() == "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:
|
||||
if widget.get_name() != "vbox_no_community":
|
||||
widget.remove_all()
|
||||
else:
|
||||
if len(self.manager_gui.community_kernels) > 0:
|
||||
# widget.hide()
|
||||
for box_widget in widget:
|
||||
box_widget.hide()
|
||||
|
||||
vbox_search_entry = Gtk.Box(
|
||||
orientation=Gtk.Orientation.VERTICAL, spacing=5
|
||||
)
|
||||
|
||||
vbox_search_entry.append(search_entry_community)
|
||||
# widget.append(hbox_warning)
|
||||
widget.append(vbox_search_entry)
|
||||
|
||||
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=12)
|
||||
# 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"
|
||||
)
|
516
usr/share/archlinux-kernel-manager/ui/ManagerGUI.py
Normal file
|
@ -0,0 +1,516 @@
|
|||
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"
|
||||
|
||||
fn.logger.info("Version = %s" % self.app_version)
|
||||
|
||||
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()
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
self.bootloader = None
|
||||
self.bootloader_grub_cfg = None
|
||||
|
||||
# self.bootloader = fn.get_boot_loader()
|
||||
|
||||
config_data = fn.setup_config(self)
|
||||
|
||||
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()
|
||||
|
||||
self.active_kernel = fn.get_active_kernel()
|
||||
|
||||
fn.logger.info("Installed kernels = %s" % len(self.installed_kernels))
|
||||
|
||||
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",
|
||||
image_path="images/48x48/akm-error.png",
|
||||
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",
|
||||
image_path="images/48x48/akm-warning.png",
|
||||
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()
|
||||
|
||||
fn.logger.info("Starting pacman db synchronization thread")
|
||||
self.queue_load_progress.put("Starting pacman db synchronization")
|
||||
|
||||
self.pacman_db_sync()
|
||||
|
||||
fn.logger.info("Starting get community kernels thread")
|
||||
self.queue_load_progress.put("Getting community based Linux kernels")
|
||||
|
||||
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()
|
||||
|
||||
# =====================================================
|
||||
# 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")
|
||||
|
||||
print(
|
||||
"---------------------------------------------------------------------------"
|
||||
)
|
||||
|
||||
GLib.idle_add(
|
||||
self.show_sync_db_message_dialog,
|
||||
sync_err,
|
||||
priority=GLib.PRIORITY_DEFAULT,
|
||||
)
|
||||
|
||||
else:
|
||||
fn.logger.info("Pacman DB synchronization completed")
|
||||
|
||||
def show_sync_db_message_dialog(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",
|
||||
image_path="images/48x48/akm-warning.png",
|
||||
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:
|
||||
fn.time.sleep(0.2)
|
||||
status = self.queue_load_progress.get()
|
||||
if status == 1:
|
||||
GLib.idle_add(
|
||||
self.splash_screen.destroy,
|
||||
priority=GLib.PRIORITY_DEFAULT,
|
||||
)
|
||||
break
|
||||
|
||||
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):
|
||||
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()
|
||||
|
||||
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():
|
||||
fn.time.sleep(0.3)
|
||||
self.default_context.iteration(False)
|
||||
|
||||
# fn.time.sleep(0.5)
|
||||
|
||||
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):
|
||||
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")
|
||||
|
||||
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
|
||||
|
||||
fn.logger.debug("Adding official kernels to UI")
|
||||
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.debug("Adding installed kernels to UI")
|
||||
self.kernel_stack.add_installed_kernels_to_stack(reload=False)
|
||||
|
||||
while self.default_context.pending():
|
||||
self.default_context.iteration(True)
|
||||
|
||||
fn.time.sleep(0.3)
|
||||
|
||||
self.queue_load_progress.put(1)
|
||||
fn.logger.info("Kernel manager UI loaded")
|
45
usr/share/archlinux-kernel-manager/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)
|
93
usr/share/archlinux-kernel-manager/ui/MessageWindow.py
Normal file
|
@ -0,0 +1,93 @@
|
|||
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, image_path, detailed_message, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
# self.set_title(title=title)
|
||||
self.set_modal(modal=True)
|
||||
self.set_resizable(False)
|
||||
|
||||
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")
|
||||
|
||||
image = Gtk.Picture.new_for_filename(os.path.join(base_dir, image_path))
|
||||
|
||||
image.set_content_fit(content_fit=Gtk.ContentFit.SCALE_DOWN)
|
||||
image.set_halign(Gtk.Align.START)
|
||||
|
||||
hbox_image = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5)
|
||||
|
||||
# hbox_image.append(image)
|
||||
|
||||
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.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_image.append(scrolled_window)
|
||||
|
||||
self.set_size_request(700, 500)
|
||||
self.set_resizable(True)
|
||||
else:
|
||||
label_message = Gtk.Label(xalign=0, yalign=0)
|
||||
label_message.set_markup("%s" % message)
|
||||
label_message.set_name("label_flowbox_message")
|
||||
|
||||
hbox_image.append(image)
|
||||
hbox_image.append(label_message)
|
||||
|
||||
vbox_message.append(hbox_image)
|
||||
|
||||
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=10)
|
||||
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()
|
630
usr/share/archlinux-kernel-manager/ui/ProgressWindow.py
Normal file
|
@ -0,0 +1,630 @@
|
|||
import sys
|
||||
import gi
|
||||
import os
|
||||
import libs.functions as fn
|
||||
from ui.MessageWindow import MessageWindow
|
||||
from gi.repository import Gtk, Gio, GLib
|
||||
|
||||
base_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
||||
|
||||
|
||||
class ProgressWindow(Gtk.Window):
|
||||
def __init__(
|
||||
self,
|
||||
title,
|
||||
action,
|
||||
textview,
|
||||
textbuffer,
|
||||
kernel,
|
||||
switch,
|
||||
source,
|
||||
manager_gui,
|
||||
**kwargs,
|
||||
):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.set_title(title=title)
|
||||
self.set_modal(modal=True)
|
||||
self.set_resizable(True)
|
||||
self.set_size_request(700, 400)
|
||||
self.connect("close-request", self.on_close)
|
||||
|
||||
self.textview = textview
|
||||
self.textbuffer = textbuffer
|
||||
|
||||
self.kernel_state_queue = fn.Queue()
|
||||
self.messages_queue = fn.Queue()
|
||||
self.kernel = kernel
|
||||
self.timeout_id = None
|
||||
self.errors_found = False
|
||||
|
||||
self.action = action
|
||||
self.switch = switch
|
||||
|
||||
self.restore = False
|
||||
|
||||
self.source = source
|
||||
self.manager_gui = manager_gui
|
||||
|
||||
self.bootloader = self.manager_gui.bootloader
|
||||
self.bootloader_grub_cfg = self.manager_gui.bootloader_grub_cfg
|
||||
|
||||
vbox_progress = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
|
||||
vbox_progress.set_name("main")
|
||||
|
||||
self.set_child(child=vbox_progress)
|
||||
|
||||
header_bar = Gtk.HeaderBar()
|
||||
self.label_title = Gtk.Label(xalign=0.5, yalign=0.5)
|
||||
|
||||
header_bar.set_show_title_buttons(True)
|
||||
|
||||
self.set_titlebar(header_bar)
|
||||
|
||||
self.label_title.set_markup("<b>%s</b>" % title)
|
||||
header_bar.set_title_widget(self.label_title)
|
||||
|
||||
vbox_icon_settings = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
|
||||
vbox_icon_settings.set_name("vbox_icon_settings")
|
||||
|
||||
lbl_heading = Gtk.Label(xalign=0.5, yalign=0.5)
|
||||
lbl_heading.set_name("label_flowbox_message")
|
||||
|
||||
lbl_padding = Gtk.Label(xalign=0.0, yalign=0.0)
|
||||
lbl_padding.set_text(" ")
|
||||
|
||||
grid_banner_img = Gtk.Grid()
|
||||
|
||||
image_settings = None
|
||||
|
||||
if action == "install":
|
||||
image_settings = Gtk.Image.new_from_file(
|
||||
os.path.join(base_dir, "images/48x48/akm-install.png")
|
||||
)
|
||||
lbl_heading.set_markup(
|
||||
"Installing <b>%s version %s </b>"
|
||||
% (self.kernel.name, self.kernel.version)
|
||||
)
|
||||
if action == "uninstall":
|
||||
image_settings = Gtk.Image.new_from_file(
|
||||
os.path.join(base_dir, "images/48x48/akm-remove.png")
|
||||
)
|
||||
lbl_heading.set_markup(
|
||||
"Removing <b>%s version %s </b>"
|
||||
% (self.kernel.name, self.kernel.version)
|
||||
)
|
||||
|
||||
# get kernel version from pacman
|
||||
self.installed_kernel_version = fn.get_kernel_version(self.kernel.name)
|
||||
|
||||
image_settings.set_halign(Gtk.Align.START)
|
||||
image_settings.set_icon_size(Gtk.IconSize.LARGE)
|
||||
|
||||
hbox_header = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5)
|
||||
hbox_header.set_name("vbox_header")
|
||||
|
||||
hbox_header.append(image_settings)
|
||||
hbox_header.append(lbl_heading)
|
||||
|
||||
vbox_progress.append(hbox_header)
|
||||
|
||||
self.spinner = Gtk.Spinner()
|
||||
self.spinner.set_spinning(True)
|
||||
|
||||
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_progress_warning = Gtk.Box(
|
||||
orientation=Gtk.Orientation.HORIZONTAL, spacing=5
|
||||
)
|
||||
hbox_progress_warning.set_name("hbox_warning")
|
||||
|
||||
hbox_progress_warning.append(image_warning)
|
||||
|
||||
self.label_progress_window_desc = Gtk.Label(xalign=0, yalign=0)
|
||||
|
||||
self.label_progress_window_desc.set_markup(
|
||||
f"Do not close this window while a kernel {self.action} activity is in progress\n"
|
||||
f"Progress can be monitored in the log below\n"
|
||||
f"<b>A reboot is recommended when Linux packages have changed</b>"
|
||||
)
|
||||
|
||||
hbox_progress_warning.append(self.label_progress_window_desc)
|
||||
|
||||
self.label_status = Gtk.Label(xalign=0, yalign=0)
|
||||
|
||||
button_close = Gtk.Button.new_with_label("Close")
|
||||
button_close.set_size_request(100, 30)
|
||||
button_close.set_halign(Gtk.Align.END)
|
||||
|
||||
button_close.connect(
|
||||
"clicked",
|
||||
self.on_button_close_response,
|
||||
)
|
||||
|
||||
self.label_spinner_progress = Gtk.Label(xalign=0, yalign=0)
|
||||
if self.action == "install":
|
||||
self.label_spinner_progress.set_markup(
|
||||
"<b>Please wait kernel %s is in progress</b>" % "installation"
|
||||
)
|
||||
elif self.action == "uninstall":
|
||||
self.label_spinner_progress.set_markup(
|
||||
"<b>Please wait kernel %s is in progress</b>" % "removal"
|
||||
)
|
||||
|
||||
self.hbox_spinner = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5)
|
||||
self.hbox_spinner.append(self.label_spinner_progress)
|
||||
self.hbox_spinner.append(self.spinner)
|
||||
|
||||
vbox_padding = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=20)
|
||||
vbox_padding.set_valign(Gtk.Align.END)
|
||||
|
||||
label_padding = Gtk.Label(xalign=0, yalign=0)
|
||||
label_padding.set_valign(Gtk.Align.END)
|
||||
vbox_padding.append(label_padding)
|
||||
|
||||
hbox_button_close = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=20)
|
||||
|
||||
hbox_button_close.append(button_close)
|
||||
hbox_button_close.set_halign(Gtk.Align.END)
|
||||
|
||||
self.scrolled_window = Gtk.ScrolledWindow()
|
||||
self.scrolled_window.set_propagate_natural_height(True)
|
||||
self.scrolled_window.set_propagate_natural_width(True)
|
||||
self.scrolled_window.set_policy(
|
||||
Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC
|
||||
)
|
||||
|
||||
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)
|
||||
|
||||
if self.textview.get_buffer() is not None:
|
||||
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)
|
||||
self.scrolled_window.set_child(self.textview)
|
||||
|
||||
self.scrolled_window.set_size_request(300, 300)
|
||||
|
||||
vbox_progress.append(hbox_progress_warning)
|
||||
vbox_progress.append(self.notify_revealer)
|
||||
vbox_progress.append(self.scrolled_window)
|
||||
vbox_progress.append(self.hbox_spinner)
|
||||
vbox_progress.append(self.label_status)
|
||||
vbox_progress.append(vbox_padding)
|
||||
vbox_progress.append(hbox_button_close)
|
||||
|
||||
self.present()
|
||||
|
||||
self.linux_headers = None
|
||||
|
||||
if (
|
||||
self.source == "official"
|
||||
and action == "install"
|
||||
or action == "uninstall"
|
||||
and self.source == "official"
|
||||
):
|
||||
if kernel.name == "linux":
|
||||
self.linux_headers = "linux-headers"
|
||||
if kernel.name == "linux-rt":
|
||||
self.linux_headers = "linux-rt-headers"
|
||||
if kernel.name == "linux-rt-lts":
|
||||
self.linux_headers = "linux-rt-lts-headers"
|
||||
if kernel.name == "linux-hardened":
|
||||
self.linux_headers = "linux-hardened-headers"
|
||||
if kernel.name == "linux-zen":
|
||||
self.linux_headers = "linux-zen-headers"
|
||||
if kernel.name == "linux-lts":
|
||||
self.linux_headers = "linux-lts-headers"
|
||||
|
||||
self.official_kernels = [
|
||||
"%s/packages/l/%s/%s-x86_64%s"
|
||||
% (
|
||||
fn.archlinux_mirror_archive_url,
|
||||
kernel.name,
|
||||
kernel.version,
|
||||
kernel.file_format,
|
||||
),
|
||||
"%s/packages/l/%s/%s-x86_64%s"
|
||||
% (
|
||||
fn.archlinux_mirror_archive_url,
|
||||
self.linux_headers,
|
||||
kernel.headers,
|
||||
kernel.file_format,
|
||||
),
|
||||
]
|
||||
|
||||
# in the event an install goes wrong, fallback and reinstall previous kernel
|
||||
|
||||
if self.source == "official":
|
||||
self.restore_kernel = None
|
||||
|
||||
for inst_kernel in fn.get_installed_kernels():
|
||||
if inst_kernel.name == self.kernel.name:
|
||||
|
||||
self.restore_kernel = inst_kernel
|
||||
break
|
||||
|
||||
if self.restore_kernel:
|
||||
fn.logger.info("Restore kernel = %s" % self.restore_kernel.name)
|
||||
fn.logger.info(
|
||||
"Restore kernel version = %s" % self.restore_kernel.version
|
||||
)
|
||||
else:
|
||||
fn.logger.info("No previous %s kernel installed" % self.kernel.name)
|
||||
else:
|
||||
fn.logger.info("Community kernel, no kernel restore available")
|
||||
|
||||
if fn.check_pacman_lockfile() is False:
|
||||
th_monitor_messages_queue = fn.threading.Thread(
|
||||
name=fn.thread_monitor_messages,
|
||||
target=fn.monitor_messages_queue,
|
||||
daemon=True,
|
||||
args=(self,),
|
||||
)
|
||||
|
||||
th_monitor_messages_queue.start()
|
||||
|
||||
if fn.is_thread_alive(fn.thread_monitor_messages):
|
||||
self.textbuffer.delete(
|
||||
self.textbuffer.get_start_iter(), self.textbuffer.get_end_iter()
|
||||
)
|
||||
|
||||
if not fn.is_thread_alive(fn.thread_check_kernel_state):
|
||||
th_check_kernel_state = fn.threading.Thread(
|
||||
name=fn.thread_check_kernel_state,
|
||||
target=self.check_kernel_state,
|
||||
daemon=True,
|
||||
)
|
||||
th_check_kernel_state.start()
|
||||
|
||||
if action == "install" and self.source == "community":
|
||||
self.label_notify_revealer.set_text(
|
||||
"Installing from %s" % kernel.repository
|
||||
)
|
||||
self.reveal_notify()
|
||||
event = (
|
||||
"%s [INFO]: Installing kernel from repository %s, kernel = %s-%s\n"
|
||||
% (
|
||||
fn.datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
|
||||
self.kernel.repository,
|
||||
self.kernel.name,
|
||||
self.kernel.version,
|
||||
)
|
||||
)
|
||||
self.messages_queue.put(event)
|
||||
|
||||
if not fn.is_thread_alive(fn.thread_install_community_kernel):
|
||||
th_install_ch = fn.threading.Thread(
|
||||
name=fn.thread_install_community_kernel,
|
||||
target=fn.install_community_kernel,
|
||||
args=(self,),
|
||||
daemon=True,
|
||||
)
|
||||
|
||||
th_install_ch.start()
|
||||
|
||||
if action == "install" and self.source == "official":
|
||||
self.label_notify_revealer.set_text("Installing kernel packages ...")
|
||||
|
||||
self.reveal_notify()
|
||||
|
||||
event = "%s [INFO]: Installing kernel = %s | version = %s\n" % (
|
||||
fn.datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
|
||||
self.kernel.name,
|
||||
self.kernel.version,
|
||||
)
|
||||
self.messages_queue.put(event)
|
||||
|
||||
if not fn.is_thread_alive(fn.thread_install_archive_kernel):
|
||||
th_install = fn.threading.Thread(
|
||||
name=fn.thread_install_archive_kernel,
|
||||
target=fn.install_archive_kernel,
|
||||
args=(self,),
|
||||
daemon=True,
|
||||
)
|
||||
|
||||
th_install.start()
|
||||
|
||||
if action == "uninstall":
|
||||
if fn.check_pacman_lockfile() is False:
|
||||
self.label_notify_revealer.set_text("Removing kernel packages ...")
|
||||
self.reveal_notify()
|
||||
|
||||
event = "%s [INFO]: Uninstalling kernel %s %s\n" % (
|
||||
fn.datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
|
||||
self.kernel.name,
|
||||
self.kernel.version,
|
||||
)
|
||||
self.messages_queue.put(event)
|
||||
|
||||
if not fn.is_thread_alive(fn.thread_uninstall_kernel):
|
||||
th_uninstall_kernel = fn.threading.Thread(
|
||||
name=fn.thread_uninstall_kernel,
|
||||
target=self.uninstall_kernel,
|
||||
daemon=True,
|
||||
)
|
||||
|
||||
th_uninstall_kernel.start()
|
||||
else:
|
||||
self.label_notify_revealer.set_text(
|
||||
"Pacman lockfile found cannot continue ..."
|
||||
)
|
||||
|
||||
self.reveal_notify()
|
||||
|
||||
fn.logger.error(
|
||||
"Pacman lockfile found, is another pacman process running ?"
|
||||
)
|
||||
|
||||
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 on_button_close_response(self, widget):
|
||||
if fn.check_pacman_process(self):
|
||||
mw = MessageWindow(
|
||||
title="Pacman process running",
|
||||
message="Pacman is busy processing a transaction .. please wait",
|
||||
image_path="images/48x48/akm-progress.png",
|
||||
transient_for=self,
|
||||
detailed_message=False,
|
||||
)
|
||||
|
||||
mw.present()
|
||||
else:
|
||||
self.destroy()
|
||||
|
||||
def on_close(self, data):
|
||||
if fn.check_pacman_process(self):
|
||||
mw = MessageWindow(
|
||||
title="Pacman process running",
|
||||
message="Pacman is busy processing a transaction .. please wait",
|
||||
image_path="images/48x48/akm-progress.png",
|
||||
transient_for=self,
|
||||
detailed_message=False,
|
||||
)
|
||||
|
||||
mw.present()
|
||||
else:
|
||||
self.destroy()
|
||||
|
||||
def check_kernel_state(self):
|
||||
returncode = None
|
||||
kernel = None
|
||||
while True:
|
||||
items = self.kernel_state_queue.get()
|
||||
|
||||
try:
|
||||
if items is not None:
|
||||
returncode, action, kernel = items
|
||||
|
||||
if returncode == 0:
|
||||
self.label_notify_revealer.set_text(
|
||||
"Kernel %s completed" % action
|
||||
)
|
||||
self.reveal_notify()
|
||||
|
||||
fn.logger.info("Kernel %s completed" % action)
|
||||
|
||||
event = "%s [INFO]: <b>Kernel %s completed</b>\n" % (
|
||||
fn.datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
|
||||
action,
|
||||
)
|
||||
self.messages_queue.put(event)
|
||||
|
||||
if returncode == 1:
|
||||
self.errors_found = True
|
||||
|
||||
self.label_notify_revealer.set_text("Kernel %s failed" % action)
|
||||
self.reveal_notify()
|
||||
|
||||
fn.logger.error("Kernel %s failed" % action)
|
||||
|
||||
event = "%s <b>[ERROR]: Kernel %s failed</b>\n" % (
|
||||
fn.datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
|
||||
action,
|
||||
)
|
||||
self.messages_queue.put(event)
|
||||
|
||||
self.label_status.set_markup(
|
||||
"<span foreground='orange'><b>Kernel %s failed - see logs above</b></span>"
|
||||
% action
|
||||
)
|
||||
|
||||
# undo action here if action == install
|
||||
|
||||
event = (
|
||||
"%s<b> [INFO]: Attempting to undo previous Linux package changes</b>\n"
|
||||
% (
|
||||
fn.datetime.datetime.now().strftime(
|
||||
"%Y-%m-%d-%H-%M-%S"
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
self.messages_queue.put(event)
|
||||
|
||||
if action == "install" and self.restore_kernel is not None:
|
||||
self.restore = True
|
||||
fn.logger.info(
|
||||
"Installation failed, attempting removal of previous Linux package changes"
|
||||
)
|
||||
self.set_title("Kernel installation failed")
|
||||
|
||||
self.label_spinner_progress.set_markup(
|
||||
"<b>Please wait restoring kernel %s</b>"
|
||||
% self.restore_kernel.version
|
||||
)
|
||||
|
||||
fn.uninstall(self)
|
||||
|
||||
fn.logger.info(
|
||||
"Restoring previously installed kernel %s"
|
||||
% self.restore_kernel.version
|
||||
)
|
||||
|
||||
self.official_kernels = [
|
||||
"%s/packages/l/%s/%s-%s-x86_64%s"
|
||||
% (
|
||||
fn.archlinux_mirror_archive_url,
|
||||
self.restore_kernel.name,
|
||||
self.restore_kernel.name,
|
||||
self.restore_kernel.version,
|
||||
".pkg.tar.zst",
|
||||
),
|
||||
"%s/packages/l/%s/%s-%s-x86_64%s"
|
||||
% (
|
||||
fn.archlinux_mirror_archive_url,
|
||||
self.linux_headers,
|
||||
self.linux_headers,
|
||||
self.restore_kernel.version,
|
||||
".pkg.tar.zst",
|
||||
),
|
||||
]
|
||||
self.errors_found = False
|
||||
fn.install_archive_kernel(self)
|
||||
self.set_title("Kernel installation failed")
|
||||
self.label_status.set_markup(
|
||||
f"<span foreground='orange'><b>Kernel %s failed - see logs above</b></span>\n"
|
||||
% action
|
||||
)
|
||||
|
||||
# self.spinner.set_spinning(False)
|
||||
# self.hbox_spinner.hide()
|
||||
#
|
||||
# self.label_progress_window_desc.set_markup(
|
||||
# f"<b>This window can be now closed</b>\n"
|
||||
# f"<b>A reboot is recommended when Linux packages have changed</b>"
|
||||
# )
|
||||
|
||||
# break
|
||||
else:
|
||||
if (
|
||||
returncode == 0
|
||||
and "-headers" in kernel
|
||||
or action == "uninstall"
|
||||
or action == "install"
|
||||
and self.errors_found is False
|
||||
):
|
||||
|
||||
fn.update_bootloader(self)
|
||||
self.update_installed_list()
|
||||
self.update_official_list()
|
||||
|
||||
if len(self.manager_gui.community_kernels) > 0:
|
||||
self.update_community_list()
|
||||
|
||||
if self.restore == False:
|
||||
self.label_title.set_markup(
|
||||
"<b>Kernel %s completed</b>" % action
|
||||
)
|
||||
|
||||
self.label_status.set_markup(
|
||||
"<span foreground='orange'><b>Kernel %s completed</b></span>"
|
||||
% action
|
||||
)
|
||||
|
||||
self.spinner.set_spinning(False)
|
||||
self.hbox_spinner.hide()
|
||||
|
||||
self.label_progress_window_desc.set_markup(
|
||||
f"<b>This window can be now closed</b>\n"
|
||||
f"<b>A reboot is recommended when Linux packages have changed</b>"
|
||||
)
|
||||
else:
|
||||
self.label_title.set_markup(
|
||||
"<b>Kernel %s failed</b>" % action
|
||||
)
|
||||
|
||||
self.label_status.set_markup(
|
||||
"<span foreground='orange'><b>Kernel %s failed</b></span>"
|
||||
% action
|
||||
)
|
||||
|
||||
self.spinner.set_spinning(False)
|
||||
self.hbox_spinner.hide()
|
||||
|
||||
self.label_progress_window_desc.set_markup(
|
||||
f"<b>This window can be now closed</b>\n"
|
||||
f"<b>Previous kernel restored due to failure</b>\n"
|
||||
f"<b>A reboot is recommended when Linux packages have changed</b>"
|
||||
)
|
||||
|
||||
# # else:
|
||||
# self.spinner.set_spinning(False)
|
||||
# self.hbox_spinner.hide()
|
||||
#
|
||||
# self.label_progress_window_desc.set_markup(
|
||||
# f"<b>This window can be now closed</b>\n"
|
||||
# f"<b>A reboot is recommended when Linux packages have changed</b>"
|
||||
# )
|
||||
|
||||
break
|
||||
except Exception as e:
|
||||
fn.logger.error("Exception in check_kernel_state(): %s" % e)
|
||||
|
||||
finally:
|
||||
self.kernel_state_queue.task_done()
|
||||
|
||||
def update_installed_list(self):
|
||||
self.manager_gui.installed_kernels = fn.get_installed_kernels()
|
||||
GLib.idle_add(
|
||||
self.manager_gui.kernel_stack.add_installed_kernels_to_stack, True
|
||||
)
|
||||
|
||||
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 update_community_list(self):
|
||||
self.manager_gui.installed_kernels = fn.get_installed_kernels()
|
||||
GLib.idle_add(
|
||||
self.manager_gui.kernel_stack.add_community_kernels_to_stack,
|
||||
True,
|
||||
)
|
||||
|
||||
def uninstall_kernel(self):
|
||||
event = "%s [INFO]: Uninstalling kernel %s\n" % (
|
||||
fn.datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
|
||||
self.kernel.version,
|
||||
)
|
||||
|
||||
self.messages_queue.put(event)
|
||||
|
||||
fn.uninstall(self)
|
713
usr/share/archlinux-kernel-manager/ui/SettingsWindow.py
Normal file
|
@ -0,0 +1,713 @@
|
|||
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
|
||||
)
|
||||
vbox_community_warning.set_name("box")
|
||||
|
||||
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("box")
|
||||
|
||||
hbox_warning.append(image_warning)
|
||||
|
||||
label_pacman_no_community = Gtk.Label(xalign=0, yalign=0)
|
||||
label_pacman_no_community.set_markup(
|
||||
f"<b>Cannot find any supported unofficial pacman repository's</b>\n"
|
||||
f"Add unofficial pacman repository's to use community based kernels"
|
||||
)
|
||||
|
||||
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:
|
||||
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",
|
||||
image_path="images/48x48/akm-warning.png",
|
||||
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(),
|
||||
image_path="images/48x48/akm-warning.png",
|
||||
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_community_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 update_community_list(self):
|
||||
self.manager_gui.installed_kernels = fn.get_installed_kernels()
|
||||
|
||||
GLib.idle_add(
|
||||
self.manager_gui.kernel_stack.add_community_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
|
27
usr/share/archlinux-kernel-manager/ui/SplashScreen.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
import gi
|
||||
import libs.functions as fn
|
||||
|
||||
gi.require_version("Gtk", "4.0")
|
||||
from gi.repository import Gtk, Gio, GLib, GdkPixbuf, GObject, Gdk
|
||||
|
||||
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_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/364x408/akm-tux-splash.png")
|
||||
)
|
||||
)
|
||||
tux_icon.set_content_fit(content_fit=Gtk.ContentFit.FILL)
|
||||
|
||||
self.set_child(child=tux_icon)
|
||||
self.present()
|
30
usr/share/archlinux-kernel-manager/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)
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="48px" height="48px" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g><path style="opacity:0.816" fill="#0d0c0b" d="M 19.5,-0.5 C 22.1667,-0.5 24.8333,-0.5 27.5,-0.5C 28.8361,1.01027 30.0027,2.67694 31,4.5C 31.2599,8.24977 31.9266,11.9164 33,15.5C 38.3468,20.4952 40.5134,26.4952 39.5,33.5C 38.089,35.539 36.089,36.539 33.5,36.5C 33.7678,34.901 33.4345,33.5676 32.5,32.5C 32.5911,26.0144 30.9244,20.0144 27.5,14.5C 27.5,13.5 27.5,12.5 27.5,11.5C 27.9899,9.05165 27.1566,7.38498 25,6.5C 23.3468,6.81978 22.3468,7.81978 22,9.5C 18.3165,5.68172 17.1498,6.34838 18.5,11.5C 18.5,12.5 18.5,13.5 18.5,14.5C 15.8975,20.3075 13.8975,26.3075 12.5,32.5C 11.1667,32.5 9.83333,32.5 8.5,32.5C 9.56139,26.4778 12.0614,21.1445 16,16.5C 16.3333,11.8333 16.6667,7.16667 17,2.5C 18.045,1.62656 18.8783,0.626561 19.5,-0.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#8d887c" d="M 27.5,11.5 C 27.1667,11.5 26.8333,11.5 26.5,11.5C 25.5084,11.6716 24.8417,11.3382 24.5,10.5C 23.1667,10.5 21.8333,10.5 20.5,10.5C 19.8333,10.8333 19.1667,11.1667 18.5,11.5C 17.1498,6.34838 18.3165,5.68172 22,9.5C 22.3468,7.81978 23.3468,6.81978 25,6.5C 27.1566,7.38498 27.9899,9.05165 27.5,11.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#121212" d="M 24.5,10.5 C 24.6395,8.66298 25.3061,8.32964 26.5,9.5C 26.0431,10.2975 25.3764,10.6309 24.5,10.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#f8cc10" d="M 20.5,10.5 C 21.8333,10.5 23.1667,10.5 24.5,10.5C 24.8417,11.3382 25.5084,11.6716 26.5,11.5C 25.3126,13.9754 23.3126,14.9754 20.5,14.5C 20.5,13.1667 20.5,11.8333 20.5,10.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#da9607" d="M 20.5,10.5 C 20.5,11.8333 20.5,13.1667 20.5,14.5C 23.3126,14.9754 25.3126,13.9754 26.5,11.5C 26.8333,11.5 27.1667,11.5 27.5,11.5C 27.5,12.5 27.5,13.5 27.5,14.5C 25.8439,15.1465 24.1772,15.8131 22.5,16.5C 20.9271,16.2483 19.5938,15.5817 18.5,14.5C 18.5,13.5 18.5,12.5 18.5,11.5C 19.1667,11.1667 19.8333,10.8333 20.5,10.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#f3f3f0" d="M 18.5,14.5 C 19.5938,15.5817 20.9271,16.2483 22.5,16.5C 24.1772,15.8131 25.8439,15.1465 27.5,14.5C 30.9244,20.0144 32.5911,26.0144 32.5,32.5C 31.5084,32.3284 30.8417,32.6618 30.5,33.5C 30.5,35.1667 30.5,36.8333 30.5,38.5C 29.5,38.8333 28.8333,39.5 28.5,40.5C 25.418,42.181 22.0847,42.8476 18.5,42.5C 17.8333,41.5 17.1667,40.5 16.5,39.5C 18.0281,39.4827 18.5281,38.816 18,37.5C 16.549,35.5359 14.7157,34.2026 12.5,33.5C 12.5,33.1667 12.5,32.8333 12.5,32.5C 13.8975,26.3075 15.8975,20.3075 18.5,14.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#f0ad01" d="M 8.5,32.5 C 9.83333,32.5 11.1667,32.5 12.5,32.5C 12.5,32.8333 12.5,33.1667 12.5,33.5C 13.8465,35.5368 15.1798,37.5368 16.5,39.5C 17.1667,40.5 17.8333,41.5 18.5,42.5C 18.5,43.5 18.5,44.5 18.5,45.5C 16.6208,46.3414 14.6208,46.6747 12.5,46.5C 10.1617,44.9605 7.49508,44.2938 4.5,44.5C 3.62356,44.6309 2.95689,44.2975 2.5,43.5C 3.2305,40.8908 3.7305,38.2241 4,35.5C 5.87781,34.9473 7.37781,33.9473 8.5,32.5 Z"/></g>
|
||||
<g><path style="opacity:0.981" fill="#f5b601" d="M 30.5,33.5 C 30.8417,32.6618 31.5084,32.3284 32.5,32.5C 33.4345,33.5676 33.7678,34.901 33.5,36.5C 36.089,36.539 38.089,35.539 39.5,33.5C 40.3771,35.7278 41.7104,37.7278 43.5,39.5C 40.0688,42.3166 36.0688,43.9833 31.5,44.5C 31.815,40.6286 31.4816,36.9619 30.5,33.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#1b1610" d="M 12.5,33.5 C 14.7157,34.2026 16.549,35.5359 18,37.5C 18.5281,38.816 18.0281,39.4827 16.5,39.5C 15.1798,37.5368 13.8465,35.5368 12.5,33.5 Z"/></g>
|
||||
<g><path style="opacity:0.779" fill="#0f0f0e" d="M 28.5,40.5 C 29.4614,42.2646 29.7947,44.2646 29.5,46.5C 25.9359,45.5773 22.2693,45.244 18.5,45.5C 18.5,44.5 18.5,43.5 18.5,42.5C 22.0847,42.8476 25.418,42.181 28.5,40.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#bd7600" d="M 30.5,33.5 C 31.4816,36.9619 31.815,40.6286 31.5,44.5C 36.0688,43.9833 40.0688,42.3166 43.5,39.5C 44.525,39.8966 44.6917,40.5632 44,41.5C 41.7218,42.719 39.5551,44.0523 37.5,45.5C 31.0762,47.6961 28.7428,45.3627 30.5,38.5C 30.5,36.8333 30.5,35.1667 30.5,33.5 Z"/></g>
|
||||
<g><path style="opacity:0.282" fill="#835100" d="M 4.5,44.5 C 7.49508,44.2938 10.1617,44.9605 12.5,46.5C 9.57184,46.4349 6.90517,45.7682 4.5,44.5 Z"/></g>
|
||||
<g><path style="opacity:0.635" fill="#4d2b02" d="M 18.5,45.5 C 18.5,46.1667 18.5,46.8333 18.5,47.5C 16.5,47.5 14.5,47.5 12.5,47.5C 12.5,47.1667 12.5,46.8333 12.5,46.5C 14.6208,46.6747 16.6208,46.3414 18.5,45.5 Z"/></g>
|
||||
<g><path style="opacity:0.657" fill="#3e2403" d="M 30.5,38.5 C 28.7428,45.3627 31.0762,47.6961 37.5,45.5C 37.1667,46.1667 36.8333,46.8333 36.5,47.5C 34.1667,47.5 31.8333,47.5 29.5,47.5C 29.5,47.1667 29.5,46.8333 29.5,46.5C 29.7947,44.2646 29.4614,42.2646 28.5,40.5C 28.8333,39.5 29.5,38.8333 30.5,38.5 Z"/></g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.9 KiB |
104
usr/share/polkit-1/actions/org.archlinux.akm.policy
Normal file
|
@ -0,0 +1,104 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN" "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
|
||||
<policyconfig>
|
||||
<vendor>ArcoLinux</vendor>
|
||||
<vendor_url>http://arcolinux.info/</vendor_url>
|
||||
<icon_name>package-x-generic</icon_name>
|
||||
<action id="org.arcolinux.pkexec.akm">
|
||||
<description>Add/Remove Linux kernels from Arch Linux based systems</description>
|
||||
<description xml:lang="zh_TW">變更您自身的使用者資料</description>
|
||||
<description xml:lang="zh_CN">修改您的用户数据</description>
|
||||
<description xml:lang="uk">Зміна даних вашого користувача</description>
|
||||
<description xml:lang="tr">Kullanıcı bilgilerinizi değiştirin</description>
|
||||
<description xml:lang="sv">Ändra ditt egna användardata</description>
|
||||
<description xml:lang="sr">Измените ваше личне корисничке податке</description>
|
||||
<description xml:lang="sr@latin">Izmenite vaše lične korisničke podatke</description>
|
||||
<description xml:lang="sl">Spremenite lastne uporabniške podatke</description>
|
||||
<description xml:lang="sk">Zmeniť svoje vlastné používateľské údaje</description>
|
||||
<description xml:lang="ru">Изменить личные пользовательские данные</description>
|
||||
<description xml:lang="pt">Alterar os seus próprios dados</description>
|
||||
<description xml:lang="pt_BR">Alterar dados do próprio usuário</description>
|
||||
<description xml:lang="pl">Zmiana własnych danych</description>
|
||||
<description xml:lang="pa">ਆਪਣਾ ਯੂਜ਼ਰ ਡਾਟਾ ਬਦਲੋ</description>
|
||||
<description xml:lang="oc">Modificar sas pròprias donadas</description>
|
||||
<description xml:lang="nl">Uw eigen gebruikersgegevens bewerken</description>
|
||||
<description xml:lang="lv">Mainīt pašam savus lietotāja datus</description>
|
||||
<description xml:lang="lt">Keisti savo naudotojo duomenis</description>
|
||||
<description xml:lang="ko">개인 사용자 데이터 변경</description>
|
||||
<description xml:lang="kk">Өзіңіздің пайдаланушы ақпаратыңызды өзгерту</description>
|
||||
<description xml:lang="ka">თქვენი პირადი ინფორმაციის შეცვლა</description>
|
||||
<description xml:lang="ja">自身のユーザーデータを変更する</description>
|
||||
<description xml:lang="it">Cambia i propri dati utente</description>
|
||||
<description xml:lang="id">Ubah data penggunamu sendiri</description>
|
||||
<description xml:lang="ia">Modificar tu proprie datos de usator</description>
|
||||
<description xml:lang="hu">Saját felhasználói adatainak módosítása</description>
|
||||
<description xml:lang="hr">Promijenite vlastite korisničke podatke</description>
|
||||
<description xml:lang="gl">Cambiar os seus propios datos de usuario</description>
|
||||
<description xml:lang="fur">Cambie i tiei dâts utent</description>
|
||||
<description xml:lang="fr">Modifier ses propres données</description>
|
||||
<description xml:lang="fi">Muuta omia käyttäjätietojasi</description>
|
||||
<description xml:lang="eu">Aldatu zure erabiltzaile-datuak</description>
|
||||
<description xml:lang="es">Cambie sus propios datos de usuario</description>
|
||||
<description xml:lang="eo">Ŝanĝi viajn proprajn uzantodatumojn</description>
|
||||
<description xml:lang="en">Change your own user data</description>
|
||||
<description xml:lang="en_GB">Change your own user data</description>
|
||||
<description xml:lang="el">Αλλάξτε τα δεδομένα χρήστη σας</description>
|
||||
<description xml:lang="de">Ändern Sie Ihre eigenen Benutzerdaten</description>
|
||||
<description xml:lang="da">Skift data for din egen bruger</description>
|
||||
<description xml:lang="cs">Změnit své vlastní údaje</description>
|
||||
<description xml:lang="ca">Canvieu les dades d'usuari pròpies</description>
|
||||
<description xml:lang="ast">Camudacia de los tos datos d'usuariu</description>
|
||||
<description xml:lang="ar">غيّر بيانات المستخدم خاصتك</description>
|
||||
<message>Authentication is required to change your own user data</message>
|
||||
<message xml:lang="zh_TW">若要變更您自身的使用者資料需要核對身分</message>
|
||||
<message xml:lang="zh_CN">需要授权以修改您的用户数据</message>
|
||||
<message xml:lang="uk">Для зміни даних вашого користувача потрібно пройти розпізнавання</message>
|
||||
<message xml:lang="tr">Kendi kullanıcı bilginizi değiştirmek için kimlik kanıtlaması gereklidir</message>
|
||||
<message xml:lang="sv">Autentisering krävs för att ändra ditt egna användardata</message>
|
||||
<message xml:lang="sr">Потребно је потврђивање идентитета за промену ваших личних корисничких података</message>
|
||||
<message xml:lang="sr@latin">Potrebno je potvrđivanje identiteta za promenu vaših ličnih korisničkih podataka</message>
|
||||
<message xml:lang="sl">Za spremembo lastnih podatkov je zahtevana overitev</message>
|
||||
<message xml:lang="sk">Na zmenu vlastných používateľských údajov je potrebné overenie totožnosti</message>
|
||||
<message xml:lang="ru">Для изменения личных пользовательских данных требуется аутентификация</message>
|
||||
<message xml:lang="pt">É necessária autenticação para alterar os seus próprios dados de utilizador</message>
|
||||
<message xml:lang="pt_BR">Autenticação é necessária para alterar dados do próprio usuário</message>
|
||||
<message xml:lang="pl">Wymagane jest uwierzytelnienie, aby zmienić własne dane</message>
|
||||
<message xml:lang="pa">ਤੁਹਾਡਾ ਯੂਜ਼ਰ ਡਾਟਾ ਬਦਲਣ ਲਈ ਪਰਮਾਣਿਤ ਹੋਣ ਦੀ ਲੋੜ ਹੈ</message>
|
||||
<message xml:lang="oc">Vos cal vos autentificar per modificar vòstras pròprias donadas d'utilizaire</message>
|
||||
<message xml:lang="nl">Authenticatie vereist om uw eigen gebruikersgegevens te kunnen veranderen</message>
|
||||
<message xml:lang="lv">Nepieciešama autentifikācija, lai mainītu pats savus lietotāja datus</message>
|
||||
<message xml:lang="lt">Norint keisti savo naudotojo duomenis, reikia patvirtinti tapatybę</message>
|
||||
<message xml:lang="ko">내 사용자 데이터를 변경하려면 인증해야 합니다</message>
|
||||
<message xml:lang="kk">Өзіңіздің пайдаланушы ақпаратыңызды өзгерту үшін аутентификация керек</message>
|
||||
<message xml:lang="ka">თქვენი პირადი მონაცემების შესაცვლელად აუცილებელია ავთენტიფიკაციის გავლა.</message>
|
||||
<message xml:lang="ja">自分自身のユーザーデータを変更するには認証が必要です</message>
|
||||
<message xml:lang="it">È richiesto autenticarsi per cambiare i propri dati utente</message>
|
||||
<message xml:lang="id">Otentikasi diperlukan untuk mengubah data pengguna milikmu</message>
|
||||
<message xml:lang="ia">Authentication es necessari pro modificar tu proprie datos de usator</message>
|
||||
<message xml:lang="hu">Hitelesítés szükséges a saját felhasználói adatai módosításához</message>
|
||||
<message xml:lang="hr">Potrebna je ovjera za promjenu vlastitih korisničkih podataka</message>
|
||||
<message xml:lang="gl">Requírese autenticación para cambiar os seus propios datos de usuario</message>
|
||||
<message xml:lang="fur">La autenticazion e je necssarie par cambiâ i propris dâts utent</message>
|
||||
<message xml:lang="fr">Vous devez vous authentifier pour modifier vos propres données utilisateur</message>
|
||||
<message xml:lang="fi">Omien käyttäjätietojen muuttaminen vaatii tunnistautumisen</message>
|
||||
<message xml:lang="eu">Derrigorrezkoa da autentifikatzea zure erabiltzaile-datuak aldatzeko</message>
|
||||
<message xml:lang="es">Se necesita autenticación para cambiar sus datos de usuario</message>
|
||||
<message xml:lang="eo">Aŭtentigo bezonatas por ŝanĝi viajn proprajn uzantodatumojn</message>
|
||||
<message xml:lang="en">Authentication is required to change your own user data</message>
|
||||
<message xml:lang="en_GB">Authentication is required to change your own user data</message>
|
||||
<message xml:lang="el">Απαιτείται πιστοποίηση για αλλαγή των δικών σας δεδομένων χρήστη</message>
|
||||
<message xml:lang="de">Zur Änderung Ihrer eigenen Benutzerdaten ist eine Authentifizierung erforderlich</message>
|
||||
<message xml:lang="da">Der kræves autentifikation for at skifte data for din egen bruger</message>
|
||||
<message xml:lang="cs">Pro změnu svých vlastních údajů je vyžadována autentizace</message>
|
||||
<message xml:lang="ca">Es requereix autenticació per canviar les vostres dades d'usuari</message>
|
||||
<message xml:lang="ast">Ríquese l'autenticación pa camudar los tos datos d'usuairu</message>
|
||||
<message xml:lang="ar">الاستيثاق مطلوب لتغيير بيانات المستخدم التي تملكها</message>
|
||||
<defaults>
|
||||
<allow_any>auth_admin</allow_any>
|
||||
<allow_inactive>auth_admin</allow_inactive>
|
||||
<allow_active>auth_admin</allow_active>
|
||||
</defaults>
|
||||
<annotate key="org.freedesktop.policykit.exec.path">/usr/share/archlinux-kernel-manager/archlinux-kernel-manager.py</annotate>
|
||||
<annotate key="org.freedesktop.policykit.exec.allow_gui">true</annotate>
|
||||
</action>
|
||||
</policyconfig>
|