add basic functionality for user/system toggle
This commit is contained in:
parent
b0b6b0c9df
commit
ecda8b258a
2 changed files with 113 additions and 47 deletions
|
|
@ -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
125
main.py
|
|
@ -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"""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue