'Connect `source_node` to `sink_node`. If there are more then one
equally weighted and non conflicting links possible present a
detailed dialog for link editing.'

def connect_nodes(self, source_node, sink_node):

    try:
        possible = self.scheme.propose_links(source_node, sink_node)
        log.debug('proposed    (weighted)    links:    %r', [(s1.name, s2.name, w) for (s1, s2, w) in possible])
        if (not possible):
            raise NoPossibleLinksError
        (source, sink, w) = possible[0]
        links_to_add = [(source, sink)]
        links_to_remove = []
        show_link_dialog = self.force_link_dialog
        if (len(possible) >= 2):
            (_, _, w2) = possible[1]
            if (w == w2):
                show_link_dialog = True
            if (sink.single and self.scheme.find_links(sink_node=sink_node, sink_channel=sink)):
                show_link_dialog = True
        if show_link_dialog:
            existing = self.scheme.find_links(source_node=source_node, sink_node=sink_node)
            if existing:
                initial_links = None
            else:
                initial_links = [(source, sink)]
            try:
                (rstatus, links_to_add, links_to_remove) = self.edit_links(source_node, sink_node, initial_links)
            except Exception:
                log.error('Failed    to    edit    the    links', exc_info=True)
                raise
            if (rstatus == EditLinksDialog.Rejected):
                raise UserCanceledError
        else:
            links_to_add = [scheme.SchemeLink(source_node, source_channel, sink_node, sink_channel) for (source_channel, sink_channel) in links_to_add]
            (links_to_add, links_to_remove) = add_links_plan(self.scheme, links_to_add)
        self.cleanup()
        for link in links_to_remove:
            commands.RemoveLinkCommand(self.scheme, link, parent=self.macro)
        for link in links_to_add:
            duplicate = self.scheme.find_links(link.source_node, link.source_channel, link.sink_node, link.sink_channel)
            if (not duplicate):
                commands.AddLinkCommand(self.scheme, link, parent=self.macro)
    except scheme.IncompatibleChannelTypeError:
        log.info('Cannot    connect:    invalid    channel    types.')
        self.cancel()
    except scheme.SchemeTopologyError:
        log.info('Cannot    connect:    connection    creates    a    cycle.')
        self.cancel()
    except NoPossibleLinksError:
        log.info('Cannot    connect:    no    possible    links.')
        self.cancel()
    except UserCanceledError:
        log.info('User    canceled    a    new    link    action.')
        self.cancel(UserInteraction.UserCancelReason)
    except Exception:
        log.error('An    error    occurred    during    the    creation    of    a    new    link.', exc_info=True)
        self.cancel()
    finally:
        self.force_link_dialog = False
