add basic functionality for user/system toggle

This commit is contained in:
GloriousEggroll 2025-03-27 05:52:26 -06:00
parent b0b6b0c9df
commit ecda8b258a
2 changed files with 113 additions and 47 deletions

View file

@ -246,8 +246,8 @@ class AppstreamSearcher:
packages = []
metadata = AppStream.Metadata.new()
metadata.set_format_style(AppStream.FormatStyle.CATALOG)
if self.refresh:
inst.update_appstream_full_sync(remote.get_name(), None, None, True)
#if self.refresh:
# inst.update_appstream_full_sync(remote.get_name(), None, None, True)
appstream_file = Path(remote.get_appstream_dir().get_path() + "/appstream.xml.gz")
if appstream_file.exists():
metadata.parse_file(Gio.File.new_for_path(appstream_file.as_posix()), AppStream.FormatKind.XML)
@ -333,9 +333,8 @@ class AppstreamSearcher:
installation = get_installation(system)
def process_installed_refs(inst: Flatpak.Installation, system=False):
for ref in inst.list_installed_refs_by_kind(Flatpak.RefKind.APP):
app_id = ref.format_ref()
# Get remote name from the installation
for ref in inst.list_installed_refs():
app_id = ref.get_name()
remote_name = ref.get_origin()
if system is False:
installed_refs.append((app_id, remote_name, "user"))
@ -461,8 +460,6 @@ class AppstreamSearcher:
if "installed" in category:
installed_apps = searcher.get_installed_apps()
for app_id, repo_name, repo_type in installed_apps:
parts = app_id.split('/')
app_id = parts[parts.index('app') + 1]
if repo_name:
search_result = searcher.search_flatpak(app_id, repo_name)
self.installed_results.extend(search_result)
@ -485,10 +482,13 @@ class AppstreamSearcher:
if not check_internet():
return self._handle_offline_mode()
if system:
refresh = False
searcher = get_reposearcher(system, refresh)
self.all_apps = searcher.get_all_apps()
return self._process_categories(searcher)
return self._process_categories(searcher, system)
def _initialize_metadata(self):
"""Initialize empty lists for metadata storage."""
@ -520,7 +520,7 @@ class AppstreamSearcher:
self.collection_results.extend(search_result)
return self._get_current_results()
def _process_categories(self, searcher):
def _process_categories(self, searcher, system=False):
"""Process categories and retrieve metadata."""
total_categories = sum(len(categories) for categories in self.category_groups.values())
current_category = 0
@ -530,7 +530,7 @@ class AppstreamSearcher:
if category not in self.category_groups['system']:
self._process_category(searcher, category, current_category, total_categories)
else:
self._process_system_category(searcher, category)
self._process_system_category(searcher, category, system)
current_category += 1
return self._get_current_results()
@ -585,18 +585,16 @@ class AppstreamSearcher:
except requests.RequestException as e:
logger.error(f"Error refreshing category {category}: {str(e)}")
def _process_system_category(self, searcher, category):
def _process_system_category(self, searcher, category, system=False):
"""Process system-related categories."""
if "installed" in category:
installed_apps = searcher.get_installed_apps()
installed_apps = searcher.get_installed_apps(system)
for app_id, repo_name, repo_type in installed_apps:
parts = app_id.split('/')
app_id = parts[parts.index('app') + 1]
if repo_name:
search_result = searcher.search_flatpak(app_id, repo_name)
self.installed_results.extend(search_result)
elif "updates" in category:
updates = searcher.check_updates()
updates = searcher.check_updates(system)
for app_id, repo_name, repo_type in updates:
if repo_name:
search_result = searcher.search_flatpak(app_id, repo_name)
@ -617,6 +615,7 @@ def install_flatpak(app: AppStreamPackage, repo_name=None, system=False) -> tupl
Args:
app (AppStreamPackage): The package to install.
repo_name (str): Optional repository name to use for installation
system (Optional[bool]): Whether to operate on user or system installation
Returns:
tuple[bool, str]: (success, message)
@ -644,7 +643,7 @@ def remove_flatpak(app: AppStreamPackage, repo_name=None, system=False) -> tuple
Args:
app (AppStreamPackage): The package to install.
user (Optional[bool]): Whether to operate on user or system installation
system (Optional[bool]): Whether to operate on user or system installation
Returns:
Tuple[bool, str]: (success, message)
@ -872,6 +871,8 @@ def main():
parser.add_argument('--remove', type=str, metavar='APP_ID',
help='Remove a Flatpak package')
parser.add_argument('--system', action='store_true', help='Install as system instead of user')
parser.add_argument('--refresh', action='store_true', help='Install as system instead of user')
parser.add_argument('--refresh-local', action='store_true', help='Install as system instead of user')
args = parser.parse_args()
@ -978,8 +979,6 @@ def handle_list_installed(args, searcher):
installed_apps = searcher.get_installed_apps(args.system)
print(f"\nInstalled Flatpak Applications ({len(installed_apps)}):")
for app_id, repo_name, repo_type in installed_apps:
parts = app_id.split('/')
app_id = parts[parts.index('app') + 1]
print(f"{app_id} (Repository: {repo_name}, Installation: {repo_type})")
def handle_check_updates(args, searcher):

125
main.py
View file

@ -8,6 +8,7 @@ from gi.repository import Gtk, Gio, Gdk, GLib
import libflatpak_query
import json
import threading
import subprocess
class MainWindow(Gtk.Window):
def __init__(self):
@ -159,10 +160,13 @@ class MainWindow(Gtk.Window):
)
# Create main layout
self.main_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
self.main_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.add(self.main_box)
# Create_header_bar
self.create_header_bar()
# Create panels
self.create_panels()
@ -171,6 +175,85 @@ class MainWindow(Gtk.Window):
# Select Trending by default
self.select_default_category()
def create_header_bar(self):
# Create horizontal bar
self.top_bar = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
self.top_bar.set_hexpand(True)
self.top_bar.set_spacing(6)
self.top_bar.set_border_width(6)
# Add search bar
self.searchbar = Gtk.SearchBar() # Use self.searchbar instead of searchbar
self.searchbar.set_hexpand(True)
self.searchbar.set_margin_bottom(6)
# Create search entry with icon
searchentry = Gtk.SearchEntry()
searchentry.set_placeholder_text("Search applications...")
searchentry.set_icon_from_gicon(Gtk.EntryIconPosition.PRIMARY,
Gio.Icon.new_for_string('search'))
# Connect search entry signals
searchentry.connect("search-changed", self.on_search_changed)
searchentry.connect("activate", self.on_search_activate)
# Connect search entry to search bar
self.searchbar.connect_entry(searchentry)
self.searchbar.add(searchentry)
self.searchbar.set_search_mode(True)
self.top_bar.pack_start(self.searchbar, False, False, 0)
# Create system mode switch box
system_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
# Create system mode switch
self.system_switch = Gtk.Switch()
self.system_switch.connect("notify::active", self.on_system_mode_toggled)
self.system_switch.set_vexpand(False)
# Create system mode label
system_label = Gtk.Label(label="System")
# Pack switch and label
system_box.pack_end(system_label, False, False, 0)
system_box.pack_end(self.system_switch, False, False, 0)
# Add system controls to header
self.top_bar.pack_end(system_box, False, False, 0)
# Add the top bar to the main box
self.main_box.pack_start(self.top_bar, False, True, 0)
def on_system_mode_toggled(self, switch, gparam):
"""Handle system mode toggle switch state changes"""
desired_state = switch.get_active()
if desired_state:
# Request superuser validation
try:
subprocess.run(['pkexec', 'true'], check=True)
self.system_mode = True
self.refresh_data()
self.refresh_current_page()
except subprocess.CalledProcessError:
switch.set_active(False)
dialog = Gtk.MessageDialog(
transient_for=self,
message_type=Gtk.MessageType.ERROR,
buttons=Gtk.ButtonsType.OK,
text="Authentication failed",
secondary_text="Could not enable system mode"
)
dialog.connect("response", lambda d, r: d.destroy())
dialog.show()
else:
if self.system_mode == True:
self.system_mode = False
self.refresh_data()
self.refresh_current_page()
def populate_repo_dropdown(self):
# Get list of repositories
libflatpak_query.repolist(self.system_mode)
@ -282,15 +365,22 @@ class MainWindow(Gtk.Window):
if hasattr(self, 'right_panel') and self.right_panel.get_parent():
self.main_box.remove(self.right_panel)
# Create right panel
self.right_panel = self.create_applications_panel("Applications")
# Create left panel with grouped categories
self.left_panel = self.create_grouped_category_panel("Categories", self.category_groups)
# Create right panel
self.right_panel = self.create_applications_panel("Applications")
# Create panels container
self.panels_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
self.panels_box.set_hexpand(True)
# Pack the panels with proper expansion
self.main_box.pack_end(self.right_panel, True, True, 0) # Right panel expands both ways
self.main_box.pack_start(self.left_panel, False, False, 0) # Left panel doesn't expand
self.panels_box.pack_start(self.left_panel, False, False, 0) # Left panel doesn't expand
self.panels_box.pack_end(self.right_panel, True, True, 0) # Right panel expands both ways
# Add panels container to main box
self.main_box.pack_start(self.panels_box, True, True, 0)
def create_grouped_category_panel(self, title, groups):
@ -304,25 +394,6 @@ class MainWindow(Gtk.Window):
panel_container.set_halign(Gtk.Align.FILL) # Fill horizontally
panel_container.set_valign(Gtk.Align.FILL) # Align to top
# Add search bar
self.searchbar = Gtk.SearchBar() # Use self.searchbar instead of searchbar
self.searchbar.set_hexpand(True)
self.searchbar.set_margin_bottom(6)
# Create search entry with icon
searchentry = Gtk.SearchEntry()
searchentry.set_placeholder_text("Search applications...")
searchentry.set_icon_from_gicon(Gtk.EntryIconPosition.PRIMARY,
Gio.Icon.new_for_string('search'))
# Connect search entry signals
searchentry.connect("search-changed", self.on_search_changed)
searchentry.connect("activate", self.on_search_activate)
# Connect search entry to search bar
self.searchbar.connect_entry(searchentry)
self.searchbar.add(searchentry)
# Create scrollable area
scrolled_window = Gtk.ScrolledWindow()
scrolled_window.set_hexpand(True)
@ -393,13 +464,9 @@ class MainWindow(Gtk.Window):
scrolled_window.add(container)
# Pack the scrolled window directly into main box
panel_container.pack_start(self.searchbar, False, False, 0)
panel_container.pack_start(scrolled_window, True, True, 0)
self.searchbar.set_search_mode(True)
return panel_container
#self.searchbar.show_all()
def on_search_changed(self, searchentry):
"""Handle search text changes"""