From b4536666b09ec7df8141773966c3d80802a22538 Mon Sep 17 00:00:00 2001 From: Nick Hall Date: Wed, 9 Mar 2022 00:06:03 +0000 Subject: [PATCH] Add support for thumbnailer plugins --- gramps/gen/const.py | 7 +- gramps/gen/plug/__init__.py | 1 + gramps/gen/plug/_manager.py | 5 + gramps/gen/plug/_pluginreg.py | 38 ++++- gramps/gen/plug/_thumbnailer.py | 67 ++++++++ gramps/gen/utils/thumbnails.py | 198 ++++++----------------- gramps/gui/editors/addmedia.py | 7 +- gramps/plugins/thumbnailer/__init__.py | 0 gramps/plugins/thumbnailer/gnomethumb.py | 105 ++++++++++++ gramps/plugins/thumbnailer/imagethumb.py | 101 ++++++++++++ gramps/plugins/thumbnailer/thumb.gpr.py | 59 +++++++ po/POTFILES.in | 1 + po/POTFILES.skip | 6 + 13 files changed, 429 insertions(+), 166 deletions(-) create mode 100644 gramps/gen/plug/_thumbnailer.py create mode 100644 gramps/plugins/thumbnailer/__init__.py create mode 100644 gramps/plugins/thumbnailer/gnomethumb.py create mode 100644 gramps/plugins/thumbnailer/imagethumb.py create mode 100644 gramps/plugins/thumbnailer/thumb.gpr.py diff --git a/gramps/gen/const.py b/gramps/gen/const.py index 81908bf14..c02b58ce3 100644 --- a/gramps/gen/const.py +++ b/gramps/gen/const.py @@ -163,11 +163,6 @@ PLUGINS_DIR = os.path.join(ROOT_DIR, "plugins") USE_TIPS = False -if sys.platform == 'win32': - USE_THUMBNAILER = False -else: - USE_THUMBNAILER = True - #------------------------------------------------------------------------- # # Paths to data files. @@ -254,6 +249,8 @@ DOCUMENTERS = [ #------------------------------------------------------------------------- THUMBSCALE = 96.0 THUMBSCALE_LARGE = 180.0 +SIZE_NORMAL = 0 +SIZE_LARGE = 1 XMLFILE = "data.gramps" NO_SURNAME = "(%s)" % _("none", "surname") NO_GIVEN = "(%s)" % _("none", "given-name") diff --git a/gramps/gen/plug/__init__.py b/gramps/gen/plug/__init__.py index a07d1b05a..faeefa4cb 100644 --- a/gramps/gen/plug/__init__.py +++ b/gramps/gen/plug/__init__.py @@ -41,6 +41,7 @@ from ._export import ExportPlugin from ._docgenplugin import DocGenPlugin from ._manager import BasePluginManager from ._gramplet import Gramplet +from ._thumbnailer import Thumbnailer from .utils import * from ._options import (Options, OptionListCollection, OptionList, OptionHandler, MenuOptions) diff --git a/gramps/gen/plug/_manager.py b/gramps/gen/plug/_manager.py index 51bd85a2c..1077de0cd 100644 --- a/gramps/gen/plug/_manager.py +++ b/gramps/gen/plug/_manager.py @@ -448,6 +448,11 @@ class BasePluginManager: """ return self.__pgr.database_plugins() + def get_reg_thumbnailers(self): + """ Return list of registered thumbnailers. + """ + return self.__pgr.thumbnailer_plugins() + def get_external_opt_dict(self): """ Return the dictionary of external options. """ return self.__external_opt_dict diff --git a/gramps/gen/plug/_pluginreg.py b/gramps/gen/plug/_pluginreg.py index 10c08db4d..83f6ef7af 100644 --- a/gramps/gen/plug/_pluginreg.py +++ b/gramps/gen/plug/_pluginreg.py @@ -73,8 +73,10 @@ GRAMPLET = 10 SIDEBAR = 11 DATABASE = 12 RULE = 13 +THUMBNAILER = 14 PTYPE = [REPORT, QUICKREPORT, TOOL, IMPORT, EXPORT, DOCGEN, GENERAL, - MAPSERVICE, VIEW, RELCALC, GRAMPLET, SIDEBAR, DATABASE, RULE] + MAPSERVICE, VIEW, RELCALC, GRAMPLET, SIDEBAR, DATABASE, RULE, + THUMBNAILER] PTYPE_STR = { REPORT: _('Report') , QUICKREPORT: _('Quickreport'), @@ -89,7 +91,8 @@ PTYPE_STR = { GRAMPLET: _('Gramplet'), SIDEBAR: _('Sidebar'), DATABASE: _('Database'), - RULE: _('Rule') + RULE: _('Rule'), + THUMBNAILER: _('Thumbnailer'), } #possible report categories @@ -371,6 +374,11 @@ class PluginData: The class (Person, Event, Media, etc.) the rule applies to. .. attribute:: ruleclass The exact class name of the rule; ex: HasSourceParameter + + Attributes for THUMBNAILER plugins + + .. attribute:: thumbnailer + The exact class name of the thumbnailer """ def __init__(self): @@ -452,6 +460,8 @@ class PluginData: #RULE attr self._ruleclass = None self._namespace = None + #THUMBNAILER attr + self._thumbnailer = None def _set_id(self, id): self._id = id @@ -948,10 +958,10 @@ class PluginData: sidebarclass = property(_get_sidebarclass, _set_sidebarclass) menu_label = property(_get_menu_label, _set_menu_label) - #VIEW and SIDEBAR attributes + #VIEW, SIDEBAR and THUMBNAILER attributes def _set_order(self, order): - if not self._ptype in (VIEW, SIDEBAR): - raise ValueError('order may only be set for VIEW and SIDEBAR plugins') + if not self._ptype in (VIEW, SIDEBAR, THUMBNAILER): + raise ValueError('order may only be set for VIEW/SIDEBAR/THUMBNAILER plugins') self._order = order def _get_order(self): @@ -1019,6 +1029,17 @@ class PluginData: ruleclass = property(_get_ruleclass, _set_ruleclass) namespace = property(_get_namespace, _set_namespace) + #THUMBNAILER attr + def _set_thumbnailer(self, data): + if self._ptype != THUMBNAILER: + raise ValueError('thumbnailer may only be set for THUMBNAILER plugins') + self._thumbnailer = data + + def _get_thumbnailer(self): + return self._thumbnailer + + thumbnailer = property(_get_thumbnailer, _set_thumbnailer) + def newplugin(): """ Function to create a new plugindata object, add it to list of @@ -1072,6 +1093,7 @@ def make_environment(**kwargs): 'RELCALC': RELCALC, 'GRAMPLET': GRAMPLET, 'SIDEBAR': SIDEBAR, + 'THUMBNAILER': THUMBNAILER, 'CATEGORY_TEXT': CATEGORY_TEXT, 'CATEGORY_DRAW': CATEGORY_DRAW, 'CATEGORY_CODE': CATEGORY_CODE, @@ -1389,6 +1411,12 @@ class PluginRegister: """ return self.type_plugins(RULE) + def thumbnailer_plugins(self): + """ + Return a list of :class:`PluginData` that are of type THUMBNAILER + """ + return self.type_plugins(THUMBNAILER) + def filter_load_on_reg(self): """ Return a list of :class:`PluginData` that have load_on_reg == True diff --git a/gramps/gen/plug/_thumbnailer.py b/gramps/gen/plug/_thumbnailer.py new file mode 100644 index 000000000..3728e0a1c --- /dev/null +++ b/gramps/gen/plug/_thumbnailer.py @@ -0,0 +1,67 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2022 Nick Hall +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +""" +This module provides the base class for thumbnailer plugins. +""" + +#------------------------------------------------------------------------- +# +# Standard python modules +# +#------------------------------------------------------------------------- +from abc import ABCMeta, abstractmethod + +#------------------------------------------------------------------------- +# +# Thumbnailer class +# +#------------------------------------------------------------------------- +class Thumbnailer(metaclass=ABCMeta): + + @abstractmethod + def is_supported(self, mime_type): + """ + Indicates if a mime type is supported by this thumbnailer. + + :param mime_type: mime type of the source file + :type mime_type: unicode + :rtype: bool + :returns: True if the mime type is supported by this thumbnailer + """ + + @abstractmethod + def run(self, mime_type, src_file, dest_file, size, rectangle): + """ + Generates a thumbnail image for the specified file. + + :param mime_type: mime type of the source file + :type mime_type: unicode + :param src_file: filename of the source file + :type src_file: unicode + :param dest_file: filename of the destination file + :type dest_file: unicode + :param size: required size of the thumbnail in pixels + :type size: int + :param rectangle: subsection rectangle + :type rectangle: tuple + :rtype: bool + :returns: True if the thumbnail was successfully generated + """ diff --git a/gramps/gen/utils/thumbnails.py b/gramps/gen/utils/thumbnails.py index 42f7c628a..3d3548f3a 100644 --- a/gramps/gen/utils/thumbnails.py +++ b/gramps/gen/utils/thumbnails.py @@ -2,6 +2,7 @@ # Gramps - a GTK+/GNOME based genealogy program # # Copyright (C) 2000-2007 Donald N. Allingham +# Copyright (C) 2022 Nick Hall # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -51,26 +52,9 @@ except: # #------------------------------------------------------------------------- from gramps.gen.const import (ICON, IMAGE_DIR, THUMB_LARGE, THUMB_NORMAL, - THUMBSCALE, THUMBSCALE_LARGE, USE_THUMBNAILER) -from gramps.gen.constfunc import win - -#------------------------------------------------------------------------- -# -# gconf - try loading gconf for GNOME based systems. If we find it, we -# might be able to generate thumbnails for non-image files. -# -#------------------------------------------------------------------------- -try: - #test first for the key to avoid an error in the importer that causes - #the error logger to activate - ##TODO GTK3: Is this the best way to avoid error? - import gi.repository as repo - repo.__dict__['GConf'] - from gi.repository import GConf - GCONF = True - CLIENT = GConf.Client.get_default() -except (ImportError, KeyError) as msg: - GCONF = False + SIZE_NORMAL, SIZE_LARGE) +from gramps.gen.plug import BasePluginManager, START +from gramps.gen.mime import get_type #------------------------------------------------------------------------- # @@ -78,50 +62,25 @@ except (ImportError, KeyError) as msg: # #------------------------------------------------------------------------- LOG = logging.getLogger(".thumbnail") -SIZE_NORMAL = 0 -SIZE_LARGE = 1 -#------------------------------------------------------------------------- -# -# __get_gconf_string -# -#------------------------------------------------------------------------- -def __get_gconf_string(key): - """ - Attempt to retrieve a value from the GNOME gconf database based of the - passed key. +THUMBNAILERS = [] +def get_thumbnailers(): + if len(THUMBNAILERS): + return THUMBNAILERS - :param key: GCONF key - :type key: unicode - :returns: Value associated with the GCONF key - :rtype: unicode - """ - try: - val = CLIENT.get_string(key) - except GLib.GError: - val = None - return str(val) - -#------------------------------------------------------------------------- -# -# __get_gconf_bool -# -#------------------------------------------------------------------------- -def __get_gconf_bool(key): - """ - Attempt to retrieve a value from the GNOME gconf database based of the - passed key. - - :param key: GCONF key - :type key: unicode - :returns: Value associated with the GCONF key - :rtype: bool - """ - try: - val = CLIENT.get_bool(key) - except GLib.GError: - val = None - return val + plugman = BasePluginManager.get_instance() + for pdata in plugman.get_reg_thumbnailers(): + module = plugman.load_plugin(pdata) + if not module: + print("Error loading thumbnailer '%s': skipping content" + % pdata.name) + continue + thumbnailer = getattr(module, pdata.thumbnailer)() + if pdata.order == START: + THUMBNAILERS.insert(0, thumbnailer) + else: + THUMBNAILERS.append(thumbnailer) + return THUMBNAILERS #------------------------------------------------------------------------- # @@ -176,49 +135,35 @@ def __create_thumbnail_image(src_file, mtype=None, rectangle=None, :rtype: bool :returns: True is the thumbnailwas successfully generated """ + if mtype is None: + mtype = get_type(src_file) filename = __build_thumb_path(src_file, rectangle, size) + return run_thumbnailer(mtype, src_file, filename, size, rectangle) - if mtype and not mtype.startswith('image/'): - # Not an image, so run the thumbnailer - return run_thumbnailer(mtype, src_file, filename) - else: - # build a thumbnail by scaling the image using GTK's built in - # routines. - try: - pixbuf = GdkPixbuf.Pixbuf.new_from_file(src_file) - width = pixbuf.get_width() - height = pixbuf.get_height() +def run_thumbnailer(mime_type, src_file, dest_file, size, rectangle=None): + """ + This function attempts to generate a thumbnail image. It runs the first + thumbnailer plugin that supports the given mime type. - if rectangle is not None: - upper_x = min(rectangle[0], rectangle[2])/100. - lower_x = max(rectangle[0], rectangle[2])/100. - upper_y = min(rectangle[1], rectangle[3])/100. - lower_y = max(rectangle[1], rectangle[3])/100. - sub_x = int(upper_x * width) - sub_y = int(upper_y * height) - sub_width = int((lower_x - upper_x) * width) - sub_height = int((lower_y - upper_y) * height) - if sub_width > 0 and sub_height > 0: - pixbuf = pixbuf.new_subpixbuf(sub_x, sub_y, sub_width, sub_height) - width = sub_width - height = sub_height - - if size == SIZE_LARGE: - thumbscale = THUMBSCALE_LARGE - else: - thumbscale = THUMBSCALE - scale = thumbscale / (float(max(width, height))) - - scaled_width = int(width * scale) - scaled_height = int(height * scale) - - pixbuf = pixbuf.scale_simple(scaled_width, scaled_height, - GdkPixbuf.InterpType.BILINEAR) - pixbuf.savev(filename, "png", "", "") - return True - except Exception as err: - LOG.warning("Error scaling image down: %s", str(err)) - return False + :param mime_type: mime type of the source file + :type mime_type: unicode + :param src_file: filename of the source file + :type src_file: unicode + :param dest_file: destination file for the thumbnail image + :type dest_file: unicode + :param size: option parameters specifying the desired size of the + thumbnail + :type size: int + :param rectangle: subsection rectangle (optional) + :type rectangle: tuple + :returns: True if the thumbnail was successfully generated + :rtype: bool + """ + for thumbnailer in get_thumbnailers(): + if thumbnailer.is_supported(mime_type): + if thumbnailer.run(mime_type, src_file, dest_file, size, rectangle): + return True + return False #------------------------------------------------------------------------- # @@ -241,55 +186,6 @@ def find_mime_type_pixbuf(mime_type): return GdkPixbuf.Pixbuf.new_from_file(ICON) except: return GdkPixbuf.Pixbuf.new_from_file(ICON) -#------------------------------------------------------------------------- -# -# run_thumbnailer -# -#------------------------------------------------------------------------- -def run_thumbnailer(mime_type, src_file, dest_file, size=SIZE_NORMAL): - """ - This function attempts to generate a thumbnail image for a non-image. - This includes things such as video and PDF files. This will currently - only succeed if the GNOME environment is installed, since at this point, - only the GNOME environment has the ability to generate thumbnails. - - :param mime_type: mime type of the source file - :type mime_type: unicode - :param src_file: filename of the source file - :type src_file: unicode - :param dest_file: destination file for the thumbnail image - :type dest_file: unicode - :param size: option parameters specifying the desired size of the - thumbnail - :type size: int - :returns: True if the thumbnail was successfully generated - :rtype: bool - """ - # only try this if GCONF is present, the thumbnailer has not been - # disabled, and if the src_file actually exists - if GCONF and USE_THUMBNAILER and os.path.isfile(src_file): - - # find the command and enable for the associated mime types by - # querying the gconf database - base = '/desktop/gnome/thumbnailers/%s' % mime_type.replace('/', '@') - cmd = __get_gconf_string(base + '/command') - enable = __get_gconf_bool(base + '/enable') - - # if we found the command and it has been enabled, then spawn - # of the command to build the thumbnail - if cmd and enable: - if size == SIZE_LARGE: - thumbscale = THUMBSCALE_LARGE - else: - thumbscale = THUMBSCALE - sublist = { - '%s' : "%d" % int(thumbscale), - '%u' : src_file, - '%o' : dest_file, - } - cmdlist = [ sublist.get(x, x) for x in cmd.split() ] - return os.spawnvpe(os.P_WAIT, cmdlist[0], cmdlist, os.environ) == 0 - return False #------------------------------------------------------------------------- # diff --git a/gramps/gui/editors/addmedia.py b/gramps/gui/editors/addmedia.py index 0f3d07e02..1e079363d 100644 --- a/gramps/gui/editors/addmedia.py +++ b/gramps/gui/editors/addmedia.py @@ -54,7 +54,7 @@ from gramps.gen.config import config from gramps.gen.utils.file import (media_path_full, media_path, relative_path, find_file) from gramps.gen.mime import get_type -from gramps.gen.utils.thumbnails import find_mime_type_pixbuf +from gramps.gen.utils.thumbnails import get_thumbnail_image from ..display import display_help from ..managedwindow import ManagedWindow from ..dialog import ErrorDialog, WarningDialog @@ -214,10 +214,7 @@ class AddMedia(ManagedWindow): filename = find_file( filename) if filename: mtype = get_type(filename) - if mtype and mtype.startswith("image"): - image = self.scale_image(filename, THUMBSCALE) - else: - image = find_mime_type_pixbuf(mtype) + image = get_thumbnail_image(filename, mtype) self.image.set_from_pixbuf(image) def _cleanup_on_exit(self): diff --git a/gramps/plugins/thumbnailer/__init__.py b/gramps/plugins/thumbnailer/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/gramps/plugins/thumbnailer/gnomethumb.py b/gramps/plugins/thumbnailer/gnomethumb.py new file mode 100644 index 000000000..d6328f400 --- /dev/null +++ b/gramps/plugins/thumbnailer/gnomethumb.py @@ -0,0 +1,105 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2000-2007 Donald N. Allingham +# Copyright (C) 2022 Nick Hall +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +""" +A thumbnailer that uses other system thumbnailers already installed on a +Gmone desktop. +""" + +#------------------------------------------------------------------------- +# +# Standard python modules +# +#------------------------------------------------------------------------- +import os +import glob +import logging + +#------------------------------------------------------------------------- +# +# GTK/Gnome modules +# +#------------------------------------------------------------------------- +from gi.repository import GLib + +#------------------------------------------------------------------------- +# +# Gramps modules +# +#------------------------------------------------------------------------- +from gramps.gen.const import THUMBSCALE, THUMBSCALE_LARGE, SIZE_LARGE +from gramps.gen.plug import Thumbnailer +from gramps.gen.constfunc import get_env_var, lin + +#------------------------------------------------------------------------- +# +# Constants +# +#------------------------------------------------------------------------- +LOG = logging.getLogger(".thumbnail") + + +class GnomeThumb(Thumbnailer): + def __init__(self): + self.all_mime_types = {} + if lin(): + self.__find_thumbnailers() + + def __find_thumbnailers(self): + path_list = GLib.get_system_data_dirs() + path_list.append(GLib.get_user_data_dir()) + file_list = [] + for path in path_list: + file_list.extend( + glob.glob(os.path.join(path, "thumbnailers", "*.thumbnailer")) + ) + + for filename in file_list: + kf = GLib.KeyFile() + try: + kf.load_from_file(filename, GLib.KeyFileFlags.NONE) + cmd = kf.get_string("Thumbnailer Entry", "Exec") + mime_types = kf.get_string_list("Thumbnailer Entry", "MimeType") + except GLib.GError: + continue + if cmd and mime_types: + for mime_type in mime_types: + self.all_mime_types[mime_type] = cmd + + def is_supported(self, mime_type): + return mime_type in self.all_mime_types + + def run(self, mime_type, src_file, dest_file, size, rectangle): + cmd = self.all_mime_types.get(mime_type) + if cmd: + if size == SIZE_LARGE: + thumbscale = THUMBSCALE_LARGE + else: + thumbscale = THUMBSCALE + sublist = { + "%s": "%d" % int(thumbscale), + "%u": "file://" + src_file, + "%i": src_file, + "%o": dest_file, + } + cmdlist = [sublist.get(x, x) for x in cmd.split()] + return os.spawnvpe(os.P_WAIT, cmdlist[0], cmdlist, os.environ) == 0 + return False diff --git a/gramps/plugins/thumbnailer/imagethumb.py b/gramps/plugins/thumbnailer/imagethumb.py new file mode 100644 index 000000000..1c9e969a8 --- /dev/null +++ b/gramps/plugins/thumbnailer/imagethumb.py @@ -0,0 +1,101 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2000-2007 Donald N. Allingham +# Copyright (C) 2022 Nick Hall +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +""" +A thumbnailer for images and sub-sections of images. +""" + +#------------------------------------------------------------------------- +# +# Standard python modules +# +#------------------------------------------------------------------------- +import logging + +#------------------------------------------------------------------------- +# +# GTK/Gnome modules +# +#------------------------------------------------------------------------- +from gi.repository import GdkPixbuf + +#------------------------------------------------------------------------- +# +# gramps modules +# +#------------------------------------------------------------------------- +from gramps.gen.const import THUMBSCALE, THUMBSCALE_LARGE, SIZE_LARGE +from gramps.gen.plug import Thumbnailer + +#------------------------------------------------------------------------- +# +# Constants +# +#------------------------------------------------------------------------- +LOG = logging.getLogger(".thumbnail") + + +class ImageThumb(Thumbnailer): + def is_supported(self, mime_type): + if mime_type: + return mime_type.startswith("image") + else: + return False + + def run(self, mime_type, src_file, dest_file, size, rectangle): + # build a thumbnail by scaling the image using GTK's built in + # routines. + try: + pixbuf = GdkPixbuf.Pixbuf.new_from_file(src_file) + width = pixbuf.get_width() + height = pixbuf.get_height() + + if rectangle is not None: + upper_x = min(rectangle[0], rectangle[2]) / 100.0 + lower_x = max(rectangle[0], rectangle[2]) / 100.0 + upper_y = min(rectangle[1], rectangle[3]) / 100.0 + lower_y = max(rectangle[1], rectangle[3]) / 100.0 + sub_x = int(upper_x * width) + sub_y = int(upper_y * height) + sub_width = int((lower_x - upper_x) * width) + sub_height = int((lower_y - upper_y) * height) + if sub_width > 0 and sub_height > 0: + pixbuf = pixbuf.new_subpixbuf(sub_x, sub_y, sub_width, sub_height) + width = sub_width + height = sub_height + + if size == SIZE_LARGE: + thumbscale = THUMBSCALE_LARGE + else: + thumbscale = THUMBSCALE + scale = thumbscale / (float(max(width, height))) + + scaled_width = int(width * scale) + scaled_height = int(height * scale) + + pixbuf = pixbuf.scale_simple( + scaled_width, scaled_height, GdkPixbuf.InterpType.BILINEAR + ) + pixbuf.savev(dest_file, "png", "", "") + return True + except Exception as err: + LOG.warning("Error scaling image down: %s", str(err)) + return False diff --git a/gramps/plugins/thumbnailer/thumb.gpr.py b/gramps/plugins/thumbnailer/thumb.gpr.py new file mode 100644 index 000000000..fd2541387 --- /dev/null +++ b/gramps/plugins/thumbnailer/thumb.gpr.py @@ -0,0 +1,59 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2022 Nick Hall +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +from gramps.gen.const import GRAMPS_LOCALE as glocale + +_ = glocale.translation.gettext + +MODULE_VERSION = "5.2" + +#------------------------------------------------------------------------ +# +# Default thumbnailers for Gramps +# +#------------------------------------------------------------------------ + +register( + THUMBNAILER, + id="gnomethumb", + name=_("Gnome Thumbnailer"), + description=_("Gnome Thumbnailer"), + version="1.0", + gramps_target_version=MODULE_VERSION, + status=STABLE, + fname="gnomethumb.py", + thumbnailer="GnomeThumb", + authors=["The Gramps project"], + authors_email=["http://gramps-project.org"], +) + +register( + THUMBNAILER, + id="imagethumb", + name=_("Image Thumbnailer"), + description=_("Image Thumbnailer"), + version="1.0", + gramps_target_version=MODULE_VERSION, + status=STABLE, + order=START, + fname="imagethumb.py", + thumbnailer="ImageThumb", + authors=["The Gramps project"], + authors_email=["http://gramps-project.org"], +) diff --git a/po/POTFILES.in b/po/POTFILES.in index 03bba45af..dc945c5a1 100755 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -713,6 +713,7 @@ gramps/plugins/textreport/summary.py gramps/plugins/textreport/tableofcontents.py gramps/plugins/textreport/tagreport.py gramps/plugins/textreport/textplugins.gpr.py +gramps/plugins/thumbnailer/thumb.gpr.py gramps/plugins/tool/changenames.glade gramps/plugins/tool/changenames.py gramps/plugins/tool/changetypes.glade diff --git a/po/POTFILES.skip b/po/POTFILES.skip index 17747b8bb..e5d02afc9 100644 --- a/po/POTFILES.skip +++ b/po/POTFILES.skip @@ -592,6 +592,12 @@ gramps/plugins/test/imports_test.py gramps/plugins/test/reports_test.py gramps/plugins/test/tools_test.py # +# Thumbnailers +# +gramps/plugins/thumbnailer/__init__.py +gramps/plugins/thumbnailer/gnomethumb.py +gramps/plugins/thumbnailer/imagethumb.py +# # Development tools # gramps/plugins/tool/__init__.py