Beispiel #1
0
        def _go():
            self.thumbs_window = ThumbsWindow(screen=self.screen,
                                              position=options.position,
                                              breadth=options.breadth)
            try:
                icon = varietyconfig.get_data_file("media", "variety.svg")
                self.thumbs_window.set_icon_from_file(icon)
            except Exception:
                logger.exception(lambda: "Could not set thumbs window icon")

            if self.type == "history":
                title = _("Variety History")
            elif self.type == "downloads":
                title = _("Variety Recent Downloads")
            else:
                title = _("Variety Images")

            self.thumbs_window.set_title(title)
            self.thumbs_window.connect("clicked", self.on_click)

            def _on_close(window, event):
                self.hide(force=True)

            self.thumbs_window.connect("delete-event", _on_close)

            self.mark_active(self.active_file, self.active_position)

            self.thumbs_window.start(self.images)
Beispiel #2
0
    def initialize_thumbs_window(self, gdk_thread=False):
        try:
            if not gdk_thread:
                Gdk.threads_enter()
            options = self.load_options()
            self.thumbs_window = ThumbsWindow(
                screen=self.screen, position=options.position, breadth=options.breadth)
            try:
                icon = varietyconfig.get_data_file("media", "variety.svg")
                self.thumbs_window.set_icon_from_file(icon)
            except Exception:
                logger.exception(lambda: "Could not set thumbs window icon")

            if self.type == "history":
                title = _("Variety History")
            elif self.type == "downloads":
                title = _("Variety Recent Downloads")
            else:
                title = _("Variety Images")

            self.thumbs_window.set_title(title)
            self.thumbs_window.connect("clicked", self.on_click)
            def _on_close(window, event):
                self.hide(gdk_thread=True, force=True)
            self.thumbs_window.connect("delete-event", _on_close)

            self.mark_active(self.active_file, self.active_position)

            self.thumbs_window.start(self.images)
        finally:
            if not gdk_thread:
                Gdk.threads_leave()
Beispiel #3
0
class ThumbsManager:
    POSITIONS = {
        "bottom": ThumbsWindow.BOTTOM,
        "top": ThumbsWindow.TOP,
        "left": ThumbsWindow.LEFT,
        "right": ThumbsWindow.RIGHT,
    }

    POSITION_NAMES = {
        "bottom": _("Bottom"),
        "top": _("Top"),
        "left": _("Left"),
        "right": _("Right"),
    }

    R_POSITIONS = {v: k for (k, v) in POSITIONS.items()}

    SIZES = [x * 30 for x in range(2, 11)]

    UNLIMITED = "Unlimited"

    LIMITS = [10, 50, 100, 200, 500, 1000, 2000, UNLIMITED]

    class Options:
        def __init__(self):
            self.position = ThumbsWindow.BOTTOM
            self.breadth = 120
            self.limit = 200

    def __init__(self, parent):
        self.parent = parent
        self.thumbs_window = None
        self.show_thumbs_lock = threading.Lock()

        self.pinned = False
        self.images = []
        self.screen = None

        self.type = None
        self.folders = None

        self.active_file = None
        self.active_position = None

    def create_menu(self, file):
        options = self.load_options()

        menu = Gtk.Menu()

        position_menu = Gtk.Menu()
        for p, v in ThumbsManager.POSITIONS.items():
            item = Gtk.CheckMenuItem(ThumbsManager.POSITION_NAMES[p])
            item.set_draw_as_radio(True)
            item.set_active(options.position == v)

            def _set_position(widget, pos=p):
                self.set_position(pos)

            item.connect("activate", _set_position)
            position_menu.append(item)

        size_menu = Gtk.Menu()
        for size in ThumbsManager.SIZES:
            item = Gtk.CheckMenuItem(str(size))
            item.set_draw_as_radio(True)
            item.set_active(options.breadth == size)

            def _set_size(widget, size=size):
                self.set_size(size)

            item.connect("activate", _set_size)
            size_menu.append(item)

        limit_menu = Gtk.Menu()
        for limit in ThumbsManager.LIMITS:
            item = Gtk.CheckMenuItem(str(limit))
            item.set_draw_as_radio(True)
            item.set_active(options.limit == limit)

            def _set_limit(widget, limit=limit):
                self.set_limit(limit)

            item.connect("activate", _set_limit)
            limit_menu.append(item)

        position_item = Gtk.MenuItem(_("Position"))
        position_item.set_submenu(position_menu)
        menu.append(position_item)

        size_item = Gtk.MenuItem(_("Size"))
        size_item.set_submenu(size_menu)
        menu.append(size_item)

        limit_item = Gtk.MenuItem(_("Maximum Shown Images"))
        limit_item.set_submenu(limit_menu)
        menu.append(limit_item)

        menu.append(Gtk.SeparatorMenuItem.new())

        open_file = Gtk.MenuItem(os.path.basename(file).replace("_", "__"))

        def _open_file(widget):
            self.parent.open_file(widget, file)

        open_file.connect("activate", _open_file)
        menu.append(open_file)

        open_folder = Gtk.MenuItem(_("Show Containing Folder"))

        def _open_folder(widget):
            self.parent.open_folder(widget, file)

        open_folder.connect("activate", _open_folder)
        menu.append(open_folder)

        info = Util.read_metadata(file)
        if info and "sourceURL" in info and "sourceName" in info:
            url = info["sourceURL"]
            source_name = info["sourceName"]
            if "Fetched" in source_name:
                label = _("Fetched: Show Origin")
            else:
                label = _("View at %s") % source_name

            if len(label) > 50:
                label = label[:50] + "..."

            show_origin = Gtk.MenuItem(label)

            def _show_origin(widget=None):
                logger.info(lambda: "Opening url: " + url)
                webbrowser.open_new_tab(url)

            show_origin.connect("activate", _show_origin)
            menu.append(show_origin)

        menu.append(Gtk.SeparatorMenuItem.new())
        rating_item = Gtk.MenuItem(_("Set EXIF Rating"))
        rating_item.set_submenu(
            ThumbsManager.create_rating_menu(file, self.parent))
        if not os.access(file, os.W_OK):
            rating_item.set_sensitive(False)
        menu.append(rating_item)

        menu.append(Gtk.SeparatorMenuItem.new())

        self.copy_to_favorites = Gtk.MenuItem(_("Copy to _Favorites"))
        self.copy_to_favorites.set_use_underline(True)

        def _copy_to_favorites(widget):
            self.parent.copy_to_favorites(widget, file)

        self.copy_to_favorites.connect("activate", _copy_to_favorites)
        menu.append(self.copy_to_favorites)

        self.move_to_favorites = Gtk.MenuItem(_("Move to _Favorites"))
        self.move_to_favorites.set_use_underline(True)

        def _move_to_favorites(widget):
            self.parent.move_to_favorites(widget, file)
            self.remove_image(file)

        self.move_to_favorites.connect("activate", _move_to_favorites)
        self.move_to_favorites.set_visible(False)
        menu.append(self.move_to_favorites)

        trash_item = Gtk.MenuItem(_("Delete to _Trash"))
        trash_item.set_use_underline(True)

        def _trash(widget):
            self.parent.move_to_trash(widget, file)

        trash_item.connect("activate", _trash)
        menu.append(trash_item)

        focus = Gtk.MenuItem(_("Where is it from?"))
        focus.set_sensitive(self.parent.get_source(file) is not None)

        def _focus(widget):
            self.parent.focus_in_preferences(widget, file)

        focus.connect("activate", _focus)
        menu.append(focus)

        menu.append(Gtk.SeparatorMenuItem.new())

        def close(widget):
            self.hide(force=True)

        close_item = Gtk.MenuItem(_("Close"))
        close_item.connect("activate", close)
        menu.append(close_item)

        menu.show_all()

        favs_op = self.parent.determine_favorites_operation(file)
        self.parent.update_favorites_menuitems(self, False, favs_op)

        return menu

    @staticmethod
    def create_rating_menu(file, main_window):
        def _set_rating_maker(rating):
            def _set_rating(widget, rating=rating):
                try:
                    Util.set_rating(file, rating)
                    main_window.on_rating_changed(file)
                except Exception:
                    logger.exception(lambda: "Could not set EXIF rating")
                    main_window.show_notification(
                        _("Could not set EXIF rating"))

            return _set_rating

        try:
            actual_rating = Util.get_rating(file)
        except Exception:
            actual_rating = None

        rating_menu = Gtk.Menu()
        for rating in range(5, 0, -1):
            item = Gtk.CheckMenuItem("\u2605" * rating)
            item.set_draw_as_radio(True)
            item.set_active(actual_rating == rating)
            item.set_sensitive(not item.get_active())
            item.connect("activate", _set_rating_maker(rating))
            rating_menu.append(item)

        rating_menu.append(Gtk.SeparatorMenuItem.new())

        unrated_item = Gtk.CheckMenuItem(_("Unrated"))
        unrated_item.set_draw_as_radio(True)
        unrated_item.set_active(actual_rating is None or actual_rating == 0)
        unrated_item.set_sensitive(not unrated_item.get_active())
        unrated_item.connect("activate", _set_rating_maker(None))
        rating_menu.append(unrated_item)

        rejected_item = Gtk.CheckMenuItem(_("Rejected"))
        rejected_item.set_draw_as_radio(True)
        rejected_item.set_active(actual_rating is not None
                                 and actual_rating < 0)
        rejected_item.set_sensitive(not rejected_item.get_active())
        rejected_item.connect("activate", _set_rating_maker(-1))
        rating_menu.append(rejected_item)

        rating_menu.show_all()
        return rating_menu

    def repaint(self):
        self.hide(keep_settings=True)
        if self.images:
            self.show(self.unlimited_images,
                      screen=self.screen,
                      type=self.type,
                      folders=self.folders)

    def set_position(self, position):
        logger.info(lambda: "Setting thumbs position " + str(position))
        options = self.load_options()
        options.position = ThumbsManager.POSITIONS[position]
        self.save_options(options)
        self.repaint()

    def set_size(self, size):
        logger.info(lambda: "Setting thumbs size " + str(size))
        options = self.load_options()
        options.breadth = size
        self.save_options(options)
        self.repaint()

    def set_limit(self, limit):
        logger.info(lambda: "Setting thumbs limit " + str(limit))
        options = self.load_options()
        options.limit = limit
        self.save_options(options)
        self.repaint()

    def pin(self, widget=None):
        self.pinned = True

    def on_click(self, thumbs_window, file, widget, event):
        file = file
        self.pin()

        def _resume_scrolling(menu=None):
            thumbs_window.resume_scrolling()

        thumbs_window.pause_scrolling()
        if event.button == 1:
            if self.is_showing("history"):
                index = [info["eventbox"]
                         for info in thumbs_window.all].index(widget)
                self.parent.move_to_history_position(index)
            else:
                self.parent.set_wallpaper(file)
            _resume_scrolling()
        else:
            menu = self.create_menu(file)

            def _compute_position(*args, **kwargs):
                x, y = event.get_root_coords()[0], event.get_root_coords()[1]
                h = menu.get_preferred_height()[1]
                return x, y - h if y - h >= 40 else y, True

            menu.connect("deactivate", _resume_scrolling)
            menu.popup(None, None, _compute_position, None, 0, event.time)

    def mark_active(self, file=None, position=None):
        self.active_file = file
        self.active_position = position
        if self.thumbs_window:
            if self.is_showing("history"):
                self.thumbs_window.mark_active(position=position)
            else:
                self.thumbs_window.mark_active(file=file)

    def show(self, images, screen=None, type=None, folders=None):
        options = self.load_options()
        with self.show_thumbs_lock:
            self.unlimited_images = images
            self.type = type
            limit = len(self.unlimited_images
                        ) if options.limit == self.UNLIMITED else options.limit
            self.images = self.unlimited_images[:limit]
            self.screen = screen
            self.folders = folders

            def _go():
                try:
                    if self.thumbs_window:
                        self.thumbs_window.destroy()
                        self.thumbs_window = None

                    if len(self.images) > 0:
                        self.initialize_thumbs_window()
                except Exception:
                    logger.exception(lambda: "Could not create thumbs window:")

            Util.add_mainloop_task(_go)

    def initialize_thumbs_window(self):
        options = self.load_options()

        def _go():
            self.thumbs_window = ThumbsWindow(screen=self.screen,
                                              position=options.position,
                                              breadth=options.breadth)
            try:
                icon = varietyconfig.get_data_file("media", "variety.svg")
                self.thumbs_window.set_icon_from_file(icon)
            except Exception:
                logger.exception(lambda: "Could not set thumbs window icon")

            if self.type == "history":
                title = _("Variety History")
            elif self.type == "downloads":
                title = _("Variety Recent Downloads")
            else:
                title = _("Variety Images")

            self.thumbs_window.set_title(title)
            self.thumbs_window.connect("clicked", self.on_click)

            def _on_close(window, event):
                self.hide(force=True)

            self.thumbs_window.connect("delete-event", _on_close)

            self.mark_active(self.active_file, self.active_position)

            self.thumbs_window.start(self.images)

        Util.add_mainloop_task(_go)

    def load_options(self):
        options = ThumbsManager.Options()
        try:
            config = ConfigObj(
                os.path.join(self.parent.config_folder, "ui.conf"))
            try:
                s = config["thumbs_position"].lower()
                options.position = ThumbsManager.POSITIONS[s]
            except Exception:
                logger.exception(
                    lambda: "Missing or bad thumbs_position option in ui.conf")

            try:
                options.breadth = int(config["thumbs_size"])
            except Exception:
                logger.exception(
                    lambda: "Missing or bad thumbs_size option in ui.conf")

            try:
                options.limit = (int(config["thumbs_limit"])
                                 if config["thumbs_limit"] != self.UNLIMITED
                                 else self.UNLIMITED)
            except Exception:
                logger.exception(
                    lambda: "Missing or bad thumbs_limit option in ui.conf")
        except Exception:
            logger.exception(lambda: "Could not read ui.conf")

        self.save_options(options)
        return options

    def save_options(self, options):
        try:
            config = ConfigObj(
                os.path.join(self.parent.config_folder, "ui.conf"))
            try:
                config["thumbs_position"] = ThumbsManager.R_POSITIONS[
                    options.position]
                config["thumbs_size"] = options.breadth
                config["thumbs_limit"] = str(options.limit)
                config.write()
            except Exception:
                logger.exception(
                    lambda: "Missing or bad thumbs_position option in ui.conf")
        except Exception:
            logger.exception(lambda: "Could not save ui.conf")

    def hide(self, force=True, keep_settings=False):
        if force:
            self.pinned = False

        if self.pinned:
            return

        if not keep_settings:
            self.type = None
            self.images = []
            self.screen = None
            self.folders = None

        if self.thumbs_window:

            def _go():
                self.thumbs_window.destroy()
                self.thumbs_window = None

            Util.add_mainloop_task(_go)
            self.parent.update_indicator(auto_changed=False)

    def remove_image(self, file):
        self.images = [f for f in self.images if f != file]
        if self.thumbs_window:
            if self.thumbs_window.fits_in_screen(+1000):
                self.repaint()
            else:
                self.thumbs_window.remove_image(file)

    def add_image(self, file):
        self.images.insert(0, file)
        if not self.thumbs_window:
            self.initialize_thumbs_window()
        else:
            self.thumbs_window.add_image(file, at_front=True)

    def is_showing(self, type):
        return self.type == type

    def get_folders(self):
        return self.folders
Beispiel #4
0
class ThumbsManager():
    POSITIONS = {
        "bottom": ThumbsWindow.BOTTOM,
        "top": ThumbsWindow.TOP,
        "left": ThumbsWindow.LEFT,
        "right": ThumbsWindow.RIGHT
    }

    POSITION_NAMES = {
        "bottom": _("Bottom"),
        "top": _("Top"),
        "left": _("Left"),
        "right": _("Right")
    }

    R_POSITIONS = dict((v, k) for (k,v) in POSITIONS.items())

    SIZES = [x*30 for x in xrange(2, 11)]

    class Options():
        def __init__(self):
            self.position = ThumbsWindow.BOTTOM
            self.breadth = 120

    def __init__(self, parent):
        self.parent = parent
        self.thumbs_window = None
        self.show_thumbs_lock = threading.Lock()

        self.pinned = False
        self.images = []
        self.screen = None

        self.type = None
        self.folders = None

        self.active_file = None
        self.active_position = None

    def create_menu(self, file):
        options = self.load_options()

        menu = Gtk.Menu()

        position_menu = Gtk.Menu()
        for p, v in ThumbsManager.POSITIONS.items():
            item = Gtk.CheckMenuItem(ThumbsManager.POSITION_NAMES[p])
            item.set_draw_as_radio(True)
            item.set_active(options.position == v)
            def _set_position(widget, pos=p): self.set_position(pos)
            item.connect("activate", _set_position)
            position_menu.append(item)

        size_menu = Gtk.Menu()
        for size in ThumbsManager.SIZES:
            item = Gtk.CheckMenuItem(str(size))
            item.set_draw_as_radio(True)
            item.set_active(options.breadth == size)
            def _set_size(widget, size=size): self.set_size(size)
            item.connect("activate", _set_size)
            size_menu.append(item)

        position_item = Gtk.MenuItem(_("Position"))
        position_item.set_submenu(position_menu)
        menu.append(position_item)

        size_item = Gtk.MenuItem(_("Size"))
        size_item.set_submenu(size_menu)
        menu.append(size_item)

        menu.append(Gtk.SeparatorMenuItem.new())

        open_file = Gtk.MenuItem(os.path.basename(file).replace('_', '__'))
        def _open_file(widget): self.parent.open_file(widget, file)
        open_file.connect("activate", _open_file)
        menu.append(open_file)

        open_folder = Gtk.MenuItem(_("Show Containing Folder"))
        def _open_folder(widget): self.parent.open_folder(widget, file)
        open_folder.connect("activate", _open_folder)
        menu.append(open_folder)

        info = Util.read_metadata(file)
        if info and "sourceURL" in info and "sourceName" in info:
            url = info["sourceURL"]
            source_name = info["sourceName"]
            if "Fetched" in source_name:
                label = _("Fetched: Show Origin")
            else:
                label = _("View at %s") % source_name

            if len(label) > 50:
                label = label[:50] + "..."

            show_origin = Gtk.MenuItem(label)

            def _show_origin(widget=None):
                logger.info(lambda: "Opening url: " + url)
                webbrowser.open_new_tab(url)

            show_origin.connect("activate", _show_origin)
            menu.append(show_origin)

        menu.append(Gtk.SeparatorMenuItem.new())
        rating_item  = Gtk.MenuItem(_("Set EXIF Rating"))
        rating_item.set_submenu(ThumbsManager.create_rating_menu(file, self.parent))
        if not os.access(file, os.W_OK):
            rating_item.set_sensitive(False)
        menu.append(rating_item)

        menu.append(Gtk.SeparatorMenuItem.new())

        self.copy_to_favorites = Gtk.MenuItem(_("Copy to _Favorites"))
        self.copy_to_favorites.set_use_underline(True)
        def _copy_to_favorites(widget):
            self.parent.copy_to_favorites(widget, file)
        self.copy_to_favorites.connect("activate", _copy_to_favorites)
        menu.append(self.copy_to_favorites)

        self.move_to_favorites = Gtk.MenuItem(_("Move to _Favorites"))
        self.move_to_favorites.set_use_underline(True)
        def _move_to_favorites(widget):
            self.parent.move_to_favorites(widget, file)
            self.remove_image(file)
        self.move_to_favorites.connect("activate", _move_to_favorites)
        self.move_to_favorites.set_visible(False)
        menu.append(self.move_to_favorites)

        trash_item = Gtk.MenuItem(_("Delete to _Trash"))
        trash_item.set_use_underline(True)
        def _trash(widget):
            self.parent.move_to_trash(widget, file)
        trash_item.connect("activate", _trash)
        menu.append(trash_item)

        focus = Gtk.MenuItem(_("Where is it from?"))
        focus.set_sensitive(self.parent.get_source(file) is not None)
        def _focus(widget):
            self.parent.focus_in_preferences(widget, file)
        focus.connect("activate", _focus)
        menu.append(focus)

        menu.append(Gtk.SeparatorMenuItem.new())

        def close(widget):
            self.hide(gdk_thread=True, force=True)
        close_item = Gtk.MenuItem(_("Close"))
        close_item.connect("activate", close)
        menu.append(close_item)

        menu.show_all()

        favs_op = self.parent.determine_favorites_operation(file)
        self.parent.update_favorites_menuitems(self, False, favs_op)

        return menu

    @staticmethod
    def create_rating_menu(file, main_window):
        def _set_rating_maker(rating):
            def _set_rating(widget, rating=rating):
                try:
                    Util.set_rating(file, rating)
                    main_window.on_rating_changed(file)
                except Exception:
                    logger.exception(lambda: "Could not set EXIF rating")
                    main_window.show_notification(_("Could not set EXIF rating"))
            return _set_rating

        try:
            actual_rating = Util.get_rating(file)
        except Exception:
            actual_rating = None

        rating_menu = Gtk.Menu()
        for rating in xrange(5, 0, -1):
            item = Gtk.CheckMenuItem(u"\u2605" * rating)
            item.set_draw_as_radio(True)
            item.set_active(actual_rating == rating)
            item.set_sensitive(not item.get_active())
            item.connect("activate", _set_rating_maker(rating))
            rating_menu.append(item)

        rating_menu.append(Gtk.SeparatorMenuItem.new())

        unrated_item = Gtk.CheckMenuItem(_("Unrated"))
        unrated_item.set_draw_as_radio(True)
        unrated_item.set_active(actual_rating is None or actual_rating == 0)
        unrated_item.set_sensitive(not unrated_item.get_active())
        unrated_item.connect("activate", _set_rating_maker(None))
        rating_menu.append(unrated_item)

        rejected_item = Gtk.CheckMenuItem(_("Rejected"))
        rejected_item.set_draw_as_radio(True)
        rejected_item.set_active(actual_rating is not None and actual_rating < 0)
        rejected_item.set_sensitive(not rejected_item.get_active())
        rejected_item.connect("activate", _set_rating_maker(-1))
        rating_menu.append(rejected_item)

        rating_menu.show_all()
        return rating_menu

    def repaint(self):
        self.hide(gdk_thread=True, keep_settings=True)
        if self.images:
            self.show(self.images, gdk_thread=True, screen=self.screen, type=self.type, folders=self.folders)

    def set_position(self, position):
        logger.info(lambda: "Setting thumbs position " + str(position))
        options = self.load_options()
        options.position = ThumbsManager.POSITIONS[position]
        self.save_options(options)
        self.repaint()

    def set_size(self, size):
        logger.info(lambda: "Setting thumbs size " + str(size))
        options = self.load_options()
        options.breadth = size
        self.save_options(options)
        self.repaint()

    def pin(self, widget=None):
        self.pinned = True

    def on_click(self, thumbs_window, file, widget, event):
        file = _u(file)
        self.pin()
        def _resume_scrolling(menu=None):
            thumbs_window.resume_scrolling()
        thumbs_window.pause_scrolling()
        if event.button == 1:
            if self.is_showing("history"):
                index = [info["eventbox"] for info in thumbs_window.all].index(widget)
                self.parent.move_to_history_position(index)
            else:
                self.parent.set_wallpaper(file)
            _resume_scrolling()
        else:
            menu = self.create_menu(file)
            def _compute_position(a, b, event=event):
                x, y = event.get_root_coords()[0], event.get_root_coords()[1]
                h = menu.get_preferred_height()[1]
                return x, y - h if y - h >= 40 else y, True
            menu.connect("deactivate", _resume_scrolling)
            menu.popup(None, None, _compute_position, None, 0, event.time)

    def mark_active(self, file=None, position=None):
        self.active_file = file
        self.active_position = position
        if self.thumbs_window:
            if self.is_showing("history"):
                self.thumbs_window.mark_active(position=position)
            else:
                self.thumbs_window.mark_active(file=file)

    def show(self, images, gdk_thread=False, screen=None, type=None, folders=None):
        with self.show_thumbs_lock:
            self.type = type
            self.images = images
            self.screen = screen
            self.folders = folders

            try:
                if self.thumbs_window:
                    try:
                        if not gdk_thread:
                            Gdk.threads_enter()
                        self.thumbs_window.destroy()
                        self.thumbs_window = None
                    finally:
                        if not gdk_thread:
                            Gdk.threads_leave()

                if len(self.images) > 0:
                    self.initialize_thumbs_window(gdk_thread=gdk_thread)
            except Exception:
                logger.exception(lambda: "Could not create thumbs window:")

    def initialize_thumbs_window(self, gdk_thread=False):
        try:
            if not gdk_thread:
                Gdk.threads_enter()
            options = self.load_options()
            self.thumbs_window = ThumbsWindow(
                screen=self.screen, position=options.position, breadth=options.breadth)
            try:
                icon = varietyconfig.get_data_file("media", "variety.svg")
                self.thumbs_window.set_icon_from_file(icon)
            except Exception:
                logger.exception(lambda: "Could not set thumbs window icon")

            if self.type == "history":
                title = _("Variety History")
            elif self.type == "downloads":
                title = _("Variety Recent Downloads")
            else:
                title = _("Variety Images")

            self.thumbs_window.set_title(title)
            self.thumbs_window.connect("clicked", self.on_click)
            def _on_close(window, event):
                self.hide(gdk_thread=True, force=True)
            self.thumbs_window.connect("delete-event", _on_close)

            self.mark_active(self.active_file, self.active_position)

            self.thumbs_window.start(self.images)
        finally:
            if not gdk_thread:
                Gdk.threads_leave()

    def load_options(self):
        options = ThumbsManager.Options()
        options.position = ThumbsWindow.BOTTOM
        options.breadth = 120
        try:
            config = ConfigObj(os.path.join(self.parent.config_folder, "ui.conf"))
            try:
                s = config["thumbs_position"].lower()
                options.position = ThumbsManager.POSITIONS[s]
            except Exception:
                logger.exception(lambda: "Missing or bad thumbs_position option in ui.conf")

            try:
                options.breadth = int(config["thumbs_size"])
            except Exception:
                logger.exception(lambda: "Missing or bad thumbs_size option in ui.conf")
        except Exception:
            logger.exception(lambda: "Could not read ui.conf")

        return options

    def save_options(self, options):
        try:
            config = ConfigObj(os.path.join(self.parent.config_folder, "ui.conf"))
            try:
                config["thumbs_position"] = ThumbsManager.R_POSITIONS[options.position]
                config["thumbs_size"] = options.breadth
                config.write()
            except Exception:
                logger.exception(lambda: "Missing or bad thumbs_position option in ui.conf")
        except Exception:
            logger.exception(lambda: "Could not save ui.conf")


    def hide(self, gdk_thread=False, force=True, keep_settings=False):
        if force:
            self.pinned = False

        if self.pinned:
            return

        if not keep_settings:
            self.type = None
            self.images = []
            self.screen = None
            self.folders = None

        if self.thumbs_window:
            try:
                try:
                    if not gdk_thread:
                        Gdk.threads_enter()
                    self.thumbs_window.destroy()
                    self.thumbs_window = None
                    self.parent.update_indicator(is_gtk_thread=True, auto_changed=False)
                finally:
                    if not gdk_thread:
                        Gdk.threads_leave()
            except Exception:
                pass

    def remove_image(self, file, gdk_thread=True):
        self.images = [f for f in self.images if f != file]
        if self.thumbs_window:
            if self.thumbs_window.fits_in_screen(+1000):
                self.repaint()
            else:
                self.thumbs_window.remove_image(file, gdk_thread)

    def add_image(self, file, gdk_thread=True):
        self.images.insert(0, file)
        if not self.thumbs_window:
            self.initialize_thumbs_window(gdk_thread=gdk_thread)
        else:
            self.thumbs_window.add_image(file, gdk_thread, at_front=True)

    def is_showing(self, type):
        return self.type == type

    def get_folders(self):
        return self.folders