├── .devcontainer ├── Dockerfile └── devcontainer.json ├── .github └── FUNDING.yml ├── .gitignore ├── COPYING ├── Justfile ├── README.md ├── build-aux ├── flatpak │ ├── flatpak-bwrap-wrapper.sh │ ├── fuse-2.9.2-closefrom.patch │ ├── fuse-2.9.2-namespace-conflict-fix.patch │ ├── fuse-disable-sys-mount-under-flatpak.patch │ ├── fusermount-wrapper.sh │ ├── io.github.kolunmi.bazaar.Devel.json │ ├── polkit-autogen │ ├── polkit-build-Add-option-to-build-without-polkitd.patch │ ├── polkit-mocklib-print-indent.patch │ └── python-deps.json └── rpm │ └── bazaar.spec ├── data ├── icons │ ├── hicolor │ │ ├── scalable │ │ │ └── apps │ │ │ │ └── io.github.kolunmi.bazaar.svg │ │ └── symbolic │ │ │ └── apps │ │ │ └── io.github.kolunmi.bazaar-symbolic.svg │ └── meson.build ├── io.github.kolunmi.bazaar.desktop.in ├── io.github.kolunmi.bazaar.gschema.xml ├── io.github.kolunmi.bazaar.metainfo.xml.in ├── io.github.kolunmi.bazaar.service.in └── meson.build ├── meson.build ├── meson_options.txt ├── po ├── LINGUAS ├── POTFILES.in └── meson.build ├── src ├── bazaar.gresource.xml ├── bz-application.c ├── bz-application.h ├── bz-async-texture.c ├── bz-async-texture.h ├── bz-backend.c ├── bz-backend.h ├── bz-background.c ├── bz-background.h ├── bz-browse-widget.c ├── bz-browse-widget.h ├── bz-browse-widget.ui ├── bz-content-provider-config-schema.xml ├── bz-content-provider.c ├── bz-content-provider.h ├── bz-content-section.c ├── bz-content-section.h ├── bz-entry-group.c ├── bz-entry-group.h ├── bz-entry.c ├── bz-entry.h ├── bz-error.c ├── bz-error.h ├── bz-flatpak-entry.c ├── bz-flatpak-entry.h ├── bz-flatpak-instance.c ├── bz-flatpak-instance.h ├── bz-flatpak-private.h ├── bz-paintable-model.c ├── bz-paintable-model.h ├── bz-preferences-dialog.c ├── bz-preferences-dialog.h ├── bz-preferences-dialog.ui ├── bz-progress-bar.c ├── bz-progress-bar.h ├── bz-progress-bar.ui ├── bz-review.c ├── bz-review.h ├── bz-search-widget.c ├── bz-search-widget.h ├── bz-search-widget.ui ├── bz-section-view.c ├── bz-section-view.h ├── bz-section-view.ui ├── bz-share-dialog.c ├── bz-share-dialog.h ├── bz-share-dialog.ui ├── bz-transaction-manager.c ├── bz-transaction-manager.h ├── bz-transaction-view.c ├── bz-transaction-view.h ├── bz-transaction-view.ui ├── bz-transaction.c ├── bz-transaction.h ├── bz-update-dialog.c ├── bz-update-dialog.h ├── bz-update-dialog.ui ├── bz-util.h ├── bz-window.c ├── bz-window.h ├── bz-window.ui ├── bz-yaml-parser.c ├── bz-yaml-parser.h ├── gtk │ ├── help-overlay.ui │ └── styles.css ├── icons │ └── scalable │ │ └── actions │ │ ├── copy-symbolic.svg │ │ ├── drive-harddisk-symbolic.svg │ │ ├── external-link-symbolic.svg │ │ ├── folder-download-symbolic.svg │ │ ├── globe-symbolic.svg │ │ ├── left-large-symbolic.svg │ │ ├── license-symbolic.svg │ │ ├── people-symbolic.svg │ │ ├── regex-symbolic.svg │ │ ├── right-large-symbolic.svg │ │ ├── share-symbolic.svg │ │ ├── sidebar-show-symbolic.svg │ │ ├── starred-symbolic.svg │ │ └── user-trash-symbolic.svg ├── main.c └── meson.build └── version.sh /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:25.04 2 | 3 | RUN userdel -f -r ubuntu 4 | 5 | RUN apt-get update && apt-get install -y \ 6 | appstream \ 7 | bash-completion \ 8 | build-essential \ 9 | cmake \ 10 | gettext \ 11 | git \ 12 | libadwaita-1-dev \ 13 | libdex-dev \ 14 | libflatpak-dev \ 15 | libglycin-1-dev \ 16 | libglycin-gtk4-1-dev \ 17 | libgtk-4-dev \ 18 | liblcms2-dev \ 19 | libxmlb-dev \ 20 | libyaml-dev \ 21 | meson \ 22 | ninja-build -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Bazaar devcontainer", 3 | 4 | "build": { 5 | "dockerfile": "Dockerfile" 6 | }, 7 | 8 | "features": { 9 | "ghcr.io/devcontainers/features/common-utils:2": { 10 | "installZsh": "false", 11 | "username": "vscode", 12 | "userUid": "1000", 13 | "userGid": "1000", 14 | "upgradePackages": "true" 15 | }, 16 | "ghcr.io/devcontainers/features/github-cli:1": {} 17 | }, 18 | 19 | "remoteUser": "vscode", 20 | 21 | "customizations": { 22 | "vscode": { 23 | "extensions": [ 24 | "ms-vscode.cpptools-extension-pack" 25 | ] 26 | } 27 | }, 28 | 29 | // Wayland support 30 | "containerEnv": { 31 | "WAYLAND_DISPLAY": "${localEnv:WAYLAND_DISPLAY}", 32 | "XDG_RUNTIME_DIR": "${localEnv:XDG_RUNTIME_DIR}", 33 | "XDG_SESSION_TYPE": "${localEnv:XDG_SESSION_TYPE}" 34 | }, 35 | 36 | "mounts": [ 37 | "source=${localEnv:XDG_RUNTIME_DIR},target=${localEnv:XDG_RUNTIME_DIR},type=bind,consistency=cached" 38 | ] 39 | } -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [kolunmi] 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | .cache 3 | .flatpak-builder 4 | rpmbuild 5 | -------------------------------------------------------------------------------- /Justfile: -------------------------------------------------------------------------------- 1 | # These are just convenience scripts, NOT a build system! 2 | 3 | appid := env("BAZAAR_APPID", "io.github.kolunmi.bazaar") 4 | 5 | alias run := run-base 6 | 7 | run-base: build-base 8 | ./build/src/bazaar 9 | 10 | build-base: 11 | meson setup build --wipe 12 | ninja -C build 13 | 14 | build-flatpak $manifest="./build-aux/flatpak/io.github.kolunmi.bazaar.Devel.json" $branch="stable": 15 | #!/usr/bin/env bash 16 | mkdir -p ".flatpak-builder" 17 | FLATPAK_BUILDER_DIR=$(realpath ".flatpak-builder") 18 | cd "$(dirname "${manifest}")" 19 | FLATPAK_BUILDER="flatpak-builder" 20 | BUILDER_ARGS=() 21 | BUILDER_ARGS+=("--default-branch=${branch}") 22 | BUILDER_ARGS+=("--state-dir=${FLATPAK_BUILDER_DIR}/flatpak-builder") 23 | BUILDER_ARGS+=("--user") 24 | BUILDER_ARGS+=("--ccache") 25 | BUILDER_ARGS+=("--force-clean") 26 | BUILDER_ARGS+=("--install") 27 | BUILDER_ARGS+=("--disable-rofiles-fuse") 28 | BUILDER_ARGS+=("${FLATPAK_BUILDER_DIR}/build-dir") 29 | BUILDER_ARGS+=("$(basename "${manifest}")") 30 | 31 | if which flatpak-builder &>/dev/null ; then 32 | flatpak-builder "${BUILDER_ARGS[@]}" 33 | exit $? 34 | else 35 | flatpak run org.flatpak.Builder "${BUILDER_ARGS[@]}" 36 | exit $? 37 | fi 38 | 39 | build-rpm: 40 | #!/usr/bin/env bash 41 | mkdir -p rpmbuild 42 | podman run --rm -i -v .:/build:Z -v ./rpmbuild:/root/rpmbuild:Z registry.fedoraproject.org/fedora:latest <<'EOF' 43 | set -xeuo pipefail 44 | dnf install -y rpmdevtools 45 | mkdir -p $HOME/rpmbuild/SOURCES 46 | RPMDIR="/build/build-aux/rpm" 47 | cp "${RPMDIR}"/* $HOME/rpmbuild/SOURCES 48 | spectool -agR "${RPMDIR}"/bazaar.spec 49 | dnf builddep -y "${RPMDIR}"/bazaar.spec 50 | rpmbuild -bb "${RPMDIR}"/bazaar.spec 51 | EOF 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bazaar 2 | 3 | ![Image](https://github.com/user-attachments/assets/b247939a-0822-4bbe-9b40-9c0063198175) 4 | 5 | A new app store idea for GNOME. This is very much work-in-progress, 6 | and nothing about the current state of the project is final; I intend 7 | to add everything necessary to eclipse gnome-software in 8 | functionality, at least as far as flatpak is concerned. Much of the 9 | flatpak related code is referenced from gnome-software, which you can 10 | find [here](https://gitlab.gnome.org/GNOME/gnome-software). Thanks to 11 | everyone in the GNOME development community for creating such an 12 | awesome desktop environment! 13 | 14 | If you would like to try this project on your local machine, clone it 15 | on the cli and type these commands inside the project root: 16 | 17 | ```sh 18 | meson setup build --prefix=/usr/local 19 | ninja -C build 20 | sudo ninja -C build install 21 | bazaar service 22 | bazaar window 23 | ``` 24 | 25 | ## Supporting 26 | 27 | If you would like to support me and the development of this 28 | application (Thank you!), I have a ko-fi here! 29 | https://ko-fi.com/kolunmi 30 | 31 | ## Instructions for Distributors 32 | 33 | If you are a user, this section should be irrelevant to you, but it 34 | still may be interesting. 35 | 36 | ### Configuring the Browser 37 | 38 | As of writing, the browser does not show anything unless you customize 39 | it by detailing "sections" inside any number of YAML configuration 40 | files at locations of your choosing. I will walk you through how to 41 | create one of these YAML files, but first Bazaar needs to know where 42 | to look for them. 43 | 44 | Inside `meson_options.txt` you will see an option named 45 | `hardcoded_content_config_path`. This compile time option optionally 46 | specifies a filepath from which to load the "default" configuration at 47 | runtime. This file is NOT embedded into the binary. In case you are 48 | unfamiliar with meson options, simply add the following to your setup 49 | command: 50 | 51 | ```sh 52 | meson setup build -Dhardcoded_content_config_path=/path/to/config 53 | ``` 54 | 55 | The other way to specify configuration files is with the 56 | `--extra-content-config` cli argument. It takes a single filepath 57 | argument, and you can use this option multiple times. 58 | 59 | By the way, every configuration is independently and continuously 60 | monitored for filesystem events throughout the lifetime of the 61 | process. So, in the following tutorial, you can simply save the 62 | configuration whenever you want to see your changes; Bazaar will 63 | automatically reload the relevant parts of the browser. 64 | 65 | Once you are set up, copy and paste this snippet into the 66 | configuration and save it: 67 | 68 | ```yaml 69 | sections: 70 | - title: "Section #1" 71 | subtitle: "The first section" 72 | description: "These are some of my favorite apps!" 73 | rows: 3 74 | # use the file:// prefix for a local file 75 | banner: https://pixls.us/articles/processing-a-nightscape-in-siril/resultat_03_final.jpg 76 | # can be "fill", "contain", "cover", or "scale-down" 77 | banner-fit: cover 78 | appids: 79 | - com.usebottles.bottles 80 | - io.mgba.mGBA 81 | - net.pcsx2.PCSX2 82 | - org.blender.Blender 83 | - org.desmume.DeSmuME 84 | - org.duckstation.DuckStation 85 | - org.freecad.FreeCAD 86 | - org.gimp.GIMP 87 | - org.gnome.Builder 88 | - org.gnome.Loupe 89 | - org.inkscape.Inkscape 90 | - org.kde.krita 91 | ``` 92 | 93 | Your window should now look something like this: 94 | 95 | ![Image](https://github.com/user-attachments/assets/26cd8977-95d0-4e21-903f-e7cc7abbd776) 96 | 97 | You can play around with this a bit and customize it to fit your 98 | needs, or even add new sections (There is no limit!). Unfortunately, 99 | it may still seem a little visually bland. That's where custom css 100 | comes in! 101 | 102 | Delete the contents of your configuration and paste this snippet 103 | instead: 104 | 105 | ```yaml 106 | sections: 107 | - title: "Section #1" 108 | subtitle: "The first section" 109 | description: "These are some of my favorite apps!" 110 | rows: 3 111 | # use the file:// prefix for a local file 112 | banner: https://pixls.us/articles/processing-a-nightscape-in-siril/resultat_03_final.jpg 113 | # can be "fill", "contain", "cover", or "scale-down" 114 | banner-fit: cover 115 | appids: 116 | - com.usebottles.bottles 117 | - io.mgba.mGBA 118 | - net.pcsx2.PCSX2 119 | - org.blender.Blender 120 | - org.desmume.DeSmuME 121 | - org.duckstation.DuckStation 122 | - org.freecad.FreeCAD 123 | - org.gimp.GIMP 124 | - org.gnome.Builder 125 | - org.gnome.Loupe 126 | - org.inkscape.Inkscape 127 | - org.kde.krita 128 | classes: 129 | - my-section 130 | 131 | css: | 132 | .my-section { 133 | border: 5px solid var(--accent-fg-color); 134 | background: linear-gradient(#ff7788, #553377); 135 | } 136 | .my-section entry { 137 | background-color: alpha(var(--accent-bg-color), 0.05); 138 | } 139 | .my-section banner { 140 | opacity: 0.8; 141 | } 142 | .my-section title { 143 | border-bottom: 2px solid var(--accent-fg-color); 144 | } 145 | ``` 146 | 147 | Now Bazaar should look like this: 148 | 149 | ![Image](https://github.com/user-attachments/assets/2fb5c399-380a-48be-be6c-c5c035c2b4a0) 150 | 151 | Feel free to modify this to your liking. You can even add animations, 152 | etc. These are the current custom css names at your disposal: 153 | 154 | * banner 155 | * banner-text 156 | * banners 157 | * description 158 | * entry 159 | * entry-grid 160 | * subtitle 161 | * title 162 | 163 | To learn more about how to use css in gtk, see the following 164 | resources: 165 | 166 | * https://docs.gtk.org/gtk4/css-overview.html 167 | * https://docs.gtk.org/gtk4/css-properties.html 168 | 169 | To be continued 170 | -------------------------------------------------------------------------------- /build-aux/flatpak/flatpak-bwrap-wrapper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo "Running flatpak-bwrap wrapper, redirecting to host..." 3 | export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/flatpak/bus 4 | 5 | # Inspect which fds are currently opened, and forward them to the host side. 6 | echo "Open file descriptors:" 7 | ls -l /proc/$$/fd 8 | 9 | fds="" 10 | for fd in $(ls /proc/$$/fd); do 11 | case "$fd" in 12 | 0|1|2|3|255) 13 | ;; 14 | *) 15 | fds="${fds} --forward-fd=$fd" 16 | echo "Forwarding fd $fd" 17 | ;; 18 | esac 19 | done 20 | 21 | # Test if the `bwrap` command is available 22 | echo "Checking if bwrap is available on host system..." 23 | flatpak-spawn --host bwrap --version 24 | retval=$? 25 | 26 | if [ $retval -eq 0 ]; then 27 | echo "Using bwrap." 28 | binary="bwrap" 29 | else 30 | echo "Unable to execute bwrap, falling back to flatpak-bwrap." 31 | binary="flatpak-bwrap" 32 | fi 33 | 34 | # The actual call on the host side 35 | echo "Executing actual command on host system using flatpak-spawn..." 36 | exec flatpak-spawn --host $fds $binary "$@" -------------------------------------------------------------------------------- /build-aux/flatpak/fuse-2.9.2-closefrom.patch: -------------------------------------------------------------------------------- 1 | --- fuse-2.9.2/util/ulockmgr_server.c.closefromfix 2019-01-04 05:33:33.000000000 -0800 2 | +++ fuse-2.9.2/util/ulockmgr_server.c 2022-07-12 12:29:56.445402244 -0700 3 | @@ -124,7 +124,7 @@ 4 | return res; 5 | } 6 | 7 | -static int closefrom(int minfd) 8 | +static int _closefrom(int minfd) 9 | { 10 | DIR *dir = opendir("/proc/self/fd"); 11 | if (dir) { 12 | @@ -384,7 +384,7 @@ 13 | dup2(nullfd, 1); 14 | } 15 | close(3); 16 | - closefrom(5); 17 | + _closefrom(5); 18 | while (1) { 19 | char c; 20 | int sock; 21 | -------------------------------------------------------------------------------- /build-aux/flatpak/fuse-2.9.2-namespace-conflict-fix.patch: -------------------------------------------------------------------------------- 1 | diff -up fuse-2.9.2/include/fuse_kernel.h.conflictfix fuse-2.9.2/include/fuse_kernel.h 2 | --- fuse-2.9.2/include/fuse_kernel.h.conflictfix 2013-06-26 09:31:57.862198038 -0400 3 | +++ fuse-2.9.2/include/fuse_kernel.h 2013-06-26 09:32:19.679198365 -0400 4 | @@ -88,12 +88,16 @@ 5 | #ifndef _LINUX_FUSE_H 6 | #define _LINUX_FUSE_H 7 | 8 | -#include 9 | +#ifdef __linux__ 10 | +#include 11 | +#else 12 | +#include 13 | #define __u64 uint64_t 14 | #define __s64 int64_t 15 | #define __u32 uint32_t 16 | #define __s32 int32_t 17 | #define __u16 uint16_t 18 | +#endif 19 | 20 | /* 21 | * Version negotiation: 22 | -------------------------------------------------------------------------------- /build-aux/flatpak/fuse-disable-sys-mount-under-flatpak.patch: -------------------------------------------------------------------------------- 1 | From 1ec935f4abecd08957affc7b21bae6bf5be78931 Mon Sep 17 00:00:00 2001 2 | From: Christian Hergert 3 | Date: Thu, 12 Apr 2018 01:47:57 -0700 4 | Subject: [PATCH] libfuse: disable sys mount under flatpak 5 | 6 | --- 7 | lib/mount.c | 3 +++ 8 | 1 file changed, 3 insertions(+) 9 | 10 | diff --git a/lib/mount.c b/lib/mount.c 11 | index 7a18c11..1667db2 100644 12 | --- a/lib/mount.c 13 | +++ b/lib/mount.c 14 | @@ -392,6 +392,9 @@ static int fuse_mount_sys(const char *mnt, struct mount_opts *mo, 15 | int fd; 16 | int res; 17 | 18 | + /* disable in flatpak */ 19 | + return -2; 20 | + 21 | if (!mnt) { 22 | fprintf(stderr, "fuse: missing mountpoint parameter\n"); 23 | return -1; 24 | -- 25 | 2.17.0.rc2 26 | 27 | -------------------------------------------------------------------------------- /build-aux/flatpak/fusermount-wrapper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo "Running fusermount wrapper, redirecting to host..." 3 | export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/flatpak/bus 4 | 5 | # Test if the `fusermount` command is available 6 | echo "Checking if fusermount is available on host system..." 7 | flatpak-spawn --host fusermount --version 8 | retval=$? 9 | 10 | if [ $retval -eq 0 ]; then 11 | echo "Using fusermount." 12 | binary="fusermount" 13 | else 14 | # Some distros don't ship `fusermount` anymore, but `fusermount3` like Alpine 15 | echo "Unable to execute fusermount, trying to use fusermount3." 16 | binary="fusermount3" 17 | fi 18 | 19 | # The actual call on the host side 20 | if [ -z "$_FUSE_COMMFD" ]; then 21 | FD_ARGS= 22 | else 23 | FD_ARGS="--env=_FUSE_COMMFD=${_FUSE_COMMFD} --forward-fd=${_FUSE_COMMFD}" 24 | fi 25 | exec flatpak-spawn --host $FD_ARGS $binary "$@" -------------------------------------------------------------------------------- /build-aux/flatpak/polkit-autogen: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | gtkdocize --flavour no-tmpl 4 | autoreconf -if -------------------------------------------------------------------------------- /build-aux/flatpak/polkit-build-Add-option-to-build-without-polkitd.patch: -------------------------------------------------------------------------------- 1 | From 1073a44277316348d40d86ecec908f1d4812f360 Mon Sep 17 00:00:00 2001 2 | From: Christian Hergert 3 | Date: Mon, 27 May 2019 11:49:09 -0700 4 | Subject: [PATCH] flatpak: make polkit suitable for use within flatpak 5 | 6 | This is based on patches from Patrick Griffis with additional fixes 7 | to allow us to disable use of PAM within Flaptak. 8 | --- 9 | configure.ac | 20 ++++++++++++++++---- 10 | src/Makefile.am | 6 +++++- 11 | src/polkitagent/Makefile.am | 5 +++++ 12 | test/Makefile.am | 6 +++++- 13 | 4 files changed, 31 insertions(+), 6 deletions(-) 14 | 15 | diff --git a/configure.ac b/configure.ac 16 | index 5cedb4e..729d78d 100644 17 | --- a/configure.ac 18 | +++ b/configure.ac 19 | @@ -79,11 +79,13 @@ PKG_CHECK_MODULES(GLIB, [gmodule-2.0 gio-unix-2.0 >= 2.30.0]) 20 | AC_SUBST(GLIB_CFLAGS) 21 | AC_SUBST(GLIB_LIBS) 22 | 23 | -PKG_CHECK_MODULES(LIBJS, [mozjs-60]) 24 | +AS_IF([test x${enable_polkitd} = yes], [ 25 | + PKG_CHECK_MODULES(LIBJS, [mozjs-60]) 26 | 27 | -AC_SUBST(LIBJS_CFLAGS) 28 | -AC_SUBST(LIBJS_CXXFLAGS) 29 | -AC_SUBST(LIBJS_LIBS) 30 | + AC_SUBST(LIBJS_CFLAGS) 31 | + AC_SUBST(LIBJS_CXXFLAGS) 32 | + AC_SUBST(LIBJS_LIBS) 33 | +]) 34 | 35 | EXPAT_LIB="" 36 | AC_ARG_WITH(expat, [ --with-expat= Use expat from here], 37 | @@ -236,6 +238,15 @@ if test "x$with_systemdsystemunitdir" != "xno"; then 38 | fi 39 | AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$systemdsystemunitdir"]) 40 | 41 | +dnl --------------------------------------------------------------------------- 42 | +dnl - Disable polkitd when using library alone 43 | +dnl --------------------------------------------------------------------------- 44 | + 45 | +AC_ARG_ENABLE([polkitd], 46 | + [AS_HELP_STRING([--disable-polkitd], [Do not build polkitd])], 47 | + [enable_polkitd=$enableval], [enable_polkitd=yes]) 48 | +AM_CONDITIONAL(BUILD_POLKITD, [test x${enable_polkitd} = yes]) 49 | + 50 | dnl --------------------------------------------------------------------------- 51 | dnl - User for running polkitd 52 | dnl --------------------------------------------------------------------------- 53 | @@ -579,6 +590,7 @@ echo " 54 | Session tracking: ${SESSION_TRACKING} 55 | PAM support: ${have_pam} 56 | systemdsystemunitdir: ${systemdsystemunitdir} 57 | + polkitd: ${enable_polkitd} 58 | polkitd user: ${POLKITD_USER}" 59 | 60 | if test "$have_pam" = yes ; then 61 | diff --git a/src/Makefile.am b/src/Makefile.am 62 | index 09fc7b3..c6fe91b 100644 63 | --- a/src/Makefile.am 64 | +++ b/src/Makefile.am 65 | @@ -1,5 +1,9 @@ 66 | 67 | -SUBDIRS = polkit polkitbackend polkitagent programs 68 | +SUBDIRS = polkit polkitagent programs 69 | + 70 | +if BUILD_POLKITD 71 | +SUBDIRS += polkitbackend 72 | +endif 73 | 74 | if BUILD_EXAMPLES 75 | SUBDIRS += examples 76 | diff --git a/src/polkitagent/Makefile.am b/src/polkitagent/Makefile.am 77 | index 49720db..633f9d4 100644 78 | --- a/src/polkitagent/Makefile.am 79 | +++ b/src/polkitagent/Makefile.am 80 | @@ -79,6 +79,7 @@ libpolkit_agent_1_la_LIBADD = \ 81 | 82 | libpolkit_agent_1_la_LDFLAGS = -export-symbols-regex '(^polkit_.*)' 83 | 84 | +if !POLKIT_AUTHFW_NONE 85 | libprivdir = $(prefix)/lib/polkit-1 86 | libpriv_PROGRAMS = polkit-agent-helper-1 87 | 88 | @@ -113,6 +114,8 @@ polkit_agent_helper_1_LDFLAGS = \ 89 | $(AM_LDFLAGS) \ 90 | $(NULL) 91 | 92 | +endif # !POLKIT_AUTHFW_NONE 93 | + 94 | if HAVE_INTROSPECTION 95 | 96 | girdir = $(INTROSPECTION_GIRDIR) 97 | @@ -142,6 +145,7 @@ include $(INTROSPECTION_MAKEFILE) 98 | 99 | endif # HAVE_INTROSPECTION 100 | 101 | +if !POLKIT_AUTHFW_NONE 102 | # polkit-agent-helper-1 need to be setuid root because it's used to 103 | # authenticate not only the invoking user, but possibly also root 104 | # and/or other users. 105 | @@ -149,6 +153,7 @@ endif # HAVE_INTROSPECTION 106 | install-data-hook: 107 | -chown root $(DESTDIR)$(libprivdir)/polkit-agent-helper-1 108 | -chmod 4755 $(DESTDIR)$(libprivdir)/polkit-agent-helper-1 109 | +endif # !POLKIT_AUTHFW_NONE 110 | 111 | EXTRA_DIST = polkitagentmarshal.list polkitagentenumtypes.h.template polkitagentenumtypes.c.template 112 | CLEANFILES = $(gir_DATA) $(typelibs_DATA) 113 | diff --git a/test/Makefile.am b/test/Makefile.am 114 | index 59d0680..d43b0fe 100644 115 | --- a/test/Makefile.am 116 | +++ b/test/Makefile.am 117 | @@ -1,7 +1,11 @@ 118 | 119 | -SUBDIRS = mocklibc . polkit polkitbackend 120 | +SUBDIRS = mocklibc . polkit 121 | AM_CFLAGS = $(GLIB_CFLAGS) 122 | 123 | +if BUILD_POLKITD 124 | +SUBDIRS += polkitbackend 125 | +endif 126 | + 127 | noinst_LTLIBRARIES = libpolkit-test-helper.la 128 | libpolkit_test_helper_la_SOURCES = polkittesthelper.c polkittesthelper.h 129 | libpolkit_test_helper_la_LIBADD = $(GLIB_LIBS) 130 | -- 131 | 2.21.0 132 | 133 | -------------------------------------------------------------------------------- /build-aux/flatpak/polkit-mocklib-print-indent.patch: -------------------------------------------------------------------------------- 1 | From fab336d25955910f99b083c3280c0abe7007d452 Mon Sep 17 00:00:00 2001 2 | From: Sergei Trofimovich 3 | Date: Sun, 3 Dec 2023 23:06:30 +0000 4 | Subject: [PATCH] test/mocklibc: fix build against 5 | 6 | polkit> ../subprojects/mocklibc-1.0/src/netgroup-debug.c: In function 'netgroup_debug_print_entry': 7 | polkit> ../subprojects/mocklibc-1.0/src/netgroup-debug.c:25:3: error: implicit declaration of function 'print_indent' [-Wimplicit-function-declaration] 8 | polkit> 25 | print_indent(stream, indent); 9 | polkit> | ^~~~~~~~~~~~ 10 | --- 11 | test/mocklibc/src/netgroup-debug.c | 11 +++++++++++ 12 | test/mocklibc/src/netgroup.c | 11 ----------- 13 | 2 files changed, 11 insertions(+), 11 deletions(-) 14 | 15 | diff --git a/test/mocklibc/src/netgroup-debug.c b/test/mocklibc/src/netgroup-debug.c 16 | index 81d6e728..46e5b25f 100644 17 | --- a/test/mocklibc/src/netgroup-debug.c 18 | +++ b/test/mocklibc/src/netgroup-debug.c 19 | @@ -21,6 +21,17 @@ 20 | #include 21 | #include 22 | 23 | +/** 24 | + * Print a varaible indentation to the stream. 25 | + * @param stream Stream to print to 26 | + * @param indent Number of indents to use 27 | + */ 28 | +static void print_indent(FILE *stream, unsigned int indent) { 29 | + int i; 30 | + for (i = 0; i < indent; i++) 31 | + fprintf(stream, " "); 32 | +} 33 | + 34 | void netgroup_debug_print_entry(struct entry *entry, FILE *stream, unsigned int indent) { 35 | print_indent(stream, indent); 36 | 37 | diff --git a/test/mocklibc/src/netgroup.c b/test/mocklibc/src/netgroup.c 38 | index 06a8a894..e16e4519 100644 39 | --- a/test/mocklibc/src/netgroup.c 40 | +++ b/test/mocklibc/src/netgroup.c 41 | @@ -71,17 +71,6 @@ static char *parser_copy_word(char **cur) { 42 | return result; 43 | } 44 | 45 | -/** 46 | - * Print a varaible indentation to the stream. 47 | - * @param stream Stream to print to 48 | - * @param indent Number of indents to use 49 | - */ 50 | -void print_indent(FILE *stream, unsigned int indent) { 51 | - int i; 52 | - for (i = 0; i < indent; i++) 53 | - fprintf(stream, " "); 54 | -} 55 | - 56 | /** 57 | * Connect entries with 'child' type to their child entries. 58 | * @param headentry Head of list of entries that need to be connected 59 | -- 60 | GitLab 61 | 62 | -------------------------------------------------------------------------------- /build-aux/flatpak/python-deps.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "python3-deps", 3 | "buildsystem": "simple", 4 | "build-commands": [ 5 | "pip3 install --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} pyparsing" 6 | ], 7 | "sources": [ 8 | { 9 | "type": "file", 10 | "url": "https://files.pythonhosted.org/packages/b9/b8/6b32b3e84014148dcd60dd05795e35c2e7f4b72f918616c61fdce83d27fc/pyparsing-2.3.1.tar.gz", 11 | "sha256": "66c9268862641abcac4a96ba74506e594c884e3f57690a696d21ad8210ed667a" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /build-aux/rpm/bazaar.spec: -------------------------------------------------------------------------------- 1 | # renovate: datasource=git-refs depName=https://github.com/kolunmi/bazaar.git 2 | %global commit 84c30ce0ebf3d3c57bd6b77df40e5778a01e15e8 3 | %global shortcommit %(c=%{commit}; echo ${c:0:7}) 4 | %global appid io.github.kolunmi.bazaar 5 | 6 | Name: bazaar 7 | Version: %{shortcommit} 8 | Release: 1%{?dist} 9 | Summary: A new app store idea for GNOME. 10 | 11 | License: GPL-3.0-only 12 | URL: https://github.com/kolunmi/bazaar 13 | Source0: %{url}/archive/%{commit}.tar.gz 14 | 15 | BuildRequires: meson 16 | BuildRequires: libadwaita-devel 17 | BuildRequires: libxmlb-devel 18 | BuildRequires: flatpak-devel 19 | BuildRequires: glycin-devel 20 | BuildRequires: glycin-gtk4-devel 21 | BuildRequires: libdex-devel 22 | BuildRequires: desktop-file-utils 23 | Requires: glycin-libs 24 | Requires: libadwaita 25 | 26 | %description 27 | %summary 28 | 29 | %prep 30 | %autosetup -n bazaar-%{commit} 31 | 32 | %build 33 | %meson 34 | %meson_build 35 | 36 | %install 37 | %meson_install 38 | 39 | %files 40 | %license COPYING 41 | %doc README.md 42 | %{_datadir}/applications/%{appid}.desktop 43 | %{_bindir}/%{name} 44 | %{_datadir}/dbus-1/services/%{appid}.service 45 | %{_datadir}/glib-2.0/schemas/%{appid}.gschema.xml 46 | %{_datadir}/icons/hicolor/scalable/apps/%{appid}.svg 47 | %{_datadir}/icons/hicolor/symbolic/apps/%{appid}-symbolic.svg 48 | %{_datadir}/metainfo/%{appid}.metainfo.xml 49 | 50 | %changelog 51 | * Sat May 17 2025 Tulip Blossom 52 | - Init package 53 | -------------------------------------------------------------------------------- /data/icons/hicolor/symbolic/apps/io.github.kolunmi.bazaar-symbolic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /data/icons/meson.build: -------------------------------------------------------------------------------- 1 | application_id = 'io.github.kolunmi.bazaar' 2 | 3 | scalable_dir = 'hicolor' / 'scalable' / 'apps' 4 | install_data( 5 | scalable_dir / ('@0@.svg').format(application_id), 6 | install_dir: get_option('datadir') / 'icons' / scalable_dir 7 | ) 8 | 9 | symbolic_dir = 'hicolor' / 'symbolic' / 'apps' 10 | install_data( 11 | symbolic_dir / ('@0@-symbolic.svg').format(application_id), 12 | install_dir: get_option('datadir') / 'icons' / symbolic_dir 13 | ) 14 | -------------------------------------------------------------------------------- /data/io.github.kolunmi.bazaar.desktop.in: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=Bazaar 3 | Exec=bazaar 4 | Icon=io.github.kolunmi.bazaar 5 | Terminal=false 6 | Type=Application 7 | Categories=Utility; 8 | Keywords=GTK; 9 | StartupNotify=true 10 | -------------------------------------------------------------------------------- /data/io.github.kolunmi.bazaar.gschema.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | true 6 | Show Animated Background 7 | Whether to show the animated icon background on the home page 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /data/io.github.kolunmi.bazaar.metainfo.xml.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | io.github.kolunmi.bazaar 4 | CC0-1.0 5 | GPL-3.0-or-later 6 | 7 | Bazaar 8 | 9 | Keep the summary shorter, between 10 and 35 characters 10 | 11 |

No description

12 |
13 | 14 | 15 | Adam Masciola 16 | 17 | 18 | https://github.com/kolunmi/bazaar 19 | https://github.com/kolunmi/bazaar 20 | https://github.com/kolunmi/bazaar/issues 21 | https://github.com/kolunmi/bazaar/tree/master/po 22 | https://github.com/kolunmi/bazaar/blob/master/README.md 23 | https://github.com/kolunmi/bazaar/discussions 24 | https://github.com/sponsors/kolunmi 25 | https://github.com/kolunmi 26 | https://github.com/kolunmi/bazaar 27 | 28 | bazaar 29 | io.github.kolunmi.bazaar.desktop 30 | 31 | 32 | 33 | 34 | #ff00ff 35 | #993d3d 36 | 37 | 38 | 39 | 40 | https://private-user-images.githubusercontent.com/113054217/443949986-1e305d42-8907-49d0-8522-ad9f9ed483a4.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NDc1MTg2MTIsIm5iZiI6MTc0NzUxODMxMiwicGF0aCI6Ii8xMTMwNTQyMTcvNDQzOTQ5OTg2LTFlMzA1ZDQyLTg5MDctNDlkMC04NTIyLWFkOWY5ZWQ0ODNhNC5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjUwNTE3JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI1MDUxN1QyMTQ1MTJaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT0xZDEyN2JlODExNzc4MGJjZTMyNDU3OTYzNzJjMTVmMmU0OWE5NzE5ODc3YTBmNTgzNzY2NjkzMGNjMzA0MjdlJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.PsquhbTag3GuLjbdldbShEnQgT20gT4H7oRQGYYHgQQ 41 | Main Bazaar window showing Blender 42 | 43 | 44 | 45 | 46 | 47 | 48 | https://example.org/changelog.html#version_1.0.1 49 | 50 |

Release description

51 |
    52 |
  • List of changes
  • 53 |
  • List of changes
  • 54 |
55 |
56 |
57 |
58 |
59 | -------------------------------------------------------------------------------- /data/io.github.kolunmi.bazaar.service.in: -------------------------------------------------------------------------------- 1 | [D-BUS Service] 2 | Name=io.github.kolunmi.bazaar 3 | Exec=@bindir@/bazaar service 4 | -------------------------------------------------------------------------------- /data/meson.build: -------------------------------------------------------------------------------- 1 | desktop_file = i18n.merge_file( 2 | input: 'io.github.kolunmi.bazaar.desktop.in', 3 | output: 'io.github.kolunmi.bazaar.desktop', 4 | type: 'desktop', 5 | po_dir: '../po', 6 | install: true, 7 | install_dir: get_option('datadir') / 'applications' 8 | ) 9 | 10 | desktop_utils = find_program('desktop-file-validate', required: false) 11 | if desktop_utils.found() 12 | test('Validate desktop file', desktop_utils, args: [desktop_file]) 13 | endif 14 | 15 | appstream_file = i18n.merge_file( 16 | input: 'io.github.kolunmi.bazaar.metainfo.xml.in', 17 | output: 'io.github.kolunmi.bazaar.metainfo.xml', 18 | po_dir: '../po', 19 | install: true, 20 | install_dir: get_option('datadir') / 'metainfo' 21 | ) 22 | 23 | appstreamcli = find_program('appstreamcli', required: false, disabler: true) 24 | test('Validate appstream file', appstreamcli, 25 | args: ['validate', '--no-net', '--explain', appstream_file]) 26 | 27 | install_data('io.github.kolunmi.bazaar.gschema.xml', 28 | install_dir: get_option('datadir') / 'glib-2.0' / 'schemas' 29 | ) 30 | 31 | compile_schemas = find_program('glib-compile-schemas', required: false, disabler: true) 32 | test('Validate schema file', 33 | compile_schemas, 34 | args: ['--strict', '--dry-run', meson.current_source_dir()]) 35 | 36 | 37 | service_conf = configuration_data() 38 | service_conf.set('bindir', get_option('prefix') / get_option('bindir')) 39 | configure_file( 40 | input: 'io.github.kolunmi.bazaar.service.in', 41 | output: 'io.github.kolunmi.bazaar.service', 42 | configuration: service_conf, 43 | install_dir: get_option('datadir') / 'dbus-1' / 'services' 44 | ) 45 | 46 | subdir('icons') 47 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('bazaar', 'c', 2 | version: run_command('version.sh', 'get-vcs').stdout().strip(), 3 | meson_version: '>= 1.0.0', 4 | default_options: [ 'warning_level=2', 'werror=false', 'c_std=gnu11', ], 5 | ) 6 | 7 | i18n = import('i18n') 8 | gnome = import('gnome') 9 | cc = meson.get_compiler('c') 10 | 11 | config_h = configuration_data() 12 | 13 | config_h.set_quoted('PACKAGE_VERSION', meson.project_version()) 14 | config_h.set_quoted('GETTEXT_PACKAGE', 'bazaar') 15 | config_h.set_quoted('LOCALEDIR', get_option('prefix') / get_option('localedir')) 16 | config_h.set_quoted('DONATE_LINK', 'https://ko-fi.com/kolunmi') 17 | 18 | if get_option('hardcoded_blocklist_path') != '' 19 | config_h.set_quoted('HARDCODED_BLOCKLIST', get_option('hardcoded_blocklist_path')) 20 | endif 21 | if get_option('hardcoded_content_config_path') != '' 22 | config_h.set_quoted('HARDCODED_CONTENT_CONFIG', get_option('hardcoded_content_config_path')) 23 | endif 24 | 25 | configure_file(output: 'config.h', configuration: config_h) 26 | add_project_arguments(['-I' + meson.project_build_root()], language: 'c') 27 | 28 | 29 | project_c_args = [] 30 | test_c_args = [ 31 | '-Wcast-align', 32 | '-Wdeclaration-after-statement', 33 | '-Werror=address', 34 | '-Werror=array-bounds', 35 | '-Werror=empty-body', 36 | '-Werror=implicit', 37 | '-Werror=implicit-function-declaration', 38 | '-Werror=incompatible-pointer-types', 39 | '-Werror=init-self', 40 | '-Werror=int-conversion', 41 | '-Werror=int-to-pointer-cast', 42 | '-Werror=main', 43 | '-Werror=misleading-indentation', 44 | '-Werror=missing-braces', 45 | '-Werror=missing-include-dirs', 46 | '-Werror=nonnull', 47 | '-Werror=overflow', 48 | '-Werror=parenthesis', 49 | '-Werror=pointer-arith', 50 | '-Werror=pointer-to-int-cast', 51 | '-Werror=redundant-decls', 52 | '-Werror=return-type', 53 | '-Werror=sequence-point', 54 | '-Werror=shadow', 55 | '-Werror=strict-prototypes', 56 | '-Werror=trigraphs', 57 | '-Werror=undef', 58 | '-Werror=write-strings', 59 | '-Wformat-nonliteral', 60 | '-Wignored-qualifiers', 61 | '-Wimplicit-function-declaration', 62 | '-Wlogical-op', 63 | '-Wmissing-declarations', 64 | '-Wmissing-format-attribute', 65 | '-Wmissing-include-dirs', 66 | '-Wmissing-noreturn', 67 | '-Wnested-externs', 68 | '-Wno-cast-function-type', 69 | '-Wno-dangling-pointer', 70 | '-Wno-missing-field-initializers', 71 | '-Wno-sign-compare', 72 | '-Wno-unused-parameter', 73 | '-Wold-style-definition', 74 | '-Wpointer-arith', 75 | '-Wredundant-decls', 76 | '-Wstrict-prototypes', 77 | '-Wswitch-default', 78 | '-Wswitch-enum', 79 | '-Wundef', 80 | '-Wuninitialized', 81 | '-Wunused', 82 | '-fno-strict-aliasing', 83 | ['-Werror=format-security', '-Werror=format=2'], 84 | ] 85 | if get_option('buildtype') != 'plain' 86 | test_c_args += '-fstack-protector-strong' 87 | endif 88 | foreach arg: test_c_args 89 | if cc.has_multi_arguments(arg) 90 | project_c_args += arg 91 | endif 92 | endforeach 93 | add_project_arguments(project_c_args, language: 'c') 94 | 95 | 96 | 97 | 98 | subdir('data') 99 | subdir('src') 100 | subdir('po') 101 | 102 | gnome.post_install( 103 | glib_compile_schemas: true, 104 | gtk_update_icon_cache: true, 105 | update_desktop_database: true, 106 | ) 107 | -------------------------------------------------------------------------------- /meson_options.txt: -------------------------------------------------------------------------------- 1 | option('hardcoded_blocklist_path', 2 | type: 'string', 3 | value: '', 4 | description: 'Hardcoded absolute path to a package name blocklist which will be read at runtime') 5 | 6 | option('hardcoded_content_config_path', 7 | type: 'string', 8 | value: '', 9 | description: 'Hardcoded absolute path to a yaml content configuration which will be read at runtime') 10 | -------------------------------------------------------------------------------- /po/LINGUAS: -------------------------------------------------------------------------------- 1 | # Please keep this file sorted alphabetically. 2 | -------------------------------------------------------------------------------- /po/POTFILES.in: -------------------------------------------------------------------------------- 1 | # List of source files containing translatable strings. 2 | # Please keep this file sorted alphabetically. 3 | data/io.github.kolunmi.bazaar.desktop.in 4 | data/io.github.kolunmi.bazaar.gschema.xml 5 | data/io.github.kolunmi.bazaar.metainfo.xml.in 6 | src/bz-application.c 7 | src/bz-error.c 8 | src/bz-preferences-dialog.ui 9 | src/bz-search-widget.ui 10 | src/bz-share-dialog.ui 11 | src/bz-transaction-manager.c 12 | src/bz-transaction-view.ui 13 | src/bz-transaction.c 14 | src/bz-update-dialog.ui 15 | src/bz-window.c 16 | src/bz-window.ui 17 | src/main.c 18 | -------------------------------------------------------------------------------- /po/meson.build: -------------------------------------------------------------------------------- 1 | i18n.gettext('bazaar', preset: 'glib') 2 | -------------------------------------------------------------------------------- /src/bazaar.gresource.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | gtk/styles.css 5 | bz-progress-bar.ui 6 | bz-window.ui 7 | bz-transaction-view.ui 8 | bz-search-widget.ui 9 | bz-browse-widget.ui 10 | bz-section-view.ui 11 | bz-update-dialog.ui 12 | bz-share-dialog.ui 13 | bz-preferences-dialog.ui 14 | bz-content-provider-config-schema.xml 15 | gtk/help-overlay.ui 16 | 17 | icons/scalable/actions/regex-symbolic.svg 18 | icons/scalable/actions/license-symbolic.svg 19 | icons/scalable/actions/people-symbolic.svg 20 | icons/scalable/actions/globe-symbolic.svg 21 | icons/scalable/actions/drive-harddisk-symbolic.svg 22 | icons/scalable/actions/external-link-symbolic.svg 23 | icons/scalable/actions/folder-download-symbolic.svg 24 | icons/scalable/actions/user-trash-symbolic.svg 25 | icons/scalable/actions/share-symbolic.svg 26 | icons/scalable/actions/copy-symbolic.svg 27 | icons/scalable/actions/starred-symbolic.svg 28 | icons/scalable/actions/left-large-symbolic.svg 29 | icons/scalable/actions/right-large-symbolic.svg 30 | icons/scalable/actions/sidebar-show-symbolic.svg 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/bz-application.h: -------------------------------------------------------------------------------- 1 | /* bz-application.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | G_BEGIN_DECLS 26 | 27 | #define BZ_TYPE_APPLICATION (bz_application_get_type ()) 28 | G_DECLARE_FINAL_TYPE (BzApplication, bz_application, BZ, APPLICATION, AdwApplication) 29 | 30 | G_END_DECLS 31 | -------------------------------------------------------------------------------- /src/bz-async-texture.c: -------------------------------------------------------------------------------- 1 | /* bz-async-texture.c 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #include "config.h" 22 | 23 | #include 24 | #include 25 | 26 | #include "bz-async-texture.h" 27 | #include "bz-util.h" 28 | 29 | struct _BzAsyncTexture 30 | { 31 | GObject parent_instance; 32 | 33 | GFile *source; 34 | gboolean loaded; 35 | 36 | DexFuture *task; 37 | GdkPaintable *paintable; 38 | }; 39 | 40 | static void paintable_iface_init (GdkPaintableInterface *iface); 41 | 42 | G_DEFINE_TYPE_WITH_CODE ( 43 | BzAsyncTexture, 44 | bz_async_texture, 45 | G_TYPE_OBJECT, 46 | G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE, paintable_iface_init)) 47 | 48 | enum 49 | { 50 | PROP_0, 51 | 52 | PROP_SOURCE, 53 | PROP_LOADED, 54 | 55 | LAST_PROP 56 | }; 57 | static GParamSpec *props[LAST_PROP] = { 0 }; 58 | 59 | BZ_DEFINE_DATA ( 60 | load, 61 | Load, 62 | { 63 | BzAsyncTexture *self; 64 | GFile *file; 65 | }, 66 | BZ_RELEASE_DATA (self, g_object_unref); 67 | BZ_RELEASE_DATA (file, g_object_unref)); 68 | static DexFuture * 69 | load_fiber (LoadData *data); 70 | static DexFuture * 71 | load_finally (DexFuture *future, 72 | LoadData *data); 73 | 74 | static void 75 | bz_async_texture_dispose (GObject *object) 76 | { 77 | BzAsyncTexture *self = BZ_ASYNC_TEXTURE (object); 78 | 79 | g_clear_object (&self->source); 80 | dex_clear (&self->task); 81 | g_clear_object (&self->paintable); 82 | 83 | G_OBJECT_CLASS (bz_async_texture_parent_class)->dispose (object); 84 | } 85 | 86 | static void 87 | bz_async_texture_get_property (GObject *object, 88 | guint prop_id, 89 | GValue *value, 90 | GParamSpec *pspec) 91 | { 92 | BzAsyncTexture *self = BZ_ASYNC_TEXTURE (object); 93 | 94 | switch (prop_id) 95 | { 96 | case PROP_SOURCE: 97 | g_value_set_object (value, self->source); 98 | break; 99 | case PROP_LOADED: 100 | g_value_set_boolean (value, self->loaded); 101 | break; 102 | default: 103 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 104 | } 105 | } 106 | 107 | static void 108 | bz_async_texture_set_property (GObject *object, 109 | guint prop_id, 110 | const GValue *value, 111 | GParamSpec *pspec) 112 | { 113 | // BzAsyncTexture *self = BZ_ASYNC_TEXTURE (object); 114 | 115 | switch (prop_id) 116 | { 117 | case PROP_SOURCE: 118 | case PROP_LOADED: 119 | default: 120 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 121 | } 122 | } 123 | 124 | static void 125 | bz_async_texture_class_init (BzAsyncTextureClass *klass) 126 | { 127 | GObjectClass *object_class = G_OBJECT_CLASS (klass); 128 | 129 | object_class->dispose = bz_async_texture_dispose; 130 | object_class->get_property = bz_async_texture_get_property; 131 | object_class->set_property = bz_async_texture_set_property; 132 | 133 | props[PROP_SOURCE] = 134 | g_param_spec_object ( 135 | "source", 136 | NULL, NULL, 137 | G_TYPE_FILE, 138 | G_PARAM_READABLE); 139 | 140 | props[PROP_LOADED] = 141 | g_param_spec_boolean ( 142 | "loaded", 143 | NULL, NULL, 144 | FALSE, 145 | G_PARAM_READABLE); 146 | 147 | g_object_class_install_properties (object_class, LAST_PROP, props); 148 | } 149 | 150 | static void 151 | bz_async_texture_init (BzAsyncTexture *self) 152 | { 153 | self->paintable = gdk_paintable_new_empty (0, 0); 154 | } 155 | 156 | void 157 | paintable_snapshot (GdkPaintable *paintable, 158 | GdkSnapshot *snapshot, 159 | double width, 160 | double height) 161 | { 162 | BzAsyncTexture *self = BZ_ASYNC_TEXTURE (paintable); 163 | return gdk_paintable_snapshot (self->paintable, snapshot, width, height); 164 | } 165 | 166 | GdkPaintable * 167 | paintable_get_current_image (GdkPaintable *paintable) 168 | { 169 | BzAsyncTexture *self = BZ_ASYNC_TEXTURE (paintable); 170 | return gdk_paintable_get_current_image (self->paintable); 171 | } 172 | 173 | GdkPaintableFlags 174 | paintable_get_flags (GdkPaintable *paintable) 175 | { 176 | BzAsyncTexture *self = BZ_ASYNC_TEXTURE (paintable); 177 | return 0; 178 | } 179 | 180 | int 181 | paintable_get_intrinsic_width (GdkPaintable *paintable) 182 | { 183 | BzAsyncTexture *self = BZ_ASYNC_TEXTURE (paintable); 184 | return gdk_paintable_get_intrinsic_width (self->paintable); 185 | } 186 | 187 | int 188 | paintable_get_intrinsic_height (GdkPaintable *paintable) 189 | { 190 | BzAsyncTexture *self = BZ_ASYNC_TEXTURE (paintable); 191 | return gdk_paintable_get_intrinsic_height (self->paintable); 192 | } 193 | 194 | double 195 | paintable_get_intrinsic_aspect_ratio (GdkPaintable *paintable) 196 | { 197 | BzAsyncTexture *self = BZ_ASYNC_TEXTURE (paintable); 198 | return gdk_paintable_get_intrinsic_aspect_ratio (self->paintable); 199 | } 200 | 201 | static void 202 | paintable_iface_init (GdkPaintableInterface *iface) 203 | { 204 | iface->snapshot = paintable_snapshot; 205 | iface->get_current_image = paintable_get_current_image; 206 | iface->get_flags = paintable_get_flags; 207 | iface->get_intrinsic_width = paintable_get_intrinsic_width; 208 | iface->get_intrinsic_height = paintable_get_intrinsic_height; 209 | iface->get_intrinsic_aspect_ratio = paintable_get_intrinsic_aspect_ratio; 210 | } 211 | 212 | BzAsyncTexture * 213 | bz_async_texture_new (GFile *source) 214 | { 215 | BzAsyncTexture *self = NULL; 216 | g_autoptr (LoadData) data = NULL; 217 | g_autoptr (DexFuture) future = NULL; 218 | 219 | g_return_val_if_fail (G_IS_FILE (source), NULL); 220 | 221 | self = g_object_new (BZ_TYPE_ASYNC_TEXTURE, NULL); 222 | self->source = g_object_ref (source); 223 | 224 | data = load_data_new (); 225 | data->self = g_object_ref (self); 226 | data->file = g_object_ref (source); 227 | 228 | future = dex_scheduler_spawn ( 229 | dex_thread_pool_scheduler_get_default (), 230 | 0, (DexFiberFunc) load_fiber, 231 | load_data_ref (data), load_data_unref); 232 | future = dex_future_finally ( 233 | future, 234 | (DexFutureCallback) load_finally, 235 | load_data_ref (data), load_data_unref); 236 | self->task = g_steal_pointer (&future); 237 | 238 | return self; 239 | } 240 | 241 | static DexFuture * 242 | load_fiber (LoadData *data) 243 | { 244 | g_autoptr (GError) local_error = NULL; 245 | g_autoptr (GlyLoader) loader = NULL; 246 | g_autoptr (GlyImage) image = NULL; 247 | g_autoptr (GlyFrame) frame = NULL; 248 | g_autoptr (GdkTexture) texture = NULL; 249 | 250 | loader = gly_loader_new (data->file); 251 | image = gly_loader_load (loader, &local_error); 252 | if (image == NULL) 253 | return dex_future_new_for_error (g_steal_pointer (&local_error)); 254 | 255 | frame = gly_image_next_frame (image, &local_error); 256 | if (frame == NULL) 257 | return dex_future_new_for_error (g_steal_pointer (&local_error)); 258 | 259 | texture = gly_gtk_frame_get_texture (frame); 260 | return dex_future_new_for_object (texture); 261 | } 262 | 263 | static DexFuture * 264 | load_finally (DexFuture *future, 265 | LoadData *data) 266 | { 267 | BzAsyncTexture *self = data->self; 268 | const GValue *value = NULL; 269 | 270 | value = dex_future_get_value (future, NULL); 271 | 272 | if (value != NULL) 273 | { 274 | g_clear_object (&self->paintable); 275 | self->paintable = g_value_dup_object (value); 276 | gdk_paintable_invalidate_contents (GDK_PAINTABLE (self)); 277 | 278 | self->loaded = TRUE; 279 | g_object_notify_by_pspec (G_OBJECT (self), props[PROP_LOADED]); 280 | } 281 | 282 | dex_clear (&self->task); 283 | return NULL; 284 | } 285 | -------------------------------------------------------------------------------- /src/bz-async-texture.h: -------------------------------------------------------------------------------- 1 | /* bz-async-texture.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | G_BEGIN_DECLS 26 | 27 | #define BZ_TYPE_ASYNC_TEXTURE (bz_async_texture_get_type ()) 28 | G_DECLARE_FINAL_TYPE (BzAsyncTexture, bz_async_texture, BZ, ASYNC_TEXTURE, GObject) 29 | 30 | BzAsyncTexture * 31 | bz_async_texture_new (GFile *source); 32 | 33 | G_END_DECLS 34 | -------------------------------------------------------------------------------- /src/bz-backend.h: -------------------------------------------------------------------------------- 1 | /* bz-backend.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | #include "bz-entry.h" 26 | #include "bz-transaction.h" 27 | 28 | G_BEGIN_DECLS 29 | 30 | #define BZ_TYPE_BACKEND (bz_backend_get_type ()) 31 | G_DECLARE_INTERFACE (BzBackend, bz_backend, BZ, BACKEND, GObject) 32 | 33 | typedef void (*BzBackendGatherEntriesFunc) ( 34 | BzEntry *entry, 35 | gpointer user_data); 36 | 37 | typedef void (*BzBackendTransactionProgressFunc) ( 38 | BzEntry *entry, 39 | const char *status, 40 | gboolean is_estimating, 41 | int progress_num, 42 | guint64 bytes_transferred, 43 | guint64 start_time, 44 | gpointer user_data); 45 | 46 | struct _BzBackendInterface 47 | { 48 | GTypeInterface parent_iface; 49 | 50 | /* DexFuture* -> gboolean */ 51 | DexFuture *(*refresh) (BzBackend *self); 52 | 53 | /* DexFuture* -> gboolean */ 54 | DexFuture *(*retrieve_remote_entries) (BzBackend *self, 55 | DexScheduler *home_scheduler, 56 | GPtrArray *blocked_names, 57 | BzBackendGatherEntriesFunc progress_func, 58 | gpointer user_data, 59 | GDestroyNotify destroy_user_data); 60 | 61 | /* DexFuture* -> GHashTable* */ 62 | DexFuture *(*retrieve_install_ids) (BzBackend *self); 63 | 64 | /* DexFuture* -> GPtrArray* -> char* */ 65 | DexFuture *(*retrieve_update_ids) (BzBackend *self); 66 | 67 | /* DexFuture* -> gboolean */ 68 | DexFuture *(*schedule_transaction) (BzBackend *self, 69 | BzEntry **installs, 70 | guint n_installs, 71 | BzEntry **updates, 72 | guint n_updates, 73 | BzEntry **removals, 74 | guint n_removals, 75 | BzBackendTransactionProgressFunc progress_func, 76 | gpointer user_data, 77 | GDestroyNotify destroy_user_data); 78 | }; 79 | 80 | DexFuture * 81 | bz_backend_refresh (BzBackend *self); 82 | 83 | DexFuture * 84 | bz_backend_retrieve_remote_entries (BzBackend *self, 85 | DexScheduler *home_scheduler, 86 | GPtrArray *blocked_names, 87 | BzBackendGatherEntriesFunc progress_func, 88 | gpointer user_data, 89 | GDestroyNotify destroy_user_data); 90 | 91 | DexFuture * 92 | bz_backend_retrieve_remote_entries_with_blocklists (BzBackend *self, 93 | DexScheduler *home_scheduler, 94 | GListModel *blocklists, 95 | BzBackendGatherEntriesFunc progress_func, 96 | gpointer user_data, 97 | GDestroyNotify destroy_user_data); 98 | 99 | DexFuture * 100 | bz_backend_retrieve_install_ids (BzBackend *self); 101 | 102 | DexFuture * 103 | bz_backend_retrieve_update_ids (BzBackend *self); 104 | 105 | DexFuture * 106 | bz_backend_schedule_transaction (BzBackend *self, 107 | BzEntry **installs, 108 | guint n_installs, 109 | BzEntry **updates, 110 | guint n_updates, 111 | BzEntry **removals, 112 | guint n_removals, 113 | BzBackendTransactionProgressFunc progress_func, 114 | gpointer user_data, 115 | GDestroyNotify destroy_user_data); 116 | 117 | DexFuture * 118 | bz_backend_merge_and_schedule_transactions (BzBackend *self, 119 | GListModel *transactions, 120 | BzBackendTransactionProgressFunc progress_func, 121 | gpointer user_data, 122 | GDestroyNotify destroy_user_data); 123 | 124 | G_END_DECLS 125 | -------------------------------------------------------------------------------- /src/bz-background.h: -------------------------------------------------------------------------------- 1 | /* bz-background.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | G_BEGIN_DECLS 26 | 27 | #define BZ_TYPE_BACKGROUND (bz_background_get_type ()) 28 | G_DECLARE_FINAL_TYPE (BzBackground, bz_background, BZ, BACKGROUND, GtkWidget) 29 | 30 | GtkWidget * 31 | bz_background_new (void); 32 | 33 | void 34 | bz_background_set_entries (BzBackground *self, 35 | GListModel *entries); 36 | 37 | GListModel * 38 | bz_background_get_entries (BzBackground *self); 39 | 40 | void 41 | bz_background_set_motion_controller (BzBackground *self, 42 | GtkEventControllerMotion *controller); 43 | 44 | GtkEventControllerMotion * 45 | bz_background_get_motion_controller (BzBackground *self); 46 | 47 | G_END_DECLS 48 | -------------------------------------------------------------------------------- /src/bz-browse-widget.c: -------------------------------------------------------------------------------- 1 | /* bz-browse-widget.c 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #include "config.h" 22 | 23 | #include "bz-browse-widget.h" 24 | #include "bz-section-view.h" 25 | 26 | struct _BzBrowseWidget 27 | { 28 | AdwBin parent_instance; 29 | 30 | GListModel *model; 31 | BzContentProvider *provider; 32 | 33 | /* Template widgets */ 34 | }; 35 | 36 | G_DEFINE_FINAL_TYPE (BzBrowseWidget, bz_browse_widget, ADW_TYPE_BIN) 37 | 38 | enum 39 | { 40 | PROP_0, 41 | 42 | PROP_MODEL, 43 | PROP_CONTENT_PROVIDER, 44 | 45 | LAST_PROP 46 | }; 47 | static GParamSpec *props[LAST_PROP] = { 0 }; 48 | 49 | static void 50 | bz_browse_widget_dispose (GObject *object) 51 | { 52 | BzBrowseWidget *self = BZ_BROWSE_WIDGET (object); 53 | 54 | g_clear_object (&self->model); 55 | g_clear_object (&self->provider); 56 | 57 | G_OBJECT_CLASS (bz_browse_widget_parent_class)->dispose (object); 58 | } 59 | 60 | static void 61 | bz_browse_widget_get_property (GObject *object, 62 | guint prop_id, 63 | GValue *value, 64 | GParamSpec *pspec) 65 | { 66 | BzBrowseWidget *self = BZ_BROWSE_WIDGET (object); 67 | 68 | switch (prop_id) 69 | { 70 | case PROP_MODEL: 71 | g_value_set_object (value, bz_browse_widget_get_model (self)); 72 | break; 73 | case PROP_CONTENT_PROVIDER: 74 | g_value_set_object (value, bz_browse_widget_get_content_provider (self)); 75 | break; 76 | default: 77 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 78 | } 79 | } 80 | 81 | static void 82 | bz_browse_widget_set_property (GObject *object, 83 | guint prop_id, 84 | const GValue *value, 85 | GParamSpec *pspec) 86 | { 87 | BzBrowseWidget *self = BZ_BROWSE_WIDGET (object); 88 | 89 | switch (prop_id) 90 | { 91 | case PROP_MODEL: 92 | bz_browse_widget_set_model (self, g_value_get_object (value)); 93 | break; 94 | case PROP_CONTENT_PROVIDER: 95 | bz_browse_widget_set_content_provider (self, g_value_get_object (value)); 96 | break; 97 | default: 98 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 99 | } 100 | } 101 | 102 | static void 103 | bz_browse_widget_class_init (BzBrowseWidgetClass *klass) 104 | { 105 | GObjectClass *object_class = G_OBJECT_CLASS (klass); 106 | GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); 107 | 108 | object_class->dispose = bz_browse_widget_dispose; 109 | object_class->get_property = bz_browse_widget_get_property; 110 | object_class->set_property = bz_browse_widget_set_property; 111 | 112 | props[PROP_MODEL] = 113 | g_param_spec_object ( 114 | "model", 115 | NULL, NULL, 116 | G_TYPE_LIST_MODEL, 117 | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); 118 | 119 | props[PROP_CONTENT_PROVIDER] = 120 | g_param_spec_object ( 121 | "content-provider", 122 | NULL, NULL, 123 | BZ_TYPE_CONTENT_PROVIDER, 124 | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); 125 | 126 | g_object_class_install_properties (object_class, LAST_PROP, props); 127 | 128 | g_type_ensure (BZ_TYPE_SECTION_VIEW); 129 | 130 | gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/bazaar/bz-browse-widget.ui"); 131 | } 132 | 133 | static void 134 | bz_browse_widget_init (BzBrowseWidget *self) 135 | { 136 | 137 | gtk_widget_init_template (GTK_WIDGET (self)); 138 | } 139 | 140 | GtkWidget * 141 | bz_browse_widget_new (GListModel *model) 142 | { 143 | return g_object_new ( 144 | BZ_TYPE_BROWSE_WIDGET, 145 | "model", model, 146 | NULL); 147 | } 148 | 149 | void 150 | bz_browse_widget_set_model (BzBrowseWidget *self, 151 | GListModel *model) 152 | { 153 | g_return_if_fail (BZ_IS_BROWSE_WIDGET (self)); 154 | g_return_if_fail (model == NULL || 155 | (G_IS_LIST_MODEL (model) && 156 | g_list_model_get_item_type (model) == BZ_TYPE_ENTRY)); 157 | 158 | g_clear_object (&self->model); 159 | if (model != NULL) 160 | self->model = g_object_ref (model); 161 | 162 | g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MODEL]); 163 | } 164 | 165 | GListModel * 166 | bz_browse_widget_get_model (BzBrowseWidget *self) 167 | { 168 | g_return_val_if_fail (BZ_IS_BROWSE_WIDGET (self), NULL); 169 | return self->model; 170 | } 171 | 172 | void 173 | bz_browse_widget_set_content_provider (BzBrowseWidget *self, 174 | BzContentProvider *provider) 175 | { 176 | g_return_if_fail (BZ_IS_BROWSE_WIDGET (self)); 177 | g_return_if_fail (provider == NULL || BZ_IS_CONTENT_PROVIDER (provider)); 178 | 179 | g_clear_object (&self->provider); 180 | if (provider != NULL) 181 | self->provider = g_object_ref (provider); 182 | 183 | g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CONTENT_PROVIDER]); 184 | } 185 | 186 | BzContentProvider * 187 | bz_browse_widget_get_content_provider (BzBrowseWidget *self) 188 | { 189 | g_return_val_if_fail (BZ_IS_BROWSE_WIDGET (self), NULL); 190 | return self->provider; 191 | } 192 | -------------------------------------------------------------------------------- /src/bz-browse-widget.h: -------------------------------------------------------------------------------- 1 | /* bz-browse-widget.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | #include "bz-content-provider.h" 26 | 27 | G_BEGIN_DECLS 28 | 29 | #define BZ_TYPE_BROWSE_WIDGET (bz_browse_widget_get_type ()) 30 | G_DECLARE_FINAL_TYPE (BzBrowseWidget, bz_browse_widget, BZ, BROWSE_WIDGET, AdwBin) 31 | 32 | GtkWidget * 33 | bz_browse_widget_new (GListModel *model); 34 | 35 | void 36 | bz_browse_widget_set_model (BzBrowseWidget *self, 37 | GListModel *model); 38 | 39 | GListModel * 40 | bz_browse_widget_get_model (BzBrowseWidget *self); 41 | 42 | void 43 | bz_browse_widget_set_content_provider (BzBrowseWidget *self, 44 | BzContentProvider *provider); 45 | 46 | BzContentProvider * 47 | bz_browse_widget_get_content_provider (BzBrowseWidget *self); 48 | 49 | G_END_DECLS 50 | -------------------------------------------------------------------------------- /src/bz-browse-widget.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 43 | 44 | -------------------------------------------------------------------------------- /src/bz-content-provider-config-schema.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/bz-content-provider.h: -------------------------------------------------------------------------------- 1 | /* bz-content-provider.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include "bz-entry.h" 24 | 25 | G_BEGIN_DECLS 26 | 27 | #define BZ_CONTENT_YAML_ERROR (bz_content_yaml_error_quark ()) 28 | GQuark bz_content_yaml_error_quark (void); 29 | 30 | typedef enum 31 | { 32 | BZ_CONTENT_YAML_ERROR_INVALID_YAML = 0, 33 | BZ_CONTENT_YAML_ERROR_INVALID_STRUCTURE, 34 | } BzContentYamlError; 35 | 36 | #define BZ_TYPE_CONTENT_PROVIDER (bz_content_provider_get_type ()) 37 | G_DECLARE_FINAL_TYPE (BzContentProvider, bz_content_provider, BZ, CONTENT_PROVIDER, GObject) 38 | 39 | BzContentProvider * 40 | bz_content_provider_new (void); 41 | 42 | void 43 | bz_content_provider_set_input_files (BzContentProvider *self, 44 | GListModel *input_files); 45 | 46 | GListModel * 47 | bz_content_provider_get_input_files (BzContentProvider *self); 48 | 49 | /* WARNING: it is ineffective to use this function unless directly after initialization */ 50 | void 51 | bz_content_provider_set_group_hash (BzContentProvider *self, 52 | GHashTable *group_hash); 53 | 54 | GHashTable * 55 | bz_content_provider_get_group_hash (BzContentProvider *self); 56 | 57 | void 58 | bz_content_provider_block (BzContentProvider *self); 59 | 60 | void 61 | bz_content_provider_unblock (BzContentProvider *self); 62 | 63 | G_END_DECLS 64 | -------------------------------------------------------------------------------- /src/bz-content-section.c: -------------------------------------------------------------------------------- 1 | /* bz-content-section.c 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #include "config.h" 22 | 23 | #include "bz-content-section.h" 24 | #include "bz-entry-group.h" 25 | 26 | typedef struct 27 | { 28 | char *error; 29 | GListModel *classes; 30 | char *title; 31 | char *subtitle; 32 | char *description; 33 | GdkPaintable *banner; 34 | GtkContentFit banner_fit; 35 | GListModel *groups; 36 | int rows; 37 | } BzContentSectionPrivate; 38 | 39 | G_DEFINE_TYPE_WITH_PRIVATE (BzContentSection, bz_content_section, G_TYPE_OBJECT) 40 | 41 | enum 42 | { 43 | PROP_0, 44 | 45 | PROP_ERROR, 46 | PROP_CLASSES, 47 | PROP_TITLE, 48 | PROP_SUBTITLE, 49 | PROP_DESCRIPTION, 50 | PROP_BANNER, 51 | PROP_BANNER_FIT, 52 | PROP_APPIDS, 53 | PROP_ROWS, 54 | 55 | LAST_PROP 56 | }; 57 | static GParamSpec *props[LAST_PROP] = { 0 }; 58 | 59 | static void 60 | bz_content_section_dispose (GObject *object) 61 | { 62 | BzContentSection *self = BZ_CONTENT_SECTION (object); 63 | BzContentSectionPrivate *priv = bz_content_section_get_instance_private (self); 64 | 65 | g_clear_pointer (&priv->error, g_free); 66 | g_clear_object (&priv->classes); 67 | g_clear_pointer (&priv->title, g_free); 68 | g_clear_pointer (&priv->subtitle, g_free); 69 | g_clear_pointer (&priv->description, g_free); 70 | g_clear_object (&priv->banner); 71 | g_clear_object (&priv->groups); 72 | 73 | G_OBJECT_CLASS (bz_content_section_parent_class)->dispose (object); 74 | } 75 | 76 | static void 77 | bz_content_section_get_property (GObject *object, 78 | guint prop_id, 79 | GValue *value, 80 | GParamSpec *pspec) 81 | { 82 | BzContentSection *self = BZ_CONTENT_SECTION (object); 83 | BzContentSectionPrivate *priv = bz_content_section_get_instance_private (self); 84 | 85 | switch (prop_id) 86 | { 87 | case PROP_ERROR: 88 | g_value_set_string (value, priv->error); 89 | break; 90 | case PROP_CLASSES: 91 | g_value_set_object (value, priv->classes); 92 | break; 93 | case PROP_TITLE: 94 | g_value_set_string (value, priv->title); 95 | break; 96 | case PROP_SUBTITLE: 97 | g_value_set_string (value, priv->subtitle); 98 | break; 99 | case PROP_DESCRIPTION: 100 | g_value_set_string (value, priv->description); 101 | break; 102 | case PROP_BANNER: 103 | g_value_set_object (value, priv->banner); 104 | break; 105 | case PROP_BANNER_FIT: 106 | g_value_set_enum (value, priv->banner_fit); 107 | break; 108 | case PROP_APPIDS: 109 | g_value_set_object (value, priv->groups); 110 | break; 111 | case PROP_ROWS: 112 | g_value_set_int (value, priv->rows); 113 | break; 114 | default: 115 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 116 | } 117 | } 118 | 119 | static void 120 | bz_content_section_set_property (GObject *object, 121 | guint prop_id, 122 | const GValue *value, 123 | GParamSpec *pspec) 124 | { 125 | BzContentSection *self = BZ_CONTENT_SECTION (object); 126 | BzContentSectionPrivate *priv = bz_content_section_get_instance_private (self); 127 | 128 | switch (prop_id) 129 | { 130 | case PROP_ERROR: 131 | g_clear_pointer (&priv->error, g_free); 132 | priv->error = g_value_dup_string (value); 133 | break; 134 | case PROP_CLASSES: 135 | g_clear_object (&priv->classes); 136 | priv->classes = g_value_dup_object (value); 137 | break; 138 | case PROP_TITLE: 139 | g_clear_pointer (&priv->title, g_free); 140 | priv->title = g_value_dup_string (value); 141 | break; 142 | case PROP_SUBTITLE: 143 | g_clear_pointer (&priv->subtitle, g_free); 144 | priv->subtitle = g_value_dup_string (value); 145 | break; 146 | case PROP_DESCRIPTION: 147 | g_clear_pointer (&priv->description, g_free); 148 | priv->description = g_value_dup_string (value); 149 | break; 150 | case PROP_BANNER: 151 | g_clear_object (&priv->banner); 152 | priv->banner = g_value_dup_object (value); 153 | break; 154 | case PROP_BANNER_FIT: 155 | priv->banner_fit = g_value_get_enum (value); 156 | break; 157 | case PROP_APPIDS: 158 | g_clear_object (&priv->groups); 159 | priv->groups = g_value_dup_object (value); 160 | break; 161 | case PROP_ROWS: 162 | priv->rows = g_value_get_int (value); 163 | break; 164 | default: 165 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 166 | } 167 | } 168 | 169 | static void 170 | bz_content_section_class_init (BzContentSectionClass *klass) 171 | { 172 | GObjectClass *object_class = G_OBJECT_CLASS (klass); 173 | 174 | object_class->set_property = bz_content_section_set_property; 175 | object_class->get_property = bz_content_section_get_property; 176 | object_class->dispose = bz_content_section_dispose; 177 | 178 | props[PROP_ERROR] = 179 | g_param_spec_string ( 180 | "error", 181 | NULL, NULL, NULL, 182 | G_PARAM_READWRITE); 183 | 184 | props[PROP_CLASSES] = 185 | g_param_spec_object ( 186 | "classes", 187 | NULL, NULL, 188 | G_TYPE_LIST_MODEL, 189 | G_PARAM_READWRITE); 190 | 191 | props[PROP_TITLE] = 192 | g_param_spec_string ( 193 | "title", 194 | NULL, NULL, NULL, 195 | G_PARAM_READWRITE); 196 | 197 | props[PROP_SUBTITLE] = 198 | g_param_spec_string ( 199 | "subtitle", 200 | NULL, NULL, NULL, 201 | G_PARAM_READWRITE); 202 | 203 | props[PROP_DESCRIPTION] = 204 | g_param_spec_string ( 205 | "description", 206 | NULL, NULL, NULL, 207 | G_PARAM_READWRITE); 208 | 209 | props[PROP_BANNER] = 210 | g_param_spec_object ( 211 | "banner", 212 | NULL, NULL, 213 | GDK_TYPE_PAINTABLE, 214 | G_PARAM_READWRITE); 215 | 216 | props[PROP_BANNER_FIT] = 217 | g_param_spec_enum ( 218 | "banner-fit", 219 | NULL, NULL, 220 | GTK_TYPE_CONTENT_FIT, 221 | GTK_CONTENT_FIT_COVER, 222 | G_PARAM_READWRITE); 223 | 224 | props[PROP_APPIDS] = 225 | g_param_spec_object ( 226 | "appids", 227 | NULL, NULL, 228 | G_TYPE_LIST_MODEL, 229 | G_PARAM_READWRITE); 230 | 231 | props[PROP_ROWS] = 232 | g_param_spec_int ( 233 | "rows", 234 | NULL, NULL, 235 | 1, 16, 3, 236 | G_PARAM_READWRITE); 237 | 238 | g_object_class_install_properties (object_class, LAST_PROP, props); 239 | } 240 | 241 | static void 242 | bz_content_section_init (BzContentSection *self) 243 | { 244 | BzContentSectionPrivate *priv = bz_content_section_get_instance_private (self); 245 | 246 | priv->rows = 3; 247 | } 248 | -------------------------------------------------------------------------------- /src/bz-content-section.h: -------------------------------------------------------------------------------- 1 | /* bz-content-section.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | G_BEGIN_DECLS 26 | 27 | #define BZ_TYPE_CONTENT_SECTION (bz_content_section_get_type ()) 28 | G_DECLARE_DERIVABLE_TYPE (BzContentSection, bz_content_section, BZ, CONTENT_SECTION, GObject) 29 | 30 | struct _BzContentSectionClass 31 | { 32 | GObjectClass parent_class; 33 | }; 34 | 35 | G_END_DECLS 36 | -------------------------------------------------------------------------------- /src/bz-entry-group.h: -------------------------------------------------------------------------------- 1 | /* bz-entry-group.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include "bz-entry.h" 24 | 25 | G_BEGIN_DECLS 26 | 27 | #define BZ_TYPE_ENTRY_GROUP (bz_entry_group_get_type ()) 28 | G_DECLARE_FINAL_TYPE (BzEntryGroup, bz_entry_group, BZ, ENTRY_GROUP, GObject) 29 | 30 | BzEntryGroup * 31 | bz_entry_group_new (void); 32 | 33 | GListModel * 34 | bz_entry_group_get_model (BzEntryGroup *self); 35 | 36 | BzEntry * 37 | bz_entry_group_get_ui_entry (BzEntryGroup *self); 38 | 39 | void 40 | bz_entry_group_add (BzEntryGroup *self, 41 | BzEntry *entry, 42 | gboolean installable, 43 | gboolean updatable, 44 | gboolean removable); 45 | 46 | void 47 | bz_entry_group_install (BzEntryGroup *self, 48 | BzEntry *entry); 49 | 50 | void 51 | bz_entry_group_remove (BzEntryGroup *self, 52 | BzEntry *entry); 53 | 54 | gboolean 55 | bz_entry_group_query_installable (BzEntryGroup *self, 56 | BzEntry *entry); 57 | 58 | gboolean 59 | bz_entry_group_query_updatable (BzEntryGroup *self, 60 | BzEntry *entry); 61 | 62 | gboolean 63 | bz_entry_group_query_removable (BzEntryGroup *self, 64 | BzEntry *entry); 65 | 66 | G_END_DECLS 67 | -------------------------------------------------------------------------------- /src/bz-entry.h: -------------------------------------------------------------------------------- 1 | /* bz-entry.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | G_BEGIN_DECLS 26 | 27 | #define BZ_TYPE_ENTRY (bz_entry_get_type ()) 28 | G_DECLARE_DERIVABLE_TYPE (BzEntry, bz_entry, BZ, ENTRY, GObject) 29 | 30 | struct _BzEntryClass 31 | { 32 | GObjectClass parent_class; 33 | }; 34 | 35 | const char * 36 | bz_entry_get_id (BzEntry *self); 37 | 38 | const char * 39 | bz_entry_get_unique_id (BzEntry *self); 40 | 41 | const char * 42 | bz_entry_get_title (BzEntry *self); 43 | 44 | const char * 45 | bz_entry_get_eol (BzEntry *self); 46 | 47 | const char * 48 | bz_entry_get_description (BzEntry *self); 49 | 50 | const char * 51 | bz_entry_get_long_description (BzEntry *self); 52 | 53 | const char * 54 | bz_entry_get_remote_repo_name (BzEntry *self); 55 | 56 | guint64 57 | bz_entry_get_size (BzEntry *self); 58 | 59 | GdkPaintable * 60 | bz_entry_get_icon_paintable (BzEntry *self); 61 | 62 | GPtrArray * 63 | bz_entry_get_search_tokens (BzEntry *self); 64 | 65 | gint 66 | bz_entry_cmp_usefulness (gconstpointer a, 67 | gconstpointer b, 68 | gpointer user_data); 69 | 70 | G_END_DECLS 71 | -------------------------------------------------------------------------------- /src/bz-error.c: -------------------------------------------------------------------------------- 1 | /* bz-error.c 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #include "config.h" 22 | 23 | #include 24 | #include 25 | 26 | #include "bz-error.h" 27 | 28 | static void 29 | error_alert_response (AdwAlertDialog *alert, 30 | gchar *response, 31 | GtkWidget *widget); 32 | 33 | void 34 | bz_show_error_for_widget (GtkWidget *widget, 35 | GtkWidget *parent, 36 | const char *text) 37 | { 38 | AdwDialog *alert = NULL; 39 | 40 | g_return_if_fail (GTK_IS_WIDGET (widget)); 41 | g_return_if_fail (parent == NULL || GTK_IS_WIDGET (parent)); 42 | g_return_if_fail (text != NULL); 43 | 44 | if (parent == NULL) 45 | parent = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW); 46 | g_assert (parent != NULL); 47 | 48 | alert = adw_alert_dialog_new (NULL, NULL); 49 | adw_alert_dialog_format_heading ( 50 | ADW_ALERT_DIALOG (alert), _ ("An Error Occured")); 51 | adw_alert_dialog_format_body ( 52 | ADW_ALERT_DIALOG (alert), 53 | "%s", text); 54 | adw_alert_dialog_add_responses ( 55 | ADW_ALERT_DIALOG (alert), 56 | "close", _ ("Close"), 57 | "copy", _ ("Copy and Close"), 58 | NULL); 59 | adw_alert_dialog_set_response_appearance ( 60 | ADW_ALERT_DIALOG (alert), "copy", ADW_RESPONSE_SUGGESTED); 61 | adw_alert_dialog_set_default_response (ADW_ALERT_DIALOG (alert), "close"); 62 | adw_alert_dialog_set_close_response (ADW_ALERT_DIALOG (alert), "close"); 63 | 64 | g_signal_connect (alert, "response", G_CALLBACK (error_alert_response), widget); 65 | adw_dialog_present (alert, GTK_WIDGET (widget)); 66 | } 67 | 68 | static void 69 | error_alert_response (AdwAlertDialog *alert, 70 | gchar *response, 71 | GtkWidget *widget) 72 | { 73 | if (g_strcmp0 (response, "copy") == 0) 74 | { 75 | const char *body = NULL; 76 | GdkClipboard *clipboard; 77 | 78 | body = adw_alert_dialog_get_body (alert); 79 | clipboard = gdk_display_get_clipboard (gdk_display_get_default ()); 80 | 81 | gdk_clipboard_set_text (clipboard, body); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/bz-error.h: -------------------------------------------------------------------------------- 1 | /* bz-error.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | G_BEGIN_DECLS 26 | 27 | /* if parent is NULL, search for window ancestor */ 28 | void 29 | bz_show_error_for_widget (GtkWidget *widget, 30 | GtkWidget *parent, 31 | const char *text); 32 | 33 | G_END_DECLS 34 | -------------------------------------------------------------------------------- /src/bz-flatpak-entry.h: -------------------------------------------------------------------------------- 1 | /* bz-flatpak-entry.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include "bz-entry.h" 24 | 25 | G_BEGIN_DECLS 26 | 27 | #define BZ_TYPE_FLATPAK_ENTRY (bz_flatpak_entry_get_type ()) 28 | G_DECLARE_FINAL_TYPE (BzFlatpakEntry, bz_flatpak_entry, BZ, FLATPAK_ENTRY, BzEntry) 29 | 30 | gboolean 31 | bz_flatpak_entry_is_user (BzFlatpakEntry *self); 32 | 33 | const char * 34 | bz_flatpak_entry_get_name (BzFlatpakEntry *self); 35 | 36 | gboolean 37 | bz_flatpak_entry_launch (BzFlatpakEntry *self, 38 | GError **error); 39 | 40 | G_END_DECLS 41 | -------------------------------------------------------------------------------- /src/bz-flatpak-instance.h: -------------------------------------------------------------------------------- 1 | /* bz-flatpak-instance.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | #include "bz-flatpak-entry.h" 26 | 27 | G_BEGIN_DECLS 28 | 29 | #define BZ_TYPE_FLATPAK_INSTANCE (bz_flatpak_instance_get_type ()) 30 | G_DECLARE_FINAL_TYPE (BzFlatpakInstance, bz_flatpak_instance, BZ, FLATPAK_INSTANCE, GObject) 31 | 32 | DexFuture * 33 | bz_flatpak_instance_new (void); 34 | 35 | G_END_DECLS 36 | -------------------------------------------------------------------------------- /src/bz-flatpak-private.h: -------------------------------------------------------------------------------- 1 | /* bz-flatpak-private.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | 26 | #include "bz-flatpak-entry.h" 27 | #include "bz-flatpak-instance.h" 28 | 29 | G_BEGIN_DECLS 30 | 31 | /* BzFlatpakInstance */ 32 | 33 | FlatpakInstallation * 34 | bz_flatpak_instance_get_installation (BzFlatpakInstance *self); 35 | 36 | /* BzFlatpakEntry */ 37 | 38 | char * 39 | bz_flatpak_ref_format_unique (FlatpakRef *ref, 40 | gboolean user); 41 | 42 | BzFlatpakEntry * 43 | bz_flatpak_entry_new_for_remote_ref (BzFlatpakInstance *instance, 44 | gboolean user, 45 | FlatpakRemote *remote, 46 | FlatpakRemoteRef *rref, 47 | AsComponent *component, 48 | const char *appstream_dir, 49 | GdkPaintable *remote_icon, 50 | GError **error); 51 | 52 | FlatpakRef * 53 | bz_flatpak_entry_get_ref (BzFlatpakEntry *self); 54 | 55 | G_END_DECLS 56 | -------------------------------------------------------------------------------- /src/bz-paintable-model.c: -------------------------------------------------------------------------------- 1 | /* bz-paintable-model.c 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #include "config.h" 22 | 23 | #include 24 | 25 | #include "bz-paintable-model.h" 26 | #include "bz-util.h" 27 | 28 | struct _BzPaintableModel 29 | { 30 | GObject parent_instance; 31 | 32 | DexScheduler *scheduler; 33 | 34 | GListModel *model; 35 | GHashTable *tracking; 36 | }; 37 | 38 | static void list_model_iface_init (GListModelInterface *iface); 39 | 40 | static void 41 | items_changed (GListModel *model, 42 | guint position, 43 | guint removed, 44 | guint added, 45 | BzPaintableModel *self); 46 | 47 | G_DEFINE_TYPE_WITH_CODE ( 48 | BzPaintableModel, 49 | bz_paintable_model, 50 | G_TYPE_OBJECT, 51 | G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, list_model_iface_init)) 52 | 53 | enum 54 | { 55 | PROP_0, 56 | 57 | PROP_MODEL, 58 | 59 | LAST_PROP 60 | }; 61 | static GParamSpec *props[LAST_PROP] = { 0 }; 62 | 63 | BZ_DEFINE_DATA ( 64 | load, 65 | Load, 66 | { 67 | BzPaintableModel *self; 68 | GFile *file; 69 | }, 70 | BZ_RELEASE_DATA (self, g_object_unref); 71 | BZ_RELEASE_DATA (file, g_object_unref)); 72 | static DexFuture * 73 | load_fiber (LoadData *data); 74 | static DexFuture * 75 | load_finally (DexFuture *future, 76 | LoadData *data); 77 | 78 | static void 79 | bz_paintable_model_dispose (GObject *object) 80 | { 81 | BzPaintableModel *self = BZ_PAINTABLE_MODEL (object); 82 | 83 | g_clear_pointer (&self->scheduler, dex_unref); 84 | g_clear_object (&self->model); 85 | g_clear_pointer (&self->tracking, g_hash_table_unref); 86 | 87 | G_OBJECT_CLASS (bz_paintable_model_parent_class)->dispose (object); 88 | } 89 | 90 | static void 91 | bz_paintable_model_get_property (GObject *object, 92 | guint prop_id, 93 | GValue *value, 94 | GParamSpec *pspec) 95 | { 96 | BzPaintableModel *self = BZ_PAINTABLE_MODEL (object); 97 | 98 | switch (prop_id) 99 | { 100 | case PROP_MODEL: 101 | g_value_set_object (value, bz_paintable_model_get_model (self)); 102 | break; 103 | default: 104 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 105 | } 106 | } 107 | 108 | static void 109 | bz_paintable_model_set_property (GObject *object, 110 | guint prop_id, 111 | const GValue *value, 112 | GParamSpec *pspec) 113 | { 114 | BzPaintableModel *self = BZ_PAINTABLE_MODEL (object); 115 | 116 | switch (prop_id) 117 | { 118 | case PROP_MODEL: 119 | bz_paintable_model_set_model (self, g_value_get_object (value)); 120 | break; 121 | default: 122 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 123 | } 124 | } 125 | 126 | static void 127 | bz_paintable_model_class_init (BzPaintableModelClass *klass) 128 | { 129 | GObjectClass *object_class = G_OBJECT_CLASS (klass); 130 | 131 | object_class->dispose = bz_paintable_model_dispose; 132 | object_class->get_property = bz_paintable_model_get_property; 133 | object_class->set_property = bz_paintable_model_set_property; 134 | 135 | props[PROP_MODEL] = 136 | g_param_spec_object ( 137 | "model", 138 | NULL, NULL, 139 | G_TYPE_LIST_MODEL, 140 | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); 141 | 142 | g_object_class_install_properties (object_class, LAST_PROP, props); 143 | } 144 | 145 | static void 146 | bz_paintable_model_init (BzPaintableModel *self) 147 | { 148 | self->tracking = g_hash_table_new_full ( 149 | g_direct_hash, g_direct_equal, 150 | g_object_unref, g_object_unref); 151 | } 152 | 153 | static GType 154 | list_model_get_item_type (GListModel *list) 155 | { 156 | return GDK_TYPE_PAINTABLE; 157 | } 158 | 159 | static guint 160 | list_model_get_n_items (GListModel *list) 161 | { 162 | BzPaintableModel *self = BZ_PAINTABLE_MODEL (list); 163 | 164 | return g_list_model_get_n_items (G_LIST_MODEL (self->model)); 165 | } 166 | 167 | static gpointer 168 | list_model_get_item (GListModel *list, 169 | guint position) 170 | { 171 | BzPaintableModel *self = BZ_PAINTABLE_MODEL (list); 172 | g_autoptr (GFile) file = NULL; 173 | GdkPaintable *lookup = NULL; 174 | 175 | file = g_list_model_get_item (G_LIST_MODEL (self->model), position); 176 | lookup = g_hash_table_lookup (self->tracking, file); 177 | 178 | if (lookup != NULL) 179 | return g_object_ref (lookup); 180 | else 181 | { 182 | GdkPaintable *temp = NULL; 183 | g_autoptr (LoadData) data = NULL; 184 | DexFuture *future = NULL; 185 | 186 | temp = gdk_paintable_new_empty (512, 512); 187 | g_hash_table_replace (self->tracking, g_object_ref (file), g_object_ref (temp)); 188 | 189 | data = load_data_new (); 190 | data->self = g_object_ref (self); 191 | data->file = g_list_model_get_item (G_LIST_MODEL (self->model), position); 192 | 193 | future = dex_scheduler_spawn ( 194 | self->scheduler, 0, (DexFiberFunc) load_fiber, 195 | load_data_ref (data), load_data_unref); 196 | future = dex_future_finally ( 197 | future, 198 | (DexFutureCallback) load_finally, 199 | load_data_ref (data), load_data_unref); 200 | 201 | /* TODO: make cancellable */ 202 | dex_future_disown (future); 203 | 204 | return temp; 205 | } 206 | } 207 | 208 | static void 209 | list_model_iface_init (GListModelInterface *iface) 210 | { 211 | iface->get_item_type = list_model_get_item_type; 212 | iface->get_n_items = list_model_get_n_items; 213 | iface->get_item = list_model_get_item; 214 | } 215 | 216 | BzPaintableModel * 217 | bz_paintable_model_new (DexScheduler *scheduler, 218 | GListModel *model) 219 | { 220 | BzPaintableModel *self = NULL; 221 | 222 | g_return_val_if_fail (DEX_IS_SCHEDULER (scheduler), NULL); 223 | 224 | self = g_object_new ( 225 | BZ_TYPE_PAINTABLE_MODEL, 226 | "model", model, 227 | NULL); 228 | self->scheduler = dex_ref (scheduler); 229 | 230 | return self; 231 | } 232 | 233 | void 234 | bz_paintable_model_set_model (BzPaintableModel *self, 235 | GListModel *model) 236 | { 237 | guint old_length = 0; 238 | 239 | g_return_if_fail (BZ_IS_PAINTABLE_MODEL (self)); 240 | g_return_if_fail (model == NULL || 241 | (G_IS_LIST_MODEL (model) && 242 | g_list_model_get_item_type (model) == G_TYPE_FILE)); 243 | 244 | if (self->model != NULL) 245 | { 246 | old_length = g_list_model_get_n_items (self->model); 247 | g_signal_handlers_disconnect_by_func ( 248 | self->model, items_changed, self); 249 | } 250 | g_clear_object (&self->model); 251 | 252 | if (model != NULL) 253 | { 254 | self->model = g_object_ref (model); 255 | g_signal_connect ( 256 | model, "items-changed", 257 | G_CALLBACK (items_changed), self); 258 | 259 | g_list_model_items_changed ( 260 | G_LIST_MODEL (self), 0, old_length, 261 | g_list_model_get_n_items (model)); 262 | } 263 | else 264 | g_list_model_items_changed ( 265 | G_LIST_MODEL (self), 0, old_length, 0); 266 | 267 | g_object_notify_by_pspec (G_OBJECT (self), props[PROP_MODEL]); 268 | } 269 | 270 | GListModel * 271 | bz_paintable_model_get_model (BzPaintableModel *self) 272 | { 273 | g_return_val_if_fail (BZ_IS_PAINTABLE_MODEL (self), NULL); 274 | 275 | return self->model; 276 | } 277 | 278 | static void 279 | items_changed (GListModel *model, 280 | guint position, 281 | guint removed, 282 | guint added, 283 | BzPaintableModel *self) 284 | { 285 | g_list_model_items_changed ( 286 | G_LIST_MODEL (self), position, removed, added); 287 | } 288 | 289 | static DexFuture * 290 | load_fiber (LoadData *data) 291 | { 292 | g_autoptr (GError) local_error = NULL; 293 | g_autoptr (GlyLoader) loader = NULL; 294 | g_autoptr (GlyImage) image = NULL; 295 | g_autoptr (GlyFrame) frame = NULL; 296 | g_autoptr (GdkTexture) texture = NULL; 297 | 298 | loader = gly_loader_new (data->file); 299 | image = gly_loader_load (loader, &local_error); 300 | if (image == NULL) 301 | return dex_future_new_for_error (g_steal_pointer (&local_error)); 302 | 303 | frame = gly_image_next_frame (image, &local_error); 304 | if (frame == NULL) 305 | return dex_future_new_for_error (g_steal_pointer (&local_error)); 306 | 307 | texture = gly_gtk_frame_get_texture (frame); 308 | return dex_future_new_for_object (texture); 309 | } 310 | 311 | static DexFuture * 312 | load_finally (DexFuture *future, 313 | LoadData *data) 314 | { 315 | BzPaintableModel *self = data->self; 316 | const GValue *value = NULL; 317 | 318 | value = dex_future_get_value (future, NULL); 319 | 320 | if (value != NULL) 321 | { 322 | guint n_files = 0; 323 | guint position = 0; 324 | GdkPaintable *paintable = NULL; 325 | 326 | n_files = g_list_model_get_n_items (G_LIST_MODEL (self->model)); 327 | for (position = 0; position < n_files; position++) 328 | { 329 | g_autoptr (GFile) file = NULL; 330 | 331 | file = g_list_model_get_item (self->model, position); 332 | if (file == data->file) 333 | break; 334 | } 335 | 336 | if (position < n_files) 337 | { 338 | paintable = g_value_get_object (value); 339 | g_hash_table_replace ( 340 | self->tracking, 341 | g_object_ref (data->file), 342 | g_object_ref (paintable)); 343 | 344 | g_list_model_items_changed ( 345 | G_LIST_MODEL (self), position, 1, 1); 346 | } 347 | } 348 | 349 | return dex_future_new_true (); 350 | } 351 | -------------------------------------------------------------------------------- /src/bz-paintable-model.h: -------------------------------------------------------------------------------- 1 | /* bz-paintable-model.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | 26 | G_BEGIN_DECLS 27 | 28 | #define BZ_TYPE_PAINTABLE_MODEL (bz_paintable_model_get_type ()) 29 | G_DECLARE_FINAL_TYPE (BzPaintableModel, bz_paintable_model, BZ, PAINTABLE_MODEL, GObject) 30 | 31 | BzPaintableModel * 32 | bz_paintable_model_new (DexScheduler *scheduler, 33 | GListModel *model); 34 | 35 | void 36 | bz_paintable_model_set_model (BzPaintableModel *self, 37 | GListModel *model); 38 | 39 | GListModel * 40 | bz_paintable_model_get_model (BzPaintableModel *self); 41 | 42 | G_END_DECLS 43 | -------------------------------------------------------------------------------- /src/bz-preferences-dialog.c: -------------------------------------------------------------------------------- 1 | /* bz-preferences-dialog.c 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #include "config.h" 22 | 23 | #include "bz-preferences-dialog.h" 24 | 25 | struct _BzPreferencesDialog 26 | { 27 | AdwDialog parent_instance; 28 | 29 | GSettings *settings; 30 | 31 | /* Template widgets */ 32 | }; 33 | 34 | G_DEFINE_FINAL_TYPE (BzPreferencesDialog, bz_preferences_dialog, ADW_TYPE_PREFERENCES_DIALOG) 35 | 36 | enum 37 | { 38 | PROP_0, 39 | 40 | PROP_SETTINGS, 41 | PROP_SHOW_ANIMATED_BACKGROUND, 42 | 43 | LAST_PROP 44 | }; 45 | static GParamSpec *props[LAST_PROP] = { 0 }; 46 | 47 | static void 48 | setting_changed (GSettings *settings, 49 | gchar *key, 50 | BzPreferencesDialog *self); 51 | 52 | static void 53 | bz_preferences_dialog_dispose (GObject *object) 54 | { 55 | BzPreferencesDialog *self = BZ_PREFERENCES_DIALOG (object); 56 | 57 | if (self->settings != NULL) 58 | g_signal_handlers_disconnect_by_func ( 59 | self->settings, setting_changed, self); 60 | g_clear_object (&self->settings); 61 | 62 | G_OBJECT_CLASS (bz_preferences_dialog_parent_class)->dispose (object); 63 | } 64 | 65 | static void 66 | bz_preferences_dialog_get_property (GObject *object, 67 | guint prop_id, 68 | GValue *value, 69 | GParamSpec *pspec) 70 | { 71 | BzPreferencesDialog *self = BZ_PREFERENCES_DIALOG (object); 72 | 73 | switch (prop_id) 74 | { 75 | case PROP_SETTINGS: 76 | g_value_set_object (value, self->settings); 77 | break; 78 | case PROP_SHOW_ANIMATED_BACKGROUND: 79 | g_value_set_boolean ( 80 | value, 81 | self->settings != NULL 82 | ? g_settings_get_boolean ( 83 | self->settings, "show-animated-background") 84 | : TRUE); 85 | break; 86 | default: 87 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 88 | } 89 | } 90 | 91 | static void 92 | bz_preferences_dialog_set_property (GObject *object, 93 | guint prop_id, 94 | const GValue *value, 95 | GParamSpec *pspec) 96 | { 97 | BzPreferencesDialog *self = BZ_PREFERENCES_DIALOG (object); 98 | 99 | switch (prop_id) 100 | { 101 | case PROP_SETTINGS: 102 | if (self->settings != NULL) 103 | g_signal_handlers_disconnect_by_func ( 104 | self->settings, setting_changed, self); 105 | g_clear_object (&self->settings); 106 | self->settings = g_value_dup_object (value); 107 | if (self->settings != NULL) 108 | g_signal_connect ( 109 | self->settings, "changed", 110 | G_CALLBACK (setting_changed), self); 111 | g_object_notify_by_pspec (object, props[PROP_SHOW_ANIMATED_BACKGROUND]); 112 | break; 113 | case PROP_SHOW_ANIMATED_BACKGROUND: 114 | if (self->settings != NULL) 115 | g_settings_set_boolean ( 116 | self->settings, 117 | "show-animated-background", 118 | g_value_get_boolean (value)); 119 | break; 120 | default: 121 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 122 | } 123 | } 124 | 125 | static void 126 | bz_preferences_dialog_class_init (BzPreferencesDialogClass *klass) 127 | { 128 | GObjectClass *object_class = G_OBJECT_CLASS (klass); 129 | GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); 130 | 131 | object_class->dispose = bz_preferences_dialog_dispose; 132 | object_class->get_property = bz_preferences_dialog_get_property; 133 | object_class->set_property = bz_preferences_dialog_set_property; 134 | 135 | props[PROP_SETTINGS] = 136 | g_param_spec_object ( 137 | "settings", 138 | NULL, NULL, 139 | G_TYPE_SETTINGS, 140 | G_PARAM_READWRITE); 141 | 142 | props[PROP_SHOW_ANIMATED_BACKGROUND] = 143 | g_param_spec_boolean ( 144 | "show-animated-background", 145 | NULL, NULL, 146 | TRUE, 147 | G_PARAM_READWRITE); 148 | 149 | g_object_class_install_properties (object_class, LAST_PROP, props); 150 | 151 | gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/bazaar/bz-preferences-dialog.ui"); 152 | } 153 | 154 | static void 155 | bz_preferences_dialog_init (BzPreferencesDialog *self) 156 | { 157 | gtk_widget_init_template (GTK_WIDGET (self)); 158 | } 159 | 160 | static void 161 | setting_changed (GSettings *settings, 162 | gchar *key, 163 | BzPreferencesDialog *self) 164 | { 165 | int prop = 0; 166 | 167 | if (g_strcmp0 (key, "show-animated-background") == 0) 168 | prop = PROP_SHOW_ANIMATED_BACKGROUND; 169 | 170 | if (prop > PROP_0 && prop < LAST_PROP) 171 | g_object_notify_by_pspec (G_OBJECT (self), props[prop]); 172 | } 173 | 174 | AdwDialog * 175 | bz_preferences_dialog_new (GSettings *settings) 176 | { 177 | BzPreferencesDialog *dialog = NULL; 178 | 179 | dialog = g_object_new ( 180 | BZ_TYPE_PREFERENCES_DIALOG, 181 | "settings", settings, 182 | NULL); 183 | 184 | return ADW_DIALOG (dialog); 185 | } 186 | -------------------------------------------------------------------------------- /src/bz-preferences-dialog.h: -------------------------------------------------------------------------------- 1 | /* bz-preferences-dialog.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | G_BEGIN_DECLS 26 | 27 | #define BZ_TYPE_PREFERENCES_DIALOG (bz_preferences_dialog_get_type ()) 28 | G_DECLARE_FINAL_TYPE (BzPreferencesDialog, bz_preferences_dialog, BZ, PREFERENCES_DIALOG, AdwPreferencesDialog) 29 | 30 | AdwDialog * 31 | bz_preferences_dialog_new (GSettings *settings); 32 | 33 | G_END_DECLS 34 | -------------------------------------------------------------------------------- /src/bz-preferences-dialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 27 | 28 | -------------------------------------------------------------------------------- /src/bz-progress-bar.c: -------------------------------------------------------------------------------- 1 | /* bz-progress-bar.c 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #include "config.h" 22 | 23 | #include "bz-progress-bar.h" 24 | 25 | struct _BzProgressBar 26 | { 27 | AdwBin parent_instance; 28 | 29 | double fraction; 30 | 31 | AdwAnimation *animation; 32 | 33 | /* Template widgets */ 34 | GtkProgressBar *bar; 35 | }; 36 | 37 | G_DEFINE_FINAL_TYPE (BzProgressBar, bz_progress_bar, ADW_TYPE_BIN) 38 | 39 | enum 40 | { 41 | PROP_0, 42 | 43 | PROP_FRACTION, 44 | 45 | LAST_PROP 46 | }; 47 | static GParamSpec *props[LAST_PROP] = { 0 }; 48 | 49 | static void 50 | bz_progress_bar_dispose (GObject *object) 51 | { 52 | BzProgressBar *self = BZ_PROGRESS_BAR (object); 53 | 54 | g_clear_object (&self->animation); 55 | 56 | G_OBJECT_CLASS (bz_progress_bar_parent_class)->dispose (object); 57 | } 58 | 59 | static void 60 | bz_progress_bar_get_property (GObject *object, 61 | guint prop_id, 62 | GValue *value, 63 | GParamSpec *pspec) 64 | { 65 | BzProgressBar *self = BZ_PROGRESS_BAR (object); 66 | 67 | switch (prop_id) 68 | { 69 | case PROP_FRACTION: 70 | g_value_set_double (value, bz_progress_bar_get_fraction (self)); 71 | break; 72 | default: 73 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 74 | } 75 | } 76 | 77 | static void 78 | bz_progress_bar_set_property (GObject *object, 79 | guint prop_id, 80 | const GValue *value, 81 | GParamSpec *pspec) 82 | { 83 | BzProgressBar *self = BZ_PROGRESS_BAR (object); 84 | 85 | switch (prop_id) 86 | { 87 | case PROP_FRACTION: 88 | bz_progress_bar_set_fraction (self, g_value_get_double (value)); 89 | break; 90 | default: 91 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 92 | } 93 | } 94 | 95 | static void 96 | bz_progress_bar_class_init (BzProgressBarClass *klass) 97 | { 98 | GObjectClass *object_class = G_OBJECT_CLASS (klass); 99 | GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); 100 | 101 | object_class->dispose = bz_progress_bar_dispose; 102 | object_class->get_property = bz_progress_bar_get_property; 103 | object_class->set_property = bz_progress_bar_set_property; 104 | 105 | props[PROP_FRACTION] = 106 | g_param_spec_double ( 107 | "fraction", 108 | NULL, NULL, 109 | 0.0, 1.0, 0.0, 110 | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); 111 | 112 | g_object_class_install_properties (object_class, LAST_PROP, props); 113 | 114 | gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/bazaar/bz-progress-bar.ui"); 115 | gtk_widget_class_bind_template_child (widget_class, BzProgressBar, bar); 116 | } 117 | 118 | static void 119 | bz_progress_bar_init (BzProgressBar *self) 120 | { 121 | AdwAnimationTarget *target = NULL; 122 | AdwSpringParams *spring = NULL; 123 | 124 | gtk_widget_init_template (GTK_WIDGET (self)); 125 | 126 | target = adw_property_animation_target_new (G_OBJECT (self->bar), "fraction"); 127 | spring = adw_spring_params_new (1.0, 0.5, 200.0); 128 | 129 | self->animation = adw_spring_animation_new ( 130 | GTK_WIDGET (self), 131 | 0.0, 132 | 0.0, 133 | spring, 134 | target); 135 | adw_spring_animation_set_epsilon ( 136 | ADW_SPRING_ANIMATION (self->animation), 0.00025); 137 | } 138 | 139 | GtkWidget * 140 | bz_progress_bar_new (void) 141 | { 142 | return g_object_new (BZ_TYPE_PROGRESS_BAR, NULL); 143 | } 144 | 145 | void 146 | bz_progress_bar_set_fraction (BzProgressBar *self, 147 | double fraction) 148 | { 149 | double current = 0.0; 150 | 151 | g_return_if_fail (BZ_IS_PROGRESS_BAR (self)); 152 | 153 | self->fraction = CLAMP (fraction, 0.0, 1.0); 154 | current = gtk_progress_bar_get_fraction (self->bar); 155 | 156 | if (self->fraction < current || 157 | G_APPROX_VALUE (current, self->fraction, 0.001)) 158 | { 159 | adw_animation_reset (self->animation); 160 | gtk_progress_bar_set_fraction (self->bar, self->fraction); 161 | } 162 | else 163 | { 164 | adw_spring_animation_set_value_from ( 165 | ADW_SPRING_ANIMATION (self->animation), 166 | current); 167 | adw_spring_animation_set_value_to ( 168 | ADW_SPRING_ANIMATION (self->animation), 169 | self->fraction); 170 | adw_spring_animation_set_initial_velocity ( 171 | ADW_SPRING_ANIMATION (self->animation), 172 | adw_spring_animation_get_velocity ( 173 | ADW_SPRING_ANIMATION (self->animation))); 174 | 175 | adw_animation_play (self->animation); 176 | } 177 | 178 | g_object_notify_by_pspec (G_OBJECT (self), props[PROP_FRACTION]); 179 | } 180 | 181 | double 182 | bz_progress_bar_get_fraction (BzProgressBar *self) 183 | { 184 | g_return_val_if_fail (BZ_IS_PROGRESS_BAR (self), 0.0); 185 | return self->fraction; 186 | } 187 | -------------------------------------------------------------------------------- /src/bz-progress-bar.h: -------------------------------------------------------------------------------- 1 | /* bz-progress-bar.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | G_BEGIN_DECLS 26 | 27 | #define BZ_TYPE_PROGRESS_BAR (bz_progress_bar_get_type ()) 28 | G_DECLARE_FINAL_TYPE (BzProgressBar, bz_progress_bar, BZ, PROGRESS_BAR, AdwBin) 29 | 30 | GtkWidget * 31 | bz_progress_bar_new (void); 32 | 33 | void 34 | bz_progress_bar_set_fraction (BzProgressBar *self, 35 | double fraction); 36 | 37 | double 38 | bz_progress_bar_get_fraction (BzProgressBar *self); 39 | 40 | G_END_DECLS 41 | -------------------------------------------------------------------------------- /src/bz-progress-bar.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /src/bz-review.c: -------------------------------------------------------------------------------- 1 | /* bz-review.c 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #include "config.h" 22 | 23 | #include "bz-review.h" 24 | 25 | typedef struct 26 | { 27 | int priority; 28 | char *id; 29 | char *summary; 30 | char *description; 31 | char *locale; 32 | double rating; 33 | char *version; 34 | char *reviewer_id; 35 | char *reviewer_name; 36 | GDateTime *date; 37 | gboolean was_self; 38 | gboolean self_voted; 39 | } BzReviewPrivate; 40 | 41 | G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (BzReview, bz_review, G_TYPE_OBJECT) 42 | 43 | enum 44 | { 45 | PROP_0, 46 | 47 | PROP_PRIORITY, 48 | PROP_ID, 49 | PROP_SUMMARY, 50 | PROP_DESCRIPTION, 51 | PROP_LOCALE, 52 | PROP_RATING, 53 | PROP_VERSION, 54 | PROP_REVIEWER_ID, 55 | PROP_REVIEWER_NAME, 56 | PROP_DATE, 57 | PROP_WAS_SELF, 58 | PROP_SELF_VOTED, 59 | 60 | LAST_PROP 61 | }; 62 | static GParamSpec *props[LAST_PROP] = { 0 }; 63 | 64 | static void 65 | bz_review_dispose (GObject *object) 66 | { 67 | BzReview *self = BZ_REVIEW (object); 68 | BzReviewPrivate *priv = bz_review_get_instance_private (self); 69 | 70 | g_clear_pointer (&priv->id, g_free); 71 | g_clear_pointer (&priv->summary, g_free); 72 | g_clear_pointer (&priv->description, g_free); 73 | g_clear_pointer (&priv->locale, g_free); 74 | g_clear_pointer (&priv->version, g_free); 75 | g_clear_pointer (&priv->reviewer_id, g_free); 76 | g_clear_pointer (&priv->reviewer_name, g_free); 77 | g_clear_pointer (&priv->date, g_date_time_unref); 78 | 79 | G_OBJECT_CLASS (bz_review_parent_class)->dispose (object); 80 | } 81 | 82 | static void 83 | bz_review_get_property (GObject *object, 84 | guint prop_id, 85 | GValue *value, 86 | GParamSpec *pspec) 87 | { 88 | BzReview *self = BZ_REVIEW (object); 89 | BzReviewPrivate *priv = bz_review_get_instance_private (self); 90 | 91 | switch (prop_id) 92 | { 93 | case PROP_PRIORITY: 94 | g_value_set_int (value, priv->priority); 95 | break; 96 | case PROP_ID: 97 | g_value_set_string (value, priv->id); 98 | break; 99 | case PROP_SUMMARY: 100 | g_value_set_string (value, priv->summary); 101 | break; 102 | case PROP_DESCRIPTION: 103 | g_value_set_string (value, priv->description); 104 | break; 105 | case PROP_LOCALE: 106 | g_value_set_string (value, priv->locale); 107 | break; 108 | case PROP_RATING: 109 | g_value_set_double (value, priv->rating); 110 | break; 111 | case PROP_VERSION: 112 | g_value_set_string (value, priv->version); 113 | break; 114 | case PROP_REVIEWER_ID: 115 | g_value_set_string (value, priv->reviewer_id); 116 | break; 117 | case PROP_REVIEWER_NAME: 118 | g_value_set_string (value, priv->reviewer_name); 119 | break; 120 | case PROP_DATE: 121 | g_value_set_boxed (value, priv->date); 122 | break; 123 | case PROP_WAS_SELF: 124 | g_value_set_boolean (value, priv->was_self); 125 | break; 126 | case PROP_SELF_VOTED: 127 | g_value_set_boolean (value, priv->self_voted); 128 | break; 129 | default: 130 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 131 | } 132 | } 133 | 134 | static void 135 | bz_review_set_property (GObject *object, 136 | guint prop_id, 137 | const GValue *value, 138 | GParamSpec *pspec) 139 | { 140 | BzReview *self = BZ_REVIEW (object); 141 | BzReviewPrivate *priv = bz_review_get_instance_private (self); 142 | 143 | switch (prop_id) 144 | { 145 | case PROP_PRIORITY: 146 | priv->priority = g_value_get_int (value); 147 | break; 148 | case PROP_ID: 149 | g_clear_pointer (&priv->id, g_free); 150 | priv->id = g_value_dup_string (value); 151 | break; 152 | case PROP_SUMMARY: 153 | g_clear_pointer (&priv->summary, g_free); 154 | priv->summary = g_value_dup_string (value); 155 | break; 156 | case PROP_DESCRIPTION: 157 | g_clear_pointer (&priv->description, g_free); 158 | priv->description = g_value_dup_string (value); 159 | break; 160 | case PROP_LOCALE: 161 | g_clear_pointer (&priv->locale, g_free); 162 | priv->locale = g_value_dup_string (value); 163 | break; 164 | case PROP_RATING: 165 | priv->rating = g_value_get_double (value); 166 | break; 167 | case PROP_VERSION: 168 | g_clear_pointer (&priv->version, g_free); 169 | priv->version = g_value_dup_string (value); 170 | break; 171 | case PROP_REVIEWER_ID: 172 | g_clear_pointer (&priv->reviewer_id, g_free); 173 | priv->reviewer_id = g_value_dup_string (value); 174 | break; 175 | case PROP_REVIEWER_NAME: 176 | g_clear_pointer (&priv->reviewer_name, g_free); 177 | priv->reviewer_name = g_value_dup_string (value); 178 | break; 179 | case PROP_DATE: 180 | g_clear_pointer (&priv->date, g_date_time_unref); 181 | priv->date = g_value_dup_boxed (value); 182 | break; 183 | case PROP_WAS_SELF: 184 | priv->was_self = g_value_get_boolean (value); 185 | break; 186 | case PROP_SELF_VOTED: 187 | priv->self_voted = g_value_get_boolean (value); 188 | break; 189 | default: 190 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 191 | } 192 | } 193 | 194 | static void 195 | bz_review_class_init (BzReviewClass *klass) 196 | { 197 | GObjectClass *object_class = G_OBJECT_CLASS (klass); 198 | 199 | object_class->set_property = bz_review_set_property; 200 | object_class->get_property = bz_review_get_property; 201 | object_class->dispose = bz_review_dispose; 202 | 203 | props[PROP_PRIORITY] = 204 | g_param_spec_int ( 205 | "priority", 206 | NULL, NULL, 207 | G_MININT, G_MAXINT, 0, 208 | G_PARAM_READWRITE); 209 | 210 | props[PROP_ID] = 211 | g_param_spec_string ( 212 | "id", 213 | NULL, NULL, NULL, 214 | G_PARAM_READWRITE); 215 | 216 | props[PROP_SUMMARY] = 217 | g_param_spec_string ( 218 | "summary", 219 | NULL, NULL, NULL, 220 | G_PARAM_READWRITE); 221 | 222 | props[PROP_DESCRIPTION] = 223 | g_param_spec_string ( 224 | "description", 225 | NULL, NULL, NULL, 226 | G_PARAM_READWRITE); 227 | 228 | props[PROP_LOCALE] = 229 | g_param_spec_string ( 230 | "locale", 231 | NULL, NULL, NULL, 232 | G_PARAM_READWRITE); 233 | 234 | props[PROP_RATING] = 235 | g_param_spec_double ( 236 | "rating", 237 | NULL, NULL, 238 | 0.0, 1.0, 0.0, 239 | G_PARAM_READWRITE); 240 | 241 | props[PROP_VERSION] = 242 | g_param_spec_string ( 243 | "version", 244 | NULL, NULL, NULL, 245 | G_PARAM_READWRITE); 246 | 247 | props[PROP_REVIEWER_ID] = 248 | g_param_spec_string ( 249 | "reviewer-id", 250 | NULL, NULL, NULL, 251 | G_PARAM_READWRITE); 252 | 253 | props[PROP_REVIEWER_NAME] = 254 | g_param_spec_string ( 255 | "reviewer-name", 256 | NULL, NULL, NULL, 257 | G_PARAM_READWRITE); 258 | 259 | props[PROP_DATE] = 260 | g_param_spec_boxed ( 261 | "date", 262 | NULL, NULL, 263 | G_TYPE_DATE_TIME, 264 | G_PARAM_READWRITE); 265 | 266 | props[PROP_WAS_SELF] = 267 | g_param_spec_boolean ( 268 | "was-self", 269 | NULL, NULL, FALSE, 270 | G_PARAM_READWRITE); 271 | 272 | props[PROP_SELF_VOTED] = 273 | g_param_spec_boolean ( 274 | "self-voted", 275 | NULL, NULL, FALSE, 276 | G_PARAM_READWRITE); 277 | 278 | g_object_class_install_properties (object_class, LAST_PROP, props); 279 | } 280 | 281 | static void 282 | bz_review_init (BzReview *self) 283 | { 284 | } 285 | -------------------------------------------------------------------------------- /src/bz-review.h: -------------------------------------------------------------------------------- 1 | /* bz-review.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | G_BEGIN_DECLS 26 | 27 | #define BZ_TYPE_REVIEW (bz_review_get_type ()) 28 | G_DECLARE_DERIVABLE_TYPE (BzReview, bz_review, BZ, REVIEW, GObject) 29 | 30 | struct _BzReviewClass 31 | { 32 | GObjectClass parent_class; 33 | }; 34 | 35 | G_END_DECLS 36 | -------------------------------------------------------------------------------- /src/bz-search-widget.h: -------------------------------------------------------------------------------- 1 | /* bz-search-widget.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | #include "bz-entry-group.h" 26 | 27 | G_BEGIN_DECLS 28 | 29 | #define BZ_TYPE_SEARCH_WIDGET (bz_search_widget_get_type ()) 30 | G_DECLARE_FINAL_TYPE (BzSearchWidget, bz_search_widget, BZ, SEARCH_WIDGET, AdwBin) 31 | 32 | GtkWidget * 33 | bz_search_widget_new (GListModel *model, 34 | const char *initial); 35 | 36 | void 37 | bz_search_widget_set_model (BzSearchWidget *self, 38 | GListModel *model); 39 | 40 | GListModel * 41 | bz_search_widget_get_model (BzSearchWidget *self); 42 | 43 | BzEntryGroup * 44 | bz_search_widget_get_selected (BzSearchWidget *self, 45 | gboolean *remove); 46 | 47 | BzEntry * 48 | bz_search_widget_get_previewing (BzSearchWidget *self); 49 | 50 | G_END_DECLS 51 | -------------------------------------------------------------------------------- /src/bz-section-view.c: -------------------------------------------------------------------------------- 1 | /* bz-section-view.c 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #include "config.h" 22 | 23 | #include "bz-entry-group.h" 24 | #include "bz-section-view.h" 25 | 26 | struct _BzSectionView 27 | { 28 | AdwBin parent_instance; 29 | 30 | BzContentSection *section; 31 | GListModel *classes; 32 | 33 | AdwAnimation *scroll_animation; 34 | 35 | /* Template widgets */ 36 | GtkScrolledWindow *entry_scroll; 37 | }; 38 | 39 | G_DEFINE_FINAL_TYPE (BzSectionView, bz_section_view, ADW_TYPE_BIN) 40 | 41 | enum 42 | { 43 | PROP_0, 44 | 45 | PROP_SECTION, 46 | 47 | LAST_PROP 48 | }; 49 | static GParamSpec *props[LAST_PROP] = { 0 }; 50 | 51 | static void 52 | move_entries (BzSectionView *self, 53 | double delta); 54 | 55 | static void 56 | bz_section_view_dispose (GObject *object) 57 | { 58 | BzSectionView *self = BZ_SECTION_VIEW (object); 59 | 60 | g_clear_object (&self->section); 61 | g_clear_object (&self->classes); 62 | g_clear_object (&self->scroll_animation); 63 | 64 | G_OBJECT_CLASS (bz_section_view_parent_class)->dispose (object); 65 | } 66 | 67 | static void 68 | bz_section_view_get_property (GObject *object, 69 | guint prop_id, 70 | GValue *value, 71 | GParamSpec *pspec) 72 | { 73 | BzSectionView *self = BZ_SECTION_VIEW (object); 74 | 75 | switch (prop_id) 76 | { 77 | case PROP_SECTION: 78 | g_value_set_object (value, bz_section_view_get_section (self)); 79 | break; 80 | default: 81 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 82 | } 83 | } 84 | 85 | static void 86 | bz_section_view_set_property (GObject *object, 87 | guint prop_id, 88 | const GValue *value, 89 | GParamSpec *pspec) 90 | { 91 | BzSectionView *self = BZ_SECTION_VIEW (object); 92 | 93 | switch (prop_id) 94 | { 95 | case PROP_SECTION: 96 | bz_section_view_set_section (self, g_value_get_object (value)); 97 | break; 98 | default: 99 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 100 | } 101 | } 102 | 103 | static void 104 | entries_left_clicked_cb (BzSectionView *self, 105 | GtkButton *button) 106 | { 107 | double width = 0.0; 108 | 109 | width = gtk_widget_get_width (GTK_WIDGET (self->entry_scroll)); 110 | move_entries (self, -width * 0.8); 111 | } 112 | 113 | static void 114 | entries_right_clicked_cb (BzSectionView *self, 115 | GtkButton *button) 116 | { 117 | double width = 0.0; 118 | 119 | width = gtk_widget_get_width (GTK_WIDGET (self->entry_scroll)); 120 | move_entries (self, width * 0.8); 121 | } 122 | 123 | static void 124 | entry_activated_cb (BzSectionView *self, 125 | guint position, 126 | GtkListView *list_view) 127 | { 128 | g_autoptr (GListModel) groups = NULL; 129 | g_autoptr (BzEntryGroup) group = NULL; 130 | BzEntry *ui_entry = NULL; 131 | 132 | g_object_get (self->section, "appids", &groups, NULL); 133 | g_assert (groups != NULL); 134 | 135 | group = g_list_model_get_item (groups, position); 136 | ui_entry = bz_entry_group_get_ui_entry (group); 137 | 138 | if (ui_entry != NULL) 139 | { 140 | const char *id = NULL; 141 | 142 | id = bz_entry_get_id (ui_entry); 143 | gtk_widget_activate_action (GTK_WIDGET (self), "app.search", "s", id); 144 | } 145 | } 146 | 147 | static void 148 | bz_section_view_class_init (BzSectionViewClass *klass) 149 | { 150 | GObjectClass *object_class = G_OBJECT_CLASS (klass); 151 | GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); 152 | 153 | object_class->dispose = bz_section_view_dispose; 154 | object_class->get_property = bz_section_view_get_property; 155 | object_class->set_property = bz_section_view_set_property; 156 | 157 | props[PROP_SECTION] = 158 | g_param_spec_object ( 159 | "section", 160 | NULL, NULL, 161 | BZ_TYPE_CONTENT_SECTION, 162 | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); 163 | 164 | g_object_class_install_properties (object_class, LAST_PROP, props); 165 | 166 | g_type_ensure (BZ_TYPE_SECTION_VIEW); 167 | 168 | gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/bazaar/bz-section-view.ui"); 169 | gtk_widget_class_bind_template_child (widget_class, BzSectionView, entry_scroll); 170 | gtk_widget_class_bind_template_callback (widget_class, entries_left_clicked_cb); 171 | gtk_widget_class_bind_template_callback (widget_class, entries_right_clicked_cb); 172 | gtk_widget_class_bind_template_callback (widget_class, entry_activated_cb); 173 | } 174 | 175 | static void 176 | bz_section_view_init (BzSectionView *self) 177 | { 178 | g_autoptr (GListModel) entry_scroll_controllers = NULL; 179 | guint n_controllers = 0; 180 | GtkAdjustment *hadjust = NULL; 181 | AdwAnimationTarget *target = NULL; 182 | AdwSpringParams *spring = NULL; 183 | 184 | gtk_widget_init_template (GTK_WIDGET (self)); 185 | 186 | entry_scroll_controllers = gtk_widget_observe_controllers (GTK_WIDGET (self->entry_scroll)); 187 | n_controllers = g_list_model_get_n_items (entry_scroll_controllers); 188 | 189 | for (guint i = 0; i < n_controllers; i++) 190 | { 191 | g_autoptr (GtkEventController) controller = NULL; 192 | 193 | controller = g_list_model_get_item (entry_scroll_controllers, i); 194 | 195 | if (GTK_IS_EVENT_CONTROLLER_SCROLL (controller)) 196 | /* Here to prevent the entry scrolled 197 | * window from interfering with the 198 | * main browser scrolled window 199 | */ 200 | gtk_event_controller_set_propagation_phase ( 201 | controller, GTK_PHASE_NONE); 202 | } 203 | 204 | hadjust = gtk_scrolled_window_get_hadjustment (self->entry_scroll); 205 | target = adw_property_animation_target_new (G_OBJECT (hadjust), "value"); 206 | spring = adw_spring_params_new (0.9, 1.5, 150.0); 207 | 208 | self->scroll_animation = adw_spring_animation_new ( 209 | GTK_WIDGET (self), 210 | 0.0, 211 | 0.0, 212 | spring, 213 | target); 214 | adw_spring_animation_set_epsilon ( 215 | ADW_SPRING_ANIMATION (self->scroll_animation), 0.00025); 216 | } 217 | 218 | GtkWidget * 219 | bz_section_view_new (BzContentSection *section) 220 | { 221 | return g_object_new ( 222 | BZ_TYPE_SECTION_VIEW, 223 | "section", section, 224 | NULL); 225 | } 226 | 227 | void 228 | bz_section_view_set_section (BzSectionView *self, 229 | BzContentSection *section) 230 | { 231 | g_return_if_fail (BZ_IS_SECTION_VIEW (self)); 232 | g_return_if_fail (section == NULL || BZ_IS_CONTENT_SECTION (section)); 233 | 234 | g_clear_object (&self->section); 235 | 236 | if (self->classes != NULL) 237 | { 238 | guint n_classes = 0; 239 | 240 | n_classes = g_list_model_get_n_items (self->classes); 241 | for (guint i = 0; i < n_classes; i++) 242 | { 243 | g_autoptr (GtkStringObject) string = NULL; 244 | const char *class = NULL; 245 | 246 | string = g_list_model_get_item (self->classes, i); 247 | class = gtk_string_object_get_string (string); 248 | 249 | gtk_widget_remove_css_class (GTK_WIDGET (self), class); 250 | } 251 | } 252 | g_clear_object (&self->classes); 253 | 254 | if (section != NULL) 255 | { 256 | self->section = g_object_ref (section); 257 | g_object_get (section, "classes", &self->classes, NULL); 258 | 259 | if (self->classes != NULL) 260 | { 261 | guint n_classes = 0; 262 | 263 | n_classes = g_list_model_get_n_items (self->classes); 264 | for (guint i = 0; i < n_classes; i++) 265 | { 266 | g_autoptr (GtkStringObject) string = NULL; 267 | const char *class = NULL; 268 | 269 | string = g_list_model_get_item (self->classes, i); 270 | class = gtk_string_object_get_string (string); 271 | 272 | gtk_widget_add_css_class (GTK_WIDGET (self), class); 273 | } 274 | } 275 | } 276 | 277 | g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SECTION]); 278 | } 279 | 280 | BzContentSection * 281 | bz_section_view_get_section (BzSectionView *self) 282 | { 283 | g_return_val_if_fail (BZ_IS_SECTION_VIEW (self), NULL); 284 | return self->section; 285 | } 286 | 287 | static void 288 | move_entries (BzSectionView *self, 289 | double delta) 290 | { 291 | GtkAdjustment *hadjust = NULL; 292 | double current = 0.0; 293 | double lower = 0.0; 294 | double upper = 0.0; 295 | double next = 0.0; 296 | 297 | hadjust = gtk_scrolled_window_get_hadjustment (self->entry_scroll); 298 | current = gtk_adjustment_get_value (hadjust); 299 | lower = gtk_adjustment_get_lower (hadjust); 300 | upper = gtk_adjustment_get_upper (hadjust) - gtk_adjustment_get_page_size (hadjust); 301 | next = adw_spring_animation_get_value_to ( 302 | ADW_SPRING_ANIMATION (self->scroll_animation)) + 303 | delta; 304 | 305 | adw_spring_animation_set_value_from ( 306 | ADW_SPRING_ANIMATION (self->scroll_animation), 307 | current); 308 | adw_spring_animation_set_value_to ( 309 | ADW_SPRING_ANIMATION (self->scroll_animation), 310 | CLAMP (next, lower, upper)); 311 | adw_spring_animation_set_initial_velocity ( 312 | ADW_SPRING_ANIMATION (self->scroll_animation), 313 | adw_spring_animation_get_velocity ( 314 | ADW_SPRING_ANIMATION (self->scroll_animation))); 315 | 316 | adw_animation_play (self->scroll_animation); 317 | } 318 | -------------------------------------------------------------------------------- /src/bz-section-view.h: -------------------------------------------------------------------------------- 1 | /* bz-section-view.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | #include "bz-content-section.h" 26 | 27 | G_BEGIN_DECLS 28 | 29 | #define BZ_TYPE_SECTION_VIEW (bz_section_view_get_type ()) 30 | G_DECLARE_FINAL_TYPE (BzSectionView, bz_section_view, BZ, SECTION_VIEW, AdwBin) 31 | 32 | GtkWidget * 33 | bz_section_view_new (BzContentSection *section); 34 | 35 | void 36 | bz_section_view_set_section (BzSectionView *self, 37 | BzContentSection *section); 38 | 39 | BzContentSection * 40 | bz_section_view_get_section (BzSectionView *self); 41 | 42 | G_END_DECLS 43 | -------------------------------------------------------------------------------- /src/bz-share-dialog.c: -------------------------------------------------------------------------------- 1 | /* bz-share-dialog.c 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #include "config.h" 22 | 23 | #include "bz-entry.h" 24 | #include "bz-share-dialog.h" 25 | 26 | struct _BzShareDialog 27 | { 28 | AdwDialog parent_instance; 29 | 30 | BzEntry *entry; 31 | 32 | /* Template widgets */ 33 | }; 34 | 35 | G_DEFINE_FINAL_TYPE (BzShareDialog, bz_share_dialog, ADW_TYPE_DIALOG) 36 | 37 | enum 38 | { 39 | PROP_0, 40 | 41 | PROP_ENTRY, 42 | 43 | LAST_PROP 44 | }; 45 | static GParamSpec *props[LAST_PROP] = { 0 }; 46 | 47 | static void 48 | bz_share_dialog_dispose (GObject *object) 49 | { 50 | BzShareDialog *self = BZ_SHARE_DIALOG (object); 51 | 52 | g_clear_object (&self->entry); 53 | 54 | G_OBJECT_CLASS (bz_share_dialog_parent_class)->dispose (object); 55 | } 56 | 57 | static void 58 | bz_share_dialog_get_property (GObject *object, 59 | guint prop_id, 60 | GValue *value, 61 | GParamSpec *pspec) 62 | { 63 | BzShareDialog *self = BZ_SHARE_DIALOG (object); 64 | 65 | switch (prop_id) 66 | { 67 | case PROP_ENTRY: 68 | g_value_set_object (value, self->entry); 69 | break; 70 | default: 71 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 72 | } 73 | } 74 | 75 | static void 76 | bz_share_dialog_set_property (GObject *object, 77 | guint prop_id, 78 | const GValue *value, 79 | GParamSpec *pspec) 80 | { 81 | BzShareDialog *self = BZ_SHARE_DIALOG (object); 82 | 83 | switch (prop_id) 84 | { 85 | case PROP_ENTRY: 86 | g_clear_object (&self->entry); 87 | self->entry = g_value_dup_object (value); 88 | break; 89 | default: 90 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 91 | } 92 | } 93 | 94 | static char * 95 | get_share_url_name (gpointer object, 96 | const char *value) 97 | { 98 | const char *sep = NULL; 99 | char *name = NULL; 100 | 101 | if (value == NULL) 102 | return NULL; 103 | 104 | sep = g_utf8_strchr (value, -1, ','); 105 | if (sep == NULL || sep == value) 106 | return NULL; 107 | 108 | name = g_malloc (sep - value + 1); 109 | memcpy (name, value, sep - value); 110 | name[sep - value] = '\0'; 111 | 112 | return name; 113 | } 114 | 115 | static char * 116 | get_share_url_link (gpointer object, 117 | const char *value) 118 | { 119 | const char *sep = NULL; 120 | 121 | if (value == NULL) 122 | return NULL; 123 | 124 | sep = g_utf8_strchr (value, -1, ','); 125 | if (sep == NULL || sep == value || sep[1] == '\0') 126 | return NULL; 127 | 128 | return g_strdup (sep + 1); 129 | } 130 | 131 | static void 132 | copy_cb (GtkListItem *list_item, 133 | GtkButton *button) 134 | { 135 | GtkStringObject *item = NULL; 136 | const char *string = NULL; 137 | g_autofree char *link = NULL; 138 | GdkClipboard *clipboard; 139 | 140 | item = gtk_list_item_get_item (list_item); 141 | string = gtk_string_object_get_string (item); 142 | link = get_share_url_link (NULL, string); 143 | 144 | clipboard = gdk_display_get_clipboard (gdk_display_get_default ()); 145 | gdk_clipboard_set_text (clipboard, link); 146 | } 147 | 148 | static void 149 | follow_link_cb (GtkListItem *list_item, 150 | GtkButton *button) 151 | { 152 | GtkStringObject *item = NULL; 153 | const char *string = NULL; 154 | g_autofree char *link = NULL; 155 | 156 | item = gtk_list_item_get_item (list_item); 157 | string = gtk_string_object_get_string (item); 158 | link = get_share_url_link (NULL, string); 159 | 160 | g_app_info_launch_default_for_uri (link, NULL, NULL); 161 | } 162 | 163 | static void 164 | bz_share_dialog_class_init (BzShareDialogClass *klass) 165 | { 166 | GObjectClass *object_class = G_OBJECT_CLASS (klass); 167 | GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); 168 | 169 | object_class->dispose = bz_share_dialog_dispose; 170 | object_class->get_property = bz_share_dialog_get_property; 171 | object_class->set_property = bz_share_dialog_set_property; 172 | 173 | props[PROP_ENTRY] = 174 | g_param_spec_object ( 175 | "entry", 176 | NULL, NULL, 177 | BZ_TYPE_ENTRY, 178 | G_PARAM_READWRITE); 179 | 180 | g_object_class_install_properties (object_class, LAST_PROP, props); 181 | 182 | gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/bazaar/bz-share-dialog.ui"); 183 | gtk_widget_class_bind_template_callback (widget_class, get_share_url_name); 184 | gtk_widget_class_bind_template_callback (widget_class, get_share_url_link); 185 | gtk_widget_class_bind_template_callback (widget_class, copy_cb); 186 | gtk_widget_class_bind_template_callback (widget_class, follow_link_cb); 187 | } 188 | 189 | static void 190 | bz_share_dialog_init (BzShareDialog *self) 191 | { 192 | gtk_widget_init_template (GTK_WIDGET (self)); 193 | } 194 | 195 | AdwDialog * 196 | bz_share_dialog_new (BzEntry *entry) 197 | { 198 | BzShareDialog *share_dialog = NULL; 199 | 200 | share_dialog = g_object_new ( 201 | BZ_TYPE_SHARE_DIALOG, 202 | "entry", entry, 203 | NULL); 204 | 205 | return ADW_DIALOG (share_dialog); 206 | } 207 | -------------------------------------------------------------------------------- /src/bz-share-dialog.h: -------------------------------------------------------------------------------- 1 | /* bz-share-dialog.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | #include "bz-entry.h" 26 | 27 | G_BEGIN_DECLS 28 | 29 | #define BZ_TYPE_SHARE_DIALOG (bz_share_dialog_get_type ()) 30 | G_DECLARE_FINAL_TYPE (BzShareDialog, bz_share_dialog, BZ, SHARE_DIALOG, AdwDialog) 31 | 32 | AdwDialog * 33 | bz_share_dialog_new (BzEntry *entry); 34 | 35 | G_END_DECLS 36 | -------------------------------------------------------------------------------- /src/bz-share-dialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 115 | 116 | -------------------------------------------------------------------------------- /src/bz-transaction-manager.h: -------------------------------------------------------------------------------- 1 | /* bz-transaction-manager.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include "bz-backend.h" 24 | #include "bz-transaction.h" 25 | 26 | G_BEGIN_DECLS 27 | 28 | #define BZ_TYPE_TRANSACTION_MANAGER (bz_transaction_manager_get_type ()) 29 | G_DECLARE_FINAL_TYPE (BzTransactionManager, bz_transaction_manager, BZ, TRANSACTION_MANAGER, GObject) 30 | 31 | BzTransactionManager * 32 | bz_transaction_manager_new (void); 33 | 34 | void 35 | bz_transaction_manager_set_backend (BzTransactionManager *self, 36 | BzBackend *backend); 37 | 38 | BzBackend * 39 | bz_transaction_manager_get_backend (BzTransactionManager *self); 40 | 41 | BzTransaction * 42 | bz_transaction_manager_get_last_success (BzTransactionManager *self); 43 | 44 | void 45 | bz_transaction_manager_add (BzTransactionManager *self, 46 | BzTransaction *transaction); 47 | 48 | G_END_DECLS 49 | -------------------------------------------------------------------------------- /src/bz-transaction-view.c: -------------------------------------------------------------------------------- 1 | /* bz-transaction-view.c 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #include "config.h" 22 | 23 | #include "bz-progress-bar.h" 24 | #include "bz-transaction-view.h" 25 | 26 | struct _BzTransactionView 27 | { 28 | AdwBin parent_instance; 29 | 30 | BzTransaction *transaction; 31 | 32 | /* Template widgets */ 33 | GtkWidget *installs; 34 | GtkSeparator *separator_1; 35 | GtkWidget *updates; 36 | GtkSeparator *separator_2; 37 | GtkWidget *removals; 38 | }; 39 | 40 | G_DEFINE_FINAL_TYPE (BzTransactionView, bz_transaction_view, ADW_TYPE_BIN) 41 | 42 | enum 43 | { 44 | PROP_0, 45 | 46 | PROP_TRANSACTION, 47 | 48 | LAST_PROP 49 | }; 50 | static GParamSpec *props[LAST_PROP] = { 0 }; 51 | 52 | static void 53 | bz_transaction_view_dispose (GObject *object) 54 | { 55 | BzTransactionView *self = BZ_TRANSACTION_VIEW (object); 56 | 57 | g_clear_object (&self->transaction); 58 | 59 | G_OBJECT_CLASS (bz_transaction_view_parent_class)->dispose (object); 60 | } 61 | 62 | static void 63 | bz_transaction_view_get_property (GObject *object, 64 | guint prop_id, 65 | GValue *value, 66 | GParamSpec *pspec) 67 | { 68 | BzTransactionView *self = BZ_TRANSACTION_VIEW (object); 69 | 70 | switch (prop_id) 71 | { 72 | case PROP_TRANSACTION: 73 | g_value_set_object (value, bz_transaction_view_get_transaction (self)); 74 | break; 75 | default: 76 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 77 | } 78 | } 79 | 80 | static void 81 | bz_transaction_view_set_property (GObject *object, 82 | guint prop_id, 83 | const GValue *value, 84 | GParamSpec *pspec) 85 | { 86 | BzTransactionView *self = BZ_TRANSACTION_VIEW (object); 87 | 88 | switch (prop_id) 89 | { 90 | case PROP_TRANSACTION: 91 | bz_transaction_view_set_transaction (self, g_value_get_object (value)); 92 | break; 93 | default: 94 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 95 | } 96 | } 97 | 98 | static gboolean 99 | invert_boolean (gpointer object, 100 | gboolean value) 101 | { 102 | return !value; 103 | } 104 | 105 | static void 106 | bz_transaction_view_class_init (BzTransactionViewClass *klass) 107 | { 108 | GObjectClass *object_class = G_OBJECT_CLASS (klass); 109 | GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); 110 | 111 | object_class->dispose = bz_transaction_view_dispose; 112 | object_class->get_property = bz_transaction_view_get_property; 113 | object_class->set_property = bz_transaction_view_set_property; 114 | 115 | props[PROP_TRANSACTION] = 116 | g_param_spec_object ( 117 | "transaction", 118 | NULL, NULL, 119 | BZ_TYPE_TRANSACTION, 120 | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); 121 | 122 | g_object_class_install_properties (object_class, LAST_PROP, props); 123 | 124 | g_type_ensure (BZ_TYPE_PROGRESS_BAR); 125 | 126 | gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/bazaar/bz-transaction-view.ui"); 127 | gtk_widget_class_bind_template_child (widget_class, BzTransactionView, installs); 128 | gtk_widget_class_bind_template_child (widget_class, BzTransactionView, separator_1); 129 | gtk_widget_class_bind_template_child (widget_class, BzTransactionView, updates); 130 | gtk_widget_class_bind_template_child (widget_class, BzTransactionView, separator_2); 131 | gtk_widget_class_bind_template_child (widget_class, BzTransactionView, removals); 132 | gtk_widget_class_bind_template_callback (widget_class, invert_boolean); 133 | } 134 | 135 | static void 136 | bz_transaction_view_init (BzTransactionView *self) 137 | { 138 | gtk_widget_init_template (GTK_WIDGET (self)); 139 | } 140 | 141 | GtkWidget * 142 | bz_transaction_view_new (BzTransaction *transaction) 143 | { 144 | return g_object_new ( 145 | BZ_TYPE_TRANSACTION_VIEW, 146 | "transaction", transaction, 147 | NULL); 148 | } 149 | 150 | void 151 | bz_transaction_view_set_transaction (BzTransactionView *self, 152 | BzTransaction *transaction) 153 | { 154 | g_return_if_fail (BZ_IS_TRANSACTION_VIEW (self)); 155 | g_return_if_fail (transaction == NULL || BZ_IS_TRANSACTION (transaction)); 156 | 157 | g_clear_object (&self->transaction); 158 | if (transaction != NULL) 159 | { 160 | GListModel *installs = NULL; 161 | GListModel *updates = NULL; 162 | GListModel *removals = NULL; 163 | gboolean installs_valid = FALSE; 164 | gboolean updates_valid = FALSE; 165 | gboolean removals_valid = FALSE; 166 | 167 | self->transaction = g_object_ref (transaction); 168 | 169 | installs = bz_transaction_get_installs (transaction); 170 | updates = bz_transaction_get_updates (transaction); 171 | removals = bz_transaction_get_removals (transaction); 172 | 173 | installs_valid = installs != NULL && g_list_model_get_n_items (installs) > 0; 174 | updates_valid = updates != NULL && g_list_model_get_n_items (updates) > 0; 175 | removals_valid = removals != NULL && g_list_model_get_n_items (removals) > 0; 176 | 177 | gtk_widget_set_visible (self->installs, installs_valid); 178 | gtk_widget_set_visible (GTK_WIDGET (self->separator_1), installs_valid && (updates_valid || removals_valid)); 179 | gtk_widget_set_visible (self->updates, updates_valid); 180 | gtk_widget_set_visible (GTK_WIDGET (self->separator_2), updates_valid && removals_valid); 181 | gtk_widget_set_visible (self->removals, removals_valid); 182 | } 183 | else 184 | { 185 | gtk_widget_set_visible (self->installs, FALSE); 186 | gtk_widget_set_visible (GTK_WIDGET (self->separator_1), FALSE); 187 | gtk_widget_set_visible (self->updates, FALSE); 188 | gtk_widget_set_visible (GTK_WIDGET (self->separator_2), FALSE); 189 | gtk_widget_set_visible (self->removals, FALSE); 190 | } 191 | 192 | g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TRANSACTION]); 193 | } 194 | 195 | BzTransaction * 196 | bz_transaction_view_get_transaction (BzTransactionView *self) 197 | { 198 | g_return_val_if_fail (BZ_IS_TRANSACTION_VIEW (self), NULL); 199 | return self->transaction; 200 | } 201 | -------------------------------------------------------------------------------- /src/bz-transaction-view.h: -------------------------------------------------------------------------------- 1 | /* bz-transaction-view.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | #include "bz-transaction.h" 26 | 27 | G_BEGIN_DECLS 28 | 29 | #define BZ_TYPE_TRANSACTION_VIEW (bz_transaction_view_get_type ()) 30 | G_DECLARE_FINAL_TYPE (BzTransactionView, bz_transaction_view, BZ, TRANSACTION_VIEW, AdwBin) 31 | 32 | GtkWidget * 33 | bz_transaction_view_new (BzTransaction *transaction); 34 | 35 | void 36 | bz_transaction_view_set_transaction (BzTransactionView *self, 37 | BzTransaction *transaction); 38 | 39 | BzTransaction * 40 | bz_transaction_view_get_transaction (BzTransactionView *self); 41 | 42 | G_END_DECLS 43 | -------------------------------------------------------------------------------- /src/bz-transaction.h: -------------------------------------------------------------------------------- 1 | /* bz-transaction.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include "bz-entry.h" 24 | 25 | G_BEGIN_DECLS 26 | 27 | #define BZ_TYPE_TRANSACTION (bz_transaction_get_type ()) 28 | G_DECLARE_DERIVABLE_TYPE (BzTransaction, bz_transaction, BZ, TRANSACTION, GObject) 29 | 30 | struct _BzTransactionClass 31 | { 32 | GObjectClass parent_class; 33 | }; 34 | 35 | BzTransaction * 36 | bz_transaction_new_full (BzEntry **installs, 37 | guint n_installs, 38 | BzEntry **updates, 39 | guint n_updates, 40 | BzEntry **removals, 41 | guint n_removals); 42 | 43 | GListModel * 44 | bz_transaction_get_installs (BzTransaction *self); 45 | 46 | GListModel * 47 | bz_transaction_get_updates (BzTransaction *self); 48 | 49 | GListModel * 50 | bz_transaction_get_removals (BzTransaction *self); 51 | 52 | G_END_DECLS 53 | -------------------------------------------------------------------------------- /src/bz-update-dialog.c: -------------------------------------------------------------------------------- 1 | /* bz-update-dialog.c 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #include "config.h" 22 | 23 | #include "bz-entry.h" 24 | #include "bz-update-dialog.h" 25 | 26 | struct _BzUpdateDialog 27 | { 28 | AdwAlertDialog parent_instance; 29 | 30 | GListModel *updates; 31 | gboolean install_accepted; 32 | 33 | /* Template widgets */ 34 | GtkListView *list_view; 35 | GtkNoSelection *selection_model; 36 | }; 37 | 38 | G_DEFINE_FINAL_TYPE (BzUpdateDialog, bz_update_dialog, ADW_TYPE_ALERT_DIALOG) 39 | 40 | static void 41 | on_response (AdwAlertDialog *alert, 42 | gchar *response, 43 | BzUpdateDialog *self); 44 | 45 | static void 46 | bz_update_dialog_dispose (GObject *object) 47 | { 48 | BzUpdateDialog *self = BZ_UPDATE_DIALOG (object); 49 | 50 | g_clear_object (&self->updates); 51 | 52 | G_OBJECT_CLASS (bz_update_dialog_parent_class)->dispose (object); 53 | } 54 | 55 | static void 56 | bz_update_dialog_class_init (BzUpdateDialogClass *klass) 57 | { 58 | GObjectClass *object_class = G_OBJECT_CLASS (klass); 59 | GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); 60 | 61 | object_class->dispose = bz_update_dialog_dispose; 62 | 63 | gtk_widget_class_set_template_from_resource (widget_class, "/io/github/kolunmi/bazaar/bz-update-dialog.ui"); 64 | gtk_widget_class_bind_template_child (widget_class, BzUpdateDialog, list_view); 65 | gtk_widget_class_bind_template_child (widget_class, BzUpdateDialog, selection_model); 66 | } 67 | 68 | static void 69 | bz_update_dialog_init (BzUpdateDialog *self) 70 | { 71 | gtk_widget_init_template (GTK_WIDGET (self)); 72 | g_signal_connect (self, "response", G_CALLBACK (on_response), self); 73 | } 74 | 75 | static void 76 | on_response (AdwAlertDialog *alert, 77 | gchar *response, 78 | BzUpdateDialog *self) 79 | { 80 | self->install_accepted = g_strcmp0 (response, "install") == 0; 81 | } 82 | 83 | AdwDialog * 84 | bz_update_dialog_new (GListModel *updates) 85 | { 86 | BzUpdateDialog *update_dialog = NULL; 87 | 88 | g_return_val_if_fail (G_IS_LIST_MODEL (updates), NULL); 89 | g_return_val_if_fail (g_list_model_get_item_type (updates) == BZ_TYPE_ENTRY, NULL); 90 | 91 | update_dialog = g_object_new (BZ_TYPE_UPDATE_DIALOG, NULL); 92 | update_dialog->updates = g_object_ref (updates); 93 | 94 | gtk_no_selection_set_model (update_dialog->selection_model, updates); 95 | 96 | return ADW_DIALOG (update_dialog); 97 | } 98 | 99 | GListModel * 100 | bz_update_dialog_was_accepted (BzUpdateDialog *self) 101 | { 102 | g_return_val_if_fail (BZ_IS_UPDATE_DIALOG (self), FALSE); 103 | 104 | return self->install_accepted ? g_object_ref (self->updates) : NULL; 105 | } 106 | -------------------------------------------------------------------------------- /src/bz-update-dialog.h: -------------------------------------------------------------------------------- 1 | /* bz-update-dialog.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | G_BEGIN_DECLS 26 | 27 | #define BZ_TYPE_UPDATE_DIALOG (bz_update_dialog_get_type ()) 28 | G_DECLARE_FINAL_TYPE (BzUpdateDialog, bz_update_dialog, BZ, UPDATE_DIALOG, AdwAlertDialog) 29 | 30 | AdwDialog * 31 | bz_update_dialog_new (GListModel *updates); 32 | 33 | GListModel * 34 | bz_update_dialog_was_accepted (BzUpdateDialog *self); 35 | 36 | G_END_DECLS 37 | -------------------------------------------------------------------------------- /src/bz-update-dialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 78 | 79 | -------------------------------------------------------------------------------- /src/bz-util.h: -------------------------------------------------------------------------------- 1 | /* bz-util.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #define BZ_RELEASE_DATA(name, unref) \ 24 | if ((unref) != NULL) \ 25 | g_clear_pointer (&self->name, (unref)); 26 | 27 | #define BZ_RELEASE_UTAG(name, remove) \ 28 | if ((remove) != NULL) \ 29 | g_clear_handle_id (&self->name, (remove)); 30 | 31 | /* va args = releases */ 32 | #define BZ_DEFINE_DATA(name, Name, layout, ...) \ 33 | typedef struct _##Name##Data Name##Data; \ 34 | struct _##Name##Data \ 35 | { \ 36 | gatomicrefcount rc; \ 37 | struct layout; \ 38 | }; \ 39 | G_GNUC_UNUSED \ 40 | static inline Name##Data * \ 41 | name##_data_new (void) \ 42 | { \ 43 | Name##Data *data = NULL; \ 44 | data = g_new0 (typeof (*data), 1); \ 45 | g_atomic_ref_count_init (&data->rc); \ 46 | return data; \ 47 | } \ 48 | G_GNUC_UNUSED \ 49 | static inline Name##Data * \ 50 | name##_data_ref (gpointer ptr) \ 51 | { \ 52 | Name##Data *self = ptr; \ 53 | g_atomic_ref_count_inc (&self->rc); \ 54 | return self; \ 55 | } \ 56 | G_GNUC_UNUSED \ 57 | static void \ 58 | name##_data_deinit (gpointer ptr) \ 59 | { \ 60 | Name##Data *self = ptr; \ 61 | __VA_ARGS__ \ 62 | } \ 63 | G_GNUC_UNUSED \ 64 | static void \ 65 | name##_data_unref (gpointer ptr) \ 66 | { \ 67 | Name##Data *self = ptr; \ 68 | if (g_atomic_ref_count_dec (&self->rc)) \ 69 | { \ 70 | name##_data_deinit (self); \ 71 | g_free (self); \ 72 | } \ 73 | } \ 74 | G_GNUC_UNUSED \ 75 | static void \ 76 | name##_data_unref_closure (gpointer data, \ 77 | GClosure *closure) \ 78 | { \ 79 | name##_data_unref (data); \ 80 | } \ 81 | G_DEFINE_AUTOPTR_CLEANUP_FUNC (Name##Data, name##_data_unref); 82 | -------------------------------------------------------------------------------- /src/bz-window.h: -------------------------------------------------------------------------------- 1 | /* bz-window.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | G_BEGIN_DECLS 26 | 27 | #define BZ_TYPE_WINDOW (bz_window_get_type ()) 28 | G_DECLARE_FINAL_TYPE (BzWindow, bz_window, BZ, WINDOW, AdwApplicationWindow) 29 | 30 | void 31 | bz_window_search (BzWindow *self, 32 | const char *text); 33 | 34 | void 35 | bz_window_toggle_transactions (BzWindow *self); 36 | 37 | void 38 | bz_window_push_update_dialog (BzWindow *self, 39 | GListModel *updates); 40 | 41 | G_END_DECLS 42 | -------------------------------------------------------------------------------- /src/bz-window.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 172 | 173 |
174 | 175 | _Preferences 176 | app.preferences 177 | 178 | 179 | _Keyboard Shortcuts 180 | win.show-help-overlay 181 | 182 | 183 | _About Bazaar 184 | app.about 185 | 186 | 187 | _Donate ❤️ 188 | app.donate 189 | 190 |
191 |
192 |
193 | -------------------------------------------------------------------------------- /src/bz-yaml-parser.h: -------------------------------------------------------------------------------- 1 | /* bz-yaml-parser.h 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #pragma once 22 | 23 | #include 24 | 25 | G_BEGIN_DECLS 26 | 27 | #define BZ_YAML_ERROR (bz_yaml_error_quark ()) 28 | GQuark bz_yaml_error_quark (void); 29 | 30 | typedef enum 31 | { 32 | BZ_YAML_ERROR_INVALID_YAML = 0, 33 | BZ_YAML_ERROR_DOES_NOT_CONFORM, 34 | BZ_YAML_ERROR_BAD_SCALAR, 35 | } BzYamlError; 36 | 37 | #define BZ_TYPE_YAML_PARSER (bz_yaml_parser_get_type ()) 38 | G_DECLARE_FINAL_TYPE (BzYamlParser, bz_yaml_parser, BZ, YAML_PARSER, GObject) 39 | 40 | BzYamlParser * 41 | bz_yaml_parser_new_for_resource_schema (const char *path); 42 | 43 | GHashTable * 44 | bz_yaml_parser_process_bytes (BzYamlParser *self, 45 | GBytes *bytes, 46 | GError **error); 47 | 48 | G_END_DECLS 49 | -------------------------------------------------------------------------------- /src/gtk/help-overlay.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | True 5 | 6 | 7 | shortcuts 8 | 10 9 | 10 | 11 | General 12 | 13 | 14 | Open Search Dialog 15 | app.search('') 16 | 17 | 18 | 19 | 20 | Refresh 21 | app.refresh 22 | 23 | 24 | 25 | 26 | Toggle Transaction Manager 27 | app.toggle-transactions 28 | 29 | 30 | 31 | 32 | Show Shortcuts 33 | win.show-help-overlay 34 | 35 | 36 | 37 | 38 | Quit 39 | app.quit 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/gtk/styles.css: -------------------------------------------------------------------------------- 1 | .global-search search { 2 | padding: 12px; 3 | border-bottom: 1px solid var(--border-color); 4 | } 5 | .global-search search > image { 6 | padding: 2px; 7 | min-width: 24px; 8 | min-height: 24px; 9 | margin-right: 6px; 10 | } 11 | .global-search search > label { 12 | font-size: 1.33333em; 13 | margin-left: 6px; 14 | margin-right: 6px; 15 | } 16 | .global-search search > text { 17 | font-size: 1.33333em; 18 | margin-left: 6px; 19 | margin-right: 6px; 20 | } 21 | .global-search search > text placeholder { 22 | opacity: 0.55; 23 | } 24 | .global-search search > button.close { 25 | padding: 2px; 26 | min-width: 24px; 27 | min-height: 24px; 28 | margin-left: 6px; 29 | margin-right: 6px; 30 | } 31 | .global-search .preview-bin { 32 | border-left: 1px solid color-mix(in srgb, var(--border-color) 25%, transparent); 33 | } 34 | 35 | .neutral-icon { 36 | padding: 4px; 37 | color: var(--accent-fg-color); 38 | background-color: var(--accent-bg-color); 39 | border-radius: 5px; 40 | } 41 | 42 | .good-icon { 43 | padding: 4px; 44 | color: var(--success-fg-color); 45 | background-color: var(--success-bg-color); 46 | border-radius: 5px; 47 | } 48 | 49 | .bad-icon { 50 | padding: 4px; 51 | color: var(--warning-fg-color); 52 | background-color: var(--warning-bg-color); 53 | border-radius: 5px; 54 | } 55 | 56 | .screenshot { 57 | border-radius: 20px; 58 | } 59 | 60 | .long-description { 61 | border-top: 2px solid var(--border-color); 62 | border-bottom: 2px solid var(--border-color); 63 | } 64 | 65 | .screenshot-scroll { 66 | border-top: 2px solid var(--border-color); 67 | border-bottom: 2px solid var(--border-color); 68 | } 69 | 70 | .browser-banner { 71 | border-radius: 25px; 72 | background-color: transparent; 73 | } 74 | .browser-banner-title { 75 | font-size: 3.2em; 76 | font-weight: bolder; 77 | } 78 | .browser-banner-subtitle { 79 | font-size: 2.0em; 80 | font-weight: bold; 81 | } 82 | .browser-banner-description { 83 | font-size: 1.33em; 84 | font-weight: normal; 85 | } 86 | -------------------------------------------------------------------------------- /src/icons/scalable/actions/copy-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/icons/scalable/actions/drive-harddisk-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/icons/scalable/actions/external-link-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/icons/scalable/actions/folder-download-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/icons/scalable/actions/globe-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/icons/scalable/actions/left-large-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/icons/scalable/actions/license-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/icons/scalable/actions/people-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/icons/scalable/actions/regex-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/icons/scalable/actions/right-large-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/icons/scalable/actions/share-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/icons/scalable/actions/sidebar-show-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/icons/scalable/actions/starred-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/icons/scalable/actions/user-trash-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | /* main.c 2 | * 3 | * Copyright 2025 Adam Masciola 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | * 18 | * SPDX-License-Identifier: GPL-3.0-or-later 19 | */ 20 | 21 | #include "config.h" 22 | 23 | #include 24 | 25 | #include "bz-application.h" 26 | 27 | int 28 | main (int argc, 29 | char *argv[]) 30 | { 31 | g_autoptr (BzApplication) app = NULL; 32 | int ret; 33 | 34 | if (argc > 1 && g_strcmp0 (argv[1], "--version") == 0) 35 | { 36 | g_print ("%s\n", PACKAGE_VERSION); 37 | return 0; 38 | } 39 | 40 | bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); 41 | bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); 42 | textdomain (GETTEXT_PACKAGE); 43 | 44 | app = g_object_new ( 45 | BZ_TYPE_APPLICATION, 46 | "application-id", "io.github.kolunmi.bazaar", 47 | "flags", G_APPLICATION_HANDLES_COMMAND_LINE, 48 | "resource-base-path", "/io/github/kolunmi/bazaar", 49 | NULL); 50 | ret = g_application_run (G_APPLICATION (app), argc, argv); 51 | 52 | return ret; 53 | } 54 | -------------------------------------------------------------------------------- /src/meson.build: -------------------------------------------------------------------------------- 1 | bz_sources = [ 2 | 'bz-application.c', 3 | 'bz-async-texture.c', 4 | 'bz-backend.c', 5 | 'bz-background.c', 6 | 'bz-browse-widget.c', 7 | 'bz-content-provider.c', 8 | 'bz-content-section.c', 9 | 'bz-entry-group.c', 10 | 'bz-entry.c', 11 | 'bz-error.c', 12 | 'bz-flatpak-entry.c', 13 | 'bz-flatpak-instance.c', 14 | 'bz-paintable-model.c', 15 | 'bz-preferences-dialog.c', 16 | 'bz-progress-bar.c', 17 | 'bz-review.c', 18 | 'bz-search-widget.c', 19 | 'bz-section-view.c', 20 | 'bz-share-dialog.c', 21 | 'bz-transaction-manager.c', 22 | 'bz-transaction-view.c', 23 | 'bz-transaction.c', 24 | 'bz-update-dialog.c', 25 | 'bz-window.c', 26 | 'bz-yaml-parser.c', 27 | 'main.c', 28 | ] 29 | 30 | bz_deps = [ 31 | cc.find_library('m', required: false), 32 | dependency('gtk4'), 33 | dependency('libadwaita-1', version: '>= 1.7'), 34 | dependency('libdex-1', version: '>= 0.9'), 35 | dependency('flatpak', version: '>= 1.9'), 36 | dependency('appstream', version : '>= 1.0'), 37 | dependency('xmlb', version : '>= 0.3.4'), 38 | dependency('glycin-1', version : '>= 1.0'), 39 | dependency('glycin-gtk4-1', version : '>= 1.0'), 40 | dependency('yaml-0.1', version : '>= 0.2.5'), 41 | ] 42 | 43 | bz_sources += gnome.compile_resources('bz-resources', 44 | 'bazaar.gresource.xml', 45 | c_name: 'bz' 46 | ) 47 | 48 | executable('bazaar', bz_sources, 49 | dependencies: bz_deps, 50 | install: true, 51 | ) 52 | -------------------------------------------------------------------------------- /version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | INSTR="$1" 4 | 5 | case "$INSTR" in 6 | get-vcs) 7 | git -C "$MESON_SOURCE_ROOT" describe --always --dirty 8 | ;; 9 | *) 10 | echo invalid arguments 1>&2 11 | exit 1 12 | ;; 13 | esac 14 | --------------------------------------------------------------------------------