Skip to content

Commit

Permalink
Add Banner Slideshow using Gtk.Stack with nice animations (#417)
Browse files Browse the repository at this point in the history
  • Loading branch information
corbin-auriti authored Jun 11, 2024
1 parent 984706d commit 68bde43
Showing 1 changed file with 93 additions and 41 deletions.
134 changes: 93 additions & 41 deletions usr/lib/linuxmint/mintinstall/mintinstall.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@
#May not work on all mice
MOUSE_BACK_BUTTON = 8

#How many miliseconds between banner slides

Check failure on line 61 in usr/lib/linuxmint/mintinstall/mintinstall.py

View workflow job for this annotation

GitHub Actions / build / build (mint22, linuxmintd/mint22-amd64, Mint 22, true) / Mint 22

miliseconds ==> milliseconds
BANNER_TIMER = 500

# package type combobox columns
# index, label, icon-name, tooltip, pkginfo
PACKAGE_TYPE_COMBO_INDEX = 0
Expand Down Expand Up @@ -620,17 +623,17 @@ 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, background, color, is_flatpak, app_json, on_clicked_action):
super(Gtk.FlowBoxChild, self).__init__()

self.pkginfo = pkginfo
self.installer = installer
self.is_flatpak = is_flatpak
self.init_name = name
self.background = background
self.color = color

self.image_uri = (f"/usr/share/linuxmint/mintinstall/featured/{name}.svg")
background = app_json["background"]
color = app_json["text_color"]

css = """
#BannerTile {
Expand Down Expand Up @@ -660,37 +663,38 @@ def __init__(self, pkginfo, installer, name, is_flatpak, app_json, on_clicked_ac
self.set_name("BannerTile")
style_provider = Gtk.CssProvider()
style_provider.load_from_data(str.encode(css))
Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),
style_provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
self.box = None
self.repopulate_tile()

def repopulate_tile(self):
if self.box is not None:
self.box.destroy()

""" Have to re-use .add_provider(style_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) for every widget because

Check failure on line 667 in usr/lib/linuxmint/mintinstall/mintinstall.py

View workflow job for this annotation

GitHub Actions / build / build (mint22, linuxmintd/mint22-amd64, Mint 22, true) / Mint 22

re-use ==> reuse
add_provider doesn't cascade to children, and cant set the whole screen context for multiple tiles

Check failure on line 668 in usr/lib/linuxmint/mintinstall/mintinstall.py

View workflow job for this annotation

GitHub Actions / build / build (mint22, linuxmintd/mint22-amd64, Mint 22, true) / Mint 22

cant ==> can't
without making them uniform """
self.get_style_context().add_provider(style_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)

label_name = Gtk.Label(xalign=0)
label_name.set_label(self.installer.get_display_name(self.pkginfo))
label_name.set_name("BannerTitle")
label_name.get_style_context().add_provider(style_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)

label_summary = Gtk.Label(xalign=0)
label_summary.set_label(self.installer.get_summary(self.pkginfo))
label_summary.set_name("BannerSummary")
label_summary.get_style_context().add_provider(style_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)

image = Gtk.Image.new_from_file(self.image_uri)

vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12, halign=Gtk.Align.START)
vbox.get_style_context().add_provider(style_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
vbox.set_border_width(6)

vbox.pack_start(label_name, False, False, 0)
vbox.pack_start(label_summary, False, False, 0)

if self.is_flatpak:
box_flatpak = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
box_flatpak.get_style_context().add_provider(style_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
box_flatpak.pack_start(Gtk.Image.new_from_icon_name("mintinstall-package-flatpak-symbolic", Gtk.IconSize.MENU), False, False, 0)
label_flatpak = Gtk.Label(label="Flathub")
label_flatpak.set_name("BannerFlatpakLabel")
label_flatpak.get_style_context().add_provider(style_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
box_flatpak.pack_start(label_flatpak, False, False, 0)
vbox.pack_start(box_flatpak, False, False, 0)

Expand Down Expand Up @@ -1414,24 +1418,30 @@ def load_banner(self):
for child in box.get_children():
child.destroy()

flowbox = Gtk.FlowBox()
flowbox.set_min_children_per_line(1)
flowbox.set_max_children_per_line(1)
flowbox.set_row_spacing(0)
flowbox.set_column_spacing(0)
flowbox.set_homogeneous(True)

flowbox.connect("child-activated", self.on_flowbox_child_activated, self.PAGE_LANDING)
stack = Gtk.Stack()
stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT_RIGHT)
stack.set_transition_duration(BANNER_TIMER)

dot_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=5)
dot_box.set_halign(Gtk.Align.CENTER)

json_array = json.load(open("/usr/share/linuxmint/mintinstall/featured/featured.json", "r"))
random.shuffle(json_array)

selected_apps = set()
num_selected = 0

tries = 0
pkginfo = None
is_flatpak = False
for app_json in json_array:
if num_selected >= 5:
break

while True:
app_json = random.sample(json_array, 1)[0]
name = app_json["name"]
background = app_json["background"]
color = app_json["text_color"]

if name in selected_apps:
continue

if name.startswith("flatpak:"):
name = name.replace("flatpak:", "")
pkginfo = self.installer.find_pkginfo(name, installer.PKG_TYPE_FLATPAK)
Expand All @@ -1444,26 +1454,68 @@ def load_banner(self):
pkginfo = self.installer.find_pkginfo(name, installer.PKG_TYPE_APT)
is_flatpak = False

if pkginfo is not None:
if self.installer.pkginfo_is_installed(pkginfo) and tries < 10:
tries += 1
continue
break
else:
tries += 1
selected_apps.add(name)
num_selected += 1

if tries > 10:
print("Error while loading the banner.")
box.hide()
return
flowbox = Gtk.FlowBox()
flowbox.set_min_children_per_line(1)
flowbox.set_max_children_per_line(1)
flowbox.set_row_spacing(0)
flowbox.set_column_spacing(0)
flowbox.set_homogeneous(True)
flowbox.connect("child-activated", self.on_flowbox_child_activated, self.PAGE_LANDING)

tile = BannerTile(pkginfo, self.installer, name, background, color, is_flatpak, app_json, self.on_banner_clicked)
flowbox.insert(tile, -1)

stack.add_named(flowbox, str(len(stack.get_children())))

icon = Gtk.Image.new_from_icon_name("media-record-symbolic", Gtk.IconSize.MENU)
icon.set_pixel_size(10)

dot_button = Gtk.Button()
dot_button.set_relief(Gtk.ReliefStyle.NONE)
dot_button.set_image(icon)
dot_button.connect("clicked", self.on_dot_clicked, stack, len(stack.get_children()) - 1)
dot_box.pack_start(dot_button, False, False, 0)

box.pack_start(stack, True, True, 0)
box.pack_start(dot_box, False, False, 5)

self.update_dot_buttons(dot_box, 0)

self.slideshow_timeout_id = GLib.timeout_add_seconds(5, self.on_slideshow_timeout, stack, dot_box)

tile = BannerTile(pkginfo, self.installer, name, is_flatpak, app_json, self.on_banner_clicked)
self.banner_app_name = pkginfo.name
flowbox.insert(tile, -1)
self.banner_tile = tile
box.pack_start(flowbox, True, True, 0)
box.show_all()

def on_dot_clicked(self, button, stack, index):
self.reset_slideshow_timer(stack, button.get_parent())
stack.set_visible_child_name(str(index))
self.update_dot_buttons(button.get_parent(), index)

def reset_slideshow_timer(self, stack, dot_box):
GLib.source_remove(self.slideshow_timeout_id)
self.slideshow_timeout_id = GLib.timeout_add_seconds(5, self.on_slideshow_timeout, stack, dot_box)

def on_slideshow_timeout(self, stack, dot_box):
visible_child = stack.get_visible_child()
index = stack.get_children().index(visible_child)
new_index = (index + 1) % len(stack.get_children())
stack.set_visible_child_name(str(new_index))
self.update_dot_buttons(dot_box, new_index)
return True

def update_dot_buttons(self, dot_box, current_index):
for i, button in enumerate(dot_box.get_children()):
if i == current_index: #Bigger do if current slide
icon = Gtk.Image.new_from_icon_name("media-record-symbolic", Gtk.IconSize.MENU)
icon.set_pixel_size(15)
button.set_image(icon)
else:
icon = Gtk.Image.new_from_icon_name("media-record-symbolic", Gtk.IconSize.MENU)
icon.set_pixel_size(10)
button.set_image(icon)

def on_banner_clicked(self, button, pkginfo):
self.show_package(pkginfo, self.PAGE_LANDING)

Expand Down

0 comments on commit 68bde43

Please sign in to comment.