mirror of
https://github.com/morgan9e/warehouse
synced 2026-04-15 00:34:42 +09:00
Add remote from file & more
Add remote from a repo file either from the picker in the popular remotes window or by a drag and drop. Allow main menu to be opened with F10
This commit is contained in:
@@ -5,7 +5,7 @@ ShortcutsWindow help_overlay {
|
||||
|
||||
ShortcutsSection {
|
||||
section-name: "shortcuts";
|
||||
max-height: 7;
|
||||
max-height: 8;
|
||||
|
||||
ShortcutsGroup {
|
||||
title: C_("shortcut window", "App Management");
|
||||
@@ -56,6 +56,11 @@ ShortcutsWindow help_overlay {
|
||||
ShortcutsGroup {
|
||||
title: C_("shortcut window", "General");
|
||||
|
||||
ShortcutsShortcut {
|
||||
title: C_("shortcut window", "Open Menu");
|
||||
action-name: "app.open-menu";
|
||||
}
|
||||
|
||||
ShortcutsShortcut {
|
||||
title: C_("shortcut window", "Show Shortcuts");
|
||||
action-name: "win.show-help-overlay";
|
||||
|
||||
@@ -50,6 +50,7 @@ class WarehouseApplication(Adw.Application):
|
||||
self.create_action("show-remotes-window", self.show_remotes_shortcut, ["<primary>m"])
|
||||
self.create_action("set-filter", self.filters_shortcut, ["<primary>t"])
|
||||
self.create_action("install-from-file", self.install_from_file, ["<primary>o"])
|
||||
self.create_action("open-menu", self.main_menu_shortcut, ["F10"])
|
||||
|
||||
def batch_mode_shortcut(self, widget, _):
|
||||
button = self.props.active_window.batch_mode_button
|
||||
@@ -75,6 +76,10 @@ class WarehouseApplication(Adw.Application):
|
||||
window = self.props.active_window
|
||||
window.filterWindowKeyboardHandler(window)
|
||||
|
||||
def main_menu_shortcut(self, widget, _):
|
||||
window = self.props.active_window
|
||||
window.main_menu.set_active(True)
|
||||
|
||||
def file_callback(self, object, result):
|
||||
window = self.props.active_window
|
||||
try:
|
||||
|
||||
@@ -3,7 +3,7 @@ using Adw 1;
|
||||
|
||||
template PopularRemotesWindow : Adw.Window {
|
||||
default-width: 450;
|
||||
default-height: 613;
|
||||
default-height: 530;
|
||||
title: "";
|
||||
|
||||
Adw.ToolbarView main_toolbar_view {
|
||||
@@ -16,7 +16,7 @@ template PopularRemotesWindow : Adw.Window {
|
||||
Adw.StatusPage {
|
||||
valign: start;
|
||||
title: _("Add a Remote");
|
||||
description: _("Choose from a list of popular remotes.");
|
||||
description: _("Choose from a list of popular remotes or add a new one.");
|
||||
Adw.Clamp {
|
||||
Box {
|
||||
orientation: vertical;
|
||||
@@ -31,6 +31,15 @@ template PopularRemotesWindow : Adw.Window {
|
||||
valign: start;
|
||||
selection-mode: none;
|
||||
styles["boxed-list"]
|
||||
|
||||
Adw.ActionRow add_from_file {
|
||||
title: _("Add a Repo File");
|
||||
activatable: true;
|
||||
}
|
||||
Adw.ActionRow custom_remote {
|
||||
title: _("Add a Custom Remote");
|
||||
activatable: true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,34 +12,52 @@ class PopularRemotesWindow(Adw.Window):
|
||||
list_of_remotes = Gtk.Template.Child()
|
||||
custom_list = Gtk.Template.Child()
|
||||
toast_overlay = Gtk.Template.Child()
|
||||
add_from_file = Gtk.Template.Child()
|
||||
custom_remote = Gtk.Template.Child()
|
||||
|
||||
def key_handler(self, _a, event, _c, _d):
|
||||
if event == Gdk.KEY_Escape:
|
||||
self.close()
|
||||
|
||||
def file_callback(self, object, result):
|
||||
try:
|
||||
file = object.open_finish(result)
|
||||
self.parent_window.addRemoteFromFile(file.get_path())
|
||||
self.close()
|
||||
except GLib.GError:
|
||||
pass
|
||||
|
||||
def addFromFileHandler(self, widet):
|
||||
filter = Gtk.FileFilter(name=_("Flatpaks Repos"))
|
||||
filter.add_suffix("flatpakrepo")
|
||||
filters = Gio.ListStore.new(Gtk.FileFilter)
|
||||
filters.append(filter)
|
||||
file_chooser = Gtk.FileDialog()
|
||||
file_chooser.set_filters(filters)
|
||||
file_chooser.set_default_filter(filter)
|
||||
file_chooser.open(self, None, self.file_callback)
|
||||
|
||||
def generate_list(self):
|
||||
self.host_remotes = self.my_utils.getHostRemotes()
|
||||
self.list_of_remotes.remove_all()
|
||||
self.custom_list.remove_all()
|
||||
host_remotes_names = []
|
||||
|
||||
for i in range(len(self.remotes)):
|
||||
remote_row = Adw.ActionRow(activatable=True)
|
||||
remote_row.set_title(self.remotes[i][0])
|
||||
remote_row.set_subtitle(self.remotes[i][3])
|
||||
image = Gtk.Image.new_from_icon_name("right-large-symbolic")
|
||||
remote_row.add_suffix(image)
|
||||
remote_row.add_suffix(Gtk.Image.new_from_icon_name("right-large-symbolic"))
|
||||
remote_row.connect("activated", self.parent_window.add_handler, self.remotes[i][1], self.remotes[i][2])
|
||||
remote_row.connect("activated", lambda *_: self.close())
|
||||
self.list_of_remotes.append(remote_row)
|
||||
|
||||
image2 = Gtk.Image.new_from_icon_name("right-large-symbolic")
|
||||
custom_remote = Adw.ActionRow(activatable=True)
|
||||
custom_remote.set_title(_("Add a Custom Remote"))
|
||||
custom_remote.add_suffix(image2)
|
||||
custom_remote.connect("activated", self.parent_window.add_handler)
|
||||
custom_remote.connect("activated", lambda *_: self.close())
|
||||
self.custom_list.append(custom_remote)
|
||||
self.add_from_file.add_suffix(Gtk.Image.new_from_icon_name("right-large-symbolic"))
|
||||
self.add_from_file.connect("activated", self.addFromFileHandler)
|
||||
#self.add_from_file.connect("activated", lambda *_: self.close())
|
||||
|
||||
self.custom_remote.add_suffix(Gtk.Image.new_from_icon_name("right-large-symbolic"))
|
||||
self.custom_remote.connect("activated", self.parent_window.add_handler)
|
||||
self.custom_remote.connect("activated", lambda *_: self.close())
|
||||
|
||||
if not self.list_of_remotes.get_row_at_index(0):
|
||||
self.list_of_remotes.set_visible(False)
|
||||
|
||||
@@ -106,7 +106,7 @@ class RemotesWindow(Adw.Window):
|
||||
def addRemoteThread(self, command):
|
||||
try:
|
||||
subprocess.run(command, capture_output=True, check=True, env=self.new_env)
|
||||
except Exception as e:
|
||||
except subprocess.CalledProcessError as e:
|
||||
self.toast_overlay.add_toast(Adw.Toast.new(_("Could not add {}").format(self.name_to_add)))
|
||||
print(e)
|
||||
|
||||
@@ -235,6 +235,86 @@ class RemotesWindow(Adw.Window):
|
||||
if link != "":
|
||||
url_update(url_entry)
|
||||
|
||||
def addRemoteFromFileThread(self, filepath, system_or_user, name):
|
||||
try:
|
||||
subprocess.run(['flatpak-spawn', '--host', 'flatpak', 'remote-add', name, filepath, f"--{system_or_user}"], capture_output=True, check=True, env=self.new_env)
|
||||
self.toast_overlay.add_toast(Adw.Toast.new(_("{} successfully added").format(name)))
|
||||
except subprocess.CalledProcessError as e:
|
||||
self.toast_overlay.add_toast(Adw.Toast.new(_("Could not add {}").format(self.name_to_add)))
|
||||
print(e)
|
||||
|
||||
def addRemoteFromFile(self, filepath):
|
||||
def response(dialog, response, _a):
|
||||
if response == "cancel":
|
||||
self.should_pulse = False
|
||||
return
|
||||
|
||||
self.progress_bar.set_visible(True)
|
||||
user_or_system = "user"
|
||||
if system_check.get_active():
|
||||
user_or_system = "system"
|
||||
|
||||
task = Gio.Task.new(None, None, self.addRemoteCallback)
|
||||
task.run_in_thread(lambda *_: self.addRemoteFromFileThread(filepath, user_or_system, name_row.get_text()))
|
||||
|
||||
def name_update(widget):
|
||||
is_enabled = True
|
||||
self.name_to_add = widget.get_text()
|
||||
name_pattern = re.compile(r'^[a-zA-Z\-]+$')
|
||||
if not name_pattern.match(self.name_to_add):
|
||||
is_enabled = False
|
||||
|
||||
if is_enabled:
|
||||
widget.remove_css_class("error")
|
||||
else:
|
||||
widget.add_css_class("error")
|
||||
|
||||
if len(self.name_to_add) == 0:
|
||||
is_enabled = False
|
||||
|
||||
dialog.set_response_enabled("continue", is_enabled)
|
||||
|
||||
self.should_pulse = True
|
||||
self.mainPulser()
|
||||
|
||||
name = filepath.split('/')
|
||||
name = name[len(name) - 1]
|
||||
|
||||
dialog = Adw.MessageDialog.new(self, _("Add {}?").format(name))
|
||||
dialog.set_close_response("cancel")
|
||||
dialog.add_response("cancel", _("Cancel"))
|
||||
dialog.add_response("continue", _("Add"))
|
||||
dialog.set_response_enabled("continue", False)
|
||||
dialog.set_response_appearance("continue", Adw.ResponseAppearance.SUGGESTED)
|
||||
dialog.connect("response", response, dialog.choose_finish)
|
||||
|
||||
# Create Widgets
|
||||
options_box = Gtk.Box(orientation="vertical")
|
||||
options_list = Gtk.ListBox(selection_mode="none", margin_top=15)
|
||||
name_row = Adw.EntryRow(title=_("Name"))
|
||||
name_row.connect("changed", name_update)
|
||||
user_row = Adw.ActionRow(title=_("User"), subtitle=_("The app will be available to only you"))
|
||||
system_row = Adw.ActionRow(title=_("System"), subtitle=_("The app will be available to every user on the system"))
|
||||
user_check = Gtk.CheckButton()
|
||||
system_check = Gtk.CheckButton()
|
||||
|
||||
# Apply Widgets
|
||||
user_row.add_prefix(user_check)
|
||||
user_row.set_activatable_widget(user_check)
|
||||
system_row.add_prefix(system_check)
|
||||
system_row.set_activatable_widget(system_check)
|
||||
user_check.set_group(system_check)
|
||||
options_list.append(name_row)
|
||||
options_list.append(user_row)
|
||||
options_list.append(system_row)
|
||||
options_box.append(options_list)
|
||||
dialog.set_extra_child(options_box)
|
||||
|
||||
# Calls
|
||||
user_check.set_active(True)
|
||||
options_list.add_css_class("boxed-list")
|
||||
Gtk.Window.present(dialog)
|
||||
|
||||
def showPopularRemotes(self, widget):
|
||||
|
||||
remotes = [
|
||||
@@ -259,10 +339,7 @@ class RemotesWindow(Adw.Window):
|
||||
if remotes[i][1] not in host_remotes_names:
|
||||
non_added_remotes.append(remotes[i])
|
||||
|
||||
if len(non_added_remotes) > 0:
|
||||
PopularRemotesWindow(self, non_added_remotes).present()
|
||||
else:
|
||||
self.add_handler(widget)
|
||||
PopularRemotesWindow(self, non_added_remotes).present()
|
||||
|
||||
def __init__(self, main_window, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
@@ -27,7 +27,7 @@ template WarehouseWindow : Adw.ApplicationWindow {
|
||||
}
|
||||
|
||||
[end]
|
||||
MenuButton {
|
||||
MenuButton main_menu {
|
||||
icon-name: "open-menu-symbolic";
|
||||
tooltip-text: _("Main Menu");
|
||||
menu-model: primary_menu;
|
||||
|
||||
@@ -19,11 +19,13 @@
|
||||
import os
|
||||
import pathlib
|
||||
import subprocess
|
||||
import re
|
||||
|
||||
from gi.repository import Adw, Gdk, Gio, GLib, Gtk
|
||||
from .properties_window import show_properties_window
|
||||
from .filter_window import FilterWindow
|
||||
from .common import myUtils
|
||||
from .remotes_window import RemotesWindow
|
||||
|
||||
@Gtk.Template(resource_path="/io/github/flattool/Warehouse/window.ui")
|
||||
class WarehouseWindow(Adw.ApplicationWindow):
|
||||
@@ -48,6 +50,7 @@ class WarehouseWindow(Adw.ApplicationWindow):
|
||||
main_toolbar_view = Gtk.Template.Child()
|
||||
filter_button = Gtk.Template.Child()
|
||||
scrolled_window = Gtk.Template.Child()
|
||||
main_menu = Gtk.Template.Child()
|
||||
|
||||
main_progress_bar = Gtk.ProgressBar(visible=False, pulse_step=0.7, can_target=False)
|
||||
main_progress_bar.add_css_class("osd")
|
||||
@@ -503,17 +506,20 @@ class WarehouseWindow(Adw.ApplicationWindow):
|
||||
total_visible += 1
|
||||
|
||||
if total_visible > 0:
|
||||
#self.main_stack.set_visible_child(self.main_box)
|
||||
self.windowSetEmpty(False)
|
||||
else:
|
||||
# self.main_stack.set_visible_child(self.no_flatpaks)
|
||||
self.windowSetEmpty(True)
|
||||
self.filter_button.set_sensitive(True)
|
||||
|
||||
def installCallback(self, _a, _b):
|
||||
self.main_progress_bar.set_visible(False)
|
||||
self.should_pulse = False
|
||||
self.refresh_list_of_flatpaks(self, False)
|
||||
|
||||
if self.my_utils.install_success:
|
||||
self.toast_overlay.add_toast(Adw.Toast.new(_("Installed successfully")))
|
||||
self.refresh_list_of_flatpaks(self, False)
|
||||
else:
|
||||
self.toast_overlay.add_toast(Adw.Toast.new(_("Could not install app")))
|
||||
|
||||
def installThread(self, filepath, user_or_system):
|
||||
self.my_utils.installFlatpak([filepath], None, user_or_system)
|
||||
@@ -570,7 +576,15 @@ class WarehouseWindow(Adw.ApplicationWindow):
|
||||
Gtk.Window.present(dialog)
|
||||
|
||||
def drop_callback(self, target, _x, _y, _data):
|
||||
print(target.get_value().get_path())
|
||||
filepath = target.get_value().get_path()
|
||||
if filepath.endswith(".flatpak") or filepath.endswith(".flatpakref"):
|
||||
self.install_file(filepath)
|
||||
elif filepath.endswith(".flatpakrepo"):
|
||||
remotes_window = RemotesWindow(self)
|
||||
remotes_window.present()
|
||||
remotes_window.addRemoteFromFile(filepath)
|
||||
else:
|
||||
self.toast_overlay.add_toast(Adw.Toast.new(_("File type not supported")))
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
@@ -584,6 +598,9 @@ class WarehouseWindow(Adw.ApplicationWindow):
|
||||
self.settings.bind("is-maximized", self, "maximized", Gio.SettingsBindFlags.DEFAULT)
|
||||
self.settings.bind("is-fullscreen", self, "fullscreened", Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
self.new_env = dict( os.environ )
|
||||
self.new_env['LC_ALL'] = 'C'
|
||||
|
||||
if self.host_flatpaks == [['', '']]:
|
||||
self.windowSetEmpty(True)
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user