diff --git a/data/icons/dot-symbolic.svg b/data/icons/dot-symbolic.svg new file mode 100644 index 0000000..c94c8e1 --- /dev/null +++ b/data/icons/dot-symbolic.svg @@ -0,0 +1,2 @@ + + diff --git a/data/icons/folder-templates-symbolic.svg b/data/icons/folder-templates-symbolic.svg new file mode 100644 index 0000000..4e5faac --- /dev/null +++ b/data/icons/folder-templates-symbolic.svg @@ -0,0 +1,4 @@ + + + + diff --git a/data/icons/vertical-arrows-long-symbolic.svg b/data/icons/vertical-arrows-long-symbolic.svg new file mode 100644 index 0000000..ac7a6ee --- /dev/null +++ b/data/icons/vertical-arrows-long-symbolic.svg @@ -0,0 +1,2 @@ + + diff --git a/src/main_window/window.py b/src/main_window/window.py index 023e863..8595323 100644 --- a/src/main_window/window.py +++ b/src/main_window/window.py @@ -24,6 +24,7 @@ import time from gi.repository import Adw, Gdk, Gio, GLib, Gtk from .packages_page import PackagesPage +from .user_data_page import UserDataPage from .const import Config from .error_toast import ErrorToast from .status_box import StatusBox @@ -74,6 +75,8 @@ class WarehouseWindow(Adw.ApplicationWindow): file_drop = Gtk.DropTarget.new(Gio.File, Gdk.DragAction.COPY) self.pages = { self.packages_row: PackagesPage, + + self.user_data_row: UserDataPage, } # Apply diff --git a/src/meson.build b/src/meson.build index 9c2023e..3f25607 100644 --- a/src/meson.build +++ b/src/meson.build @@ -11,6 +11,8 @@ blueprints = custom_target('blueprints', 'packages_page/packages_page.blp', 'filters_page/filters_page.blp', 'properties_page/properties_page.blp', + 'user_data_page/user_data_page.blp', + 'widgets/data_box.blp', 'change_version_page/change_version_page.blp', ), output: '.', @@ -62,6 +64,8 @@ warehouse_sources = [ 'filters_page/filters_page.py', 'properties_page/properties_page.py', 'change_version_page/change_version_page.py', + 'user_data_page/user_data_page.py', + 'widgets/data_box.py', '../data/style.css', ] diff --git a/src/user_data_page/user_data_page.blp b/src/user_data_page/user_data_page.blp new file mode 100644 index 0000000..1bbd1cd --- /dev/null +++ b/src/user_data_page/user_data_page.blp @@ -0,0 +1,254 @@ +using Gtk 4.0; +using Adw 1; + +template $UserDataPage : Adw.BreakpointBin { + // title: _("User Data"); + width-request: 1; + height-request: 1; + + Adw.Breakpoint { + condition ("max-width: 585") + + setters { + header_bar.show-title: false; + switcher_bar.reveal: true; + switcher_bar.visible: true; + } + } + + Adw.ToolbarView { + [top] + Adw.HeaderBar header_bar { + title-widget: + Adw.ViewSwitcher { + stack: stack; + policy: wide; + } + ; + [start] + ToggleButton search_button { + icon-name: "system-search-symbolic"; + tooltip-text: _("Search User Data"); + } + [end] + MenuButton sort_button { + popover: sort_pop; + icon-name: "vertical-arrows-long-symbolic"; + tooltip-text: _("Sort User Data"); + } + [end] + ToggleButton select_button { + icon-name: "selection-mode-symbolic"; + tooltip-text: _("Select User Data"); + } + } + [top] + Adw.Clamp { + SearchBar search_bar { + search-mode-enabled: bind search_button.active bidirectional; + key-capture-widget: template; + + SearchEntry search_entry { + hexpand: true; + placeholder-text: _("Search User Data"); + } + } + } + [bottom] + Revealer { + reveal-child: bind select_button.active; + transition-type: slide_up; + [center] + Box bottom_bar { + styles ["toolbar"] + hexpand: true; + homogeneous: true; + Button select_all_button { + styles ["raised"] + Adw.ButtonContent { + icon-name: "selection-mode-symbolic"; + label: _("Select All"); + can-shrink: true; + } + } + Button copy_button { + styles ["raised"] + Adw.ButtonContent { + icon-name: "edit-copy-symbolic"; + label: _("Copy"); + can-shrink: true; + } + } + Button uninstall_button { + styles ["raised"] + Adw.ButtonContent { + icon-name: "user-trash-symbolic"; + label: _("Uninstall"); + can-shrink: true; + } + } + } + } + [bottom] + Adw.ViewSwitcherBar switcher_bar { + stack: stack; + visible: false; + } + Adw.ViewStack stack { + Adw.ViewStackPage { + name: "active"; + title: _("Active Data"); + icon-name: "file-manager-symbolic"; + child: + ScrolledWindow { + Box { + orientation: vertical; + Box { + orientation: vertical; + margin-start: 24; + margin-end: 24; + Label { + label: _("Active User Data"); + styles ["title-1"] + hexpand: true; + halign: start; + } + Label { + label: "32 Items - 39.7 GB"; + styles ["title-3"] + hexpand: true; + halign: start; + } + } + Separator { + margin-start: 12; + margin-end: 12; + margin-top: 9; + margin-bottom: 6; + } + FlowBox flow_box { + styles ["boxed-list"] + homogeneous: true; + valign: start; + selection-mode: none; + max-children-per-line: 6; + margin-start: 12; + margin-end: 12; + margin-bottom: 12; + } + } + } + ; + } + Adw.ViewStackPage { + name: "leftover"; + title: _("Leftover Data"); + icon-name: "folder-templates-symbolic"; + child: + ScrolledWindow { + Box { + orientation: vertical; + Box { + orientation: vertical; + margin-start: 24; + margin-end: 24; + Label { + label: _("Leftover User Data"); + styles ["title-1"] + hexpand: true; + halign: start; + } + Label { + label: "25 Items - 18.6 GB"; + styles ["title-3"] + hexpand: true; + halign: start; + } + } + Separator { + margin-start: 12; + margin-end: 12; + margin-top: 9; + margin-bottom: 6; + } + FlowBox { + styles ["boxed-list"] + homogeneous: true; + valign: start; + selection-mode: none; + max-children-per-line: 6; + margin-start: 12; + margin-end: 12; + margin-bottom: 12; + } + } + } + ; + } + } + } +} + +Popover sort_pop { + styles ["menu"] + Box { + orientation: vertical; + margin-start: 6; + margin-end: 6; + margin-top: 6; + margin-bottom: 6; + Box { + homogeneous: true; + spacing: 3; + ToggleButton asc { + styles ["flat"] + label: _("Ascending"); + can-focus: bind asc.active inverted; + can-target: bind asc.active inverted; + } + ToggleButton dsc { + styles ["flat"] + label: _("Descending"); + active: bind asc.active inverted bidirectional; + can-focus: bind dsc.active inverted; + can-target: bind dsc.active inverted; + } + } + Separator { + } + Box sort_list { + orientation: vertical; + ToggleButton sort_name { + styles ["flat"] + can-focus: bind sort_name.active inverted; + can-target: bind sort_name.active inverted; + Label { + styles ["body"] + halign: start; + label: _("Sort By Name"); + } + } + ToggleButton sort_id { + styles ["flat"] + can-focus: bind sort_id.active inverted; + can-target: bind sort_id.active inverted; + Label { + styles ["body"] + halign: start; + label: _("Sort By ID"); + } + } + ToggleButton sort_size { + active: true; + can-focus: bind sort_size.active inverted; + can-target: bind sort_size.active inverted; + styles ["flat"] + Label { + styles ["body"] + halign: start; + label: _("Sort By Size"); + } + } + } + } +} \ No newline at end of file diff --git a/src/user_data_page/user_data_page.py b/src/user_data_page/user_data_page.py new file mode 100644 index 0000000..f5ad5a8 --- /dev/null +++ b/src/user_data_page/user_data_page.py @@ -0,0 +1,58 @@ +from gi.repository import Adw, Gtk, GLib, Gio, Pango +from .host_info import HostInfo +from .error_toast import ErrorToast +from .data_box import DataBox + +@Gtk.Template(resource_path="/io/github/flattool/Warehouse/user_data_page/user_data_page.ui") +class UserDataPage(Adw.BreakpointBin): + __gtype_name__ = 'UserDataPage' + gtc = Gtk.Template.Child + select_button = gtc() + flow_box = gtc() + sort_pop = gtc() + sort_list = gtc() + sort_name = gtc() + sort_id = gtc() + sort_size = gtc() + + # Referred to in the main window + # It is used to determine if a new page should be made or not + # This must be set to the created object from within the class's __init__ method + instance = None + + def set_selection_mode(self, is_enabled): + i = 0 + while row := self.flow_box.get_child_at_index(i): + i += 1 + row = row.get_child() + row.check_button.set_visible(is_enabled) + row.check_button.set_active(False) + + def sort_handler(self, button): + if button.get_active() == False: + return + self.sort_name.set_active(self.sort_name is button) + self.sort_id.set_active(self.sort_id is button) + self.sort_size.set_active(self.sort_size is button) + if button is self.sort_name: + self.sort_id.grab_focus() + else: + self.sort_name.grab_focus() + + def __init__(self, main_window, **kwargs): + super().__init__(**kwargs) + + # Apply + self.__class__.instance = self + + for i in range(10): + box = DataBox(main_window, "/home/heliguy/.var/app/io.github.io.github.flattool.Warehouse/") + self.flow_box.append(box) + self.flow_box.get_child_at_index(i).set_focusable(False) + + # self.select_button.connect("toggled", lambda *_: self.set_selection_mode(self.select_button.get_active())) + # self.flow_box.connect("child-activated", lambda _, item: (cb := (row := item.get_child()).check_button).set_active((not cb.get_active()) if row.get_activatable() else False)) + + self.sort_name.connect("toggled", self.sort_handler) + self.sort_id.connect("toggled", self.sort_handler) + self.sort_size.connect("toggled", self.sort_handler) \ No newline at end of file diff --git a/src/warehouse.gresource.xml b/src/warehouse.gresource.xml index 52f9312..5b40ffa 100644 --- a/src/warehouse.gresource.xml +++ b/src/warehouse.gresource.xml @@ -9,7 +9,9 @@ filters_page/filters_page.ui properties_page/properties_page.ui change_version_page/change_version_page.ui + user_data_page/user_data_page.ui widgets/status_box.ui + widgets/data_box.ui @@ -49,5 +51,8 @@ ../data/icons/error-small-symbolic.svg ../data/icons/copy-symbolic.svg ../data/icons/double-ended-arrows-vertical-symbolic.svg + ../data/icons/vertical-arrows-long-symbolic.svg + ../data/icons/dot-symbolic.svg + ../data/icons/folder-templates-symbolic.svg diff --git a/src/widgets/data_box.blp b/src/widgets/data_box.blp new file mode 100644 index 0000000..695d814 --- /dev/null +++ b/src/widgets/data_box.blp @@ -0,0 +1,77 @@ +using Gtk 4.0; +using Adw 1; + +template $DataBox : ListBox { + selection-mode: none; + styles ["boxed-list"] + Adw.ActionRow row { + activatable: bind check_button.visible; + width-request: 275; + [child] + Box root_box { + orientation: vertical; + Box title_box { + margin-top: 12; + margin-bottom: 12; + Image app_icon { + margin-start: 12; + margin-end: 12; + icon-name: "application-x-executable-symbolic"; + icon-size: large; + } + Box label_box { + orientation: vertical; + Label title_label { + label: "No Title Set"; + hexpand: true; + halign: start; + ellipsize: middle; + margin-end: 12; + styles ["title-4"] + } + Label subtitle_label { + label: "No subtitle set"; + hexpand: true; + halign: start; + ellipsize: middle; + margin-end: 12; + } + } + } + Box content_box { + spacing: 6; + margin-start: 12; + margin-end: 6; + margin-bottom: 6; + Label size_label { + label: "No size set"; + halign: start; + hexpand: true; + } + Button copy_button { + icon-name: "copy-symbolic"; + tooltip-text: _("Copy Path"); + visible: bind check_button.visible inverted; + styles ["flat", "circular"] + } + Button open_button { + icon-name: "folder-open-symbolic"; + tooltip-text: _("Open User Data"); + visible: bind check_button.visible inverted; + styles ["flat", "circular"] + } + Button trash_button { + icon-name: "user-trash-symbolic"; + tooltip-text: _("Trash User Data"); + visible: bind check_button.visible inverted; + styles ["flat", "circular"] + } + CheckButton check_button { + visible: false; + sensitive: bind check_button.visible; + styles ["selection-mode"] + } + } + } + } +} \ No newline at end of file diff --git a/src/widgets/data_box.py b/src/widgets/data_box.py new file mode 100644 index 0000000..d67c5c1 --- /dev/null +++ b/src/widgets/data_box.py @@ -0,0 +1,13 @@ +from gi.repository import Adw, Gtk, GLib, Gio, Pango +from .host_info import HostInfo + +@Gtk.Template(resource_path="/io/github/flattool/Warehouse/widgets/data_box.ui") +class DataBox(Gtk.ListBox): + __gtype_name__ = 'DataBox' + gtc = Gtk.Template.Child + + title_label = gtc() + check_button = gtc() + + def __init__(self, main_window, path, **kwargs): + super().__init__(**kwargs) \ No newline at end of file