Files
warehouse/src/main_window/window.py
2024-10-12 15:17:33 -04:00

242 lines
9.1 KiB
Python

# window.py
#
# Copyright 2023 Heliguy
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3 of the License only.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# SPDX-License-Identifier: GPL-3.0-only
import os
import pathlib
import subprocess
import re
import time
from gi.repository import Adw, Gdk, Gio, GLib, Gtk, GObject
from .host_info import HostInfo
from .packages_page import PackagesPage
from .remotes_page import RemotesPage
from .user_data_page import UserDataPage
from .snapshot_page import SnapshotPage
from .install_page import InstallPage
from .const import Config
from .error_toast import ErrorToast
@Gtk.Template(resource_path="/io/github/flattool/Warehouse/main_window/window.ui")
class WarehouseWindow(Adw.ApplicationWindow):
__gtype_name__ = "WarehouseWindow"
gtc = Gtk.Template.Child
main_breakpoint = gtc()
toast_overlay = gtc()
file_drop_stack = gtc()
main_split = gtc()
file_drop_view = gtc()
stack = gtc()
refresh_button = gtc()
navigation_row_listbox = gtc()
packages_row = gtc()
remotes_row = gtc()
user_data_row = gtc()
snapshots_row = gtc()
install_row = gtc()
def key_handler(self, controller, keyval, keycode, state):
if keyval == Gdk.KEY_w and state == Gdk.ModifierType.CONTROL_MASK:
self.close()
# if keyval == Gdk.KEY_Escape:
# self.batch_mode_button.set_active(False)
def start_loading(self, *args):
for _, page in self.pages.items():
if page.instance:
page.instance.start_loading()
def end_loading(self, *args):
for _, page in self.pages.items():
if page.instance:
page.instance.end_loading()
self.refresh_button.set_sensitive(True)
self.refresh_requested = False
def do_refresh(self):
self.start_loading()
self.refresh_button.set_sensitive(False)
HostInfo.get_flatpaks(callback=self.end_loading)
def refresh_handler(self, *args):
if len(self.refresh_lockouts) == 0:
self.do_refresh()
else:
self.refresh_requested = True
def add_refresh_lockout(self, reason):
self.refresh_lockouts.append(reason)
self.refresh_button.set_sensitive(False)
def remove_refresh_lockout(self, reason):
if reason in self.refresh_lockouts:
self.refresh_lockouts.remove(reason)
if len(self.refresh_lockouts) == 0:
if self.refresh_requested:
self.do_refresh()
else:
self.refresh_button.set_sensitive(True)
def navigation_handler(self, _, row):
row = row.get_child()
page = self.pages[row]
self.stack.set_visible_child(page)
self.settings.set_string("page-shown", page.page_name)
if self.main_split.get_collapsed():
self.main_split.set_show_sidebar(False)
def activate_row(self, nav_row):
idx = 0
while row := self.navigation_row_listbox.get_row_at_index(idx):
idx += 1
if row.get_child() is nav_row:
row.activate()
nav_row.grab_focus()
break
def save_sidebar_state(self, *args):
state = self.main_split.get_show_sidebar()
self.settings.set_boolean("sidebar-shown", state)
print(self.settings.get_boolean("sidebar-shown"))
def show_saved_page(self):
page_to_show = self.settings.get_string("page-shown")
page_found = False
for row, page in self.pages.items():
self.stack.add_child(page)
if page.page_name == page_to_show:
page_found = True
self.activate_row(row)
if not page_found:
self.navigation_row_listbox.get_row_at_index(0).activate()
def on_file_drop(self, drop_target, value, x, y):
try:
paks = []
remotes = []
for file in value:
path = file.get_path()
if path.endswith(".flatpak") or path.endswith(".flatpakref"):
paks.append(Gio.File.new_for_path(path))
elif path.endswith(".flatpakrepo"):
remotes.append(path)
else:
dialog = Adw.AlertDialog(
heading=_("Unsupported Filetype"),
body=_("Only .flatpak, .flatpakref, and .flatpakrepo files are supported."),
)
dialog.add_response("continue", _("OK"))
dialog.present(self)
return
if len(remotes) > 0 and len(paks) > 0:
dialog = Adw.AlertDialog(
heading=_("Mixed Filetypes"),
body=_("Flatpaks and remotes cannot be installed at the same time."),
)
dialog.add_css_class("error")
dialog.add_response("continue", _("OK"))
dialog.present(self)
return
if len(remotes) > 1:
dialog = Adw.AlertDialog(
heading=_("Too Many Remotes"),
body=_("Only one remote at a time is supported."),
)
dialog.add_response("continue", _("OK"))
dialog.present(self)
return
if len(remotes) == 1:
# Adding a remote
self.activate_row(self.remotes_row)
remotes_page = self.pages[self.remotes_row]
remotes_page.local_file_handler(remotes[0])
elif len(paks) > 0:
# Add packages
self.activate_row(self.install_row)
install_page = self.pages[self.install_row]
install_page.select_page.file_dialog_handler(paks)
except Exception as e:
self.toast_overlay.add_toast(ErrorToast(_("Could not open files"), str(e)).toast)
def on_drop_enter(self, *args):
self.file_drop_stack.set_visible_child(self.file_drop_view)
return 1
def on_drop_leave(self, *args):
self.file_drop_stack.set_visible_child(self.main_split)
def __init__(self, **kwargs):
super().__init__(**kwargs)
# Extra Object Creation
HostInfo.main_window = self
ErrorToast.main_window = self
self.settings = Gio.Settings.new("io.github.flattool.Warehouse")
self.pages = {
self.packages_row: PackagesPage(main_window=self),
self.remotes_row: RemotesPage(main_window=self),
self.user_data_row: UserDataPage(main_window=self),
self.snapshots_row: SnapshotPage(main_window=self),
self.install_row: InstallPage(main_window=self),
}
self.navigation_row_listbox.connect("row-activated", self.navigation_handler)
self.show_saved_page()
self.refresh_lockouts = []
self.refresh_requested = False
file_drop = Gtk.DropTarget.new(Gdk.FileList, Gdk.DragAction.COPY)
event_controller = Gtk.EventControllerKey()
# Apply
self.add_controller(file_drop)
self.add_controller(event_controller)
self.settings.bind("window-width", self, "default-width", Gio.SettingsBindFlags.DEFAULT)
self.settings.bind("window-height", self, "default-height", Gio.SettingsBindFlags.DEFAULT)
self.settings.bind("is-maximized", self, "maximized", Gio.SettingsBindFlags.DEFAULT)
self.settings.bind("is-fullscreen", self, "fullscreened", Gio.SettingsBindFlags.DEFAULT)
# self.scrolled_window.add_controller(file_drop)
# self.main_split.set_content(PackagesPage(self))
if Config.DEVEL:
self.add_css_class("devel")
# Connections
file_drop.connect("drop", self.on_file_drop)
file_drop.connect("enter", self.on_drop_enter)
file_drop.connect("leave", self.on_drop_leave)
event_controller.connect("key-pressed", self.key_handler)
# file_drop.connect("drop", self.drop_callback)
self.refresh_button.connect("clicked", self.refresh_handler)
# self.activate_row(self.user_data_row)
# self.main_split.set_show_sidebar(self.settings.get_boolean("sidebar-shown"))
# GLib.idle_add(lambda *_: self.main_split.set_show_sidebar(False))
# print(self.settings.get_boolean("sidebar-shown"))
# self.main_split.connect("notify::show-sidebar", self.save_sidebar_state)
self.start_loading()
HostInfo.get_flatpaks(callback=self.end_loading)
# GLib.idle_add(lambda *_: self.main_split.set_show_sidebar(False))