#!/usr/bin/python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib

COMMON_ICONS = [
    'document-new','document-open','document-save','document-save-as','document-print',
    'edit-copy','edit-cut','edit-paste','edit-undo','edit-redo','edit-find','edit-select-all',
    'go-home','go-up','go-down','go-previous','go-next','go-first','go-last',
    'view-refresh','view-fullscreen','view-restore','zoom-in','zoom-out','zoom-fit-best',
    'help-about','help-contents','preferences-system','system-shutdown','system-reboot',
    'application-exit','window-close','window-new','window-maximize','window-minimize',
    'media-playback-start','media-playback-stop','media-playback-pause','media-record',
    'media-skip-forward','media-skip-backward','media-seek-forward','media-seek-backward',
    'audio-volume-high','audio-volume-medium','audio-volume-low','audio-volume-muted',
    'network-wired','network-wireless','network-offline','folder','folder-open',
    'user-home','user-desktop','user-trash','computer','drive-harddisk',
    'image-x-generic','audio-x-generic','video-x-generic','text-x-generic',
    'format-text-bold','format-text-italic','format-text-underline',
    'list-add','list-remove','mail-message-new','mail-send-receive',
    'weather-clear','weather-clouds','weather-rain','weather-snow',
    'face-smile','face-sad','face-surprise','emblem-default','emblem-important',
    'dialog-information','dialog-warning','dialog-error','dialog-question',
    'appointment-new','contact-new','address-book-new','stock_new-appointment',
    'battery','battery-full','battery-low','battery-caution','battery-missing',
]

class App(Gtk.Window):
    def __init__(self):
        super().__init__(title='Icon Browser')
        self.set_default_size(720, 540)
        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        vbox.set_margin_top(6); vbox.set_margin_bottom(6)
        vbox.set_margin_start(6); vbox.set_margin_end(6)
        self.add(vbox)
        hb = Gtk.Box(spacing=6)
        self.search = Gtk.SearchEntry()
        self.search.connect('search-changed', self.filter_icons)
        hb.pack_start(self.search, True, True, 0)
        self.count_lbl = Gtk.Label()
        hb.pack_start(self.count_lbl, False, False, 0)
        vbox.pack_start(hb, False, False, 0)
        # icon grid (flowbox)
        sw = Gtk.ScrolledWindow()
        self.flow = Gtk.FlowBox()
        self.flow.set_valign(Gtk.Align.START)
        self.flow.set_max_children_per_line(12)
        self.flow.set_selection_mode(Gtk.SelectionMode.SINGLE)
        self.flow.connect('child-activated', self.on_icon_click)
        sw.add(self.flow)
        vbox.pack_start(sw, True, True, 0)
        # preview
        self.preview_box = Gtk.Box(spacing=10)
        self.preview_box.set_margin_top(6)
        self.prev_icons = {}
        for sz in [16, 24, 32, 48, 64]:
            img = Gtk.Image()
            self.prev_icons[sz] = img
            vb = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=2)
            vb.pack_start(img, False, False, 0)
            vb.add(Gtk.Label(label=f'{sz}px'))
            self.preview_box.pack_start(vb, False, False, 0)
        self.icon_name_lbl = Gtk.Label(label='Click an icon to preview', xalign=0)
        self.preview_box.pack_start(self.icon_name_lbl, True, True, 0)
        vbox.pack_start(self.preview_box, False, False, 0)
        theme = Gtk.IconTheme.get_default()
        self.all_icons = sorted(set(COMMON_ICONS) | set(theme.list_icons(None) or []))
        self.populate_icons(self.all_icons)
    def populate_icons(self, icons):
        for child in self.flow.get_children(): self.flow.remove(child)
        theme = Gtk.IconTheme.get_default()
        shown = 0
        for name in icons[:300]:
            if theme.has_icon(name):
                img = Gtk.Image.new_from_icon_name(name, Gtk.IconSize.LARGE_TOOLBAR)
                btn = Gtk.Button()
                btn.set_image(img)
                btn.set_tooltip_text(name)
                btn._icon_name = name
                self.flow.add(btn)
                shown += 1
        self.flow.show_all()
        self.count_lbl.set_text(f'{shown} icons')
    def filter_icons(self, *_):
        q = self.search.get_text().lower()
        filtered = [n for n in self.all_icons if q in n] if q else self.all_icons
        self.populate_icons(filtered)
    def on_icon_click(self, flow, child):
        btn = child.get_child()
        if hasattr(btn, '_icon_name'):
            name = btn._icon_name
            self.icon_name_lbl.set_text(name)
            theme = Gtk.IconTheme.get_default()
            for sz, img in self.prev_icons.items():
                if theme.has_icon(name):
                    img.set_from_icon_name(name, Gtk.IconSize.INVALID)
                    img.set_pixel_size(sz)
                else:
                    img.clear()

win = App()
win.connect('destroy', Gtk.main_quit)
win.show_all()
Gtk.main()
