Add support for thumbnailer plugins
This commit is contained in:
parent
a45d86f0ad
commit
b4536666b0
@ -163,11 +163,6 @@ PLUGINS_DIR = os.path.join(ROOT_DIR, "plugins")
|
|||||||
|
|
||||||
USE_TIPS = False
|
USE_TIPS = False
|
||||||
|
|
||||||
if sys.platform == 'win32':
|
|
||||||
USE_THUMBNAILER = False
|
|
||||||
else:
|
|
||||||
USE_THUMBNAILER = True
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# Paths to data files.
|
# Paths to data files.
|
||||||
@ -254,6 +249,8 @@ DOCUMENTERS = [
|
|||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
THUMBSCALE = 96.0
|
THUMBSCALE = 96.0
|
||||||
THUMBSCALE_LARGE = 180.0
|
THUMBSCALE_LARGE = 180.0
|
||||||
|
SIZE_NORMAL = 0
|
||||||
|
SIZE_LARGE = 1
|
||||||
XMLFILE = "data.gramps"
|
XMLFILE = "data.gramps"
|
||||||
NO_SURNAME = "(%s)" % _("none", "surname")
|
NO_SURNAME = "(%s)" % _("none", "surname")
|
||||||
NO_GIVEN = "(%s)" % _("none", "given-name")
|
NO_GIVEN = "(%s)" % _("none", "given-name")
|
||||||
|
@ -41,6 +41,7 @@ from ._export import ExportPlugin
|
|||||||
from ._docgenplugin import DocGenPlugin
|
from ._docgenplugin import DocGenPlugin
|
||||||
from ._manager import BasePluginManager
|
from ._manager import BasePluginManager
|
||||||
from ._gramplet import Gramplet
|
from ._gramplet import Gramplet
|
||||||
|
from ._thumbnailer import Thumbnailer
|
||||||
from .utils import *
|
from .utils import *
|
||||||
from ._options import (Options, OptionListCollection, OptionList,
|
from ._options import (Options, OptionListCollection, OptionList,
|
||||||
OptionHandler, MenuOptions)
|
OptionHandler, MenuOptions)
|
||||||
|
@ -448,6 +448,11 @@ class BasePluginManager:
|
|||||||
"""
|
"""
|
||||||
return self.__pgr.database_plugins()
|
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):
|
def get_external_opt_dict(self):
|
||||||
""" Return the dictionary of external options. """
|
""" Return the dictionary of external options. """
|
||||||
return self.__external_opt_dict
|
return self.__external_opt_dict
|
||||||
|
@ -73,8 +73,10 @@ GRAMPLET = 10
|
|||||||
SIDEBAR = 11
|
SIDEBAR = 11
|
||||||
DATABASE = 12
|
DATABASE = 12
|
||||||
RULE = 13
|
RULE = 13
|
||||||
|
THUMBNAILER = 14
|
||||||
PTYPE = [REPORT, QUICKREPORT, TOOL, IMPORT, EXPORT, DOCGEN, GENERAL,
|
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 = {
|
PTYPE_STR = {
|
||||||
REPORT: _('Report') ,
|
REPORT: _('Report') ,
|
||||||
QUICKREPORT: _('Quickreport'),
|
QUICKREPORT: _('Quickreport'),
|
||||||
@ -89,7 +91,8 @@ PTYPE_STR = {
|
|||||||
GRAMPLET: _('Gramplet'),
|
GRAMPLET: _('Gramplet'),
|
||||||
SIDEBAR: _('Sidebar'),
|
SIDEBAR: _('Sidebar'),
|
||||||
DATABASE: _('Database'),
|
DATABASE: _('Database'),
|
||||||
RULE: _('Rule')
|
RULE: _('Rule'),
|
||||||
|
THUMBNAILER: _('Thumbnailer'),
|
||||||
}
|
}
|
||||||
|
|
||||||
#possible report categories
|
#possible report categories
|
||||||
@ -371,6 +374,11 @@ class PluginData:
|
|||||||
The class (Person, Event, Media, etc.) the rule applies to.
|
The class (Person, Event, Media, etc.) the rule applies to.
|
||||||
.. attribute:: ruleclass
|
.. attribute:: ruleclass
|
||||||
The exact class name of the rule; ex: HasSourceParameter
|
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):
|
def __init__(self):
|
||||||
@ -452,6 +460,8 @@ class PluginData:
|
|||||||
#RULE attr
|
#RULE attr
|
||||||
self._ruleclass = None
|
self._ruleclass = None
|
||||||
self._namespace = None
|
self._namespace = None
|
||||||
|
#THUMBNAILER attr
|
||||||
|
self._thumbnailer = None
|
||||||
|
|
||||||
def _set_id(self, id):
|
def _set_id(self, id):
|
||||||
self._id = id
|
self._id = id
|
||||||
@ -948,10 +958,10 @@ class PluginData:
|
|||||||
sidebarclass = property(_get_sidebarclass, _set_sidebarclass)
|
sidebarclass = property(_get_sidebarclass, _set_sidebarclass)
|
||||||
menu_label = property(_get_menu_label, _set_menu_label)
|
menu_label = property(_get_menu_label, _set_menu_label)
|
||||||
|
|
||||||
#VIEW and SIDEBAR attributes
|
#VIEW, SIDEBAR and THUMBNAILER attributes
|
||||||
def _set_order(self, order):
|
def _set_order(self, order):
|
||||||
if not self._ptype in (VIEW, SIDEBAR):
|
if not self._ptype in (VIEW, SIDEBAR, THUMBNAILER):
|
||||||
raise ValueError('order may only be set for VIEW and SIDEBAR plugins')
|
raise ValueError('order may only be set for VIEW/SIDEBAR/THUMBNAILER plugins')
|
||||||
self._order = order
|
self._order = order
|
||||||
|
|
||||||
def _get_order(self):
|
def _get_order(self):
|
||||||
@ -1019,6 +1029,17 @@ class PluginData:
|
|||||||
ruleclass = property(_get_ruleclass, _set_ruleclass)
|
ruleclass = property(_get_ruleclass, _set_ruleclass)
|
||||||
namespace = property(_get_namespace, _set_namespace)
|
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():
|
def newplugin():
|
||||||
"""
|
"""
|
||||||
Function to create a new plugindata object, add it to list of
|
Function to create a new plugindata object, add it to list of
|
||||||
@ -1072,6 +1093,7 @@ def make_environment(**kwargs):
|
|||||||
'RELCALC': RELCALC,
|
'RELCALC': RELCALC,
|
||||||
'GRAMPLET': GRAMPLET,
|
'GRAMPLET': GRAMPLET,
|
||||||
'SIDEBAR': SIDEBAR,
|
'SIDEBAR': SIDEBAR,
|
||||||
|
'THUMBNAILER': THUMBNAILER,
|
||||||
'CATEGORY_TEXT': CATEGORY_TEXT,
|
'CATEGORY_TEXT': CATEGORY_TEXT,
|
||||||
'CATEGORY_DRAW': CATEGORY_DRAW,
|
'CATEGORY_DRAW': CATEGORY_DRAW,
|
||||||
'CATEGORY_CODE': CATEGORY_CODE,
|
'CATEGORY_CODE': CATEGORY_CODE,
|
||||||
@ -1389,6 +1411,12 @@ class PluginRegister:
|
|||||||
"""
|
"""
|
||||||
return self.type_plugins(RULE)
|
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):
|
def filter_load_on_reg(self):
|
||||||
"""
|
"""
|
||||||
Return a list of :class:`PluginData` that have load_on_reg == True
|
Return a list of :class:`PluginData` that have load_on_reg == True
|
||||||
|
67
gramps/gen/plug/_thumbnailer.py
Normal file
67
gramps/gen/plug/_thumbnailer.py
Normal file
@ -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
|
||||||
|
"""
|
@ -2,6 +2,7 @@
|
|||||||
# Gramps - a GTK+/GNOME based genealogy program
|
# Gramps - a GTK+/GNOME based genealogy program
|
||||||
#
|
#
|
||||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||||
|
# Copyright (C) 2022 Nick Hall
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# 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
|
# 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,
|
from gramps.gen.const import (ICON, IMAGE_DIR, THUMB_LARGE, THUMB_NORMAL,
|
||||||
THUMBSCALE, THUMBSCALE_LARGE, USE_THUMBNAILER)
|
SIZE_NORMAL, SIZE_LARGE)
|
||||||
from gramps.gen.constfunc import win
|
from gramps.gen.plug import BasePluginManager, START
|
||||||
|
from gramps.gen.mime import get_type
|
||||||
#-------------------------------------------------------------------------
|
|
||||||
#
|
|
||||||
# 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
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
@ -78,50 +62,25 @@ except (ImportError, KeyError) as msg:
|
|||||||
#
|
#
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
LOG = logging.getLogger(".thumbnail")
|
LOG = logging.getLogger(".thumbnail")
|
||||||
SIZE_NORMAL = 0
|
|
||||||
SIZE_LARGE = 1
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
THUMBNAILERS = []
|
||||||
#
|
def get_thumbnailers():
|
||||||
# __get_gconf_string
|
if len(THUMBNAILERS):
|
||||||
#
|
return THUMBNAILERS
|
||||||
#-------------------------------------------------------------------------
|
|
||||||
def __get_gconf_string(key):
|
|
||||||
"""
|
|
||||||
Attempt to retrieve a value from the GNOME gconf database based of the
|
|
||||||
passed key.
|
|
||||||
|
|
||||||
:param key: GCONF key
|
plugman = BasePluginManager.get_instance()
|
||||||
:type key: unicode
|
for pdata in plugman.get_reg_thumbnailers():
|
||||||
:returns: Value associated with the GCONF key
|
module = plugman.load_plugin(pdata)
|
||||||
:rtype: unicode
|
if not module:
|
||||||
"""
|
print("Error loading thumbnailer '%s': skipping content"
|
||||||
try:
|
% pdata.name)
|
||||||
val = CLIENT.get_string(key)
|
continue
|
||||||
except GLib.GError:
|
thumbnailer = getattr(module, pdata.thumbnailer)()
|
||||||
val = None
|
if pdata.order == START:
|
||||||
return str(val)
|
THUMBNAILERS.insert(0, thumbnailer)
|
||||||
|
else:
|
||||||
#-------------------------------------------------------------------------
|
THUMBNAILERS.append(thumbnailer)
|
||||||
#
|
return THUMBNAILERS
|
||||||
# __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
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
@ -176,48 +135,34 @@ def __create_thumbnail_image(src_file, mtype=None, rectangle=None,
|
|||||||
:rtype: bool
|
:rtype: bool
|
||||||
:returns: True is the thumbnailwas successfully generated
|
:returns: True is the thumbnailwas successfully generated
|
||||||
"""
|
"""
|
||||||
|
if mtype is None:
|
||||||
|
mtype = get_type(src_file)
|
||||||
filename = __build_thumb_path(src_file, rectangle, size)
|
filename = __build_thumb_path(src_file, rectangle, size)
|
||||||
|
return run_thumbnailer(mtype, src_file, filename, size, rectangle)
|
||||||
|
|
||||||
if mtype and not mtype.startswith('image/'):
|
def run_thumbnailer(mime_type, src_file, dest_file, size, rectangle=None):
|
||||||
# Not an image, so run the thumbnailer
|
"""
|
||||||
return run_thumbnailer(mtype, src_file, filename)
|
This function attempts to generate a thumbnail image. It runs the first
|
||||||
else:
|
thumbnailer plugin that supports the given mime type.
|
||||||
# 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:
|
:param mime_type: mime type of the source file
|
||||||
upper_x = min(rectangle[0], rectangle[2])/100.
|
:type mime_type: unicode
|
||||||
lower_x = max(rectangle[0], rectangle[2])/100.
|
:param src_file: filename of the source file
|
||||||
upper_y = min(rectangle[1], rectangle[3])/100.
|
:type src_file: unicode
|
||||||
lower_y = max(rectangle[1], rectangle[3])/100.
|
:param dest_file: destination file for the thumbnail image
|
||||||
sub_x = int(upper_x * width)
|
:type dest_file: unicode
|
||||||
sub_y = int(upper_y * height)
|
:param size: option parameters specifying the desired size of the
|
||||||
sub_width = int((lower_x - upper_x) * width)
|
thumbnail
|
||||||
sub_height = int((lower_y - upper_y) * height)
|
:type size: int
|
||||||
if sub_width > 0 and sub_height > 0:
|
:param rectangle: subsection rectangle (optional)
|
||||||
pixbuf = pixbuf.new_subpixbuf(sub_x, sub_y, sub_width, sub_height)
|
:type rectangle: tuple
|
||||||
width = sub_width
|
:returns: True if the thumbnail was successfully generated
|
||||||
height = sub_height
|
:rtype: bool
|
||||||
|
"""
|
||||||
if size == SIZE_LARGE:
|
for thumbnailer in get_thumbnailers():
|
||||||
thumbscale = THUMBSCALE_LARGE
|
if thumbnailer.is_supported(mime_type):
|
||||||
else:
|
if thumbnailer.run(mime_type, src_file, dest_file, size, rectangle):
|
||||||
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
|
return True
|
||||||
except Exception as err:
|
|
||||||
LOG.warning("Error scaling image down: %s", str(err))
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
@ -241,55 +186,6 @@ def find_mime_type_pixbuf(mime_type):
|
|||||||
return GdkPixbuf.Pixbuf.new_from_file(ICON)
|
return GdkPixbuf.Pixbuf.new_from_file(ICON)
|
||||||
except:
|
except:
|
||||||
return GdkPixbuf.Pixbuf.new_from_file(ICON)
|
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
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
|
@ -54,7 +54,7 @@ from gramps.gen.config import config
|
|||||||
from gramps.gen.utils.file import (media_path_full, media_path, relative_path,
|
from gramps.gen.utils.file import (media_path_full, media_path, relative_path,
|
||||||
find_file)
|
find_file)
|
||||||
from gramps.gen.mime import get_type
|
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 ..display import display_help
|
||||||
from ..managedwindow import ManagedWindow
|
from ..managedwindow import ManagedWindow
|
||||||
from ..dialog import ErrorDialog, WarningDialog
|
from ..dialog import ErrorDialog, WarningDialog
|
||||||
@ -214,10 +214,7 @@ class AddMedia(ManagedWindow):
|
|||||||
filename = find_file( filename)
|
filename = find_file( filename)
|
||||||
if filename:
|
if filename:
|
||||||
mtype = get_type(filename)
|
mtype = get_type(filename)
|
||||||
if mtype and mtype.startswith("image"):
|
image = get_thumbnail_image(filename, mtype)
|
||||||
image = self.scale_image(filename, THUMBSCALE)
|
|
||||||
else:
|
|
||||||
image = find_mime_type_pixbuf(mtype)
|
|
||||||
self.image.set_from_pixbuf(image)
|
self.image.set_from_pixbuf(image)
|
||||||
|
|
||||||
def _cleanup_on_exit(self):
|
def _cleanup_on_exit(self):
|
||||||
|
0
gramps/plugins/thumbnailer/__init__.py
Normal file
0
gramps/plugins/thumbnailer/__init__.py
Normal file
105
gramps/plugins/thumbnailer/gnomethumb.py
Normal file
105
gramps/plugins/thumbnailer/gnomethumb.py
Normal file
@ -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
|
101
gramps/plugins/thumbnailer/imagethumb.py
Normal file
101
gramps/plugins/thumbnailer/imagethumb.py
Normal file
@ -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
|
59
gramps/plugins/thumbnailer/thumb.gpr.py
Normal file
59
gramps/plugins/thumbnailer/thumb.gpr.py
Normal file
@ -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"],
|
||||||
|
)
|
@ -713,6 +713,7 @@ gramps/plugins/textreport/summary.py
|
|||||||
gramps/plugins/textreport/tableofcontents.py
|
gramps/plugins/textreport/tableofcontents.py
|
||||||
gramps/plugins/textreport/tagreport.py
|
gramps/plugins/textreport/tagreport.py
|
||||||
gramps/plugins/textreport/textplugins.gpr.py
|
gramps/plugins/textreport/textplugins.gpr.py
|
||||||
|
gramps/plugins/thumbnailer/thumb.gpr.py
|
||||||
gramps/plugins/tool/changenames.glade
|
gramps/plugins/tool/changenames.glade
|
||||||
gramps/plugins/tool/changenames.py
|
gramps/plugins/tool/changenames.py
|
||||||
gramps/plugins/tool/changetypes.glade
|
gramps/plugins/tool/changetypes.glade
|
||||||
|
@ -592,6 +592,12 @@ gramps/plugins/test/imports_test.py
|
|||||||
gramps/plugins/test/reports_test.py
|
gramps/plugins/test/reports_test.py
|
||||||
gramps/plugins/test/tools_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
|
# Development tools
|
||||||
#
|
#
|
||||||
gramps/plugins/tool/__init__.py
|
gramps/plugins/tool/__init__.py
|
||||||
|
Loading…
x
Reference in New Issue
Block a user