IGN:Updated translations and various minor bug fixes

This commit is contained in:
Kovid Goyal 2008-12-23 13:32:42 -08:00
parent 252dd342e0
commit 58a09d73f0
37 changed files with 7206 additions and 5515 deletions

View File

@ -2,8 +2,30 @@ from __future__ import with_statement
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
import sys
from calibre.ptempfile import PersistentTemporaryFile
class Plugin(object):
'''
A calibre plugin. Useful members include:
* ``self.plugin_path``: Stores path to the zip file that contains
this plugin or None if it is a builtin
plugin
* ``self.site_customization``: Stores a customization string entered
by the user.
Methods that should be overridden in sub classes:
* :method:`initialize`
* :method:`customization_help`
Useful methods:
* :method:`temporary_file`
'''
#: List of platforms this plugin works on
#: For example: ``['windows', 'osx', 'linux']
supported_platforms = []
@ -29,25 +51,95 @@ class Plugin(object):
#: The earliest version of calibre this plugin requires
minimum_calibre_version = (0, 4, 118)
type = _('Base')
def __init__(self, plugin_path):
self.plugin_path = plugin_path
self.site_customization = None
def initialize(self):
'''
Called once when calibre plugins are initialized. Plugins are re-initialized
every time a new plugin is added.
:param plugin_path: Path to the zip file this plugin is distributed in.
'''
self.plugin_path = plugin_path
Perform any plugin specific initialization here, such as extracting
resources from the plugin zip file. The path to the zip file is
available as ``self.plugin_path``.
def customization_help(self):
Note that ``self.site_customization`` is **not** available at this point.
'''
pass
@classmethod
def customization_help(cls):
'''
Return a string giving help on how to customize this plugin.
By default raise a :class:`NotImplementedError`, which indicates that
the plugin does not require customization.
the plugin does not require customization.
If you re-implement this method in your subclass, the user will
be asked to enter a string as customization for this plugin.
The customization string will be available as
``self.site_customization``.
Site customization could be anything, for example, the path to
a needed binary on the user's computer.
'''
raise NotImplementedError
def run(self, path_to_ebook, site_customization=''):
def temporary_file(self, suffix):
'''
Return a file-like object that is a temporary file on the file system.
This file will remain available even after being closed and will only
be removed on interpreter shutdown. Use the ``name`` member of the
returned object to access the full path to the created temporary file.
:param suffix: The suffix that the temporary file will have.
'''
return PersistentTemporaryFile(suffix)
@classmethod
def is_customizable(cls):
try:
cls.customization_help()
return True
except NotImplementedError:
return False
def __enter__(self, *args):
if self.plugin_path is not None:
sys.path.insert(0, self.plugin_path)
def __exit__(self, *args):
if self.plugin_path in sys.path:
sys.path.remove(self.plugin_path)
class FileTypePlugin(Plugin):
'''
A plugin that is associated with a particular set of file types.
'''
#: List of file types for which this plugin should be run
#: For example: ``set(['lit', 'mobi', 'prc'])``
file_types = set([])
#: If True, this plugin is run when books are added
#: to the database
on_import = False
#: If True, this plugin is run whenever an any2* tool
#: is used, on the file passed to the any2* tool.
on_preprocess = False
#: If True, this plugin is run after an any2* tool is
#: used, on the final file produced by the tool.
on_postprocess = False
type = _('File type')
def run(self, path_to_ebook):
'''
Run the plugin. Must be implemented in subclasses.
It should perform whatever modifications are required
@ -57,12 +149,10 @@ class Plugin(object):
it should raise an Exception. The default implementation
simply return the path to the original ebook.
:param path_to_ebook: Absolute path to the ebook
:param site_customization: A (possibly empty) string that the user
has specified to customize this plugin.
For example, it could be the path to a needed
executable on her system.
The modified ebook file should be created with the
:method:`temporary_file` method.
:param path_to_ebook: Absolute path to the ebook.
:return: Absolute path to the modified ebook.
'''
# Default implementation does nothing

View File

@ -0,0 +1,29 @@
from __future__ import with_statement
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
import textwrap
from calibre.customize import FileTypePlugin
from calibre.constants import __version__
class HTML2ZIP(FileTypePlugin):
name = 'HTML to ZIP'
author = 'Kovid Goyal'
description = textwrap.dedent(_('''\
Follow all local links in an HTML file and create a ZIP \
file containing all linked files. This plugin is run \
every time you add an HTML file to the library.\
'''))
version = tuple(map(int, (__version__.split('.'))[:3]))
file_types = ['html', 'htm', 'xhtml', 'xhtm']
supported_platforms = ['windows', 'osx', 'linux']
on_import = True
def run(self, htmlfile):
of = self.temporary_file('_plugin_html2zip.zip')
from calibre.ebooks.html import gui_main as html2oeb
html2oeb(htmlfile, of)
return of.name
plugins = [HTML2ZIP]

View File

@ -1,28 +0,0 @@
from __future__ import with_statement
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
from calibre.customize import Plugin as PluginBase
class Plugin(PluginBase):
'''
A plugin that is associated with a particular set of file types.
'''
#: List of file types for which this plugin should be run
#: For example: ``['lit', 'mobi', 'prc']``
file_types = []
#: If True, this plugin is run when books are added
#: to the database
on_import = False
#: If True, this plugin is run whenever an any2* tool
#: is used, on the file passed to the any2* tool.
on_preprocess = False
#: If True, this plugin is run after an any2* tool is
#: used, on the final file produced by the tool.
on_postprocess = False

View File

@ -4,8 +4,8 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
import os, shutil, traceback, functools, sys
from calibre.customize import Plugin
from calibre.customize.filetype import Plugin as FileTypePlugin
from calibre.customize import Plugin, FileTypePlugin
from calibre.customize.builtins import plugins as builtin_plugins
from calibre.constants import __version__, iswindows, isosx
from calibre.utils.config import make_config_dir, Config, ConfigProxy, \
plugin_dir, OptionParser
@ -24,7 +24,7 @@ from zipfile import ZipFile
def _config():
c = Config('customize')
c.add_opt('plugins', default={}, help=_('Installed plugins'))
c.add_opt('filetype_mapping', default={}, help=_('Maping for filetype plugins'))
c.add_opt('filetype_mapping', default={}, help=_('Mapping for filetype plugins'))
c.add_opt('plugin_customization', default={}, help=_('Local plugin customization'))
c.add_opt('disabled_plugins', default=set([]), help=_('Disabled plugins'))
@ -100,12 +100,13 @@ def _run_filetype_plugins(path_to_file, ft, occasion='preprocess'):
for plugin in occasion.get(ft, []):
if is_disabled(plugin):
continue
sc = customization.get(plugin.name, '')
try:
nfp = plugin.run(path_to_file, sc)
except:
print 'Running file type plugin %s failed with traceback:'%plugin.name
traceback.print_exc()
plugin.site_customization = customization.get(plugin.name, '')
with plugin:
try:
nfp = plugin.run(path_to_file)
except:
print 'Running file type plugin %s failed with traceback:'%plugin.name
traceback.print_exc()
return nfp
run_plugins_on_import = functools.partial(_run_filetype_plugins,
@ -117,10 +118,10 @@ run_plugins_on_postprocess = functools.partial(_run_filetype_plugins,
def initialize_plugin(plugin, path_to_zip_file):
print 'Initializing plugin', plugin.name
try:
plugin(path_to_zip_file)
except Exception:
print 'Failed to initialize plugin:', plugin.name, plugin.version
tb = traceback.format_exc()
raise InvalidPlugin((_('Initialization of plugin %s failed with traceback:')
%tb) + '\n'+tb)
@ -164,10 +165,10 @@ def enable_plugin(plugin_or_name):
def initialize_plugins():
global _initialized_plugins
_initialized_plugins = []
for zfp in config['plugins'].values():
for zfp in list(config['plugins'].values()) + builtin_plugins:
try:
plugin = load_plugin(zfp)
initialize_plugin(plugin, zfp)
plugin = load_plugin(zfp) if not isinstance(zfp, type) else zfp
initialize_plugin(plugin, zfp if not isinstance(zfp, type) else zfp)
_initialized_plugins.append(plugin)
except:
print 'Failed to initialize plugin...'
@ -195,6 +196,9 @@ def option_parser():
help=_('Disable the named plugin'))
return parser
def initialized_plugins():
return _initialized_plugins
def main(args=sys.argv):
parser = option_parser()
if len(args) < 2:
@ -216,11 +220,19 @@ def main(args=sys.argv):
if opts.disable_plugin is not None:
disable_plugin(opts.disable_plugin.strip())
if opts.list_plugins:
print 'Name\tVersion\tDisabled\tLocal Customization'
for plugin in _initialized_plugins:
print '%s\t%s\t%s\t%s'%(plugin.name, plugin.version, is_disabled(plugin),
config['plugin_customization'].get(plugin.name))
print '\t', plugin.customization_help()
fmt = '%-15s%-20s%-15s%-15s%s'
print fmt%tuple(('Type|Name|Version|Disabled|Site Customization'.split('|')))
print
for plugin in initialized_plugins():
print fmt%(
plugin.type, plugin.name,
plugin.version, is_disabled(plugin),
config['plugin_customization'].get(plugin.name, '')
)
print '\t', plugin.description
if plugin.is_customizable():
print '\t', plugin.customization_help()
print
return 0

View File

@ -21,8 +21,8 @@ Run an embedded python interpreter.
'Module specifications are of the form full.name.of.module,path_to_module.py', default=None
)
parser.add_option('-c', '--command', help='Run python code.', default=None)
parser.add_option('-g', '--run-gui', help='Run the GUI', default=False,
action='store_true')
parser.add_option('-g', '--gui', default=False, action='store_true',
help='Run the GUI',)
parser.add_option('--migrate', action='store_true', default=False,
help='Migrate old database. Needs two arguments. Path to library1.db and path to new library folder.')
return parser
@ -74,9 +74,9 @@ def migrate(old, new):
def main(args=sys.argv):
opts, args = option_parser().parse_args(args)
if opts.run_gui:
if opts.gui:
from calibre.gui2.main import main
main()
main(['calibre'])
elif opts.update_module:
mod, path = opts.update_module.partition(',')[0], opts.update_module.partition(',')[-1]
update_module(mod, os.path.expanduser(path))

View File

@ -1044,11 +1044,12 @@ def main(args=sys.argv):
return 0
def gui_main(htmlfile):
def gui_main(htmlfile, pt=None):
'''
Convenience wrapper for use in recursively importing HTML files.
'''
pt = PersistentTemporaryFile('_html2oeb_gui.oeb.zip')
if pt is None:
pt = PersistentTemporaryFile('_html2oeb_gui.oeb.zip')
pt.close()
opts = '''
pretty_print = True

View File

@ -14,7 +14,6 @@ from calibre import __author__, islinux, iswindows, isosx
from calibre.startup import get_lang
from calibre.utils.config import Config, ConfigProxy, dynamic
import calibre.resources as resources
from calibre.ebooks.html import gui_main as html2oeb
NONE = QVariant() #: Null value to return from the data function of item models
@ -389,14 +388,6 @@ def pixmap_to_data(pixmap, format='JPEG'):
pixmap.save(buf, format)
return str(ba.data())
html_pat = re.compile(r'\.x{0,1}htm(l{0,1})\s*$', re.IGNORECASE)
def import_format(path):
if html_pat.search(path) is not None:
try:
return html2oeb(path), 'zip'
except:
traceback.print_exc()
return None, None
try:
from calibre.utils.single_qt_application import SingleApplication

View File

@ -1,32 +1,111 @@
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
import os, re, time
import os, re, time, textwrap
from PyQt4.QtGui import QDialog, QMessageBox, QListWidgetItem, QIcon, \
from PyQt4.Qt import QDialog, QMessageBox, QListWidgetItem, QIcon, \
QDesktopServices, QVBoxLayout, QLabel, QPlainTextEdit, \
QStringListModel
from PyQt4.QtCore import SIGNAL, QTimer, Qt, QSize, QVariant, QUrl
QStringListModel, QAbstractItemModel, \
SIGNAL, QTimer, Qt, QSize, QVariant, QUrl, \
QModelIndex
from calibre.constants import islinux, iswindows
from calibre.gui2.dialogs.config_ui import Ui_Dialog
from calibre.gui2 import qstring_to_unicode, choose_dir, error_dialog, config, \
warning_dialog, ALL_COLUMNS
ALL_COLUMNS, NONE
from calibre.utils.config import prefs
from calibre.gui2.widgets import FilenamePattern
from calibre.gui2.library import BooksModel
from calibre.ebooks import BOOK_EXTENSIONS
from calibre.ebooks.epub.iterator import is_supported
from calibre.library import server_config
from calibre.customize.ui import initialized_plugins, is_disabled
class PluginModel(QAbstractItemModel):
def __init__(self, *args):
QAbstractItemModel.__init__(self, *args)
self.icon = QVariant(QIcon(':/images/plugins.svg'))
self.populate()
def populate(self):
self._data = {}
for plugin in initialized_plugins():
if plugin.type not in self._data:
self._data[plugin.type] = [plugin]
else:
self._data[plugin.type].append(plugin)
self.categories = sorted(self._data.keys())
def index(self, row, column, parent):
if not self.hasIndex(row, column, parent):
return QModelIndex()
if parent.isValid():
return self.createIndex(row, column, parent.row())
else:
return self.createIndex(row, column, -1)
def parent(self, index):
if not index.isValid() or index.internalId() == -1:
return QModelIndex()
return self.createIndex(index.internalId(), 0, -1)
def rowCount(self, parent):
if not parent.isValid():
return len(self.categories)
if parent.internalId() == -1:
category = self.categories[parent.row()]
return len(self._data[category])
return 0
def columnCount(self, parent):
return 1
def index_to_plugin(self, index):
category = self.categories[index.parent().row()]
return self._data[category][index.row()]
def flags(self, index):
if not index.isValid():
return 0
if index.internalId() == -1:
return Qt.ItemIsEnabled
flags = Qt.ItemIsSelectable
if not is_disabled(self.data(index, Qt.UserRole)):
flags |= Qt.ItemIsEnabled
return flags
def data(self, index, role):
if not index.isValid():
return NONE
if index.internalId() == -1:
if role == Qt.DisplayRole:
category = self.categories[index.row()]
return QVariant(category + _(' plugins'))
else:
plugin = self.index_to_plugin(index)
if role == Qt.DisplayRole:
ver = '.'.join(map(str, plugin.version))
desc = '\n'.join(textwrap.wrap(plugin.description, 70))
return QVariant('%s (%s) by %s\n%s'%(plugin.name, ver, plugin.author, desc))
if role == Qt.DecorationRole:
return self.icon
if role == Qt.UserRole:
return plugin
return NONE
class CategoryModel(QStringListModel):
def __init__(self, *args):
QStringListModel.__init__(self, *args)
self.setStringList([_('General'), _('Interface'), _('Advanced'),
_('Content\nServer')])
_('Content\nServer'), _('Plugins')])
self.icons = list(map(QVariant, map(QIcon,
[':/images/dialog_information.svg', ':/images/lookfeel.svg',
':/images/view.svg', ':/images/network-server.svg'])))
':/images/view.svg', ':/images/network-server.svg',
':/images/plugins.svg'])))
def data(self, index, role):
if role == Qt.DecorationRole:
@ -139,6 +218,8 @@ class ConfigDialog(QDialog, Ui_Dialog):
self.priority.setVisible(iswindows)
self.priority_label.setVisible(iswindows)
self.category_view.setCurrentIndex(self._category_model.index(0))
self._plugin_model = PluginModel()
self.plugin_view.setModel(self._plugin_model)
def up_column(self):
idx = self.columns.currentRow()

View File

@ -72,7 +72,7 @@
</sizepolicy>
</property>
<property name="currentIndex" >
<number>0</number>
<number>4</number>
</property>
<widget class="QWidget" name="page_3" >
<layout class="QVBoxLayout" name="verticalLayout" >
@ -767,6 +767,111 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="page_5" >
<layout class="QVBoxLayout" name="verticalLayout_6" >
<item>
<widget class="QLabel" name="label_8" >
<property name="text" >
<string>Here you can customize the behavior of Calibre by controlling what plugins it uses.</string>
</property>
<property name="wordWrap" >
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QTreeView" name="plugin_view" >
<property name="iconSize" >
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="animated" >
<bool>true</bool>
</property>
<property name="headerHidden" >
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6" >
<item>
<widget class="QPushButton" name="toggle_plugin" >
<property name="text" >
<string>Enable/&amp;Disable plugin</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="customize_plugin" >
<property name="text" >
<string>&amp;Customize plugin</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBox_4" >
<property name="title" >
<string>Add new plugin</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5" >
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5" >
<item>
<widget class="QLabel" name="label_14" >
<property name="text" >
<string>Plugin &amp;file:</string>
</property>
<property name="buddy" >
<cstring>plugin_path</cstring>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="plugin_path" />
</item>
<item>
<widget class="QToolButton" name="button_plugin_browse" >
<property name="text" >
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4" >
<item>
<spacer name="horizontalSpacer_2" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="button_plugin_add" >
<property name="text" >
<string>&amp;Add</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>

View File

@ -49,11 +49,8 @@ class JobsDialog(QDialog, Ui_JobsDialog):
self.connect(self.running_time_timer, SIGNAL('timeout()'), self.update_running_time)
self.running_time_timer.start(1000)
def update_running_time(self):
model = self.model
for row, job in enumerate(model.jobs):
if job.is_running:
self.jobs_view.dataChanged(model.index(row, 3), model.index(row, 3))
def update_running_time(self, *args):
self.model.running_time_updated()
def kill_job(self):
for index in self.jobs_view.selectedIndexes():

View File

@ -11,7 +11,7 @@ from PyQt4.QtGui import QPixmap, QListWidgetItem, QErrorMessage, QDialog
from calibre.gui2 import qstring_to_unicode, error_dialog, file_icon_provider, \
choose_files, pixmap_to_data, choose_images, import_format
choose_files, pixmap_to_data, choose_images
from calibre.gui2.dialogs.metadata_single_ui import Ui_MetadataSingleDialog
from calibre.gui2.dialogs.fetch_metadata import FetchMetadata
from calibre.gui2.dialogs.tag_editor import TagEditor
@ -21,6 +21,7 @@ from calibre.ebooks.metadata import authors_to_sort_string, string_to_authors, a
from calibre.ebooks.metadata.library_thing import login, cover_from_isbn, LibraryThingError
from calibre import islinux
from calibre.utils.config import prefs
from calibre.customize.ui import run_plugins_on_import
class Format(QListWidgetItem):
def __init__(self, parent, ext, size, path=None):
@ -84,9 +85,7 @@ class MetadataSingleDialog(QDialog, Ui_MetadataSingleDialog):
QErrorMessage(self.window).showMessage("You do not have "+\
"permission to read the file: " + _file)
continue
nf = import_format(_file)[0]
if nf is not None:
_file = nf
_file = run_plugins_on_import(_file, os.path.splitext(_file)[1].lower())
size = os.stat(_file).st_size
ext = os.path.splitext(_file)[1].lower()
if '.' in ext:

View File

@ -2254,7 +2254,7 @@
id="mask7160"
maskUnits="userSpaceOnUse">
<path
style="opacity:1;fill:url(#radialGradient7164);fill-opacity:1;stroke:none;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.08779998;stroke-opacity:1"
style="opacity:1;fill-opacity:1;stroke:none;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.08779998;stroke-opacity:1"
d="M 137.37423,-51.650649 C 136.90963,-51.650649 136.53048,-51.183286 136.53048,-50.619399 L 136.53048,-0.18189907 C 141.47984,0.40821793 146.5415,0.72435094 151.68673,0.72435094 C 164.60291,0.72435094 176.96094,-1.191205 188.40548,-4.713149 L 188.40548,-50.619399 C 188.40548,-51.183286 188.02634,-51.650649 187.56173,-51.650649 L 137.37423,-51.650649 z "
id="path7162" />
</mask>

Before

Width:  |  Height:  |  Size: 168 KiB

After

Width:  |  Height:  |  Size: 168 KiB

View File

@ -0,0 +1,694 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://web.resource.org/cc/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.0"
id="Layer_1"
x="0px"
y="0px"
width="128"
height="128"
viewBox="0 0 112 112"
enable-background="new 0 0 112 112"
xml:space="preserve"
sodipodi:version="0.32"
inkscape:version="0.45.1"
sodipodi:docname="preferences-plugin.svg.svgz"
sodipodi:docbase="/home/david/Desktop"
inkscape:output_extension="org.inkscape.output.svgz.inkscape"><metadata
id="metadata95"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
id="defs93"><linearGradient
inkscape:collect="always"
id="linearGradient13107"><stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop13109" /><stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop13111" /></linearGradient><linearGradient
id="linearGradient7263"><stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="0"
id="stop7265" /><stop
style="stop-color:#ffffff;stop-opacity:0.48453608;"
offset="1"
id="stop7267" /></linearGradient><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient3216"
x1="1.999"
y1="55.862"
x2="109.998"
y2="55.862"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient3218"
gradientUnits="userSpaceOnUse"
x1="1.999"
y1="55.862"
x2="109.998"
y2="55.862" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient3222"
gradientUnits="userSpaceOnUse"
x1="1.999"
y1="55.862"
x2="109.998"
y2="55.862" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient3226"
gradientUnits="userSpaceOnUse"
x1="1.999"
y1="55.862"
x2="109.998"
y2="55.862" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient3230"
gradientUnits="userSpaceOnUse"
x1="1.999"
y1="55.862"
x2="109.998"
y2="55.862" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient3234"
gradientUnits="userSpaceOnUse"
x1="1.999"
y1="55.862"
x2="109.998"
y2="55.862" /><filter
inkscape:collect="always"
id="filter3248"><feGaussianBlur
inkscape:collect="always"
stdDeviation="0.5392541"
id="feGaussianBlur3250" /></filter><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient3304"
gradientUnits="userSpaceOnUse"
x1="1.999"
y1="55.862"
x2="109.998"
y2="55.862" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient3306"
gradientUnits="userSpaceOnUse"
x1="1.999"
y1="55.862"
x2="109.998"
y2="55.862" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient3310"
gradientUnits="userSpaceOnUse"
x1="1.999"
y1="55.862"
x2="109.998"
y2="55.862" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient3314"
gradientUnits="userSpaceOnUse"
x1="1.999"
y1="55.862"
x2="109.998"
y2="55.862" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient3318"
gradientUnits="userSpaceOnUse"
x1="1.999"
y1="55.862"
x2="109.998"
y2="55.862" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient3322"
gradientUnits="userSpaceOnUse"
x1="1.999"
y1="55.862"
x2="109.998"
y2="55.862" /><filter
inkscape:collect="always"
id="filter4299"><feGaussianBlur
inkscape:collect="always"
stdDeviation="0.26962705"
id="feGaussianBlur4301" /></filter><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient4328"
gradientUnits="userSpaceOnUse"
x1="88.745003"
y1="55.154892"
x2="94.44165"
y2="95.81353" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient4334"
gradientUnits="userSpaceOnUse"
x1="91.39418"
y1="55.862"
x2="89.845459"
y2="26.322001" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient4338"
gradientUnits="userSpaceOnUse"
x1="56.799774"
y1="11.643"
x2="80.800003"
y2="26.163515" /><filter
inkscape:collect="always"
id="filter6290"><feGaussianBlur
inkscape:collect="always"
stdDeviation="2.24"
id="feGaussianBlur6292" /></filter><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4344"
id="linearGradient9215"
x1="75.195961"
y1="-4"
x2="94.433243"
y2="113.6292"
gradientUnits="userSpaceOnUse" /><filter
inkscape:collect="always"
id="filter12134"><feGaussianBlur
inkscape:collect="always"
stdDeviation="2.4"
id="feGaussianBlur12136" /></filter><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient13107"
id="linearGradient13113"
x1="46.91169"
y1="116"
x2="48.325901"
y2="-2.5101759"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient13107"
id="linearGradient13161"
gradientUnits="userSpaceOnUse"
x1="46.91169"
y1="116"
x2="48.325901"
y2="-2.5101759" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient13107"
id="linearGradient13163"
gradientUnits="userSpaceOnUse"
x1="46.91169"
y1="116"
x2="48.325901"
y2="-2.5101759" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4344"
id="linearGradient13165"
gradientUnits="userSpaceOnUse"
x1="75.195961"
y1="-4"
x2="94.433243"
y2="113.6292" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4344"
id="linearGradient13167"
gradientUnits="userSpaceOnUse"
x1="75.195961"
y1="-4"
x2="94.433243"
y2="113.6292" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient13175"
gradientUnits="userSpaceOnUse"
x1="91.39418"
y1="55.862"
x2="89.845459"
y2="26.322001" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient13179"
gradientUnits="userSpaceOnUse"
x1="88.745003"
y1="55.154892"
x2="94.44165"
y2="95.81353" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient13183"
gradientUnits="userSpaceOnUse"
x1="1.999"
y1="55.862"
x2="109.998"
y2="55.862" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient13187"
gradientUnits="userSpaceOnUse"
x1="1.999"
y1="55.862"
x2="109.998"
y2="55.862" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient13191"
gradientUnits="userSpaceOnUse"
x1="56.799774"
y1="11.643"
x2="80.800003"
y2="26.163515" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient13221"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.009217,0,0,0.9999274,-0.5151412,-5.9972184)"
x1="35.38496"
y1="13.143368"
x2="70.239304"
y2="69.509804" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient7263"
id="linearGradient13223"
gradientUnits="userSpaceOnUse"
x1="1.999"
y1="35.897853"
x2="109.99844"
y2="35.897853"
gradientTransform="matrix(1.0092222,0,0,0.9999326,-0.5151516,-5.9975816)" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_2_"
id="linearGradient13243"
x1="62.578949"
y1="127.77134"
x2="58.966991"
y2="-31.68124"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient13245"
gradientUnits="userSpaceOnUse"
x1="1.999"
y1="55.862"
x2="109.998"
y2="55.862" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient13247"
gradientUnits="userSpaceOnUse"
x1="23.533312"
y1="107.83435"
x2="28.680723"
y2="78.514572" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient13249"
gradientUnits="userSpaceOnUse"
x1="1.999"
y1="55.862"
x2="109.998"
y2="55.862" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient13251"
gradientUnits="userSpaceOnUse"
x1="1.999"
y1="55.862"
x2="109.998"
y2="55.862" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient13257"
gradientUnits="userSpaceOnUse"
x1="88.745003"
y1="55.154892"
x2="94.44165"
y2="95.81353" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient13259"
gradientUnits="userSpaceOnUse"
x1="63.870842"
y1="86.705002"
x2="109.998"
y2="55.862" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient13265"
gradientUnits="userSpaceOnUse"
x1="56.799774"
y1="11.643"
x2="80.800003"
y2="26.163515" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient13267"
gradientUnits="userSpaceOnUse"
x1="45.839619"
y1="18.38534"
x2="109.998"
y2="55.862" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient13269"
gradientUnits="userSpaceOnUse"
x1="91.39418"
y1="55.862"
x2="89.845459"
y2="26.322001" /><linearGradient
inkscape:collect="always"
xlink:href="#SVGID_9_"
id="linearGradient13271"
gradientUnits="userSpaceOnUse"
x1="63.870842"
y1="21.023001"
x2="109.998"
y2="55.862" /><filter
inkscape:collect="always"
id="filter18426"><feGaussianBlur
inkscape:collect="always"
stdDeviation="1.12"
id="feGaussianBlur18428" /></filter></defs><sodipodi:namedview
inkscape:window-height="713"
inkscape:window-width="1024"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
guidetolerance="10.0"
gridtolerance="10.0"
objecttolerance="10.0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#ffffff"
id="base"
width="128px"
height="128px"
inkscape:zoom="2.8284271"
inkscape:cx="56"
inkscape:cy="62.542861"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:current-layer="g3266" />
<linearGradient
id="SVGID_2_"
gradientUnits="userSpaceOnUse"
x1="55.998501"
y1="122.1953"
x2="55.998501"
y2="-27.688801">
<stop
offset="0"
style="stop-color:#00892C"
id="stop13" />
<stop
offset="0.0791"
style="stop-color:#259E34"
id="stop15" />
<stop
offset="0.1681"
style="stop-color:#48B23B"
id="stop17" />
<stop
offset="0.2522"
style="stop-color:#61C041"
id="stop19" />
<stop
offset="0.3286"
style="stop-color:#71C944"
id="stop21" />
<stop
offset="0.3901"
style="stop-color:#71d73a;stop-opacity:1;"
id="stop23" />
<stop
offset="1"
style="stop-color:#00892C"
id="stop25" />
</linearGradient>
<linearGradient
id="SVGID_8_"
gradientUnits="userSpaceOnUse"
x1="65.537102"
y1="106.5479"
x2="65.537102"
y2="2.0360999">
<stop
offset="0"
style="stop-color:#F8FFBF"
id="stop77" />
<stop
offset="0.4"
style="stop-color:#FFFFFF"
id="stop79" />
<stop
offset="1"
style="stop-color:#F8FFBF"
id="stop81" />
</linearGradient>
<linearGradient
id="SVGID_9_"
gradientUnits="userSpaceOnUse"
x1="29.021"
y1="6.0723"
x2="70.239304"
y2="69.509804">
<stop
offset="0"
style="stop-color:#FFFFFF"
id="stop86" />
<stop
offset="1"
style="stop-color:#ffffff;stop-opacity:0;"
id="stop88" />
</linearGradient>
<g
id="g3266"
transform="matrix(0.875,0,0,0.875,6.9999998,7)"><g
style="opacity:0.5;fill:#000000;fill-opacity:1;stroke:url(#linearGradient13161);stroke-width:8;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter12134)"
id="g11155"
transform="translate(0,-2)">
<linearGradient
style="stroke:url(#linearGradient13113)"
y2="144.4818"
x2="126.7421"
y1="5.7275"
x1="19.7563"
gradientUnits="userSpaceOnUse"
id="linearGradient11157">
<stop
id="stop11159"
style="stop-color:#64ba32;stop-opacity:1;stroke:url(#linearGradient13113)"
offset="0" />
<stop
id="stop11161"
style="stop-color:#00892C;stroke:url(#linearGradient13113)"
offset="1" />
</linearGradient>
<path
id="path11163"
d="M 63.718,0 C 71.232,0 78.445,0.652 82,6 C 85.555,11.348 75.978,14.839 78.645,19.459 C 85.19,22.815 101.277,22.06 112,22 C 112,22 112,53.03 112,53.376 C 106.208,56.712 100.089,51.931 95,51 C 85.395,55.274 85.348,78.515 95,82.68 C 100.722,83.13 100.419,77.649 107,78.96 C 112.013,85.694 112,112 112,112 L 22,112 C 22,112 22.422,83.565 19.538,80.682 C 16.654,77.799 14.483,85.954 7.26,84.41 C 2.943,82.345 0,78.605 0,68 C 0,57.395 2.812,52.71 7.068,50.316 C 13.635,48.93 14.699,57.379 18.178,53.9 C 21.657,50.421 22.07,34.826 22,22 C 32.448,22 45.674,24 52,19 C 52.428,13.665 48.199,13.695 48,9 C 49.149,2.904 56.22,0.222 63.718,0 z "
clip-rule="evenodd"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient13163);stroke-width:8;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g><g
id="g4342"
style="fill:none;stroke:url(#linearGradient13165);stroke-width:8;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
transform="translate(0,-4)">
<linearGradient
id="linearGradient4344"
gradientUnits="userSpaceOnUse"
x1="19.7563"
y1="5.7275"
x2="126.7421"
y2="144.4818"
style="stroke:url(#linearGradient9215)">
<stop
offset="0"
style="stop-color:#64ba32;stop-opacity:1;"
id="stop4346" />
<stop
offset="1"
style="stop-color:#00892C;stroke:url(#linearGradient9215)"
id="stop4348" />
</linearGradient>
<path
style="fill:none;fill-rule:evenodd;stroke:url(#linearGradient13167);stroke-width:8;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
clip-rule="evenodd"
d="M 63.718,0 C 71.232,0 78.445,0.652 82,6 C 85.555,11.348 75.978,14.839 78.645,19.459 C 85.19,22.815 101.277,22.06 112,22 C 112,22 112,53.03 112,53.376 C 106.208,56.712 100.089,51.931 95,51 C 85.395,55.274 85.348,78.515 95,82.68 C 100.722,83.13 100.419,77.649 107,78.96 C 112.013,85.694 112,112 112,112 L 22,112 C 22,112 22.422,83.565 19.538,80.682 C 16.654,77.799 14.483,85.954 7.26,84.41 C 2.943,82.345 0,78.605 0,68 C 0,57.395 2.812,52.71 7.068,50.316 C 13.635,48.93 14.699,57.379 18.178,53.9 C 21.657,50.421 22.07,34.826 22,22 C 32.448,22 45.674,24 52,19 C 52.428,13.665 48.199,13.695 48,9 C 49.149,2.904 56.22,0.222 63.718,0 z "
id="path4350" />
</g><g
id="g3"
style="filter:url(#filter18426);fill:url(#linearGradient13243)"
transform="translate(0,-4)">
<linearGradient
y2="144.4818"
x2="126.7421"
y1="5.7275"
x1="19.7563"
gradientUnits="userSpaceOnUse"
id="SVGID_1_"
style="fill:url(#linearGradient13243)">
<stop
id="stop6"
style="stop-color:#76CC45;fill:url(#linearGradient13243)"
offset="0" />
<stop
id="stop8"
style="stop-color:#00892C;fill:url(#linearGradient13243)"
offset="1" />
</linearGradient>
<path
id="path10"
d="M 63.718,0 C 71.232,0 78.445,0.652 82,6 C 85.555,11.348 75.978,14.839 78.645,19.459 C 85.19,22.815 101.277,22.06 112,22 C 112,22 112,53.03 112,53.376 C 106.208,56.712 100.089,51.931 95,51 C 85.395,55.274 85.348,78.515 95,82.68 C 100.722,83.13 100.419,77.649 107,78.96 C 112.013,85.694 112,112 112,112 L 22,112 C 22,112 22.422,83.565 19.538,80.682 C 16.654,77.799 14.483,85.954 7.26,84.41 C 2.943,82.345 0,78.605 0,68 C 0,57.395 2.812,52.71 7.068,50.316 C 13.635,48.93 14.699,57.379 18.178,53.9 C 21.657,50.421 22.07,34.826 22,22 C 32.448,22 45.674,24 52,19 C 52.428,13.665 48.199,13.695 48,9 C 49.149,2.904 56.22,0.222 63.718,0 z "
clip-rule="evenodd"
style="fill:url(#linearGradient13243);fill-rule:evenodd" />
</g><path
id="path90"
d="M 108.47928,18.045036 C 108.47121,18.045036 108.46414,18.045036 108.45708,18.045036 L 107.81521,18.053036 C 105.52429,18.084034 103.11328,18.115032 100.68005,18.115032 C 88.864141,18.115032 81.849073,17.229095 77.934321,15.239241 L 77.4065,14.96926 L 77.107772,14.460297 C 75.306319,11.364522 76.910974,8.8507039 79.038404,6.1039029 C 80.439197,4.2960347 80.948851,3.5030919 81.02858,2.6521537 C 81.049773,2.4281699 81.030598,2.2031862 80.9761,1.9852021 C 80.907474,1.7072222 80.767192,1.4132435 80.562321,1.1072657 C 77.722385,-3.1224273 71.824521,-3.994364 63.779044,-3.9963639 C 61.025899,-3.9093702 51.906615,-3.1664241 50.081951,2.6851512 C 49.984057,3.0041281 49.964882,3.3441034 50.03149,3.6710797 C 50.244435,4.7130036 50.809597,5.3829555 51.522103,6.2298944 C 52.749312,7.6837885 54.27222,9.4956574 53.977528,13.160391 L 53.908902,14.028328 L 53.217588,14.569289 C 48.912269,17.942044 42.37557,18.396011 36.548351,18.396011 C 34.030355,18.396011 31.426576,18.294019 28.850044,18.195025 C 27.809541,18.154029 26.791242,18.114032 25.799182,18.081034 C 25.77597,18.081034 25.753767,18.079034 25.730555,18.079034 C 25.209799,18.079034 24.708218,18.28002 24.330771,18.637994 C 23.937176,19.012966 23.716157,19.528929 23.71212,20.06889 C 23.599089,42.061294 21.398995,47.195921 19.260464,49.316767 C 18.284552,50.279697 17.279372,50.747663 16.18639,50.747663 C 14.451546,50.747663 13.214247,49.531751 12.11319,48.44883 L 11.91942,48.260844 L 11.54702,47.90087 C 10.410641,46.825948 9.4296827,46.161996 8.0591661,46.161996 C 7.658507,46.161996 7.2174791,46.281987 6.8824192,46.503971 C 3.2118971,48.951793 1.5022835,53.875437 1.5022835,61.997847 C 1.5022835,62.619802 1.5133849,63.212759 1.5345785,63.780717 C 31.217668,64.093694 70.03518,58.029135 110.49772,33.866889 L 110.49772,20.045892 C 110.49772,19.51193 110.28275,18.999967 109.89824,18.622995 C 109.5218,18.254021 109.01013,18.045036 108.47928,18.045036 z "
clip-rule="evenodd"
style="fill:url(#linearGradient13221);fill-rule:evenodd;stroke:url(#linearGradient13223);stroke-width:1.00456667" /><g
id="g31"
style="fill:url(#linearGradient13269);filter:url(#filter4299)"
transform="translate(0,-6)">
<linearGradient
id="SVGID_3_"
gradientUnits="userSpaceOnUse"
x1="73.623001"
y1="23.672899"
x2="118.9906"
y2="23.672899"
style="fill:url(#linearGradient3216)">
<stop
offset="0"
style="stop-color:#FFFFFF;fill:url(#linearGradient3216)"
id="stop34" />
<stop
offset="1"
style="stop-color:#000000;fill:url(#linearGradient3216)"
id="stop36" />
</linearGradient>
<path
clip-rule="evenodd"
d="M 77.314,21.023 C 77.438,21.49 77.628,21.966 77.913,22.46 L 78.209,22.969 L 78.732,23.239 C 82.611,25.229 89.562,26.115 101.27,26.115 C 103.681,26.115 106.071,26.084 108.34,26.053 L 108.976,26.045 C 108.984,26.045 108.991,26.045 108.998,26.045 C 109.353,26.045 109.696,26.147 109.998,26.322 L 109.998,26.045 C 109.998,25.511 109.785,24.999 109.404,24.622 C 109.031,24.253 108.524,24.044 107.998,24.044 C 107.99,24.044 107.983,24.044 107.976,24.044 L 107.34,24.052 C 105.07,24.083 102.681,24.114 100.27,24.114 C 88.562,24.114 81.611,23.228 77.732,21.238 L 77.314,21.023 z "
id="path38"
style="fill:url(#linearGradient13271);fill-rule:evenodd" />
</g><g
id="g40"
style="fill:url(#linearGradient13257);filter:url(#filter4299)"
transform="translate(2,-6)">
<linearGradient
id="SVGID_4_"
gradientUnits="userSpaceOnUse"
x1="86.693398"
y1="83.060501"
x2="111.9058"
y2="83.060501"
style="fill:url(#linearGradient3216)">
<stop
offset="0"
style="stop-color:#FFFFFF;fill:url(#linearGradient3216)"
id="stop43" />
<stop
offset="1"
style="stop-color:#000000;fill:url(#linearGradient3216)"
id="stop45" />
</linearGradient>
<path
clip-rule="evenodd"
d="M 95.208,86.515 L 95.513,86.648 L 95.842,86.672 C 96.125,86.694 96.395,86.705 96.652,86.705 C 99.594,86.705 101.274,85.371 102.622,84.301 C 103.601,83.521 104.245,83.038 105.18,82.843 C 105.317,82.815 105.451,82.802 105.585,82.802 C 106.084,82.802 106.547,83.005 106.91,83.332 C 106.755,82.863 106.595,82.417 106.426,82.02 C 106.108,81.27 105.374,80.802 104.585,80.802 C 104.451,80.802 104.316,80.815 104.18,80.843 C 103.245,81.038 102.602,81.521 101.622,82.301 C 100.274,83.371 98.595,84.705 95.652,84.705 C 95.395,84.705 95.126,84.694 94.842,84.672 L 94.513,84.648 L 94.208,84.515 C 91.836,83.493 90.052,81.66 88.745,79.415 C 90.08,82.559 92.163,85.202 95.208,86.515 z "
id="path47"
style="fill:url(#linearGradient13259);fill-rule:evenodd" />
</g><g
id="g49"
style="fill:url(#linearGradient13249);filter:url(#filter4299)"
transform="translate(0,-6)">
<linearGradient
id="SVGID_5_"
gradientUnits="userSpaceOnUse"
x1="-3.9907"
y1="47.521"
x2="69.618896"
y2="47.521"
style="fill:url(#linearGradient3216)">
<stop
offset="0"
style="stop-color:#FFFFFF;fill:url(#linearGradient3216)"
id="stop52" />
<stop
offset="1"
style="stop-color:#000000;fill:url(#linearGradient3216)"
id="stop54" />
</linearGradient>
<path
clip-rule="evenodd"
d="M 2.999,70 C 2.999,61.877 4.693,56.953 8.327,54.503 C 8.659,54.281 9.096,54.161 9.493,54.161 C 10.851,54.161 11.823,54.826 12.949,55.9 L 13.318,56.26 L 13.51,56.448 C 14.601,57.531 15.827,58.747 17.546,58.747 C 18.629,58.747 19.625,58.278 20.592,57.315 C 22.711,55.195 24.891,50.06 25.003,28.066 C 25.007,27.526 25.227,27.01 25.616,26.635 C 25.991,26.277 26.488,26.076 27.003,26.076 C 27.026,26.076 27.048,26.078 27.071,26.078 C 28.054,26.111 29.063,26.151 30.094,26.192 C 32.647,26.292 35.227,26.393 37.722,26.393 C 43.495,26.393 49.972,25.939 54.239,22.566 L 54.924,22.025 L 54.992,21.157 C 55.2,18.538 54.487,16.873 53.62,15.601 C 53.936,16.562 54.107,17.711 53.992,19.157 L 53.924,20.025 L 53.239,20.566 C 48.973,23.939 42.496,24.393 36.722,24.393 C 34.227,24.393 31.647,24.291 29.094,24.192 C 28.063,24.151 27.054,24.111 26.071,24.078 C 26.048,24.078 26.026,24.076 26.003,24.076 C 25.487,24.076 24.99,24.277 24.616,24.635 C 24.226,25.01 24.007,25.526 24.003,26.066 C 23.891,48.06 21.711,53.195 19.592,55.316 C 18.625,56.279 17.629,56.747 16.546,56.747 C 14.827,56.747 13.601,55.531 12.51,54.448 L 12.318,54.26 L 11.949,53.9 C 10.823,52.825 9.851,52.161 8.493,52.161 C 8.096,52.161 7.659,52.281 7.327,52.503 C 3.693,54.953 1.999,59.877 1.999,68 C 1.999,73.927 2.971,77.338 4.329,79.438 C 3.52,77.321 2.999,74.334 2.999,70 z "
id="path56"
style="fill:url(#linearGradient13251);fill-rule:evenodd" />
</g><g
id="g58"
style="fill:url(#linearGradient13245);filter:url(#filter4299)"
transform="translate(-2,-4)">
<linearGradient
id="SVGID_6_"
gradientUnits="userSpaceOnUse"
x1="21.6807"
y1="95.531197"
x2="25.875299"
y2="95.531197"
style="fill:url(#linearGradient3216)">
<stop
offset="0"
style="stop-color:#FFFFFF;fill:url(#linearGradient3216)"
id="stop61" />
<stop
offset="1"
style="stop-color:#000000;fill:url(#linearGradient3216)"
id="stop63" />
</linearGradient>
<path
clip-rule="evenodd"
d="M 22.022,81.343 C 23.062,84.495 24.117,91.695 24.041,107.991 C 24.039,108.52 24.248,109.032 24.623,109.409 C 24.748,109.534 24.892,109.634 25.042,109.721 C 25.125,88.172 23.22,82.671 22.022,81.343 z "
id="path65"
style="fill:url(#linearGradient13247);fill-rule:evenodd" />
</g><g
id="g67"
style="fill:url(#linearGradient13265);filter:url(#filter4299)"
transform="translate(0,-6)">
<linearGradient
id="SVGID_7_"
gradientUnits="userSpaceOnUse"
x1="46.571301"
y1="6.8223"
x2="89.260399"
y2="6.8223"
style="fill:url(#linearGradient3216)">
<stop
offset="0"
style="stop-color:#FFFFFF;fill:url(#linearGradient3216)"
id="stop70" />
<stop
offset="1"
style="stop-color:#000000;fill:url(#linearGradient3216)"
id="stop72" />
</linearGradient>
<path
clip-rule="evenodd"
d="M 51.082,11.643 C 51.022,11.324 51.039,10.995 51.134,10.684 C 52.942,4.832 61.979,4.089 64.706,4.002 C 72.203,4.004 77.816,4.776 80.8,8.387 C 80.794,8.252 80.779,8.116 80.746,7.985 C 80.678,7.707 80.539,7.413 80.336,7.107 C 77.522,2.877 71.678,2.005 63.706,2.003 C 60.978,2.09 51.942,2.833 50.134,8.685 C 50.037,9.004 50.018,9.344 50.084,9.671 C 50.245,10.461 50.607,11.04 51.082,11.643 z "
id="path74"
style="fill:url(#linearGradient13267);fill-rule:evenodd" />
</g></g>
</svg>

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -132,6 +132,13 @@ class JobManager(QAbstractTableModel):
self.emit(SIGNAL('dataChanged(QModelIndex, QModelIndex)'),
self.index(row, 0), self.index(row, 3))
def running_time_updated(self):
for job in self.jobs:
if not job.is_running:
continue
row = self.jobs.index(job)
self.emit(SIGNAL('dataChanged(QModelIndex, QModelIndex)'),
self.index(row, 3), self.index(row, 3))
def has_device_jobs(self):
for job in self.jobs:

View File

@ -21,7 +21,7 @@ from calibre.gui2 import APP_UID, warning_dialog, choose_files, error_dialog, \
pixmap_to_data, choose_dir, ORG_NAME, \
set_sidebar_directories, Dispatcher, \
SingleApplication, Application, available_height, \
max_available_height, config, info_dialog, import_format
max_available_height, config, info_dialog
from calibre.gui2.cover_flow import CoverFlow, DatabaseImages, pictureflowerror
from calibre.library.database import LibraryDatabase
from calibre.gui2.dialogs.scheduler import Scheduler
@ -658,11 +658,11 @@ class Main(MainWindow, Ui_MainWindow):
model = self.library_view.model()
paths = list(paths)
for i, path in enumerate(paths):
npath, fmt = import_format(path)
if npath is not None:
paths[i] = npath
formats[i] = fmt
#for i, path in enumerate(paths):
# npath, fmt = import_format(path)
# if npath is not None:
# paths[i] = npath
# formats[i] = fmt
duplicates, number_added = model.add_books(paths, formats, metadata)
if duplicates:
files = _('<p>Books with the same title as the following already exist in the database. Add them anyway?<ul>')

View File

@ -358,8 +358,8 @@ list of id numbers (you can get id numbers by using the list command). For examp
return 0
def do_add_format(db, id, fmt, buffer):
db.add_format(id, fmt.upper(), buffer, index_is_id=True)
def do_add_format(db, id, fmt, path):
db.add_format_with_hooks(id, fmt.upper(), path, index_is_id=True)
def command_add_format(args, dbpath):
@ -377,10 +377,10 @@ by id. You can get id by using the list command. If the format already exists, i
print >>sys.stderr, _('You must specify an id and an ebook file')
return 1
id, file, fmt = int(args[1]), open(args[2], 'rb'), os.path.splitext(args[2])[-1]
id, path, fmt = int(args[1]), args[2], os.path.splitext(args[2])[-1]
if not fmt:
print _('ebook file must have an extension')
do_add_format(get_db(dbpath, opts), id, fmt[1:], file)
do_add_format(get_db(dbpath, opts), id, fmt[1:], path)
return 0
def do_remove_format(db, id, fmt):

View File

@ -22,7 +22,8 @@ from calibre.utils.search_query_parser import SearchQueryParser
from calibre.ebooks.metadata import string_to_authors, authors_to_string
from calibre.ebooks.metadata.meta import get_metadata
from calibre.constants import preferred_encoding, iswindows, isosx
from calibre.ptempfile import PersistentTemporaryFile
from calibre.customize.ui import run_plugins_on_import
copyfile = os.link if hasattr(os, 'link') else shutil.copyfile
filesystem_encoding = sys.getfilesystemencoding()
@ -37,6 +38,7 @@ def normpath(x):
return x
_filename_sanitize = re.compile(r'[\xae\0\\|\?\*<":>\+\[\]/]')
def sanitize_file_name(name, substitute='_'):
'''
Sanitize the filename `name`. All invalid characters are replaced by `substitute`.
@ -656,6 +658,12 @@ class LibraryDatabase2(LibraryDatabase):
if self.has_format(index, format, index_is_id):
self.remove_format(id, format, index_is_id=True)
def add_format_with_hooks(self, index, format, fpath, index_is_id=False,
path=None, notify=True):
npath = self.run_import_plugins(fpath, format)
return self.add_format(index, format, open(npath, 'rb'),
index_is_id=index_is_id, path=path, notify=notify)
def add_format(self, index, format, stream, index_is_id=False, path=None, notify=True):
id = index if index_is_id else self.id(index)
if path is None:
@ -1077,6 +1085,18 @@ class LibraryDatabase2(LibraryDatabase):
self.data.refresh_ids(self.conn, [id]) # Needed to update format list and size
return id
def run_import_plugins(self, path_or_stream, format):
format = format.lower()
if hasattr(path_or_stream, 'seek'):
path_or_stream.seek(0)
pt = PersistentTemporaryFile('_import_plugin.'+format)
shutil.copyfileobj(path_or_stream, pt, 1024**2)
pt.close()
path = pt.name
else:
path = path_or_stream
return run_plugins_on_import(path, format)
def add_books(self, paths, formats, metadata, uris=[], add_duplicates=True):
'''
Add a book to the database. The result cache is not updated.
@ -1105,12 +1125,10 @@ class LibraryDatabase2(LibraryDatabase):
self.set_path(id, True)
self.conn.commit()
self.set_metadata(id, mi)
stream = path if hasattr(path, 'read') else open(path, 'rb')
stream.seek(0)
npath = self.run_import_plugins(path, format)
stream = open(npath, 'rb')
self.add_format(id, format, stream, index_is_id=True)
if not hasattr(path, 'read'):
stream.close()
stream.close()
self.conn.commit()
self.data.refresh_ids(self.conn, ids) # Needed to update format list and size
if duplicates:

View File

@ -203,7 +203,7 @@ There can be several causes for this:
If it still wont launch, start a command prompt (press the windows key and R; then type :command:`cmd.exe` in the Run dialog that appears). At the command prompt type the following command and press Enter::
calibre-debug -c "from calibre.gui2.main import main; main()"
calibre-debug -g
Post any output you see in a help message on the `Forum <http://www.mobileread.com/forums/forumdisplay.php?f=166>`_.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff