Commit 1e760ee0 authored by Roman Alifanov's avatar Roman Alifanov

initial commit

parents
#!/usr/bin/python3
import sys
import gi
import subprocess
import threading
gi.require_version('Gtk', '4.0')
gi.require_version('Adw', '1')
from gi.repository import Gtk, Adw, GLib
class CommandRunner:
def __init__(self, on_done=None):
self.dialog = None
self.textbuffer = None
self.on_done = on_done # Callback function to be called after completion
def run_command(self, command, dialog):
self.dialog = dialog
self.textbuffer = dialog.get_child().get_child().get_buffer()
def append_log(text):
GLib.idle_add(self.textbuffer.insert_at_cursor, text)
GLib.idle_add(dialog.get_child().get_child().scroll_to_mark,
self.textbuffer.get_insert(), 0, False, 0.0, 1.0)
def read_output(source):
while True:
line = source.readline()
if line:
GLib.idle_add(append_log, line)
else:
break
def process_runner():
try:
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, text=True)
threading.Thread(target=read_output, args=(process.stdout,)).start()
threading.Thread(target=read_output, args=(process.stderr,)).start()
process.wait()
GLib.idle_add(dialog.close)
if self.on_done:
GLib.idle_add(self.on_done) # Call the callback function after completion
except subprocess.CalledProcessError as e:
GLib.idle_add(append_log, f"Ошибка: {str(e)}\n")
GLib.idle_add(dialog.close)
if self.on_done:
GLib.idle_add(self.on_done) # Call the callback function after completion
threading.Thread(target=process_runner).start()
class ApplicationManager:
@staticmethod
def get_available_applications():
output = subprocess.check_output(["epm", "play", "--list-all"], universal_newlines=True)
return ApplicationManager.parse_applications_output(output)
@staticmethod
def get_installed_applications():
output = subprocess.check_output(["epm", "play", "--list"], universal_newlines=True)
return ApplicationManager.parse_installed_applications_output(output)
@staticmethod
def parse_applications_output(output):
lines = output.splitlines()[1:]
applications = []
for line in lines:
parts = line.split(' - ')
if len(parts) == 2: # Ensure that line has exactly 2 parts
name, dscr = parts
applications.append({'name': name.strip().replace('&', '&'),
'dscr': dscr.strip().replace('&', '&')})
return applications
@staticmethod
def parse_installed_applications_output(output):
lines = output.splitlines()[1:]
return [line.split(' - ')[0].strip().split()[0] for line in lines]
class MainWindow(Gtk.ApplicationWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.set_title("eepm play gui")
self.set_default_size(400, 600)
# Инициализация основного контейнера
self.box1 = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.set_child(self.box1)
# Создание элементов UI
self.create_ui_elements()
self.show_loading_message()
self.load_applications()
def create_ui_elements(self):
# Создание скролл-окна
self.scrolled_window = Gtk.ScrolledWindow()
self.scrolled_window.set_vexpand(True)
# Создание контейнера для содержимого и группы настроек
self.content_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.preferences_group = Adw.PreferencesGroup()
self.content_box.append(self.preferences_group)
# Добавление скролл-окна в основной контейнер
self.scrolled_window.set_child(self.content_box)
self.box1.append(self.scrolled_window)
# Кнопка применения
apply_button = Gtk.Button(label="Применить")
apply_button.connect("clicked", self.on_apply_clicked)
self.box1.append(apply_button)
# Создание и добавление сообщения о загрузке
self.loading_label = Gtk.Label(label="Загрузка, пожалуйста подождите...")
self.content_box.append(self.loading_label)
self.loading_label.set_visible(False) # Изначально скрыта
def show_loading_message(self):
self.loading_label.set_visible(True)
self.preferences_group.set_visible(False) # Скрыть группу настроек во время загрузки
def hide_loading_message(self):
self.loading_label.set_visible(False)
self.preferences_group.set_visible(True) # Показать группу настроек после загрузки
def load_applications(self):
def on_done():
self.hide_loading_message() # Скрыть сообщение о загрузке, когда загрузка завершена
# Асинхронная загрузка приложений
GLib.idle_add(self._load_applications_async, on_done)
def _load_applications_async(self, on_done):
# Симуляция долгой операции
def simulate_long_running_op():
self.applications = ApplicationManager.get_available_applications()
GLib.idle_add(self.update_ui) # Обновление UI с новыми данными
GLib.idle_add(on_done)
threading.Thread(target=simulate_long_running_op).start()
def update_ui(self):
# Обновление списка установленных приложений
self.installed_apps = ApplicationManager.get_installed_applications()
# Удаление текущего preferences_group
if self.preferences_group:
self.content_box.remove(self.preferences_group)
self.preferences_group = None
# Создание нового preferences_group
self.preferences_group = Adw.PreferencesGroup()
self.content_box.append(self.preferences_group)
# Добавление новых элементов
self.checkboxes = {}
for app in self.applications:
self.add_application_row(app)
def add_application_row(self, app):
row = Adw.ActionRow(title=app['name'], subtitle=app['dscr'])
checkbox = Gtk.CheckButton()
checkbox.set_active(app['name'] in self.installed_apps)
checkbox.connect("toggled", self.on_checkbox_toggled, app['name'])
row.add_suffix(checkbox)
self.preferences_group.add(row)
self.checkboxes[app['name']] = checkbox
def on_checkbox_toggled(self, checkbox, app_name):
active = checkbox.get_active()
print(f"{app_name} {'установлен' if active else 'снят'}")
def on_apply_clicked(self, button):
self.show_loading_message() # Показать сообщение о загрузке перед выполнением команды
to_install, to_remove = self.get_install_remove_lists()
commands = self.build_commands(to_install, to_remove)
if commands:
full_command = " && ".join(commands)
pkexec_command = f'pkexec sh -c "{full_command}"'
self.show_log_dialog(pkexec_command)
def get_install_remove_lists(self):
to_install = [app_name for app_name, checkbox in self.checkboxes.items() if checkbox.get_active() and app_name not in self.installed_apps]
to_remove = [app_name for app_name, checkbox in self.checkboxes.items() if not checkbox.get_active() and app_name in self.installed_apps]
return to_install, to_remove
def build_commands(self, to_install, to_remove):
commands = []
if to_install:
commands.append(f"epm play --auto {' '.join(to_install)}")
if to_remove:
commands.append(f"epm play --auto --remove {' '.join(to_remove)}")
return commands
def show_log_dialog(self, command):
dialog = Gtk.Dialog(title="Лог выполнения", transient_for=self, modal=True)
dialog.set_default_size(400, 300)
textview = Gtk.TextView()
textview.set_editable(False)
textbuffer = textview.get_buffer()
scrolled_window = Gtk.ScrolledWindow()
scrolled_window.set_child(textview)
scrolled_window.set_vexpand(True)
dialog.set_child(scrolled_window)
dialog.present()
# Создание и передача функции обратного вызова для обновления UI
runner = CommandRunner(on_done=self.update_ui_after_log)
runner.run_command(command, dialog)
def update_ui_after_log(self):
self.update_ui() # Обновление UI после закрытия диалога
self.hide_loading_message() # Скрыть сообщение о загрузке после закрытия диалога
class MyApp(Adw.Application):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.connect('activate', self.on_activate)
def on_activate(self, app):
self.win = MainWindow(application=app)
self.win.present()
if __name__ == "__main__":
app = MyApp(application_id="com.example.GtkApplication")
app.run(sys.argv)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment