sugar-toolkit-gtk3/services/clipboard/typeregistry.py

846 lines
30 KiB
Python

import logging
from gettext import gettext as _
import urlparse
import posixpath
class FileType:
"""Generic base class for all classes representing clipboard item formats.
XXX This class's name is misleading; it represents a clipboard item
format and not a file type per se. Perhaps it should be renamed to
ClipboardItemFormat?
"""
def __init__(self, formats):
"""Initializer for this class (and all subclasses).
formats -- A dictionary of key-value pairs where the keys are MIME type
strings and the data values are the clipboard data in each
respective format. A reference to this dictionary is stored within
the object for possible use later.
This initializer is invoked when the clipboard item format object is
instantiated by the TypeRegistry class's get_type method.
"""
self._formats = formats
def get_name(self):
"""Returns a localized human-readable name for this clipboard item format.
This base-class implementation raises a NotImplementedError exception.
returns A localized string containing the clipboard item format name.
"""
raise NotImplementedError
def get_icon(self):
"""XXX Returns a "tag" to be used to get an icon for this clipboard item format (I think).
This base-class implementation raises a NotImplementedError exception.
returns XXX A string "tag" to be used to get the icon for this clipboard
item format (I think).
"""
raise NotImplementedError
def get_preview(self):
"""Returns an appropriate preview of the clipboard item data for this item format.
This base-class implementation raises a NotImplementedError exception.
returns A string containing the item preview.
"""
raise NotImplementedError
def get_activity(self):
"""Returns the activity identifier associated with this clipboard item format.
This base-class implementation raises a NotImplementedError exception.
returns A string containing the activity identifier.
"""
raise NotImplementedError
def matches_mime_type(cls, mime_type):
"""Class method to determine whether this class handles a given MIME type.
mime_type -- A string containing the MIME type.
XXX This base-class implementation currently raises a
NotImplementedError exception, but could (and should) be rewritten to
handle this functionality for *all* subclasses, since the code is
identical for all or most subclasses anyway.
returns True if this class handles the given MIME type, False otherwise.
"""
raise NotImplementedError
matches_mime_type = classmethod(matches_mime_type)
class TextFileType(FileType):
"""Represents the text clipboard item format.
XXX This class's name is misleading; it represents a clipboard item format
and not a file type per se.
"""
_types = set(['text/plain', 'UTF8_STRING', 'STRING'])
def get_name(self):
"""Returns a localized human-readable name for this clipboard item format.
returns A localized string containing the clipboard item format name.
"""
return _('Text snippet')
def get_icon(self):
"""XXX Returns a "tag" to be used to get an icon for this clipboard item format (I think).
returns XXX A string "tag" to be used to get the icon for this clipboard
item format (I think).
"""
return 'theme:object-text'
def get_preview(self):
"""Returns an appropriate preview of the clipboard item data for this item format.
For the text file format, this returns a text string containing up to
49 characters of the actual item's text.
returns A preview string containing up to 49 characters of the item's
text.
"""
for format, data in self._formats.iteritems():
if format in TextFileType._types:
text = data.get_data()
if len(text) < 50:
return text
else:
return text[0:49] + "..."
return ''
def get_activity(self):
"""Returns the activity identifier associated with this clipboard item format.
returns A string containing the activity identifier.
"""
return 'org.laptop.AbiWordActivity'
def matches_mime_type(cls, mime_type):
"""Class method to determine whether this class handles a given MIME type.
mime_type -- A string containing the MIME type.
XXX This subclass method is unnecessary; a single base class method
in the FileType class would be sufficient to handle all or most
subclasses, since the code is identical for all or most subclasses
anyway.
returns True if this class handles the given MIME type, False otherwise.
"""
return mime_type in cls._types
matches_mime_type = classmethod(matches_mime_type)
class ImageFileType(FileType):
"""Represents the "image" clipboard item format.
This clipboard item format represents *any* image format, including JPEG,
GIF, PNG and TIFF formats.
XXX This class's name is misleading; it represents a clipboard item format
and not a file type per se.
"""
_types = set(['image/jpeg', 'image/gif', 'image/png', 'image/tiff'])
def get_name(self):
"""Returns a localized human-readable name for this clipboard item format.
returns A localized string containing the clipboard item format name.
"""
return _('Image')
def get_icon(self):
"""XXX Returns a "tag" to be used to get an icon for this clipboard item format (I think).
returns XXX A string "tag" to be used to get the icon for this clipboard
item format (I think).
"""
return 'theme:object-image'
def get_preview(self):
"""Returns an appropriate preview of the clipboard item data for this item format.
XXX Currently returns an empty string.
returns A string containing the item preview.
"""
return ''
def get_activity(self):
"""Returns the activity identifier associated with this clipboard item format.
returns A string containing the activity identifier.
"""
return ''
def matches_mime_type(cls, mime_type):
"""Class method to determine whether this class handles a given MIME type.
mime_type -- A string containing the MIME type.
XXX This subclass method is unnecessary; a single base class method
in the FileType class would be sufficient to handle all or most
subclasses, since the code is identical for all or most subclasses
anyway.
returns True if this class handles the given MIME type, False otherwise.
"""
return mime_type in cls._types
matches_mime_type = classmethod(matches_mime_type)
class UriFileType(FileType):
"""Represents the URI clipboard item format.
Not to be confused with the multiple-URI UriListFileType class.
XXX This class's name is misleading; it represents a clipboard item format
and not a file type per se.
"""
_types = set(['_NETSCAPE_URL'])
def get_name(self):
"""Returns a localized human-readable name for this clipboard item format.
returns A localized string containing the clipboard item format name.
"""
return _('Web Page')
def get_icon(self):
"""XXX Returns a "tag" to be used to get an icon for this clipboard item format (I think).
returns XXX A string "tag" to be used to get the icon for this clipboard
item format (I think).
"""
return 'theme:object-link'
def get_preview(self):
"""Returns an appropriate preview of the clipboard item data for this item format.
For the URI clipboard item format, this is the URI itself.
returns A string containing the item preview, in this case the URI itself.
"""
for format, data in self._formats.iteritems():
if format in UriFileType._types:
string = data.get_data()
title = string.split("\n")[1]
return title
return ''
def get_activity(self):
"""Returns the activity identifier associated with this clipboard item format.
returns A string containing the activity identifier.
"""
return ''
def matches_mime_type(cls, mime_type):
"""Class method to determine whether this class handles a given MIME type.
mime_type -- A string containing the MIME type.
XXX This subclass method is unnecessary; a single base class method
in the FileType class would be sufficient to handle all or most
subclasses, since the code is identical for all or most subclasses
anyway.
returns True if this class handles the given MIME type, False otherwise.
"""
return mime_type in cls._types
matches_mime_type = classmethod(matches_mime_type)
class PdfFileType(FileType):
"""Represents the PDF clipboard item format.
XXX This class's name is misleading; it represents a clipboard item format
and not a file type per se.
"""
_types = set(['application/pdf', 'application/x-pdf'])
def get_name(self):
"""Returns a localized human-readable name for this clipboard item format.
returns A localized string containing the clipboard item format name.
"""
return _('PDF file')
def get_icon(self):
"""XXX Returns a "tag" to be used to get an icon for this clipboard item format (I think).
returns XXX A string "tag" to be used to get the icon for this clipboard
item format (I think).
"""
return 'theme:object-text'
def get_preview(self):
"""Returns an appropriate preview of the clipboard item data for this item format.
XXX Currently returns an empty string.
returns A string containing the item preview.
"""
return ''
def get_activity(self):
"""Returns the activity identifier associated with this clipboard item format.
returns A string containing the activity identifier.
"""
return 'org.laptop.sugar.Xbook'
def matches_mime_type(cls, mime_type):
"""Class method to determine whether this class handles a given MIME type.
mime_type -- A string containing the MIME type.
XXX This subclass method is unnecessary; a single base class method
in the FileType class would be sufficient to handle all or most
subclasses, since the code is identical for all or most subclasses
anyway.
returns True if this class handles the given MIME type, False otherwise.
"""
return mime_type in cls._types
matches_mime_type = classmethod(matches_mime_type)
class MsWordFileType(FileType):
"""Represents the MS Word clipboard item format (*cringe*).
XXX This class's name is misleading; it represents a clipboard item format
and not a file type per se.
"""
_types = set(['application/msword'])
def get_name(self):
"""Returns a localized human-readable name for this clipboard item format.
returns A localized string containing the clipboard item format name.
"""
return _('MS Word file')
def get_icon(self):
"""XXX Returns a "tag" to be used to get an icon for this clipboard item format (I think).
returns XXX A string "tag" to be used to get the icon for this clipboard
item format (I think).
"""
return 'theme:object-text'
def get_preview(self):
"""Returns an appropriate preview of the clipboard item data for this item format.
XXX Currently returns an empty string.
returns A string containing the item preview.
"""
return ''
def get_activity(self):
"""Returns the activity identifier associated with this clipboard item format.
returns A string containing the activity identifier.
"""
return 'org.laptop.AbiWordActivity'
def matches_mime_type(cls, mime_type):
"""Class method to determine whether this class handles a given MIME type.
mime_type -- A string containing the MIME type.
XXX This subclass method is unnecessary; a single base class method
in the FileType class would be sufficient to handle all or most
subclasses, since the code is identical for all or most subclasses
anyway.
returns True if this class handles the given MIME type, False otherwise.
"""
return mime_type in cls._types
matches_mime_type = classmethod(matches_mime_type)
class RtfFileType(TextFileType):
"""Represents the RTF clipboard item format (a subclass of TextFileType).
XXX This class's name is misleading; it represents a clipboard item format
and not a file type per se.
"""
_types = set(['application/rtf', 'text/rtf'])
def get_name(self):
"""Returns a localized human-readable name for this clipboard item format.
returns A localized string containing the clipboard item format name.
"""
return _('RTF file')
def matches_mime_type(cls, mime_type):
"""Class method to determine whether this class handles a given MIME type.
mime_type -- A string containing the MIME type.
XXX This subclass method is unnecessary; a single base class method
in the FileType class would be sufficient to handle all or most
subclasses, since the code is identical for all or most subclasses
anyway.
returns True if this class handles the given MIME type, False otherwise.
"""
return mime_type in cls._types
matches_mime_type = classmethod(matches_mime_type)
class AbiwordFileType(TextFileType):
"""Represents the AbiWord clipboard item format.
(XXX This class's name is misleading; it represents a clipboard item format,
not a file type per se.)
(XXX AbiWord format is a full word processing format, like the OO Text and MS Word
formats, and should not be a subclass of TextFileType! Otherwise the OO Text and
MS Word format types should also be made subclasses of TextFileType.)
"""
_types = set(['application/x-abiword'])
def get_name(self):
"""Returns a localized human-readable name for this clipboard item format.
returns A localized string containing the clipboard item format name.
"""
return _('Abiword file')
def matches_mime_type(cls, mime_type):
"""Class method to determine whether this class handles a given MIME type.
mime_type -- A string containing the MIME type.
XXX This subclass method is unnecessary; a single base class method
in the FileType class would be sufficient to handle all or most
subclasses, since the code is identical for all or most subclasses
anyway.
returns True if this class handles the given MIME type, False otherwise.
"""
return mime_type in cls._types
matches_mime_type = classmethod(matches_mime_type)
class SqueakProjectFileType(FileType):
"""Represents the Squeak Project clipboard item format.
XXX This class's name is misleading; it represents a clipboard item format
and not a file type per se.
"""
_types = set(['application/x-squeak-project'])
def get_name(self):
"""Returns a localized human-readable name for this clipboard item format.
returns A localized string containing the clipboard item format name.
"""
return _('Squeak project')
def get_icon(self):
"""XXX Returns a "tag" to be used to get an icon for this clipboard item format (I think).
returns XXX A string "tag" to be used to get the icon for this clipboard
item format (I think).
"""
return 'theme:object-squeak-project'
def get_preview(self):
"""Returns an appropriate preview of the clipboard item data for this item format.
XXX Currently returns an empty string.
returns A string containing the item preview.
"""
return ''
def get_activity(self):
"""Returns the activity identifier associated with this clipboard item format.
returns A string containing the activity identifier.
"""
return 'org.vpri.EtoysActivity'
def matches_mime_type(cls, mime_type):
"""Class method to determine whether this class handles a given MIME type.
mime_type -- A string containing the MIME type.
XXX This subclass method is unnecessary; a single base class method
in the FileType class would be sufficient to handle all or most
subclasses, since the code is identical for all or most subclasses
anyway.
returns True if this class handles the given MIME type, False otherwise.
"""
return mime_type in cls._types
matches_mime_type = classmethod(matches_mime_type)
class OOTextFileType(FileType):
"""Represents the OpenDocument Text (OpenOffice.org Writer) clipboard item format.
Note to the uninitiated: OpenDocument Text is a full word processing format,
not a simple text file.
XXX This class's name is misleading; it represents a clipboard item format
and not a file type per se.
"""
_types = set(['application/vnd.oasis.opendocument.text'])
def get_name(self):
"""Returns a localized human-readable name for this clipboard item format.
returns A localized string containing the clipboard item format name.
"""
return _('OpenOffice text file')
def get_icon(self):
"""XXX Returns a "tag" to be used to get an icon for this clipboard item format (I think).
returns XXX A string "tag" to be used to get the icon for this clipboard
item format (I think).
"""
return 'theme:object-text'
def get_preview(self):
"""Returns an appropriate preview of the clipboard item data for this item format.
XXX Currently returns an empty string.
returns A string containing the item preview.
"""
return ''
def get_activity(self):
"""Returns the activity identifier associated with this clipboard item format.
returns A string containing the activity identifier.
"""
return 'org.laptop.AbiWordActivity'
def matches_mime_type(cls, mime_type):
"""Class method to determine whether this class handles a given MIME type.
mime_type -- A string containing the MIME type.
XXX This subclass method is unnecessary; a single base class method
in the FileType class would be sufficient to handle all or most
subclasses, since the code is identical for all or most subclasses
anyway.
returns True if this class handles the given MIME type, False otherwise.
"""
return mime_type in cls._types
matches_mime_type = classmethod(matches_mime_type)
class UriListFileType(FileType):
"""Represents the URI-list clipboard item format.
Not to be confused with the single-URI UriFileType class.
XXX This class's name is misleading; it represents a clipboard item format
and not a file type per se.
"""
_types = set(['text/uri-list'])
def _is_image(self):
"""Determines whether this URI list represents an image.
Called by the get_name and get_icon methods. For this URI list to be
considered to represent an image, it must fulfil two criteria: (1) it
must have only one URI in it, and (2) the URI must end with an extension
indicating an image type (currently ".jpg", ".jpeg", ".gif", ".png", or
".svg").
returns True if there is one URI in the list and it represents an image,
False otherwise.
"""
uris = self._formats['text/uri-list'].get_data().split('\n')
if len(uris) == 1:
uri = urlparse.urlparse(uris[0])
ext = posixpath.splitext(uri.path)[1]
logging.debug(ext)
# FIXME: Bad hack, the type registry should treat text/uri-list as a special case.
if ext in ['.jpg', '.jpeg', '.gif', '.png', '.svg']:
return True
return False
def get_name(self):
"""Returns a localized human-readable name for this clipboard item format.
returns A localized string containing the clipboard item format name.
"""
if self._is_image():
return _('Image')
else:
return _('File')
def get_icon(self):
"""XXX Returns a "tag" to be used to get an icon for this clipboard item format (I think).
returns XXX A string "tag" to be used to get the icon for this clipboard
item format (I think).
"""
if self._is_image():
return 'theme:object-image'
else:
return 'theme:stock-missing'
def get_preview(self):
"""Returns an appropriate preview of the clipboard item data for this item format.
XXX Currently returns an empty string.
returns A string containing the item preview.
"""
return ''
def get_activity(self):
"""Returns the activity identifier associated with this clipboard item format.
returns A string containing the activity identifier.
"""
return ''
def matches_mime_type(cls, mime_type):
"""Class method to determine whether this class handles a given MIME type.
mime_type -- A string containing the MIME type.
XXX This subclass method is unnecessary; a single base class method
in the FileType class would be sufficient to handle all or most
subclasses, since the code is identical for all or most subclasses
anyway.
returns True if this class handles the given MIME type, False otherwise.
"""
return mime_type in cls._types
matches_mime_type = classmethod(matches_mime_type)
class XoFileType(FileType):
"""Represents the "xo" (OLPC package) clipboard item format.
XXX This class's name is misleading; it represents a clipboard item format
and not a file type per se.
"""
_types = set(['application/vnd.olpc-x-sugar'])
def get_name(self):
"""Returns a localized human-readable name for this clipboard item format.
returns A localized string containing the clipboard item format name.
"""
return _('Activity package')
def get_icon(self):
"""XXX Returns a "tag" to be used to get an icon for this clipboard item format (I think).
returns XXX A string "tag" to be used to get the icon for this clipboard
item format (I think).
"""
return 'theme:stock-missing'
def get_preview(self):
"""Returns an appropriate preview of the clipboard item data for this item format.
XXX Currently returns an empty string.
returns A string containing the item preview.
"""
return ''
def get_activity(self):
"""Returns the activity identifier associated with this clipboard item format.
returns A string containing the activity identifier.
"""
return ''
def matches_mime_type(cls, mime_type):
"""Class method to determine whether this class handles a given MIME type.
mime_type -- A string containing the MIME type.
XXX This subclass method is unnecessary; a single base class method
in the FileType class would be sufficient to handle all or most
subclasses, since the code is identical for all or most subclasses
anyway.
returns True if this class handles the given MIME type, False otherwise.
"""
return mime_type in cls._types
matches_mime_type = classmethod(matches_mime_type)
class UnknownFileType(FileType):
"""Represents an unknown clipboard item format.
XXX This class's name is misleading; it represents a clipboard item format
and not a file type per se.
"""
def get_name(self):
"""Returns a localized human-readable name for this clipboard item format.
Since this clipboard item format is unknown, the format name will be
simply "Object" or something to that effect.
returns A localized string containing the clipboard item format name.
"""
return _('Object')
def get_icon(self):
"""XXX Returns a "tag" to be used to get an icon for this clipboard item format (I think).
returns XXX A string "tag" to be used to get the icon for this clipboard
item format (I think).
"""
return 'theme:stock-missing'
def get_preview(self):
"""Returns a "preview" for this clipboard item format.
Since this clipboard item format is unknown, there can be no preview for
it, so the "preview" will be an empty string.
returns An empty string, since there can be no preview for an unknown
clipboard item format.
"""
return ''
def get_activity(self):
"""Returns the activity identifier associated with this clipboard item format.
Since this clipboard item format is unknown, there can be no activity
associated with it, so the activity identifier will be an empty string.
returns A string containing the activity identifier (an empty string in
this case).
"""
return ''
def matches_mime_type(cls, mime_type):
"""Class method to determine whether this class handles a given MIME type.
mime_type -- A string containing the MIME type.
Always returns true, since UnknownFileType is the clipboard item format
class of last resort and must be used if no other class handles the
given MIME type.
returns True if this class handles the given MIME type (always true in
this case).
"""
return true
matches_mime_type = classmethod(matches_mime_type)
class TypeRegistry:
"""Represents a registry of all clipboard item formats.
There will be one single global instantiation of this object, accessible via
the global typeregistry.get_instance method.
"""
def __init__(self):
"""Initializes the registry.
"""
self._types = []
self._types.append(PdfFileType)
self._types.append(MsWordFileType)
self._types.append(RtfFileType)
self._types.append(OOTextFileType)
self._types.append(UriListFileType)
self._types.append(UriFileType)
self._types.append(ImageFileType)
self._types.append(AbiwordFileType)
self._types.append(TextFileType)
self._types.append(SqueakProjectFileType)
self._types.append(XoFileType)
def get_type(self, formats):
"""Returns a matching clipboard item format object for the passed-in clipboard data.
formats -- A dictionary of key-value pairs where the keys are MIME type
strings and the data values are the clipboard data in each
respective format.
A reference to the given clipboard data format dictionary is stored
within the returned object for possible use later.
XXX The order of the clipboard item formats in the TypeRegistry object's
internal list matters. For example, if clipboard item data is available
in both MS Word and OO Text formats, the MS Word type will currently be
matched first, and therefore an MsWordFileType object will be returned.
Is this really what is desired? The ordering should definitely be given
some thought.
returns A clipboard item format object of a type matching one of the
MIME type keys in the formats dictionary, or an UnknownFileType
object if none of the other types is appropriate.
"""
for file_type in self._types:
for format, data in formats.iteritems():
if file_type.matches_mime_type(format):
return file_type(formats)
return UnknownFileType(formats)
_type_registry = None
def get_instance():
"""Returns the global clipboard item format registry object (global method).
Returns a reference to the global clipboard item format registry object,
instantiating it first if necessary.
returns A TypeRegistry object representing the global clipboard item format
registry.
"""
global _type_registry
if not _type_registry:
_type_registry = TypeRegistry()
return _type_registry