From d18cae4a1ec672bc1673ab290641bb3650176ad4 Mon Sep 17 00:00:00 2001 From: axtloss Date: Sat, 23 Jul 2022 23:07:28 +0200 Subject: [PATCH] =?UTF-8?q?It=20is=20completed=20=F0=9F=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Mirko Brombin --- .../scalable/apps/al.getcryst.jadegui.svg | 335 ++++++++++++++---- src/classes/install_prefs.py | 94 +++++ src/classes/meson.build | 1 + src/functions/install_screen.py | 21 +- src/functions/misc_screen.py | 4 +- src/functions/summary_screen.py | 33 +- src/functions/user_screen.py | 1 + src/pages/install_screen.blp | 1 + src/pages/misc_screen.blp | 4 +- src/pages/summary_screen.blp | 16 +- src/scripts/install.sh | 4 + src/scripts/meson.build | 2 + src/scripts/savePrefs.sh | 3 + src/utils/meson.build | 1 + src/utils/threading.py | 74 ++++ 15 files changed, 521 insertions(+), 73 deletions(-) create mode 100644 src/classes/install_prefs.py create mode 100644 src/scripts/install.sh create mode 100644 src/scripts/savePrefs.sh create mode 100644 src/utils/threading.py diff --git a/data/icons/hicolor/scalable/apps/al.getcryst.jadegui.svg b/data/icons/hicolor/scalable/apps/al.getcryst.jadegui.svg index c373ead..15a9aa0 100644 --- a/data/icons/hicolor/scalable/apps/al.getcryst.jadegui.svg +++ b/data/icons/hicolor/scalable/apps/al.getcryst.jadegui.svg @@ -1,61 +1,276 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - diff --git a/src/classes/install_prefs.py b/src/classes/install_prefs.py new file mode 100644 index 0000000..c3689e9 --- /dev/null +++ b/src/classes/install_prefs.py @@ -0,0 +1,94 @@ +# install_prefs.py +# +# Copyright 2022 +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# SPDX-License-Identifier: GPL-3.0-only + +from jade_gui.utils import disks +import json + +class InstallPrefs: + def __init__( + self, + timezone, + layout, + variant, + username, + password, + enable_sudo, + disk, + hostname, + ipv_enabled, + timeshift_enable, + desktop, + ): + self.timezone = timezone + self.layout = layout + self.variant = variant + self.username = username + self.password = password + self.enable_sudo = enable_sudo + self.disk = disk.disk + self.hostname = hostname if len(hostname) != 0 else "crystal" + self.ipv_enabled = ipv_enabled + self.timeshift_enable = timeshift_enable + self.desktop = desktop + self.is_efi = disks.get_uefi() + self.bootloader_type = "grub-efi" if self.is_efi else "grub-legacy" + self.bootloader_location = "/boot/efi" if self.is_efi else self.disk + + def generate_json(self): + prefs = { + "partition": { + "device": self.disk, + "mode": "Auto", + "efi": self.is_efi, + "partitions": "", + }, + "bootloader": { + "type": self.bootloader_type, + "location": self.bootloader_location, + }, + "locale": { + "locale": [ + self.timezone.locale + ], + "keymap": self.layout.country_shorthand, + "timezone": self.timezone.region+"/"+self.timezone.location, + }, + "networking": { + "hostname": self.hostname, + "ipv6": self.ipv_enabled, + }, + "users": [ + { + "name": self.username, + "password": self.password, + "hasroot": self.enable_sudo, + }, + ], + "rootpass": self.password, + "desktop": self.desktop.lower(), + "unakite": { + "enable": False, + "root": "/dev/null", + "oldroot": self.disk, + "efidir": "/dev/null", + "bootdev": "/dev/null", + }, + "kernel": "linux" + } + return json.dumps(prefs) diff --git a/src/classes/meson.build b/src/classes/meson.build index 6d9f5c1..812d62a 100644 --- a/src/classes/meson.build +++ b/src/classes/meson.build @@ -5,5 +5,6 @@ jade_gui_sources = [ '__init__.py', 'locale.py', 'keymap.py', + 'install_prefs.py', ] install_data(jade_gui_sources, install_dir: classesdir) \ No newline at end of file diff --git a/src/functions/install_screen.py b/src/functions/install_screen.py index 9e34244..ec04e23 100644 --- a/src/functions/install_screen.py +++ b/src/functions/install_screen.py @@ -17,8 +17,9 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -from gi.repository import Gtk, Adw +import subprocess, os +import asyncio +from gi.repository import Gtk, GLib, Adw from gettext import gettext as _ @Gtk.Template(resource_path='/al/getcryst/jadegui/pages/install_screen.ui') @@ -29,4 +30,18 @@ class InstallScreen(Adw.Bin): def __init__(self, window, main_carousel, next_page, application, **kwargs): super().__init__(**kwargs) - self.log_text.set_text("tsarnitasnri\ntnaoietnioer\ntsarnitoarsn\ntisratnoisr") + self.window = window + + def install(self): + prefs = self.window.summary_screen.installprefs.generate_json() + with open(os.getenv("HOME")+"/test.log", "wb") as f: + process = subprocess.Popen(["bash", "-c", "bash -- /app/share/jade_gui/jade_gui/scripts/install.sh"], stdout=subprocess.PIPE) + for c in iter(lambda: process.stdout.read(1), b""): + log=c + GLib.idle_add(self.update_output, c.decode("utf-8")) + f.write(c) + + def update_output(self, message): + log=self.log_text.get_label() + new_log=f"{log}{message}" + self.log_text.set_label(new_log) diff --git a/src/functions/misc_screen.py b/src/functions/misc_screen.py index df778ef..2360623 100644 --- a/src/functions/misc_screen.py +++ b/src/functions/misc_screen.py @@ -27,7 +27,7 @@ class MiscScreen(Adw.Bin): hostname_entry = Gtk.Template.Child() ipv_switch = Gtk.Template.Child() timeshift_switch = Gtk.Template.Child() - theme_switch = Gtk.Template.Child() + #theme_switch = Gtk.Template.Child() next_page_button = Gtk.Template.Child() hostname = "crystal" @@ -46,7 +46,7 @@ class MiscScreen(Adw.Bin): def carousel_next(self, widget): self.hostname = self.hostname_entry.get_text() self.ipv_enabled = self.ipv_switch.get_state() - self.crystal_theming_enabled = self.theme_switch.get_state() + #self.crystal_theming_enabled = self.theme_switch.get_state() self.timeshift_enabled = self.timeshift_switch.get_state() if self.move_to_summary: self.window.summary_screen.initialize() diff --git a/src/functions/summary_screen.py b/src/functions/summary_screen.py index c7f38da..90da21a 100644 --- a/src/functions/summary_screen.py +++ b/src/functions/summary_screen.py @@ -17,7 +17,10 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import subprocess from jade_gui.utils import disks +from jade_gui.classes.install_prefs import InstallPrefs +from jade_gui.utils.threading import RunAsync from gi.repository import Gtk, Adw from gettext import gettext as _ @@ -25,6 +28,8 @@ from gettext import gettext as _ class SummaryScreen(Adw.Bin): __gtype_name__ = "SummaryScreen" + next_page_button = Gtk.Template.Child() + timezone_label = Gtk.Template.Child() timezone_button = Gtk.Template.Child() keyboard_label = Gtk.Template.Child() @@ -44,13 +49,20 @@ class SummaryScreen(Adw.Bin): ipv_button = Gtk.Template.Child() timeshift_label = Gtk.Template.Child() timeshift_button = Gtk.Template.Child() - theme_label = Gtk.Template.Child() - theme_button = Gtk.Template.Child() #unakite_label = Gtk.Template.Child() def __init__(self, window, main_carousel, next_page, application, **kwargs): super().__init__(**kwargs) self.window = window + self.main_carousel = main_carousel + self.next_page = next_page + self.next_page_button.connect("clicked", self.carousel_next) + + def carousel_next(self, widget): + self.main_carousel.scroll_to(self.next_page, True) + #(self.window.installer_screen.install()) + subprocess.run(["bash", "-c", "bash -- /app/share/jade_gui/jade_gui/scripts/savePrefs.sh '"+self.installprefs.generate_json()+"'"], capture_output=False) + RunAsync(self.window.installer_screen.install) def initialize(self): self.timezone_button.connect("clicked", self.window.nextPage) @@ -62,7 +74,6 @@ class SummaryScreen(Adw.Bin): self.partition_button.connect("clicked", self.window.desktop_screen.carousel_next_summary) self.ipv_button.connect("clicked", self.window.desktop_screen.carousel_next_summary) self.timeshift_button.connect("clicked", self.window.desktop_screen.carousel_next_summary) - self.theme_button.connect("clicked", self.window.desktop_screen.carousel_next_summary) self.timezone_label.set_title(self.window.timezone_screen.chosen_timezone.region+"/"+self.window.timezone_screen.chosen_timezone.location) self.timezone_label.set_subtitle(self.window.timezone_screen.chosen_timezone.locale) @@ -82,6 +93,20 @@ class SummaryScreen(Adw.Bin): self.ipv_label.set_title("ipv6 enabled" if self.window.misc_screen.ipv_enabled else "ipv6 disabled") self.timeshift_label.set_title("timeshift enabled" if self.window.misc_screen.timeshift_enabled else "timeshift disabled") - self.theme_label.set_title("Crystal theming enabled" if self.window.misc_screen.crystal_theming_enabled else "Crystal theming disabled") + #self.theme_label.set_title("Crystal theming enabled" if self.window.misc_screen.crystal_theming_enabled else "Crystal theming disabled") #self.unakite_label.set_title("Unakite enabled "+"enabled" if self.window.misc_screen.) + self.installprefs = InstallPrefs( + timezone=self.window.timezone_screen.chosen_timezone, + layout=self.window.keyboard_screen.layout, + variant=self.window.keyboard_screen.variant, + username=self.window.user_screen.username, + password=self.window.user_screen.password, + enable_sudo=self.window.user_screen.sudo_enabled, + disk=self.window.partition_screen.selected_partition, + hostname=self.window.misc_screen.hostname, + ipv_enabled=self.window.misc_screen.ipv_enabled, + timeshift_enable=self.window.misc_screen.timeshift_enabled, + desktop=self.window.desktop_screen.chosen_desktop, + ) + diff --git a/src/functions/user_screen.py b/src/functions/user_screen.py index 530824f..e1f0e13 100644 --- a/src/functions/user_screen.py +++ b/src/functions/user_screen.py @@ -95,6 +95,7 @@ class UserScreen(Adw.Bin): if self.password_entry.get_text() == self.password_confirmation.get_text(): self.next_page.set_sensitive(True) self.password_confirmation.remove_css_class('error') + self.password = self.password_entry.get_text() elif self.password_entry.get_text() != self.password_confirmation.get_text(): self.next_page.set_sensitive(False) self.password_confirmation.add_css_class('error') diff --git a/src/pages/install_screen.blp b/src/pages/install_screen.blp index adaac3a..167dd51 100644 --- a/src/pages/install_screen.blp +++ b/src/pages/install_screen.blp @@ -28,6 +28,7 @@ template InstallScreen : Adw.Bin { selectable: true; xalign: 0; yalign: 0; + styles ["monospace", "terminal"] } } } diff --git a/src/pages/misc_screen.blp b/src/pages/misc_screen.blp index 404a9d7..94901a0 100644 --- a/src/pages/misc_screen.blp +++ b/src/pages/misc_screen.blp @@ -36,13 +36,13 @@ template MiscScreen : Adw.Bin { state: true; } } - Adw.ActionRow { + /*Adw.ActionRow { title: "Enable crystal theming"; Gtk.Switch theme_switch { valign: center; state: false; } - } + }*/ } } } diff --git a/src/pages/summary_screen.blp b/src/pages/summary_screen.blp index 25c6f8a..475ad0f 100644 --- a/src/pages/summary_screen.blp +++ b/src/pages/summary_screen.blp @@ -131,7 +131,7 @@ template SummaryScreen : Adw.Bin { icon-name: "document-edit-symbolic"; } } - Adw.ActionRow theme_label { + /*Adw.ActionRow theme_label { title: "crystal theming enaled/disabled"; Gtk.Button theme_button { valign: center; @@ -139,7 +139,7 @@ template SummaryScreen : Adw.Bin { icon-name: "document-edit-symbolic"; } } - /*Adw.ActionRow unakite_label { + Adw.ActionRow unakite_label { title: "unakite enaled/disabled"; Gtk.Button { valign: center; @@ -152,5 +152,17 @@ template SummaryScreen : Adw.Bin { } } } + Gtk.Overlay { + [overlay] + Gtk.Button next_page_button { + margin-end: 20; + margin-bottom: 20; + label: "Next"; + halign: end; + valign: end; + tooltip-text: "Move to next page"; + styles ["suggested-action"] + } + } } } \ No newline at end of file diff --git a/src/scripts/install.sh b/src/scripts/install.sh new file mode 100644 index 0000000..d111006 --- /dev/null +++ b/src/scripts/install.sh @@ -0,0 +1,4 @@ +#!/usr/bin/bash +flatpak-spawn --host pkexec jade /tmp/jade.json +#flatpak-spawn --host echo "hi" +#flatpak-spawn --host pkexec whoami diff --git a/src/scripts/meson.build b/src/scripts/meson.build index 741e828..9cfc3b0 100644 --- a/src/scripts/meson.build +++ b/src/scripts/meson.build @@ -5,5 +5,7 @@ jade_gui_sources = [ 'getDisks.sh', 'getDiskSize.sh', 'checkEFI.sh', + 'install.sh', + 'savePrefs.sh', ] install_data(jade_gui_sources, install_dir: scriptsdir) \ No newline at end of file diff --git a/src/scripts/savePrefs.sh b/src/scripts/savePrefs.sh new file mode 100644 index 0000000..665b1c5 --- /dev/null +++ b/src/scripts/savePrefs.sh @@ -0,0 +1,3 @@ +#!/usr/bin/bash +#echo $1 +flatpak-spawn --host bash -c "echo $1 > /tmp/jade.json" \ No newline at end of file diff --git a/src/utils/meson.build b/src/utils/meson.build index e816d8f..e2055f6 100644 --- a/src/utils/meson.build +++ b/src/utils/meson.build @@ -4,5 +4,6 @@ utilsdir = join_paths(pkgdatadir, 'jade_gui/utils') jade_gui_sources = [ '__init__.py', 'disks.py', + 'threading.py', ] install_data(jade_gui_sources, install_dir: utilsdir) \ No newline at end of file diff --git a/src/utils/threading.py b/src/utils/threading.py new file mode 100644 index 0000000..a204b05 --- /dev/null +++ b/src/utils/threading.py @@ -0,0 +1,74 @@ +# This file was taken from bottles with the permission from brombinmirko +# +# threading.py +# +# Copyright 2022 brombinmirko +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, in version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import sys +import threading +import traceback + +from gettext import gettext as _ + +from gi.repository import GLib + + + +class RunAsync(threading.Thread): + """ + This class is used to execute a function asynchronously. + It takes a function, a callback and a list of arguments as input. + """ + + def __init__(self, task_func, callback=None, *args, **kwargs): + if "DEBUG_MODE" in os.environ: + import faulthandler + faulthandler.enable() + + self.source_id = None + assert threading.current_thread() is threading.main_thread() + + super(RunAsync, self).__init__( + target=self.__target, args=args, kwargs=kwargs) + + self.task_func = task_func + + self.callback = callback if callback else lambda r, e: None + self.daemon = kwargs.pop("daemon", True) + + self.start() + + def __target(self, *args, **kwargs): + result = None + error = None + + print(f"DEBUG: Running async job [{self.task_func}].") + + try: + result = self.task_func(*args, **kwargs) + except Exception as exception: + print("ERROR: while running async job: " + f"{self.task_func}\nException: {exception}") + + error = exception + _ex_type, _ex_value, trace = sys.exc_info() + traceback.print_tb(trace) + traceback_info = '\n'.join(traceback.format_tb(trace)) + + print([str(exception), traceback_info]) + self.source_id = GLib.idle_add(self.callback, result, error) + return self.source_id +