Пример #1
0
 def actionTriggered(self, name):
     name = name[8:]
     direction = ['_', '', '^'][self.direction() + 1]
     isSpanner = name not in dynamic_marks
     if isSpanner:
         dynamic = dynamic_spanners[name]
     else:
         dynamic = '\\' + name
     cursor = self.mainwindow().textCursor()
     if not cursor.hasSelection():
         # dynamic right before the cursor?
         left = tokeniter.partition(cursor).left
         if not left or not isinstance(left[-1], ly.lex.lilypond.Dynamic):
             # no, find the first pitch
             c = lydocument.cursor(cursor)
             c.end = None
             for item in ly.rhythm.music_items(c,
                                               partial=ly.document.OUTSIDE):
                 cursor.setPosition(item.end)
                 break
         cursor.insertText(direction + dynamic)
         self.mainwindow().currentView().setTextCursor(cursor)
     else:
         c = lydocument.cursor(cursor)
         cursors = []
         for item in ly.rhythm.music_items(c):
             csr = QTextCursor(cursor.document())
             csr.setPosition(item.end)
             cursors.append(csr)
         if not cursors:
             return
         c1, c2 = cursors[0], cursors[-1]
         # are there dynamics at the cursor? then skip them
         d1 = dynamics(c1)
         if d1:
             c1 = tokeniter.cursor(c1.block(), d1[-1], start=len(d1[-1]))
         with cursortools.compress_undo(cursor):
             if len(cursors) > 1:
                 # dynamics after the end cursor?
                 d2 = dynamics(c2)
                 if isSpanner and not d2:
                     # don't terminate the spanner if there's a dynamic there
                     c2.insertText('\\!')
                 elif set(d1).intersection(dynamic_spanners.values()):
                     # write the dynamic at the end if there's a spanner at start
                     # remove ending \! if there
                     terminator = tokeniter.find("\\!", d2)
                     if terminator:
                         c2 = tokeniter.cursor(c2.block(), terminator)
                     if direction in d1:
                         c2.insertText(dynamic)
                     else:
                         c2.insertText(direction + dynamic)
                     return
             c1.insertText(direction + dynamic)
Пример #2
0
 def actionTriggered(self, name):
     name = name[8:]
     direction = ['_', '', '^'][self.direction() + 1]
     isSpanner = name not in dynamic_marks
     if isSpanner:
         dynamic = dynamic_spanners[name]
     else:
         dynamic = '\\' + name
     cursor = self.mainwindow().textCursor()
     if not cursor.hasSelection():
         # dynamic right before the cursor?
         left = tokeniter.partition(cursor).left
         if not left or not isinstance(left[-1], ly.lex.lilypond.Dynamic):
             # no, find the first pitch
             c = lydocument.cursor(cursor)
             c.end = None
             for item in ly.rhythm.music_items(c, partial=ly.document.OUTSIDE):
                 cursor.setPosition(item.end)
                 break
         cursor.insertText(direction + dynamic)
         self.mainwindow().currentView().setTextCursor(cursor)
     else:
         c = lydocument.cursor(cursor)
         cursors = []
         for item in ly.rhythm.music_items(c):
             csr = QTextCursor(cursor.document())
             csr.setPosition(item.end)
             cursors.append(csr)
         if not cursors:
             return
         c1, c2 = cursors[0], cursors[-1]
         # are there dynamics at the cursor? then skip them
         d1 = dynamics(c1)
         if d1:
             c1 = tokeniter.cursor(c1.block(), d1[-1], start=len(d1[-1]))
         with cursortools.compress_undo(cursor):
             if len(cursors) > 1:
                 # dynamics after the end cursor?
                 d2 = dynamics(c2)
                 if isSpanner and not d2:
                     # don't terminate the spanner if there's a dynamic there
                     c2.insertText('\\!')
                 elif set(d1).intersection(dynamic_spanners.values()):
                     # write the dynamic at the end if there's a spanner at start
                     # remove ending \! if there
                     terminator = tokeniter.find("\\!", d2)
                     if terminator:
                         c2 = tokeniter.cursor(c2.block(), terminator)
                     if direction in d1:
                         c2.insertText(dynamic)
                     else:
                         c2.insertText(direction + dynamic)
                     return
             c1.insertText(direction + dynamic)
Пример #3
0
def articulation_positions(cursor):
    """Returns a list of positions where an articulation can be added.
    
    Every position is given as a QTextCursor instance.
    If the cursor has a selection, all positions in the selection are returned.
    
    """
    c = lydocument.cursor(cursor)
    if not cursor.hasSelection():
        # just select til the end of the current line
        c.select_end_of_block()
        rests = True
        partial = ly.document.OUTSIDE
    else:
        rests = False
        partial = ly.document.INSIDE
    source = lydocument.Source(c, True, partial, True)
    
    positions = []
    for p in ly.rhythm.music_tokens(source):
        if not rests and isinstance(p[0], ly.lex.lilypond.Rest):
            continue
        positions.append(source.cursor(p[-1], start=len(p[-1])))
        if not cursor.hasSelection():
            break # leave if first found, that's enough
    return positions
Пример #4
0
def changeLanguage(cursor, language):
    """Changes the language of the pitch names."""
    c = lydocument.cursor(cursor, select_all=True)
    try:
        with qutil.busyCursor():
            changed = ly.pitch.translate.translate(c, language)
    except ly.pitch.PitchNameNotAvailable:
        QMessageBox.critical(
            None, app.caption(_("Pitch Name Language")),
            _("Can't perform the requested translation.\n\n"
              "The music contains quarter-tone alterations, but "
              "those are not available in the pitch language \"{name}\".").
            format(name=language))
        return
    if changed:
        return
    if not cursor.hasSelection():
        # there was no selection and no language command, so insert one
        version = (documentinfo.docinfo(cursor.document()).version()
                   or lilypondinfo.preferred().version())
        ly.pitch.translate.insert_language(c.document, language, version)
        return
    # there was a selection but no command, user must insert manually.
    QMessageBox.information(
        None, app.caption(_("Pitch Name Language")), '<p>{0}</p>'
        '<p><code>\\include "{1}.ly"</code> {2}</p>'
        '<p><code>\\language "{1}"</code> {3}</p>'.format(
            _("The pitch language of the selected text has been "
              "updated, but you need to manually add the following "
              "command to your document:"), language,
            _("(for LilyPond below 2.14), or"),
            _("(for LilyPond 2.14 and higher.)")))
Пример #5
0
def changeLanguage(cursor, language):
    """Changes the language of the pitch names."""
    c = lydocument.cursor(cursor, select_all=True)
    try:
        with qutil.busyCursor():
            changed = ly.pitch.translate.translate(c, language)
    except ly.pitch.PitchNameNotAvailable:
        QMessageBox.critical(None, app.caption(_("Pitch Name Language")), _(
            "Can't perform the requested translation.\n\n"
            "The music contains quarter-tone alterations, but "
            "those are not available in the pitch language \"{name}\"."
            ).format(name=language))
        return
    if changed:
        return
    if not cursor.hasSelection():
        # there was no selection and no language command, so insert one
        version = (documentinfo.docinfo(cursor.document()).version()
                   or lilypondinfo.preferred().version())
        ly.pitch.translate.insert_language(c.document, language, version)
        return
    # there was a selection but no command, user must insert manually.
    QMessageBox.information(None, app.caption(_("Pitch Name Language")),
        '<p>{0}</p>'
        '<p><code>\\include "{1}.ly"</code> {2}</p>'
        '<p><code>\\language "{1}"</code> {3}</p>'.format(
            _("The pitch language of the selected text has been "
                "updated, but you need to manually add the following "
                "command to your document:"),
            language,
            _("(for LilyPond below 2.14), or"),
            _("(for LilyPond 2.14 and higher.)")))
Пример #6
0
def abs2rel(cursor, startpitch, first_pitch_absolute):
    """Converts pitches from absolute to relative."""
    with qutil.busyCursor():
        c = lydocument.cursor(cursor, select_all=True)
        ly.pitch.abs2rel.abs2rel(c,
                                 startpitch=startpitch,
                                 first_pitch_absolute=first_pitch_absolute)
Пример #7
0
def spanner_positions(cursor):
    """Return a list with 0 to 2 QTextCursor instances.

    At the first cursor a starting spanner item can be inserted, at the
    second an ending item.

    """
    c = lydocument.cursor(cursor)
    if cursor.hasSelection():
        partial = ly.document.INSIDE
    else:
        # just select until the end of the current line
        c.select_end_of_block()
        partial = ly.document.OUTSIDE

    items = list(ly.rhythm.music_items(c, partial=partial))
    if cursor.hasSelection():
        del items[1:-1]
    else:
        del items[2:]

    positions = []
    for i in items:
        c = QTextCursor(cursor.document())
        c.setPosition(i.end)
        positions.append(c)
    return positions
Пример #8
0
def articulation_positions(cursor):
    """Returns a list of positions where an articulation can be added.
    
    Every position is given as a QTextCursor instance.
    If the cursor has a selection, all positions in the selection are returned.
    
    """
    c = lydocument.cursor(cursor)
    if not cursor.hasSelection():
        # just select until the end of the current line
        c.select_end_of_block()
        rests = True
        partial = ly.document.OUTSIDE
    else:
        rests = False
        partial = ly.document.INSIDE

    positions = []
    for item in ly.rhythm.music_items(c, partial):
        if not rests and item.tokens and isinstance(item.tokens[0],
                                                    ly.lex.lilypond.Rest):
            continue
        csr = QTextCursor(cursor.document())
        csr.setPosition(item.end)
        positions.append(csr)
        if not cursor.hasSelection():
            break  # leave if first found, that's enough
    return positions
Пример #9
0
def articulation_positions(cursor):
    """Returns a list of positions where an articulation can be added.
    
    Every position is given as a QTextCursor instance.
    If the cursor has a selection, all positions in the selection are returned.
    
    """
    c = lydocument.cursor(cursor)
    if not cursor.hasSelection():
        # just select until the end of the current line
        c.select_end_of_block()
        rests = True
        partial = ly.document.OUTSIDE
    else:
        rests = False
        partial = ly.document.INSIDE
    source = lydocument.Source(c, True, partial, True)

    positions = []
    for p in ly.rhythm.music_tokens(source):
        if not rests and isinstance(p[0], ly.lex.lilypond.Rest):
            continue
        positions.append(source.cursor(p[-1], start=len(p[-1])))
        if not cursor.hasSelection():
            break  # leave if first found, that's enough
    return positions
Пример #10
0
def spanner_positions(cursor):
    """Return a list with 0 to 2 QTextCursor instances.
    
    At the first cursor a starting spanner item can be inserted, at the
    second an ending item.
    
    """
    c = lydocument.cursor(cursor)
    if cursor.hasSelection():
        partial = ly.document.INSIDE
    else:
        # just select until the end of the current line
        c.select_end_of_block()
        partial = ly.document.OUTSIDE

    items = list(ly.rhythm.music_items(c, partial=partial))
    if cursor.hasSelection():
        del items[1:-1]
    else:
        del items[2:]

    positions = []
    for i in items:
        c = QTextCursor(cursor.document())
        c.setPosition(i.end)
        positions.append(c)
    return positions
Пример #11
0
def articulation_positions(cursor):
    """Returns a list of positions where an articulation can be added.
    
    Every position is given as a QTextCursor instance.
    If the cursor has a selection, all positions in the selection are returned.
    
    """
    c = lydocument.cursor(cursor)
    if not cursor.hasSelection():
        # just select until the end of the current line
        c.select_end_of_block()
        rests = True
        partial = ly.document.OUTSIDE
    else:
        rests = False
        partial = ly.document.INSIDE

    positions = []
    for item in ly.rhythm.music_items(c, partial):
        if not rests and item.tokens and isinstance(item.tokens[0], ly.lex.lilypond.Rest):
            continue
        csr = QTextCursor(cursor.document())
        csr.setPosition(item.end)
        positions.append(csr)
        if not cursor.hasSelection():
            break  # leave if first found, that's enough
    return positions
Пример #12
0
 def actionTriggered(self, name):
     # convert arpeggio_normal to arpeggioNormal, etc.
     name = _arpeggioTypes[name]
     cursor = self.mainwindow().textCursor()
     # which arpeggio type is last used?
     lastused = '\\arpeggioNormal'
     types = set(_arpeggioTypes.values())
     block = cursor.block()
     while block.isValid():
         s = types.intersection(tokeniter.tokens(block))
         if s:
             lastused = s.pop()
             break
         block = block.previous()
     # where to insert
     c = lydocument.cursor(cursor)
     c.select_end_of_block()
     with cursortools.compress_undo(cursor):
         for item in ly.rhythm.music_items(c, partial=ly.document.OUTSIDE):
             c = QTextCursor(cursor.document())
             c.setPosition(item.end)
             c.insertText('\\arpeggio')
             if name != lastused:
                 cursortools.strip_indent(c)
                 indent = c.block().text()[:c.position() -
                                           c.block().position()]
                 c.insertText(name + '\n' + indent)
             # just pick the first place
             return
Пример #13
0
def remove_trailing_whitespace(cursor):
    """Remove trailing whitespace from all lines in the selection.
    
    If there is no selection, the whole document is used.
    
    """
    ly.reformat.remove_trailing_whitespace(lydocument.cursor(cursor, select_all=True))
Пример #14
0
 def actionTriggered(self, name):
     # convert arpeggio_normal to arpeggioNormal, etc.
     name = _arpeggioTypes[name]
     cursor = self.mainwindow().textCursor()
     # which arpeggio type is last used?
     lastused = '\\arpeggioNormal'
     types = set(_arpeggioTypes.values())
     block = cursor.block()
     while block.isValid():
         s = types.intersection(tokeniter.tokens(block))
         if s:
             lastused = s.pop()
             break
         block = block.previous()
     # where to insert
     c = lydocument.cursor(cursor)
     c.select_end_of_block()
     source = lydocument.Source(c, True, ly.document.OUTSIDE, True)
     with cursortools.compress_undo(cursor):
         for p in ly.rhythm.music_tokens(source):
             c = source.cursor(p[-1], start=len(p[-1]))
             c.insertText('\\arpeggio')
             if name != lastused:
                 cursortools.strip_indent(c)
                 indent = c.block().text()[:c.position()-c.block().position()]
                 c.insertText(name + '\n' + indent)
             # just pick the first place
             return
Пример #15
0
def remove_trailing_whitespace(cursor):
    """Remove trailing whitespace from all lines in the selection.
    
    If there is no selection, the whole document is used.
    
    """
    ly.reformat.remove_trailing_whitespace(lydocument.cursor(cursor, select_all=True))
Пример #16
0
def html_inline(cursor,
                scheme='editor',
                inline=True,
                number_lines=False,
                full_html=True):
    """Return an (by default) inline-styled HTML document for the cursor's selection."""
    c = lydocument.cursor(cursor)
    return html(c, scheme, inline, number_lines, full_html)
Пример #17
0
def increase_indent(cursor):
    """Increases the indent of the line the cursor is at (or the selected lines).

    If there is no selection or the cursor is not in the first indent space,
    just inserts a Tab (or spaces).

    """
    c = lydocument.cursor(cursor)
    indenter(cursor.document()).increase_indent(c)
Пример #18
0
def increase_indent(cursor):
    """Increases the indent of the line the cursor is at (or the selected lines).
    
    If there is no selection or the cursor is not in the first indent space,
    just inserts a Tab (or spaces).
    
    """
    c = lydocument.cursor(cursor)
    indenter(cursor.document()).increase_indent(c)
Пример #19
0
def re_indent(cursor, indent_blank_lines=False):
    """Re-indents the selected region or the whole document.
    
    If indent_blank_lines is True, the indent of blank lines is made larger 
    if necessary. If False (the default), the indent of blank lines if not 
    changed if it is shorter than it should be.
    
    """
    c = lydocument.cursor(cursor, select_all=True)
    indenter(cursor.document()).indent(c, indent_blank_lines)
Пример #20
0
def re_indent(cursor, indent_blank_lines=False):
    """Re-indents the selected region or the whole document.

    If indent_blank_lines is True, the indent of blank lines is made larger
    if necessary. If False (the default), the indent of blank lines if not
    changed if it is shorter than it should be.

    """
    c = lydocument.cursor(cursor, select_all=True)
    indenter(cursor.document()).indent(c, indent_blank_lines)
Пример #21
0
    def actionTriggered(self, name):
        d = ['_', '', '^'][self.direction() + 1]
        single = ''
        if name == "grace_grace":
            inner = ''
            outer = '\\grace { ', ' }'
            single = '\\grace '
        elif name == "grace_beam":
            inner = d + '[', ']'
            outer = '\\grace { ', ' }'
        elif name == "grace_accia":
            inner = ''
            outer = '\\acciaccatura { ', ' }'
            single = '\\acciaccatura '
        elif name == "grace_appog":
            inner = ''
            outer = '\\appoggiatura { ', ' }'
            single = '\\appoggiatura '
        elif name == "grace_slash":
            inner = d + '[', ']'
            outer = '\\slashedGrace { ', ' }'
        elif name == "grace_after":
            inner = d + '{ '
            outer = '\\afterGrace ', ' }'

        cursor = self.mainwindow().textCursor()
        with cursortools.compress_undo(cursor):
            if inner:
                for i, ci in zip(inner, spanner_positions(cursor)):
                    ci.insertText(i)
            if cursor.hasSelection():
                ins = self.mainwindow().textCursor()
                ins.setPosition(cursor.selectionStart())
                ins.insertText(outer[0])
                ins.setPosition(cursor.selectionEnd())
                ins.insertText(outer[1])
            else:
                if single:
                    cursor.insertText(single)
                else:
                    c = lydocument.cursor(cursor)
                    c.end = None
                    items = list(
                        ly.rhythm.music_items(c, partial=ly.document.OUTSIDE))
                    after = self.mainwindow().textCursor()
                    try:
                        i = items[2]
                        pos = i.pos + 1
                        end = (i.tokens or i.dur_tokens)[0].end
                        after.setPosition(pos)
                        after.setPosition(end, QTextCursor.KeepAnchor)
                    except IndexError:
                        after.movePosition(cursor.EndOfLine)
                    after.insertText(outer[1])
                    cursor.insertText(outer[0])
Пример #22
0
def positions(cursor):
    """Return a list of QTextCursors describing the grob the cursor points at.
    
    When the cursor point at e.g. a slur, the returned cursors describe both
    ends of the slur.
    
    The returned list may contain zero to two cursors.
    
    """
    c = lydocument.cursor(cursor)
    c.end = None
    source = lydocument.Source(c, True)
    for token in source.tokens:
        break
    else:
        return []
    
    cur = source.cursor(token, end=0)
    cursors = [cur]
    
    # some heuristic to find the relevant range(s) the linked grob represents
    if isinstance(token, ly.lex.lilypond.Direction):
        # a _, - or ^ is found; find the next token
        for token in source:
            if not isinstance(token, (ly.lex.Space, ly.lex.Comment)):
                break
    end = token.end + source.block.position()
    if token == '\\markup':
        # find the end of the markup expression
        depth = source.state.depth()
        for token in source:
            if source.state.depth() < depth:
                end = token.end + source.block.position()
                break
    elif token == '"':
        # find the end of the string
        for token in source:
            if isinstance(token, ly.lex.StringEnd):
                end = token.end + source.block.position()
                break
    elif isinstance(token, ly.lex.MatchStart):
        # find the end of slur, beam. ligature, phrasing slur, etc.
        name = token.matchname
        nest = 1
        for token in source:
            if isinstance(token, ly.lex.MatchEnd) and token.matchname == name:
                nest -= 1
                if nest == 0:
                    cursors.append(source.cursor(token))
                    break
            elif isinstance(token, ly.lex.MatchStart) and token.matchname == name:
                nest += 1
                
    cur.setPosition(end, QTextCursor.KeepAnchor)
    return cursors
Пример #23
0
    def actionTriggered(self, name):
        d = ['_', '', '^'][self.direction()+1]
        single = ''
        if name == "grace_grace":
            inner = ''
            outer = '\\grace { ', ' }'
            single = '\\grace '
        elif name == "grace_beam":
            inner = d + '[', ']'
            outer = '\\grace { ', ' }'
        elif name == "grace_accia":
            inner = ''
            outer = '\\acciaccatura { ', ' }'
            single = '\\acciaccatura '
        elif name == "grace_appog":
            inner = ''
            outer = '\\appoggiatura { ', ' }'
            single = '\\appoggiatura '
        elif name == "grace_slash":
            inner = d + '[', ']'
            outer = '\\slashedGrace { ', ' }'
        elif name == "grace_after":
            inner = d + '{ '
            outer = '\\afterGrace ', ' }'

        cursor = self.mainwindow().textCursor()
        with cursortools.compress_undo(cursor):
            if inner:
                for i, ci in zip(inner, spanner_positions(cursor)):
                    ci.insertText(i)
            if cursor.hasSelection():
                ins = self.mainwindow().textCursor()
                ins.setPosition(cursor.selectionStart())
                ins.insertText(outer[0])
                ins.setPosition(cursor.selectionEnd())
                ins.insertText(outer[1])
            else:
                if single:
                    cursor.insertText(single)
                else:
                    c = lydocument.cursor(cursor)
                    c.end = None
                    items = list(ly.rhythm.music_items(c, partial=ly.document.OUTSIDE))
                    after = self.mainwindow().textCursor()
                    try:
                        i = items[2]
                        pos = i.pos + 1
                        end = (i.tokens or i.dur_tokens)[0].end
                        after.setPosition(pos)
                        after.setPosition(end, QTextCursor.KeepAnchor)
                    except IndexError:
                        after.movePosition(cursor.EndOfLine)
                    after.insertText(outer[1])
                    cursor.insertText(outer[0])
Пример #24
0
 def getCurrentLilyObject(self, cursor):
     """ Use cursor from textedit link to get type of object being edited."""
     lycursor = lydocument.cursor(cursor)
     self.pos = lycursor.start
     node = self.docinfo.node(self.pos)
     self.node = node
     child = self.docinfo.iter_music(node)
     for c in child:
         name = c.__class__.__name__ #get instance name
         return self.item2object(name)
     name = node.__class__.__name__
     return self.item2object(name)
Пример #25
0
def transpose(cursor, transposer, mainwindow=None):
    """Transpose pitches using the specified transposer."""
    c = lydocument.cursor(cursor, select_all=True)
    try:
        with qutil.busyCursor():
            ly.pitch.transpose.transpose(c, transposer)
    except ly.pitch.PitchNameNotAvailable as e:
        QMessageBox.critical(mainwindow, app.caption(_("Transpose")), _(
            "Can't perform the requested transposition.\n\n"
            "The transposed music would contain quarter-tone alterations "
            "that are not available in the pitch language \"{language}\"."
            ).format(language = e.language))
Пример #26
0
def rhythm_apply(cursor, mainwindow):
    durs = inputdialog.getText(mainwindow,
        _("Apply Rhythm"), _("Enter a rhythm:"),
        complete = sorted(_history),
        regexp = r'([0-9./* ]|\\breve|\\longa|\\maxima)+',
        help = "rhythm", icon = icons.get('tools-rhythm'))
    if not durs:
        return # user cancelled dialog
    durations = durs.split()
    if durations:
        _history.add(durs.strip())
        ly.rhythm.rhythm_overwrite(lydocument.cursor(cursor), durations)
Пример #27
0
def html_inline(cursor,
                scheme='editor',
                inline=True,
                number_lines=False,
                full_html=True,
                wrap_tag="pre",
                wrap_attrib="id",
                wrap_attrib_name="document"):
    """Return an (by default) inline-styled HTML document for the cursor's selection."""
    c = lydocument.cursor(cursor)
    return html(c, scheme, inline, number_lines, full_html, wrap_tag,
                wrap_attrib, wrap_attrib_name)
Пример #28
0
 def getCurrentLilyObject(self, cursor):
     """ Use cursor from textedit link to get type of object being edited."""        
     lycursor = lydocument.cursor(cursor)
     self.pos = lycursor.start        
     node = self.docinfo.node(self.pos)
     self.node = node
     child = self.docinfo.iter_music(node)
     for c in child:
         name = c.__class__.__name__ #get instance name
         return self.item2object(name)
     name = node.__class__.__name__
     return self.item2object(name)
Пример #29
0
def rhythm_apply(cursor, mainwindow):
    durs = inputdialog.getText(mainwindow,
                               _("Apply Rhythm"),
                               _("Enter a rhythm:"),
                               complete=sorted(_history),
                               regexp=r'([0-9./* ]|\\breve|\\longa|\\maxima)+',
                               help="rhythm",
                               icon=icons.get('tools-rhythm'))
    durations = durs.split()
    if durations:
        _history.add(durs.strip())
    ly.rhythm.rhythm_overwrite(lydocument.cursor(cursor), durations)
Пример #30
0
    def actionTriggered(self, name):
        d = ['_', '', '^'][self.direction()+1]
        single = ''
        if name == "grace_grace":
            inner = ''
            outer = '\\grace { ', ' }'
            single = '\\grace '
        elif name == "grace_beam":
            inner = d + '[', ']'
            outer = '\\grace { ', ' }'
        elif name == "grace_accia":
            inner = ''
            outer = '\\acciaccatura { ', ' }'
            single = '\\acciaccatura '
        elif name == "grace_appog":
            inner = ''
            outer = '\\appoggiatura { ', ' }'
            single = '\\appoggiatura '
        elif name == "grace_slash":
            inner = d + '[', ']'
            outer = '\\slashedGrace { ', ' }'
        elif name == "grace_after":
            inner = d + '{ '
            outer = '\\afterGrace ', ' }'               

        cursor = self.mainwindow().textCursor()
        with cursortools.compress_undo(cursor):
            if inner:     
                for i, ci in zip(inner, spanner_positions(cursor)):
                    ci.insertText(i)
            if cursor.hasSelection():
                ins = self.mainwindow().textCursor()      
                ins.setPosition(cursor.selectionStart())
                ins.insertText(outer[0])
                ins.setPosition(cursor.selectionEnd())
                ins.insertText(outer[1])
            else:
                if single:
                    cursor.insertText(single)
                else:
                    c = lydocument.cursor(cursor)
                    c.end = None
                    source = lydocument.Source(c, True, ly.document.OUTSIDE, True)
                    music_list = list(ly.rhythm.music_tokens(source))
                    try:
                        m = music_list[2][0]
                        after = source.cursor(m, 1)
                    except IndexError:                      
                        after = self.mainwindow().textCursor()
                        after.movePosition(cursor.EndOfLine)        
                    after.insertText(outer[1])
                    cursor.insertText(outer[0])
Пример #31
0
def transpose(cursor, transposer, mainwindow=None):
    """Transpose pitches using the specified transposer."""
    c = lydocument.cursor(cursor, select_all=True)
    try:
        with qutil.busyCursor():
            ly.pitch.transpose.transpose(c, transposer)
    except ly.pitch.PitchNameNotAvailable as e:
        QMessageBox.critical(
            mainwindow, app.caption(_("Transpose")),
            _("Can't perform the requested transposition.\n\n"
              "The transposed music would contain quarter-tone alterations "
              "that are not available in the pitch language \"{language}\".").
            format(language=e.language))
Пример #32
0
 def actionTriggered(self, name):
     cursor = self.mainwindow().textCursor()
     style = _glissandoStyles[name]
     c = lydocument.cursor(cursor)
     c.select_end_of_block()
     for item in ly.rhythm.music_items(c, partial=ly.document.OUTSIDE):
         c = QTextCursor(cursor.document())
         c.setPosition(item.end)
         if style:
             text = "-\\tweak #'style #'{0} \\glissando".format(style)
         else:
             text = '\\glissando'
         c.insertText(text)
         return
Пример #33
0
 def actionTriggered(self, name):
     cursor = self.mainwindow().textCursor()
     style = _glissandoStyles[name]
     c = lydocument.cursor(cursor)
     c.select_end_of_block()
     for item in ly.rhythm.music_items(c, partial=ly.document.OUTSIDE):
         c = QTextCursor(cursor.document())
         c.setPosition(item.end)
         if style:
             text = "-\\tweak #'style #'{0} \\glissando".format(style)
         else:
             text = '\\glissando'
         c.insertText(text)
         return
Пример #34
0
 def actionTriggered(self, name):
     cursor = self.mainwindow().textCursor()
     style = _glissandoStyles[name]
     c = lydocument.cursor(cursor)
     c.select_end_of_block()
     source = lydocument.Source(c, True, ly.document.OUTSIDE, True)
     for p in ly.rhythm.music_tokens(source):
         c = source.cursor(p[-1], start=len(p[-1]))
         if style:
             text = "-\\tweak #'style #'{0} \\glissando".format(style)
         else:
             text = '\\glissando'
         c.insertText(text)
         return
Пример #35
0
def force_directions(cursor, direction):
    """Force the directions to be all the same, neutral, up or down."""
    from PyQt5.QtGui import QTextCursor
    import re
    reg = re.compile('(.*)(Up|Down|Neutral)')
    c = lydocument.cursor(cursor)
    source = ly.document.Source(c, None, ly.document.PARTIAL, True)
    with c.document as d:
        for t in source:
            if isinstance(t, ly.lex.lilypond.Direction):
                d[t.pos] = dir_operators[direction]
            elif isinstance(t, ly.lex.lilypond.Command):
                match = reg.match(t)
                if match:
                    updated = match.groups()[0] + dir_commands[direction]
                    del d[t.pos:t.end-1]
                    d[t.pos] = updated
Пример #36
0
def force_directions(cursor, direction):
    """Force the directions to be all the same, neutral, up or down."""
    from PyQt5.QtGui import QTextCursor
    import re
    reg = re.compile('(.*)(Up|Down|Neutral)')
    c = lydocument.cursor(cursor)
    source = ly.document.Source(c, None, ly.document.PARTIAL, True)
    with c.document as d:
        for t in source:
            if isinstance(t, ly.lex.lilypond.Direction):
                d[t.pos] = dir_operators[direction]
            elif isinstance(t, ly.lex.lilypond.Command):
                match = reg.match(t)
                if match:
                    updated = match.groups()[0] + dir_commands[direction]
                    del d[t.pos:t.end - 1]
                    d[t.pos] = updated
Пример #37
0
 def hyphenate(self):
     """Hyphenates selected Lyrics text."""
     view = self.mainwindow().currentView()
     cursor = view.textCursor()
     found = []
     c = lydocument.cursor(cursor, select_all=True)
     # find text to hyphenate
     source = lydocument.Source(c)
     for token in source:
         if isinstance(token, ly.lex.lilypond.LyricText):
             # a word found
             pos = source.position(token)
             for m in _word_re.finditer(token):
                 found.append((pos + m.start(), pos + m.end(), m.group()))
     if not found and cursor.hasSelection():
         # no tokens were found, then tokenize the text again as if in lyricmode
         start = cursor.selectionStart()
         state = ly.lex.State(ly.lex.lilypond.ParseLyricMode)
         for token in state.tokens(cursor.selection().toPlainText()):
             if isinstance(token, ly.lex.lilypond.LyricText):
                 # a word found
                 pos = start + token.pos
                 for m in _word_re.finditer(token):
                     found.append(
                         (pos + m.start(), pos + m.end(), m.group()))
     if not found and cursor.hasSelection():
         # still not succeeded, then try flat text
         for m in _word_re.finditer(cursor.selection().toPlainText()):
             found.append((start + m.start(), start + m.end(), m.group()))
     if found:
         import hyphendialog
         h = hyphendialog.HyphenDialog(self.mainwindow()).hyphenator()
         if h:
             with c.document as d:
                 for start, end, word in found:
                     hyph_word = h.inserted(word, ' -- ')
                     if word != hyph_word:
                         d[start:end] = hyph_word
Пример #38
0
 def hyphenate(self):
     """Hyphenates selected Lyrics text."""
     view = self.mainwindow().currentView()
     cursor = view.textCursor()
     found = []
     c = lydocument.cursor(cursor, select_all=True)
     # find text to hyphenate
     source = lydocument.Source(c)
     for token in source:
         if isinstance(token, ly.lex.lilypond.LyricText):
             # a word found
             pos = source.position(token)
             for m in _word_re.finditer(token):
                 found.append((pos + m.start(), pos + m.end(), m.group()))
     if not found and cursor.hasSelection():
         # no tokens were found, then tokenize the text again as if in lyricmode
         start = cursor.selectionStart()
         state = ly.lex.State(ly.lex.lilypond.ParseLyricMode)
         for token in state.tokens(cursor.selection().toPlainText()):
             if isinstance(token, ly.lex.lilypond.LyricText):
                 # a word found
                 pos = start + token.pos
                 for m in _word_re.finditer(token):
                     found.append((pos + m.start(), pos + m.end(), m.group()))
     if not found and cursor.hasSelection():
         # still not succeeded, then try flat text
         for m in _word_re.finditer(cursor.selection().toPlainText()):
             found.append((start + m.start(), start + m.end(), m.group()))
     if found:
         import hyphendialog
         h = hyphendialog.HyphenDialog(self.mainwindow()).hyphenator()
         if h:
             with c.document as d:
                 for start, end, word in found:
                     hyph_word = h.inserted(word, ' -- ')
                     if word != hyph_word:
                         d[start:end] = hyph_word
Пример #39
0
def spanner_positions(cursor):
    """Return a list with 0 to 2 QTextCursor instances.
    
    At the first cursor a starting spanner item can be inserted, at the
    second an ending item.
    
    """   
    c = lydocument.cursor(cursor)
    if cursor.hasSelection():
        partial = ly.document.INSIDE
    else:
        # just select until the end of the current line
        c.select_end_of_block()
        partial = ly.document.OUTSIDE
    source = lydocument.Source(c, True, partial, True)
      
    positions = [source.cursor(p[-1], start=len(p[-1]))
        for p in ly.rhythm.music_tokens(source)]
    
    if cursor.hasSelection():
        del positions[1:-1]
    else:
        del positions[2:]
    return positions
Пример #40
0
def rhythm_copy(cursor):
    _clipboard[:] = ly.rhythm.rhythm_extract(lydocument.cursor(cursor))
Пример #41
0
def rhythm_explicit(cursor):
    ly.rhythm.rhythm_explicit(lydocument.cursor(cursor))
Пример #42
0
def rhythm_implicit_per_line(cursor):
    ly.rhythm.rhythm_implicit_per_line(lydocument.cursor(cursor))
Пример #43
0
def rhythm_remove(cursor):
    ly.rhythm.rhythm_remove(lydocument.cursor(cursor))
Пример #44
0
def rhythm_remove_fraction_scaling(cursor):
    ly.rhythm.rhythm_remove_fraction_scaling(lydocument.cursor(cursor))
Пример #45
0
def rhythm_undot(cursor):
    ly.rhythm.rhythm_undot(lydocument.cursor(cursor))
Пример #46
0
def rhythm_halve(cursor):
    ly.rhythm.rhythm_halve(lydocument.cursor(cursor))
Пример #47
0
def rhythm_explicit(cursor):
    ly.rhythm.rhythm_explicit(lydocument.cursor(cursor))
Пример #48
0
def abs2rel(cursor, startpitch, first_pitch_absolute):
    """Converts pitches from absolute to relative."""
    with qutil.busyCursor():
        c = lydocument.cursor(cursor, select_all=True)
        ly.pitch.abs2rel.abs2rel(c, startpitch=startpitch, first_pitch_absolute=first_pitch_absolute)
Пример #49
0
def rhythm_copy(cursor):
    _clipboard[:] = ly.rhythm.rhythm_extract(lydocument.cursor(cursor))
Пример #50
0
def rhythm_remove(cursor):
    ly.rhythm.rhythm_remove(lydocument.cursor(cursor))
Пример #51
0
def decrease_indent(cursor):
    """Decreases the indent of the line the cursor is at (or the selected lines)."""
    c = lydocument.cursor(cursor)
    indenter(cursor.document()).decrease_indent(c)
Пример #52
0
def rhythm_paste(cursor):
    ly.rhythm.rhythm_overwrite(lydocument.cursor(cursor), _clipboard)
Пример #53
0
def rel2abs(cursor, first_pitch_absolute):
    """Converts pitches from relative to absolute."""
    with qutil.busyCursor():
        c = lydocument.cursor(cursor, select_all=True)
        ly.pitch.rel2abs.rel2abs(c, first_pitch_absolute=first_pitch_absolute)
Пример #54
0
 def decorator(cursor, *args):
     c = lydocument.cursor(cursor)
     remove = func(c, *args)
     with c.document as d:
         for start, end in remove:
             del d[start:end]
Пример #55
0
def rhythm_double(cursor):
    ly.rhythm.rhythm_double(lydocument.cursor(cursor))
Пример #56
0
def rhythm_implicit_per_line(cursor):
    ly.rhythm.rhythm_implicit_per_line(lydocument.cursor(cursor))