'Apply the metadata changes in id_map to the database synchronously
id_map must be a mapping of ids to Metadata objects. Set any fields you
do not want updated in the Metadata object to null. An easy way to do
that is to create a metadata object as Metadata(_(\'Unknown\')) and then
only set the fields you want changed on this object.
callback can be either None or a function accepting a single argument,
in which case it is called after applying is complete with the list of
changed ids.
id_map can also be a mapping of ids to 2-tuple\'s where each 2-tuple
contains the absolute paths to an OPF and cover file respectively. If
either of the paths is None, then the corresponding metadata is not
updated.'

def apply_metadata_changes(self, id_map, title=None, msg='', callback=None, merge_tags=True, merge_comments=False, icon=None):

    if (title is None):
        title = _('Applying    changed    metadata')
    self.apply_id_map = list(id_map.iteritems())
    self.apply_current_idx = 0
    self.apply_failures = []
    self.applied_ids = set()
    self.apply_pd = None
    self.apply_callback = callback
    if (len(self.apply_id_map) > 1):
        from calibre.gui2.dialogs.progress import ProgressDialog
        self.apply_pd = ProgressDialog(title, msg, min=0, max=(len(self.apply_id_map) - 1), parent=self.gui, cancelable=False, icon=icon)
        self.apply_pd.setModal(True)
        self.apply_pd.show()
    self._am_merge_tags = merge_tags
    self._am_merge_comments = merge_comments
    self.do_one_apply()
