mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Add support for file type plugins to calibre, so that 3rd party developers can customize calibre.
This commit is contained in:
parent
4d82cb5196
commit
660fa430f8
@ -2,7 +2,7 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
__appname__ = 'calibre'
|
__appname__ = 'calibre'
|
||||||
__version__ = '0.4.117'
|
__version__ = '0.4.118'
|
||||||
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
||||||
'''
|
'''
|
||||||
Various run time constants.
|
Various run time constants.
|
||||||
|
@ -52,6 +52,12 @@ class Plugin(object):
|
|||||||
#: The earliest version of calibre this plugin requires
|
#: The earliest version of calibre this plugin requires
|
||||||
minimum_calibre_version = (0, 4, 118)
|
minimum_calibre_version = (0, 4, 118)
|
||||||
|
|
||||||
|
#: If False, the user will not be able to disable this plugin. Use with
|
||||||
|
#: care.
|
||||||
|
can_be_disabled = True
|
||||||
|
|
||||||
|
#: The type of this plugin. Used for categorizing plugins in the
|
||||||
|
#: GUI
|
||||||
type = _('Base')
|
type = _('Base')
|
||||||
|
|
||||||
def __init__(self, plugin_path):
|
def __init__(self, plugin_path):
|
||||||
@ -71,8 +77,7 @@ class Plugin(object):
|
|||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@classmethod
|
def customization_help(self, gui=False):
|
||||||
def customization_help(cls):
|
|
||||||
'''
|
'''
|
||||||
Return a string giving help on how to customize this plugin.
|
Return a string giving help on how to customize this plugin.
|
||||||
By default raise a :class:`NotImplementedError`, which indicates that
|
By default raise a :class:`NotImplementedError`, which indicates that
|
||||||
@ -85,6 +90,8 @@ class Plugin(object):
|
|||||||
|
|
||||||
Site customization could be anything, for example, the path to
|
Site customization could be anything, for example, the path to
|
||||||
a needed binary on the user's computer.
|
a needed binary on the user's computer.
|
||||||
|
|
||||||
|
:param gui: If True return HTML help, otherwise return plain text help.
|
||||||
'''
|
'''
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@ -99,10 +106,9 @@ class Plugin(object):
|
|||||||
'''
|
'''
|
||||||
return PersistentTemporaryFile(suffix)
|
return PersistentTemporaryFile(suffix)
|
||||||
|
|
||||||
@classmethod
|
def is_customizable(self):
|
||||||
def is_customizable(cls):
|
|
||||||
try:
|
try:
|
||||||
cls.customization_help()
|
self.customization_help()
|
||||||
return True
|
return True
|
||||||
except NotImplementedError:
|
except NotImplementedError:
|
||||||
return False
|
return False
|
||||||
|
@ -92,10 +92,12 @@ def reread_filetype_plugins():
|
|||||||
_on_postprocess[ft].append(plugin)
|
_on_postprocess[ft].append(plugin)
|
||||||
|
|
||||||
|
|
||||||
def _run_filetype_plugins(path_to_file, ft, occasion='preprocess'):
|
def _run_filetype_plugins(path_to_file, ft=None, occasion='preprocess'):
|
||||||
occasion = {'import':_on_import, 'preprocess':_on_preprocess,
|
occasion = {'import':_on_import, 'preprocess':_on_preprocess,
|
||||||
'postprocess':_on_postprocess}[occasion]
|
'postprocess':_on_postprocess}[occasion]
|
||||||
customization = config['plugin_customization']
|
customization = config['plugin_customization']
|
||||||
|
if ft is None:
|
||||||
|
ft = os.path.splitext(path_to_file)[-1].lower().replace('.', '')
|
||||||
nfp = path_to_file
|
nfp = path_to_file
|
||||||
for plugin in occasion.get(ft, []):
|
for plugin in occasion.get(ft, []):
|
||||||
if is_disabled(plugin):
|
if is_disabled(plugin):
|
||||||
@ -107,6 +109,10 @@ def _run_filetype_plugins(path_to_file, ft, occasion='preprocess'):
|
|||||||
except:
|
except:
|
||||||
print 'Running file type plugin %s failed with traceback:'%plugin.name
|
print 'Running file type plugin %s failed with traceback:'%plugin.name
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
x = lambda j : os.path.normpath(os.path.normcase(j))
|
||||||
|
if occasion == 'postprocess' and x(nfp) != x(path_to_file):
|
||||||
|
shutil.copyfile(nfp, path_to_file)
|
||||||
|
nfp = path_to_file
|
||||||
return nfp
|
return nfp
|
||||||
|
|
||||||
run_plugins_on_import = functools.partial(_run_filetype_plugins,
|
run_plugins_on_import = functools.partial(_run_filetype_plugins,
|
||||||
@ -119,7 +125,7 @@ run_plugins_on_postprocess = functools.partial(_run_filetype_plugins,
|
|||||||
|
|
||||||
def initialize_plugin(plugin, path_to_zip_file):
|
def initialize_plugin(plugin, path_to_zip_file):
|
||||||
try:
|
try:
|
||||||
plugin(path_to_zip_file)
|
return plugin(path_to_zip_file)
|
||||||
except Exception:
|
except Exception:
|
||||||
print 'Failed to initialize plugin:', plugin.name, plugin.version
|
print 'Failed to initialize plugin:', plugin.name, plugin.version
|
||||||
tb = traceback.format_exc()
|
tb = traceback.format_exc()
|
||||||
@ -130,9 +136,9 @@ def initialize_plugin(plugin, path_to_zip_file):
|
|||||||
def add_plugin(path_to_zip_file):
|
def add_plugin(path_to_zip_file):
|
||||||
make_config_dir()
|
make_config_dir()
|
||||||
plugin = load_plugin(path_to_zip_file)
|
plugin = load_plugin(path_to_zip_file)
|
||||||
initialize_plugin(plugin, path_to_zip_file)
|
plugin = initialize_plugin(plugin, path_to_zip_file)
|
||||||
plugins = config['plugins']
|
plugins = config['plugins']
|
||||||
zfp = os.path.join(plugin_dir, 'name.zip')
|
zfp = os.path.join(plugin_dir, plugin.name+'.zip')
|
||||||
if os.path.exists(zfp):
|
if os.path.exists(zfp):
|
||||||
os.remove(zfp)
|
os.remove(zfp)
|
||||||
shutil.copyfile(path_to_zip_file, zfp)
|
shutil.copyfile(path_to_zip_file, zfp)
|
||||||
@ -151,6 +157,9 @@ def find_plugin(name):
|
|||||||
|
|
||||||
def disable_plugin(plugin_or_name):
|
def disable_plugin(plugin_or_name):
|
||||||
x = getattr(plugin_or_name, 'name', plugin_or_name)
|
x = getattr(plugin_or_name, 'name', plugin_or_name)
|
||||||
|
plugin = find_plugin(x)
|
||||||
|
if not plugin.can_be_disabled:
|
||||||
|
raise ValueError('Plugin %s cannot be disabled'%x)
|
||||||
dp = config['disabled_plugins']
|
dp = config['disabled_plugins']
|
||||||
dp.add(x)
|
dp.add(x)
|
||||||
config['disabled_plugins'] = dp
|
config['disabled_plugins'] = dp
|
||||||
@ -168,7 +177,7 @@ def initialize_plugins():
|
|||||||
for zfp in list(config['plugins'].values()) + builtin_plugins:
|
for zfp in list(config['plugins'].values()) + builtin_plugins:
|
||||||
try:
|
try:
|
||||||
plugin = load_plugin(zfp) if not isinstance(zfp, type) else zfp
|
plugin = load_plugin(zfp) if not isinstance(zfp, type) else zfp
|
||||||
initialize_plugin(plugin, zfp if not isinstance(zfp, type) else zfp)
|
plugin = initialize_plugin(plugin, zfp if not isinstance(zfp, type) else zfp)
|
||||||
_initialized_plugins.append(plugin)
|
_initialized_plugins.append(plugin)
|
||||||
except:
|
except:
|
||||||
print 'Failed to initialize plugin...'
|
print 'Failed to initialize plugin...'
|
||||||
@ -199,6 +208,14 @@ def option_parser():
|
|||||||
def initialized_plugins():
|
def initialized_plugins():
|
||||||
return _initialized_plugins
|
return _initialized_plugins
|
||||||
|
|
||||||
|
def customize_plugin(plugin, custom):
|
||||||
|
d = config['plugin_customization']
|
||||||
|
d[plugin.name] = custom.strip()
|
||||||
|
config['plugin_customization'] = d
|
||||||
|
|
||||||
|
def plugin_customization(plugin):
|
||||||
|
return config['plugin_customization'].get(plugin.name, '')
|
||||||
|
|
||||||
def main(args=sys.argv):
|
def main(args=sys.argv):
|
||||||
parser = option_parser()
|
parser = option_parser()
|
||||||
if len(args) < 2:
|
if len(args) < 2:
|
||||||
@ -214,7 +231,7 @@ def main(args=sys.argv):
|
|||||||
if plugin is None:
|
if plugin is None:
|
||||||
print 'No plugin with the name %s exists'%name
|
print 'No plugin with the name %s exists'%name
|
||||||
return 1
|
return 1
|
||||||
config['plugin_customization'][plugin.name] = custom.strip()
|
customize_plugin(plugin, custom)
|
||||||
if opts.enable_plugin is not None:
|
if opts.enable_plugin is not None:
|
||||||
enable_plugin(opts.enable_plugin.strip())
|
enable_plugin(opts.enable_plugin.strip())
|
||||||
if opts.disable_plugin is not None:
|
if opts.disable_plugin is not None:
|
||||||
@ -227,7 +244,7 @@ def main(args=sys.argv):
|
|||||||
print fmt%(
|
print fmt%(
|
||||||
plugin.type, plugin.name,
|
plugin.type, plugin.name,
|
||||||
plugin.version, is_disabled(plugin),
|
plugin.version, is_disabled(plugin),
|
||||||
config['plugin_customization'].get(plugin.name, '')
|
plugin_customization(plugin)
|
||||||
)
|
)
|
||||||
print '\t', plugin.description
|
print '\t', plugin.description
|
||||||
if plugin.is_customizable():
|
if plugin.is_customizable():
|
||||||
|
@ -18,6 +18,7 @@ from calibre.ptempfile import TemporaryDirectory
|
|||||||
from calibre.ebooks.metadata import MetaInformation
|
from calibre.ebooks.metadata import MetaInformation
|
||||||
from calibre.ebooks.metadata.opf2 import OPFCreator
|
from calibre.ebooks.metadata.opf2 import OPFCreator
|
||||||
from calibre.utils.zipfile import ZipFile
|
from calibre.utils.zipfile import ZipFile
|
||||||
|
from calibre.customize.ui import run_plugins_on_preprocess
|
||||||
|
|
||||||
def lit2opf(path, tdir, opts):
|
def lit2opf(path, tdir, opts):
|
||||||
from calibre.ebooks.lit.reader import LitReader
|
from calibre.ebooks.lit.reader import LitReader
|
||||||
@ -118,6 +119,7 @@ def unarchive(path, tdir):
|
|||||||
|
|
||||||
def any2epub(opts, path, notification=None, create_epub=True,
|
def any2epub(opts, path, notification=None, create_epub=True,
|
||||||
oeb_cover=False, extract_to=None):
|
oeb_cover=False, extract_to=None):
|
||||||
|
path = run_plugins_on_preprocess(path)
|
||||||
ext = os.path.splitext(path)[1]
|
ext = os.path.splitext(path)[1]
|
||||||
if not ext:
|
if not ext:
|
||||||
raise ValueError('Unknown file type: '+path)
|
raise ValueError('Unknown file type: '+path)
|
||||||
|
@ -48,6 +48,7 @@ from calibre.ebooks.epub import initialize_container, PROFILES
|
|||||||
from calibre.ebooks.epub.split import split
|
from calibre.ebooks.epub.split import split
|
||||||
from calibre.ebooks.epub.fonts import Rationalizer
|
from calibre.ebooks.epub.fonts import Rationalizer
|
||||||
from calibre.constants import preferred_encoding
|
from calibre.constants import preferred_encoding
|
||||||
|
from calibre.customize.ui import run_plugins_on_postprocess
|
||||||
from calibre import walk, CurrentDir, to_unicode
|
from calibre import walk, CurrentDir, to_unicode
|
||||||
|
|
||||||
content = functools.partial(os.path.join, u'content')
|
content = functools.partial(os.path.join, u'content')
|
||||||
@ -386,6 +387,7 @@ def convert(htmlfile, opts, notification=None, create_epub=True,
|
|||||||
epub = initialize_container(opts.output)
|
epub = initialize_container(opts.output)
|
||||||
epub.add_dir(tdir)
|
epub.add_dir(tdir)
|
||||||
epub.close()
|
epub.close()
|
||||||
|
run_plugins_on_postprocess(opts.output, 'epub')
|
||||||
logger.info(_('Output written to ')+opts.output)
|
logger.info(_('Output written to ')+opts.output)
|
||||||
|
|
||||||
if opts.show_opf:
|
if opts.show_opf:
|
||||||
|
@ -34,6 +34,7 @@ from calibre import LoggingInterface
|
|||||||
from calibre import plugins
|
from calibre import plugins
|
||||||
msdes, msdeserror = plugins['msdes']
|
msdes, msdeserror = plugins['msdes']
|
||||||
import calibre.ebooks.lit.mssha1 as mssha1
|
import calibre.ebooks.lit.mssha1 as mssha1
|
||||||
|
from calibre.customize.ui import run_plugins_on_postprocess
|
||||||
|
|
||||||
__all__ = ['LitWriter']
|
__all__ = ['LitWriter']
|
||||||
|
|
||||||
@ -734,6 +735,7 @@ def oeb2lit(opts, opfpath):
|
|||||||
lit = LitWriter(OEBBook(opfpath, logger=logger), logger=logger)
|
lit = LitWriter(OEBBook(opfpath, logger=logger), logger=logger)
|
||||||
with open(litpath, 'wb') as f:
|
with open(litpath, 'wb') as f:
|
||||||
lit.dump(f)
|
lit.dump(f)
|
||||||
|
run_plugins_on_postprocess(litpath, 'lit')
|
||||||
logger.log_info(_('Output written to ')+litpath)
|
logger.log_info(_('Output written to ')+litpath)
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,6 +18,8 @@ from calibre.ebooks.lrf.epub.convert_from import process_file as epub2lrf
|
|||||||
from calibre.ebooks.lrf.mobi.convert_from import process_file as mobi2lrf
|
from calibre.ebooks.lrf.mobi.convert_from import process_file as mobi2lrf
|
||||||
from calibre.ebooks.lrf.fb2.convert_from import process_file as fb22lrf
|
from calibre.ebooks.lrf.fb2.convert_from import process_file as fb22lrf
|
||||||
|
|
||||||
|
from calibre.customize.ui import run_plugins_on_postprocess, run_plugins_on_preprocess
|
||||||
|
|
||||||
def largest_file(files):
|
def largest_file(files):
|
||||||
maxsize, file = 0, None
|
maxsize, file = 0, None
|
||||||
for f in files:
|
for f in files:
|
||||||
@ -108,6 +110,7 @@ def odt2lrf(path, options, logger):
|
|||||||
|
|
||||||
def process_file(path, options, logger=None):
|
def process_file(path, options, logger=None):
|
||||||
path = os.path.abspath(os.path.expanduser(path))
|
path = os.path.abspath(os.path.expanduser(path))
|
||||||
|
path = run_plugins_on_preprocess(path)
|
||||||
tdir = None
|
tdir = None
|
||||||
if logger is None:
|
if logger is None:
|
||||||
level = logging.DEBUG if options.verbose else logging.INFO
|
level = logging.DEBUG if options.verbose else logging.INFO
|
||||||
@ -160,6 +163,7 @@ def process_file(path, options, logger=None):
|
|||||||
if not convertor:
|
if not convertor:
|
||||||
raise UnknownFormatError(_('Converting from %s to LRF is not supported.')%ext)
|
raise UnknownFormatError(_('Converting from %s to LRF is not supported.')%ext)
|
||||||
convertor(path, options, logger)
|
convertor(path, options, logger)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
os.chdir(cwd)
|
os.chdir(cwd)
|
||||||
if tdir and os.path.exists(tdir):
|
if tdir and os.path.exists(tdir):
|
||||||
|
@ -19,6 +19,7 @@ from calibre.ebooks.lrf.pylrs.pylrs import Book, BookSetting, ImageStream, Image
|
|||||||
from calibre.ebooks.metadata import MetaInformation
|
from calibre.ebooks.metadata import MetaInformation
|
||||||
from calibre.ebooks.metadata.opf import OPFCreator
|
from calibre.ebooks.metadata.opf import OPFCreator
|
||||||
from calibre.ebooks.epub.from_html import config as html2epub_config, convert as html2epub
|
from calibre.ebooks.epub.from_html import config as html2epub_config, convert as html2epub
|
||||||
|
from calibre.customize.ui import run_plugins_on_preprocess
|
||||||
try:
|
try:
|
||||||
from calibre.utils.PythonMagickWand import \
|
from calibre.utils.PythonMagickWand import \
|
||||||
NewMagickWand, NewPixelWand, \
|
NewMagickWand, NewPixelWand, \
|
||||||
@ -383,7 +384,9 @@ def create_lrf(pages, profile, opts, thumbnail=None):
|
|||||||
|
|
||||||
|
|
||||||
def do_convert(path_to_file, opts, notification=lambda m, p: p, output_format='lrf'):
|
def do_convert(path_to_file, opts, notification=lambda m, p: p, output_format='lrf'):
|
||||||
|
path_to_file = run_plugins_on_preprocess(path_to_file)
|
||||||
source = path_to_file
|
source = path_to_file
|
||||||
|
|
||||||
if not opts.title:
|
if not opts.title:
|
||||||
opts.title = os.path.splitext(os.path.basename(source))[0]
|
opts.title = os.path.splitext(os.path.basename(source))[0]
|
||||||
if not opts.output:
|
if not opts.output:
|
||||||
|
@ -12,6 +12,7 @@ from urllib import unquote
|
|||||||
from urlparse import urlparse
|
from urlparse import urlparse
|
||||||
from math import ceil, floor
|
from math import ceil, floor
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
from calibre.customize.ui import run_plugins_on_postprocess
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from PIL import Image as PILImage
|
from PIL import Image as PILImage
|
||||||
@ -1931,6 +1932,7 @@ def process_file(path, options, logger=None):
|
|||||||
oname = os.path.join(os.getcwd(), name)
|
oname = os.path.join(os.getcwd(), name)
|
||||||
oname = os.path.abspath(os.path.expanduser(oname))
|
oname = os.path.abspath(os.path.expanduser(oname))
|
||||||
conv.writeto(oname, lrs=options.lrs)
|
conv.writeto(oname, lrs=options.lrs)
|
||||||
|
run_plugins_on_postprocess(oname, 'lrf')
|
||||||
logger.info('Output written to %s', oname)
|
logger.info('Output written to %s', oname)
|
||||||
conv.cleanup()
|
conv.cleanup()
|
||||||
return oname
|
return oname
|
||||||
|
@ -6,19 +6,21 @@ from PyQt4.Qt import QDialog, QMessageBox, QListWidgetItem, QIcon, \
|
|||||||
QDesktopServices, QVBoxLayout, QLabel, QPlainTextEdit, \
|
QDesktopServices, QVBoxLayout, QLabel, QPlainTextEdit, \
|
||||||
QStringListModel, QAbstractItemModel, \
|
QStringListModel, QAbstractItemModel, \
|
||||||
SIGNAL, QTimer, Qt, QSize, QVariant, QUrl, \
|
SIGNAL, QTimer, Qt, QSize, QVariant, QUrl, \
|
||||||
QModelIndex
|
QModelIndex, QInputDialog
|
||||||
|
|
||||||
from calibre.constants import islinux, iswindows
|
from calibre.constants import islinux, iswindows
|
||||||
from calibre.gui2.dialogs.config_ui import Ui_Dialog
|
from calibre.gui2.dialogs.config_ui import Ui_Dialog
|
||||||
from calibre.gui2 import qstring_to_unicode, choose_dir, error_dialog, config, \
|
from calibre.gui2 import qstring_to_unicode, choose_dir, error_dialog, config, \
|
||||||
ALL_COLUMNS, NONE
|
ALL_COLUMNS, NONE, info_dialog, choose_files
|
||||||
from calibre.utils.config import prefs
|
from calibre.utils.config import prefs
|
||||||
from calibre.gui2.widgets import FilenamePattern
|
from calibre.gui2.widgets import FilenamePattern
|
||||||
from calibre.gui2.library import BooksModel
|
from calibre.gui2.library import BooksModel
|
||||||
from calibre.ebooks import BOOK_EXTENSIONS
|
from calibre.ebooks import BOOK_EXTENSIONS
|
||||||
from calibre.ebooks.epub.iterator import is_supported
|
from calibre.ebooks.epub.iterator import is_supported
|
||||||
from calibre.library import server_config
|
from calibre.library import server_config
|
||||||
from calibre.customize.ui import initialized_plugins, is_disabled
|
from calibre.customize.ui import initialized_plugins, is_disabled, enable_plugin, \
|
||||||
|
disable_plugin, customize_plugin, \
|
||||||
|
plugin_customization, add_plugin
|
||||||
|
|
||||||
class PluginModel(QAbstractItemModel):
|
class PluginModel(QAbstractItemModel):
|
||||||
|
|
||||||
@ -65,6 +67,20 @@ class PluginModel(QAbstractItemModel):
|
|||||||
category = self.categories[index.parent().row()]
|
category = self.categories[index.parent().row()]
|
||||||
return self._data[category][index.row()]
|
return self._data[category][index.row()]
|
||||||
|
|
||||||
|
def plugin_to_index(self, plugin):
|
||||||
|
for i, category in enumerate(self.categories):
|
||||||
|
parent = self.index(i, 0, QModelIndex())
|
||||||
|
for j, p in enumerate(self._data[category]):
|
||||||
|
if plugin == p:
|
||||||
|
return self.index(j, 0, parent)
|
||||||
|
return QModelIndex()
|
||||||
|
|
||||||
|
def refresh_plugin(self, plugin, rescan=False):
|
||||||
|
if rescan:
|
||||||
|
self.populate()
|
||||||
|
idx = self.plugin_to_index(plugin)
|
||||||
|
self.emit(SIGNAL('dataChanged(QModelIndex,QModelIndex)'), idx, idx)
|
||||||
|
|
||||||
def flags(self, index):
|
def flags(self, index):
|
||||||
if not index.isValid():
|
if not index.isValid():
|
||||||
return 0
|
return 0
|
||||||
@ -86,8 +102,12 @@ class PluginModel(QAbstractItemModel):
|
|||||||
plugin = self.index_to_plugin(index)
|
plugin = self.index_to_plugin(index)
|
||||||
if role == Qt.DisplayRole:
|
if role == Qt.DisplayRole:
|
||||||
ver = '.'.join(map(str, plugin.version))
|
ver = '.'.join(map(str, plugin.version))
|
||||||
desc = '\n'.join(textwrap.wrap(plugin.description, 70))
|
desc = '\n'.join(textwrap.wrap(plugin.description, 50))
|
||||||
return QVariant('%s (%s) by %s\n%s'%(plugin.name, ver, plugin.author, desc))
|
ans='%s (%s) by %s\n%s'%(plugin.name, ver, plugin.author, desc)
|
||||||
|
c = plugin_customization(plugin)
|
||||||
|
if c:
|
||||||
|
ans += '\nCustomization: '+c
|
||||||
|
return QVariant(ans)
|
||||||
if role == Qt.DecorationRole:
|
if role == Qt.DecorationRole:
|
||||||
return self.icon
|
return self.icon
|
||||||
if role == Qt.UserRole:
|
if role == Qt.UserRole:
|
||||||
@ -220,6 +240,54 @@ class ConfigDialog(QDialog, Ui_Dialog):
|
|||||||
self.category_view.setCurrentIndex(self._category_model.index(0))
|
self.category_view.setCurrentIndex(self._category_model.index(0))
|
||||||
self._plugin_model = PluginModel()
|
self._plugin_model = PluginModel()
|
||||||
self.plugin_view.setModel(self._plugin_model)
|
self.plugin_view.setModel(self._plugin_model)
|
||||||
|
self.connect(self.toggle_plugin, SIGNAL('clicked()'), lambda : self.modify_plugin(op='toggle'))
|
||||||
|
self.connect(self.customize_plugin, SIGNAL('clicked()'), lambda : self.modify_plugin(op='customize'))
|
||||||
|
self.connect(self.button_plugin_browse, SIGNAL('clicked()'), self.find_plugin)
|
||||||
|
self.connect(self.button_plugin_add, SIGNAL('clicked()'), self.add_plugin)
|
||||||
|
|
||||||
|
def add_plugin(self):
|
||||||
|
path = unicode(self.plugin_path.text())
|
||||||
|
if path and os.access(path, os.R_OK) and path.lower().endswith('.zip'):
|
||||||
|
add_plugin(path)
|
||||||
|
self._plugin_model.populate()
|
||||||
|
self._plugin_model.reset()
|
||||||
|
else:
|
||||||
|
error_dialog(self, _('No valid plugin path'),
|
||||||
|
_('%s is not a valid plugin path')%path).exec_()
|
||||||
|
|
||||||
|
def find_plugin(self):
|
||||||
|
path = choose_files(self, 'choose plugin dialog', _('Choose plugin'),
|
||||||
|
filters=[('Plugins', ['zip'])], all_files=False,
|
||||||
|
select_only_single_file=True)
|
||||||
|
if path:
|
||||||
|
self.plugin_path.setText(path[0])
|
||||||
|
|
||||||
|
def modify_plugin(self, op=''):
|
||||||
|
index = self.plugin_view.currentIndex()
|
||||||
|
if index.isValid():
|
||||||
|
plugin = self._plugin_model.index_to_plugin(index)
|
||||||
|
if not plugin.can_be_disabled:
|
||||||
|
error_dialog(self,_('Plugin cannot be disabled'),
|
||||||
|
_('The plugin %s cannot be disabled')%plugin.name).exec_()
|
||||||
|
return
|
||||||
|
if op == 'toggle':
|
||||||
|
if is_disabled(plugin):
|
||||||
|
enable_plugin(plugin)
|
||||||
|
else:
|
||||||
|
disable_plugin(plugin)
|
||||||
|
self._plugin_model.refresh_plugin(plugin)
|
||||||
|
if op == 'customize':
|
||||||
|
if not plugin.is_customizable():
|
||||||
|
info_dialog(self, _('Plugin not customizable'),
|
||||||
|
_('Plugin %s does not need customization')%plugin.name).exec_()
|
||||||
|
return
|
||||||
|
help = plugin.customization_help()
|
||||||
|
text, ok = QInputDialog.getText(self, _('Customize %s')%plugin.name,
|
||||||
|
help)
|
||||||
|
if ok:
|
||||||
|
customize_plugin(plugin, unicode(text))
|
||||||
|
self._plugin_model.refresh_plugin(plugin)
|
||||||
|
|
||||||
|
|
||||||
def up_column(self):
|
def up_column(self):
|
||||||
idx = self.columns.currentRow()
|
idx = self.columns.currentRow()
|
||||||
|
@ -839,6 +839,10 @@
|
|||||||
<property name="text" >
|
<property name="text" >
|
||||||
<string>...</string>
|
<string>...</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="icon" >
|
||||||
|
<iconset resource="../images.qrc" >
|
||||||
|
<normaloff>:/images/document_open.svg</normaloff>:/images/document_open.svg</iconset>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -85,11 +85,9 @@ class MetadataSingleDialog(QDialog, Ui_MetadataSingleDialog):
|
|||||||
QErrorMessage(self.window).showMessage("You do not have "+\
|
QErrorMessage(self.window).showMessage("You do not have "+\
|
||||||
"permission to read the file: " + _file)
|
"permission to read the file: " + _file)
|
||||||
continue
|
continue
|
||||||
_file = run_plugins_on_import(_file, os.path.splitext(_file)[1].lower())
|
_file = run_plugins_on_import(_file)
|
||||||
size = os.stat(_file).st_size
|
size = os.stat(_file).st_size
|
||||||
ext = os.path.splitext(_file)[1].lower()
|
ext = os.path.splitext(_file)[1].lower().replace('.', '')
|
||||||
if '.' in ext:
|
|
||||||
ext = ext.replace('.', '')
|
|
||||||
for row in range(self.formats.count()):
|
for row in range(self.formats.count()):
|
||||||
fmt = self.formats.item(row)
|
fmt = self.formats.item(row)
|
||||||
if fmt.ext == ext:
|
if fmt.ext == ext:
|
||||||
|
@ -661,6 +661,7 @@ class LibraryDatabase2(LibraryDatabase):
|
|||||||
def add_format_with_hooks(self, index, format, fpath, index_is_id=False,
|
def add_format_with_hooks(self, index, format, fpath, index_is_id=False,
|
||||||
path=None, notify=True):
|
path=None, notify=True):
|
||||||
npath = self.run_import_plugins(fpath, format)
|
npath = self.run_import_plugins(fpath, format)
|
||||||
|
format = os.path.splitext(npath)[-1].lower().replace('.', '').upper()
|
||||||
return self.add_format(index, format, open(npath, 'rb'),
|
return self.add_format(index, format, open(npath, 'rb'),
|
||||||
index_is_id=index_is_id, path=path, notify=notify)
|
index_is_id=index_is_id, path=path, notify=notify)
|
||||||
|
|
||||||
@ -1126,6 +1127,7 @@ class LibraryDatabase2(LibraryDatabase):
|
|||||||
self.conn.commit()
|
self.conn.commit()
|
||||||
self.set_metadata(id, mi)
|
self.set_metadata(id, mi)
|
||||||
npath = self.run_import_plugins(path, format)
|
npath = self.run_import_plugins(path, format)
|
||||||
|
format = os.path.splitext(npath)[-1].lower().replace('.', '').upper()
|
||||||
stream = open(npath, 'rb')
|
stream = open(npath, 'rb')
|
||||||
self.add_format(id, format, stream, index_is_id=True)
|
self.add_format(id, format, stream, index_is_id=True)
|
||||||
stream.close()
|
stream.close()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user