.. include:: global.rst

.. currentmodule:: calibre.customize.__init__

.. _customize:

Customizing |app|
==================================

|app| has a highly modular design. Various parts of it can be customized. You can learn how to create
*recipes* to add new sources of online content to |app| in the Section :ref:`news`. Here, you will learn,
first, how to use environment variables and *tweaks* to customize |app|'s behavior,  and then how to
specify your own static resources like icons and templates to override the defaults and finally how to 
use *plugins* to add functionality to |app|.

.. contents::
    :depth: 2
    :local:

Environment variables
-----------------------

    * ``CALIBRE_CONFIG_DIRECTORY`` - sets the directory where configuration files are stored/read.
    * ``CALIBRE_TEMP_DIR`` - sets the temporary directory used by calibre
    * ``CALIBRE_OVERRIDE_DATABASE_PATH`` - allows you to specify the full path to metadata.db. Using this variable you can have metadata.db be in a location other than the library folder. Useful if your library folder is on a networked drive that does not support file locking.
    * ``CALIBRE_DEVELOP_FROM`` - Used to run from a calibre development environment. See :ref:`develop`.
    * ``CALIBRE_OVERRIDE_LANG`` - Used to force the language used by the interface (ISO 639 language code)
    * ``CALIBRE_DISABLE_UDISKS`` - Used to disable the use of udisks for mounting/ejecting. Set it to 1 to use calibre-mount-helper instead.
    * ``SYSFS_PATH`` - Use if sysfs is mounted somewhere other than /sys
    * ``http_proxy`` - Used on linux to specify an HTTP proxy

Tweaks
------------

Tweaks are small changes that you can specify to control various aspects of |app|'s behavior. You can change them by going to Preferences->Advanced->Tweaks.
The default values for the tweaks are reproduced below

.. literalinclude:: ../../../resources/default_tweaks.py


Overriding icons, templates, etcetera
----------------------------------------

|app| allows you to override the static resources, like icons, templates, javascript, etc. with customized versions that you like.
All static resources are stored in the resources sub-folder of the calibre install location. On Windows, this is usually
:file:`C:\Program Files\Calibre2\resources`. On OS X, :file:`/Applications/calibre.app/Contents/Resources/resources/`. On linux, if you are using the binary installer
from the calibre website it will be :file:`/opt/calibre/resources`. These paths can change depending on where you choose to install |app|. 

You should not change the files in this resources folder, as your changes will get overwritten the next time you update |app|. Instead, go to
:guilabel:`Preferences->Advanced->Miscellaneous` and click :guilabel:`Open calibre configuration directory`. In this configuration directory, create a sub-folder called resources and place the files you want to override in it. Place the files in the appropriate sub folders, for example place images in :file:`resources/images`, etc. 
|app| will automatically use your custom file in preference to the builtin one the next time it is started.

For example, if you wanted to change the icon for the :guilabel:`Remove books` action, you would first look in the builtin resources folder and see that the relevant file is
:file:`resources/images/trash.svg`. Assuming you have an alternate icon in svg format called :file:`mytrash.svg` you would save it in the configuration directory as :file:`resources/images/trash.svg`. All the icons used by the calibre user interface are in :file:`resources/images` and its sub-folders.

A Hello World plugin
------------------------

Suppose you have an installation of |app| that you are using to self publish various e-documents in EPUB and LRF
format. You would like all file generated by |app| to have their publisher set as "Hello world", here's how to do it.
Create a file name :file:`my_plugin.py` (the file name must end with plugin.py) and enter the following Python code into it:

.. code-block:: python

  import os
  from calibre.customize import FileTypePlugin

  class HelloWorld(FileTypePlugin):

    name                = 'Hello World Plugin' # Name of the plugin
    description         = 'Set the publisher to Hello World for all new conversions' 
    supported_platforms = ['windows', 'osx', 'linux'] # Platforms this plugin will run on
    author              = 'Acme Inc.' # The author of this plugin
    version             = (1, 0, 0)   # The version number of this plugin
    file_types          = set(['epub', 'lrf']) # The file types that this plugin will be applied to
    on_postprocess      = True # Run this plugin after conversion is complete
    
    def run(self, path_to_ebook):
      from calibre.ebooks.metadata.meta import get_metadata, set_metadata
      file = open(path_to_ebook, 'r+b')
      ext  = os.path.splitext(path_to_ebook)[-1][1:].lower()
      mi = get_metadata(file, ext)
      mi.publisher = 'Hello World'
      set_metadata(file, mi, ext)
      return path_to_ebook

That's all. To add this code to |app| as a plugin, simply create a zip file with::

    zip plugin.zip my_plugin.py

You can download the Hello World plugin from 
`helloworld_plugin.zip  <http://calibre-ebook.com/downloads/helloworld_plugin.zip>`_. 
Now either use the configuration dialog in |app| GUI to add this zip file as a plugin, or
use the command::

    calibre-customize -a plugin.zip

Every time you use calibre to convert a book, the plugin's :meth:`run` method will be called and the 
converted book will have its publisher set to "Hello World". For more information about 
|app|'s plugin system, read on...


A Hello World GUI plugin
---------------------------

Here's a simple Hello World plugin for the |app| GUI. It will cause a box to popup with the message "Hellooo World!" when you press Ctrl+Shift+H

.. note:: Only available in calibre versions ``>= 0.7.32``.

.. code-block:: python

    from calibre.customize import InterfaceActionBase

    class HelloWorldBase(InterfaceActionBase):

        name = 'Hello World GUI'
        author = 'The little green man'

        def load_actual_plugin(self, gui):
            from calibre.gui2.actions import InterfaceAction

            class HelloWorld(InterfaceAction):
                name = 'Hello World GUI'
                action_spec = ('Hello World!', 'add_book.png', None,
                        _('Ctrl+Shift+H'))

                def genesis(self):
                    self.qaction.triggered.connect(self.hello_world)

                def hello_world(self, *args):
                    from calibre.gui2 import info_dialog
                    info_dialog(self.gui, 'Hello World!', 'Hellooo World!',
                            show=True)

            return HelloWorld(gui, self.site_customization)

You can also have it show up in the toolbars/context menu by going to Preferences->Toolbars and adding this plugin to the locations you want it to be in.

While this plugin is utterly useless, note that all calibre GUI actions like adding/saving/removing/viewing/etc. are implemented as plugins, so there is no limit to what you can achieve. The key thing to remember is that the plugin has access to the full |app| GUI via ``self.gui``.


The Plugin base class
------------------------

As you may have noticed above, all |app| plugins are classes. The Plugin classes are organized in a hierarchy at the top of which
is :class:`calibre.customize.Plugin`. The has excellent in source documentation for its various features, here I will discuss a
few of the important ones.

First, all plugins must supply a list of platforms they have been tested on by setting the ``supported_platforms`` member as in the
example above. 

If the plugin needs to do any initialization, it should implement the :meth:`initialize` method. The path to the plugin zip file
is available as ``self.plugin_path``. The initialization method could be used to load any needed resources from the zip file. 

If the plugin needs to be customized (i.e. it needs some information from the user), it should implement the :meth:`customization_help`
method, to indicate to |app| that it needs user input. This can be useful, for example, to ask the user to input the path to a needed system 
binary or the URL of a website, etc. When |app| asks the user for the customization information, the string retuned by the :meth:`customization_help`
method is used as help text to le thte user know what information is needed. 

Another useful method is :meth:`temporary_file`, which returns a file handle to an opened temporary file. If your plugin needs to make use 
of temporary files, it should use this method. Temporary file cleanup is then taken care of automatically.

In addition, whenever plugins are run, their zip files are automatically added to the start of ``sys.path``, so you can directly import
any python files you bundle in the zip files. Note that this is not available when the plugin is being initialized, only when it is being run.

Finally, plugins can have a priority (a positive integer). Higher priority plugins are run in preference tolower priority ones in a given context. 
By default all plugins have priority 1. You can change that by setting the member :attr:'priority` in your subclass.

See :ref:`pluginsPlugin` for details.

File type plugins
-------------------

File type plugins are intended to be associated with specific file types (as identified by extension). They can be run on several different occassions.

  * When books/formats are added ot the |app| database (if :attr:`on_import` is set to True).
  * Just before an any2whatever converter is run on an input file (if :attr:`on_preprocess` is set to True).
  * After an any2whatever converter has run, on the output file (if :attr:`on_postprocess` is set to True).

File type plugins specify which file types they are associated with by specifying the :attr:`file_types` member as in the above example.
the actual work should be done in the :meth:`run` method, which must return the path to the modified ebook (it can be the same as the original
if the modifcations are done in place). 

See :ref:`pluginsFTPlugin` for details.

Metadata plugins
-------------------

Metadata plugins add the ability to read/write metadata from ebook files to |app|. See :ref:`pluginsMetadataPlugin` for details. 

.. toctree::
   :hidden:
   
   plugins

Metadata download plugins
----------------------------

Metadata download plugins add various sources that |app| uses to download metadata based on title/author/isbn etc. See :ref:`pluginsMetadataSource`
for details.
