Commit 0fe97096 authored by Roman Alifanov's avatar Roman Alifanov

implemented `epm play --product-alternatives` support

parent d2dbfef2
......@@ -48,9 +48,13 @@ class ApplicationManager:
parts = line.split(' - ', 1) # Ограничить сплит до 2 частей
if len(parts) == 2:
name, dscr = map(str.strip, parts)
alternatives = ApplicationManager.get_alternatives(name)
applications.append({
'name': name.replace('&', '&'),
'dscr': dscr.replace('&', '&')
'dscr': dscr.replace('&', '&'),
"alt": alternatives.split()
})
else:
# Логгирование некорректной строки для диагностики
......@@ -59,6 +63,14 @@ class ApplicationManager:
return applications
@staticmethod
def get_alternatives(name):
alternatives, stderr = subprocess.Popen([
"epm", "play", "--product-alternatives", name
], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, text=True, bufsize=1
).communicate()
return alternatives
@staticmethod
def parse_installed_applications_output(output):
lines = output.splitlines()[1:]
return [line.split(' - ')[0].strip().split()[0] for line in lines]
......@@ -77,7 +77,6 @@ class ApplicationRow(Adw.ActionRow):
super().__init__(title=app['name'], subtitle=app['dscr'])
self.app = app
self.is_installed = is_installed
self.set_selectable(False)
self.set_activatable(True)
......@@ -86,6 +85,22 @@ class ApplicationRow(Adw.ActionRow):
self.add_prefix(self.icon_image)
IconLoader.load_icon_async(self.app['name'], self.set_icon)
self.have_alternatives = False
alternatives = Gtk.StringList()
if app["alt"]:
self.have_alternatives = True
alternatives.append("default")
for alternative in app["alt"]:
alternatives.append(alternative)
self.alt_dropdown = Gtk.DropDown()
self.alt_dropdown.props.model = alternatives
self.alt_dropdown.set_valign(Gtk.Align.CENTER)
self.alt_dropdown.set_halign(Gtk.Align.CENTER)
self.add_suffix(self.alt_dropdown)
self.checkbox = Gtk.CheckButton()
self.checkbox.add_css_class("selection-mode")
......
......@@ -16,7 +16,7 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# SPDX-License-Identifier: AGPL-3.0-or-later
from gi.repository import Gtk, Adw, GObject
from gi.repository import Gtk, Adw, GObject, GLib
import gettext
......@@ -114,24 +114,35 @@ class EepmPlayGuiWindow(Adw.ApplicationWindow):
self.props.is_loading = True
self.update_button_status()
ApplicationManager.get_available_applications(self.on_applications_loaded)
ApplicationManager.get_installed_applications(self.on_installed_apps_loaded)
def on_installed_apps_loaded(self, installed_apps, error=None):
if error:
print(f"Error: {error}")
else:
self.installed_apps = installed_apps
self.clear_choice_listbox()
self.props.is_loading = False
return
self.rows = {}
for app in self.applications:
self.add_application_row(app)
self.installed_apps = installed_apps
self.clear_choice_listbox()
self.rows = {}
GLib.timeout_add(100, self.check_applications_loaded)
self.choice_listbox.invalidate_filter()
self.props.is_loading = False
def check_applications_loaded(self):
if self.applications is not None:
print("Applications loaded. Updating UI...")
self.populate_choice_listbox()
self.update_button_status()
return False
return True
def populate_choice_listbox(self):
for app in self.applications:
self.add_application_row(app)
self.choice_listbox.invalidate_filter()
self.props.is_loading = False
def clear_choice_listbox(self):
self.choice_listbox.remove_all()
......@@ -152,7 +163,7 @@ class EepmPlayGuiWindow(Adw.ApplicationWindow):
def update_button_status(self):
"""Update the button status based on the current selection."""
to_install, to_remove = self.get_install_remove_lists()
to_install, to_remove = self.get_current_status()
button_states = {
(True, True): (_("Remove and install applications"), "suggested-action"),
......@@ -171,6 +182,22 @@ class EepmPlayGuiWindow(Adw.ApplicationWindow):
# Add the new CSS class
self.apply_button.add_css_class(css_class)
def get_current_status(self):
installed_apps = self.installed_apps or []
rows = self.rows or {}
to_install = [
app_name for app_name, row in rows.items()
if row.checkbox.get_active() and app_name not in installed_apps
]
to_remove = [
app_name for app_name, row in rows.items()
if not row.checkbox.get_active() and app_name in installed_apps
]
return to_install, to_remove
def on_search_changed(self, search_entry):
self.choice_listbox.invalidate_filter() # Обновление фильтра при изменении поиска
......@@ -233,7 +260,8 @@ class EepmPlayGuiWindow(Adw.ApplicationWindow):
rows = self.rows or {}
to_install = [
app_name for app_name, row in rows.items()
app_name + "=" + row.alt_dropdown.props.selected_item.props.string if row.have_alternatives and row.alt_dropdown.props.selected_item.props.string != "default" else app_name
for app_name, row in rows.items()
if row.checkbox.get_active() and app_name not in installed_apps
]
......
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