Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a verified badge for flatpaks. #409

Merged
merged 2 commits into from
Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 59 additions & 87 deletions usr/lib/linuxmint/mintinstall/mintinstall.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
DEGREES = pi / 180

FALLBACK_PACKAGE_ICON_PATH = "/usr/share/linuxmint/mintinstall/data/available.png"
VERIFIED_IMAGE_PATH = "/usr/share/linuxmint/mintinstall/data/verified.svg"
FLATHUB_MEDIA_BASE_URL = "https://dl.flathub.org/media/"

#Hardcoded mouse back button key for button-press-event
Expand All @@ -60,6 +61,7 @@
SEARCH_IN_CATEGORY = "search-in-category"
HAMONIKR_SCREENSHOTS = "hamonikr-screenshots"
PACKAGE_TYPE_PREFERENCE = "search-package-type-preference"
SEARCH_VERIFIED_ONLY = "search-verified-only"
# Allowed values
PACKAGE_TYPE_PREFERENCE_ALL = "all"
PACKAGE_TYPE_PREFERENCE_APT = "apt"
Expand Down Expand Up @@ -597,7 +599,7 @@ def set_fraction(self, fraction):


class BannerTile(Gtk.FlowBoxChild):
def __init__(self, pkginfo, installer, name, is_flatpak, app_json, on_clicked_action):
def __init__(self, pkginfo, installer, name, is_flatpak, show_verified, app_json, on_clicked_action):
super(Gtk.FlowBoxChild, self).__init__()

self.pkginfo = pkginfo
Expand Down Expand Up @@ -661,6 +663,8 @@ def __init__(self, pkginfo, installer, name, is_flatpak, app_json, on_clicked_ac
label_flatpak = Gtk.Label(label="Flathub")
label_flatpak.set_name("BannerFlatpakLabel")
box_flatpak.pack_start(label_flatpak, False, False, 0)
if show_verified:
box_flatpak.pack_start(Gtk.Image.new_from_icon_name("mintinstall-verified-symbolic", Gtk.IconSize.MENU), False, False, 0)
vbox.pack_start(box_flatpak, False, False, 0)

hbox = Gtk.Box(spacing=24)
Expand All @@ -669,84 +673,9 @@ def __init__(self, pkginfo, installer, name, is_flatpak, app_json, on_clicked_ac

self.add(hbox)

class PackageRow(Gtk.ListBoxRow):
def __init__(self, pkginfo, icon, summary, installer, from_search=False, review_info=None):
super(Gtk.ListBoxRow, self).__init__()
self.pkginfo = pkginfo
self.installed_mark = Gtk.Image()
self.installer = installer
self.asapp = self.installer.get_appstream_app_for_pkginfo(pkginfo)

glade_file = "/usr/share/linuxmint/mintinstall/package-row.glade"
self.builder = Gtk.Builder()
self.builder.add_from_file(glade_file)

self.main_box = self.builder.get_object("package_row")
self.add(self.main_box)
self.main_box.connect("button-press-event", lambda w, e: Gdk.EVENT_PROPAGATE)
self.main_box.connect("button-release-event", lambda w, e: Gdk.EVENT_PROPAGATE)

self.app_icon_holder = self.builder.get_object("app_icon_holder")
self.app_display_name = self.builder.get_object("app_display_name")
self.app_summary = self.builder.get_object("app_summary")
self.flatpak_badge = self.builder.get_object("flatpak_badge")
self.category_label = self.builder.get_object("category_label")
self.installed_mark = self.builder.get_object("installed_mark")

self.app_icon_holder.add(icon)

display_name = self.installer.get_display_name(pkginfo)
display_name = GLib.markup_escape_text(display_name)

if pkginfo.pkg_hash.startswith("f"):
self.flatpak_badge.show()
else:
self.flatpak_badge.hide()

self.app_display_name.set_label(display_name)
self.app_summary.set_label(summary)
self.show_all()

if review_info:
self.fill_rating_widget(review_info)

self.refresh_state()

def refresh_state(self):
self.installed = self.installer.pkginfo_is_installed(self.pkginfo)

if self.installed:
self.installed_mark.set_from_icon_name("mintinstall-installed", Gtk.IconSize.LARGE_TOOLBAR)
else:
self.installed_mark.clear()

def fill_rating_widget(self, review_info):
review_info_box = self.builder.get_object("review_info_box")

stars_box = self.builder.get_object("stars_box")

rating = review_info.avg_rating
remaining_stars = 5
while rating >= 1.0:
stars_box.pack_start(Gtk.Image.new_from_icon_name("starred-symbolic", Gtk.IconSize.MENU), False, False, 0)
rating -= 1
remaining_stars -= 1
if rating > 0.0:
stars_box.pack_start(Gtk.Image.new_from_icon_name("semi-starred-symbolic", Gtk.IconSize.MENU), False, False, 0)
remaining_stars -= 1
for i in range (remaining_stars):
stars_box.pack_start(Gtk.Image.new_from_icon_name("non-starred-symbolic", Gtk.IconSize.MENU), False, False, 0)
stars_box.show_all()

num_reviews_label = self.builder.get_object("num_reviews_label")

# TRANSLATORS: showing specific number of reviews in the list view and the header of the package details.
review_text = gettext.ngettext("%d Review", "%d Reviews", review_info.num_reviews) % review_info.num_reviews
num_reviews_label.set_label(review_text)

class VerticalPackageTile(Gtk.FlowBoxChild):
class PackageTile(Gtk.FlowBoxChild):
def __init__(self, pkginfo, icon, installer, show_package_type=False, review_info=None):
super(VerticalPackageTile, self).__init__()
super(PackageTile, self).__init__()

self.button = Gtk.Button();
self.button.connect("clicked", self._activate_fb_child)
Expand All @@ -764,7 +693,7 @@ def __init__(self, pkginfo, icon, installer, show_package_type=False, review_inf
self.pkg_category = pkginfo.categories[1]


glade_file = "/usr/share/linuxmint/mintinstall/vertical-tile.glade"
glade_file = "/usr/share/linuxmint/mintinstall/package-tile.glade"
self.builder = Gtk.Builder()
self.builder.add_from_file(glade_file)

Expand All @@ -778,6 +707,7 @@ def __init__(self, pkginfo, icon, installer, show_package_type=False, review_inf
self.package_type_emblem = self.builder.get_object("package_type_emblem")
self.package_type_name = self.builder.get_object("package_type_name")
self.installed_mark = self.builder.get_object("installed_mark")
self.verified_mark = self.builder.get_object("verified_mark")

self.icon_holder.add(icon)

Expand All @@ -802,9 +732,21 @@ def __init__(self, pkginfo, icon, installer, show_package_type=False, review_inf
if remote_info is None:
self.package_type_name.set_label(pkginfo.remote.capitalize())

self.package_type_box.set_tooltip_text(_("This package is a Flatpak"))
verified = False
try:
asapp = self.installer.get_appstream_app_for_pkginfo(pkginfo)
verified = asapp.get_metadata()["flathub::verification::verified"]
except (AttributeError, KeyError):
pass

self.package_type_emblem.set_from_icon_name("mintinstall-package-flatpak-symbolic", Gtk.IconSize.MENU)
self.package_type_box.show()

if verified:
self.package_type_box.set_tooltip_text(_("This package is a Flatpak from a verified source"))
self.verified_mark.set_visible(True)
else:
self.package_type_box.set_tooltip_text(_("This package is a Flatpak"))
else:
self.package_type_name.hide()
self.package_type_emblem.hide()
Expand Down Expand Up @@ -1172,6 +1114,7 @@ def create_window(self, starting_page):
self.progress_box = self.builder.get_object("progress_box")
self.action_button = self.builder.get_object("action_button")
self.launch_button = self.builder.get_object("launch_button")
self.verified_box = self.builder.get_object("verified_box")
self.active_tasks_button = self.builder.get_object("active_tasks_button")
self.active_tasks_spinner = self.builder.get_object("active_tasks_spinner")
self.no_packages_found_label = self.builder.get_object("no_packages_found_label")
Expand Down Expand Up @@ -1238,10 +1181,20 @@ def list_header_func(row, before, user_data=None):
package_type_menuitem.show()
search_submenu.append(package_type_menuitem)

separator = Gtk.SeparatorMenuItem()
separator.show()
search_submenu.append(separator)

separator = Gtk.SeparatorMenuItem()
separator.show()
submenu.append(separator)

search_summary_menuitem = Gtk.CheckMenuItem(label=_("Only include verified flatpaks in search results"))
search_summary_menuitem.set_active(self.settings.get_boolean(SEARCH_VERIFIED_ONLY))
self.settings.bind(SEARCH_VERIFIED_ONLY, search_summary_menuitem, "active", Gio.SettingsBindFlags.DEFAULT)
search_summary_menuitem.show()
search_submenu.append(search_summary_menuitem)

self.refresh_cache_menuitem = Gtk.MenuItem(label=_("Refresh the list of packages"))
self.refresh_cache_menuitem.connect("activate", self.on_refresh_cache_clicked)
self.refresh_cache_menuitem.show()
Expand Down Expand Up @@ -1464,7 +1417,9 @@ def load_banner(self):
box.hide()
return

tile = BannerTile(pkginfo, self.installer, name, is_flatpak, app_json, self.on_banner_clicked)
show_verified = is_flatpak and self.flatpak_is_verified(pkginfo)

tile = BannerTile(pkginfo, self.installer, name, is_flatpak, show_verified, app_json, self.on_banner_clicked)
self.banner_app_name = pkginfo.name
flowbox.insert(tile, -1)
box.pack_start(flowbox, True, True, 0)
Expand Down Expand Up @@ -1512,7 +1467,7 @@ def load_top_rated(self):
else:
review_info = None
icon = self.get_application_icon(pkginfo, FEATURED_ICON_SIZE)
tile = VerticalPackageTile(pkginfo, icon, self.installer, show_package_type=True, review_info=review_info)
tile = PackageTile(pkginfo, icon, self.installer, show_package_type=True, review_info=review_info)
size_group.add_widget(tile)
self.flowbox_top_rated.insert(tile, -1)
self.picks_tiles.append(tile)
Expand Down Expand Up @@ -1568,7 +1523,7 @@ def load_featured(self):
else:
review_info = None
icon = self.get_application_icon(pkginfo, FEATURED_ICON_SIZE)
tile = VerticalPackageTile(pkginfo, icon, self.installer, show_package_type=True, review_info=review_info)
tile = PackageTile(pkginfo, icon, self.installer, show_package_type=True, review_info=review_info)
size_group.add_widget(tile)
self.flowbox_featured.insert(tile, -1)
self.picks_tiles.append(tile)
Expand Down Expand Up @@ -2528,6 +2483,7 @@ def show_search_results(self, terms):

search_in_summary = self.settings.get_boolean(SEARCH_IN_SUMMARY)
search_in_description = self.settings.get_boolean(SEARCH_IN_DESCRIPTION)
verified_flatpaks_only = self.settings.get_boolean(SEARCH_VERIFIED_ONLY)

package_type_preference = self.settings.get_string(PACKAGE_TYPE_PREFERENCE)
hidden_packages = set()
Expand All @@ -2539,9 +2495,13 @@ def idle_search_one_package(pkginfos):
self.search_idle_timer = 0
return False

flatpak = pkginfo.pkg_hash.startswith("f")
is_match = False

while True:
if flatpak and verified_flatpaks_only and not self.flatpak_is_verified(pkginfo):
break

if all(piece in pkginfo.name.upper() for piece in termsSplit):
is_match = True
pkginfo.search_tier = 0
Expand All @@ -2550,7 +2510,7 @@ def idle_search_one_package(pkginfos):
# may not actually contain the app's name. In this case their display
# names are better. The 'name' is still checked first above, because
# it's static - get_display_name() may involve a lookup with appstream.
if pkginfo.pkg_hash.startswith("f") and all(piece in self.installer.get_display_name(pkginfo).upper() for piece in termsSplit):
if flatpak and all(piece in self.installer.get_display_name(pkginfo).upper() for piece in termsSplit):
is_match = True
pkginfo.search_tier = 0
break
Expand All @@ -2566,9 +2526,9 @@ def idle_search_one_package(pkginfos):

if is_match:
searched_packages.append(pkginfo)
if package_type_preference == PACKAGE_TYPE_PREFERENCE_APT and pkginfo.pkg_hash.startswith("a"):
if package_type_preference == PACKAGE_TYPE_PREFERENCE_APT and not flatpak:
hidden_packages.add(FLATPAK_EQUIVS.get(pkginfo.name))
elif package_type_preference == PACKAGE_TYPE_PREFERENCE_FLATPAK and pkginfo.pkg_hash.startswith("f"):
elif package_type_preference == PACKAGE_TYPE_PREFERENCE_FLATPAK and flatpak:
hidden_packages.add(DEB_EQUIVS.get(pkginfo.name))

# Repeat until empty
Expand Down Expand Up @@ -2767,7 +2727,7 @@ def idle_show_one_package(self, pkginfos, collisions):
else:
review_info = None

tile = VerticalPackageTile(pkginfo, icon, self.installer, show_package_type=True, review_info=review_info)
tile = PackageTile(pkginfo, icon, self.installer, show_package_type=True, review_info=review_info)
self.flowbox_applications.insert(tile, -1)
self.category_tiles.append(tile)

Expand All @@ -2786,6 +2746,15 @@ def on_tile_keypress(self, row, event, data=None):

return Gdk.EVENT_PROPAGATE

def flatpak_is_verified(self, pkginfo):
try:
asapp = self.installer.get_appstream_app_for_pkginfo(pkginfo)
return asapp.get_metadata()["flathub::verification::verified"]
except (AttributeError, KeyError):
pass

return False

def package_type_combo_changed(self, combo):
iter = combo.get_active_iter()
if iter:
Expand Down Expand Up @@ -2870,10 +2839,13 @@ def show_package(self, pkginfo, previous_page):
self.package_type_combo.set_active_iter(to_use_iter)
self.package_type_combo.set_tooltip_text(tooltip)

self.verified_box.hide()

if pkginfo.pkg_hash.startswith("f"):
self.flatpak_details_vgroup.show()
# We don't know flatpak versions until the task reports back, apt we know immediately.
self.builder.get_object("application_version").set_label("")
self.verified_box.set_visible(self.flatpak_is_verified(pkginfo))
else:
self.flatpak_details_vgroup.hide()
self.builder.get_object("application_version").set_label(self.installer.get_version(pkginfo))
Expand Down
5 changes: 5 additions & 0 deletions usr/share/glib-2.0/schemas/com.linuxmint.install.gschema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,10 @@
<summary></summary>
<description></description>
</key>
<key type="b" name="search-verified-only">
<default>false</default>
<summary>Only include verified flatpaks in search results.</summary>
<description></description>
</key>
</schema>
</schemalist>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading