def update_plugin_dialog(package_name=None, update_args=None,<EOL>update_kwargs=None, ignore_not_installed=True):
thread_context = {}<EOL>if package_name is None:<EOL><INDENT>installed_plugins_ = installed_plugins(only_conda=True)<EOL>installed_package_names = [plugin_i['<STR_LIT>']<EOL>for plugin_i in installed_plugins_]<EOL>package_name = installed_package_names<EOL>logger.info('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>if isinstance(package_name, (str,)):<EOL><INDENT>package_name = [package_name]<EOL><DEDENT>try:<EOL><INDENT>conda_package_infos = ch.package_version(package_name, verbose=False)<EOL><DEDENT>except ch.PackageNotFound as exception:<EOL><INDENT>if not ignore_not_installed:<EOL><INDENT>raise<EOL><DEDENT>logger.warning(str(exception))<EOL>conda_package_infos = exception.available<EOL><DEDENT>package_name = [package_i['<STR_LIT:name>'] for package_i in conda_package_infos]<EOL>logger.info('<STR_LIT>',<EOL>'<STR_LIT:U+002CU+0020>'.join('<STR_LIT>'.format(name_i)<EOL>for name_i in package_name))<EOL><DEDENT>package_name_list = '<STR_LIT:U+002CU+0020>'.join('<STR_LIT>'.format(name_i)<EOL>for name_i in package_name)<EOL>package_name_lines = '<STR_LIT:\n>'.join('<STR_LIT>'.format(name_i)<EOL>for name_i in package_name)<EOL>def _update(update_complete, package_name):<EOL><INDENT>'''<STR_LIT>'''<EOL>try:<EOL><INDENT>with lh.logging_restore(clear_handlers=True):<EOL><INDENT>args = update_args or []<EOL>kwargs = update_kwargs or {}<EOL>kwargs['<STR_LIT>'] = package_name<EOL>update_response = update(*args, **kwargs)<EOL>thread_context['<STR_LIT>'] = update_response<EOL><DEDENT>install_info_ = ch.install_info(update_response)<EOL>if any(install_info_):<EOL><INDENT>def _status():<EOL><INDENT>updated_packages = []<EOL>for package_name_i in package_name:<EOL><INDENT>if any(linked_i[<NUM_LIT:0>].startswith(package_name_i)<EOL>for linked_i in install_info_[<NUM_LIT:1>]):<EOL><INDENT>updated_packages.append(package_name_i)<EOL><DEDENT><DEDENT>def _version_lines(package_info_tuples):<EOL><INDENT>return (['<STR_LIT>'] + list('<STR_LIT>'<EOL>.format(name_i, channel_i)<EOL>for name_i, channel_i in<EOL>package_info_tuples) +<EOL>['<STR_LIT>'])<EOL><DEDENT>detailed_message_lines = []<EOL>if install_info_[<NUM_LIT:0>]:<EOL><INDENT>detailed_message_lines.append('<STR_LIT>')<EOL>(detailed_message_lines<EOL>.extend(_version_lines(install_info_[<NUM_LIT:0>])))<EOL><DEDENT>if install_info_[<NUM_LIT:1>]:<EOL><INDENT>detailed_message_lines.append('<STR_LIT>')<EOL>(detailed_message_lines<EOL>.extend(_version_lines(install_info_[<NUM_LIT:1>])))<EOL><DEDENT>dialog.props.secondary_text ='<STR_LIT:\n>'.join(detailed_message_lines)<EOL>dialog.props.secondary_use_markup = True<EOL>dialog.props.use_markup = True<EOL>if updated_packages:<EOL><INDENT>message = ('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>.format(package_name_lines))<EOL><DEDENT>else:<EOL><INDENT>message = ('<STR_LIT>'<EOL>'<STR_LIT>')<EOL><DEDENT>dialog.props.text = message<EOL><DEDENT><DEDENT>else:<EOL><INDENT>def _status():<EOL><INDENT>dialog.props.text = ('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>.format(package_name_list))<EOL>dialog.props.use_markup = True<EOL><DEDENT><DEDENT>gobject.idle_add(_status)<EOL><DEDENT>except Exception as exception:<EOL><INDENT>def _error():<EOL><INDENT>dialog.props.text = ('<STR_LIT>'<EOL>.format(package_name_lines))<EOL>dialog.props.use_markup = True<EOL>exception_markup = gobject.markup_escape_text(str(exception))<EOL>exception_markup = exception_markup.replace(r'<STR_LIT:\n>', '<STR_LIT:\n>')<EOL>content_area = dialog.get_content_area()<EOL>label = gtk.Label()<EOL>label.set_markup(exception_markup)<EOL>error_scroll = gtk.ScrolledWindow()<EOL>error_scroll.set_policy(gtk.POLICY_AUTOMATIC,<EOL>gtk.POLICY_AUTOMATIC)<EOL>error_scroll.add_with_viewport(label)<EOL>error_scroll.show_all()<EOL>content_area.pack_start(error_scroll, expand=True, fill=True)<EOL><DEDENT>gobject.idle_add(_error)<EOL>thread_context['<STR_LIT>'] = None<EOL><DEDENT>update_complete.set()<EOL><DEDENT>def _pulse(update_complete, progress_bar):<EOL><INDENT>'''<STR_LIT>'''<EOL>while not update_complete.wait(<NUM_LIT:1.> / <NUM_LIT:16>):<EOL><INDENT>gobject.idle_add(progress_bar.pulse)<EOL><DEDENT>def _on_complete():<EOL><INDENT>progress_bar.set_fraction(<NUM_LIT:1.>)<EOL>progress_bar.hide()<EOL>dialog.action_area.get_children()[<NUM_LIT:1>].props.sensitive = True<EOL>dialog.action_area.get_children()[<NUM_LIT:1>].grab_focus()<EOL><DEDENT>gobject.idle_add(_on_complete)<EOL><DEDENT>dialog = gtk.MessageDialog(buttons=gtk.BUTTONS_OK_CANCEL)<EOL>dialog.set_position(gtk.WIN_POS_MOUSE)<EOL>dialog.props.resizable = True<EOL>progress_bar = gtk.ProgressBar()<EOL>content_area = dialog.get_content_area()<EOL>content_area.pack_start(progress_bar, True, True, <NUM_LIT:5>)<EOL>content_area.show_all()<EOL>dialog.action_area.get_children()[<NUM_LIT:1>].props.sensitive = False<EOL>dialog.props.title = '<STR_LIT>'<EOL>if len(package_name) > <NUM_LIT:1>:<EOL><INDENT>dialog.props.text = ('<STR_LIT>'<EOL>.format(package_name_lines))<EOL><DEDENT>else:<EOL><INDENT>dialog.props.text = ('<STR_LIT>'<EOL>.format(package_name[<NUM_LIT:0>]))<EOL><DEDENT>dialog.props.use_markup = True<EOL>update_complete = threading.Event()<EOL>progress_thread = threading.Thread(target=_pulse, args=(update_complete,<EOL>progress_bar, ))<EOL>progress_thread.daemon = True<EOL>progress_thread.start()<EOL>update_thread = threading.Thread(target=_update, args=(update_complete,<EOL>package_name, ))<EOL>update_thread.daemon = True<EOL>update_thread.start()<EOL>dialog.run()<EOL>dialog.destroy()<EOL>return thread_context.get('<STR_LIT>')<EOL>
Launch dialog to track status of update of specified plugin package.

.. versionadded:: 0.19

.. versionchanged:: 0.20
    Add support for updating multiple packages (update all **installed**
    plugins by default).

    Add :data:`update_args` and :data:`update_kwargs` arguments.

.. versionchanged:: 0.20.1
    Disable "OK" button until update has completed.

    Add "Cancel" button.

.. versionchanged:: 0.20.3
    Fix typo in handling of attempt to update plugin packages that are not
    installed.

.. versionchanged:: 0.23
    Add :data:`ignore_not_installed` parameter.

.. versionchanged:: 0.23.1
    Fix bug in status message markup syntax when no packages are unlinked
    **or** linked.

Parameters
----------
package_name : str or list, optional
    Conda MicroDrop plugin package name, e.g., `microdrop.mr-box-plugin`.

    Multiple plugin package names may be provided as a list.

    If no package name(s) specified, update **all installed** plugin
    packages.
update_args : list or tuple, optional
    Extra arguments to pass to :func:`mpm.api.update` call.
update_kwargs : dict, optional
    Extra keyword arguments to pass to :func:`mpm.api.update` call.
ignore_not_installed : bool, optional
    If ``True`` (*default*), ignore plugin packages that are not installed
    as Conda packages.

    Otherwise, a :class:`conda_heplers.PackageNotFound` exception will be
    raised for plugins that are not installed as Conda packages.

Returns
-------
dict or None
    Conda install log.

    If dialog is closed or cancelled, ``None`` is returned.

Notes
-----
This function launches two threads; one to pulse the progress bar
periodically, and one to run the actual update attempt.