Exemple #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)
Exemple #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)
Exemple #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
Exemple #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.)")))
Exemple #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.)")))
Exemple #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)
Exemple #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
Exemple #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
Exemple #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
Exemple #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
Exemple #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
Exemple #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
Exemple #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))
Exemple #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
Exemple #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))
Exemple #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)
Exemple #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)
Exemple #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)
Exemple #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)
Exemple #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)
Exemple #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])
Exemple #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
Exemple #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])
Exemple #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)
Exemple #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))
Exemple #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)
Exemple #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)
Exemple #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)
Exemple #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)
Exemple #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])
Exemple #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))
Exemple #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
Exemple #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
Exemple #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
Exemple #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
Exemple #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
Exemple #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
Exemple #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
Exemple #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
Exemple #40
0
def rhythm_copy(cursor):
    _clipboard[:] = ly.rhythm.rhythm_extract(lydocument.cursor(cursor))
Exemple #41
0
def rhythm_explicit(cursor):
    ly.rhythm.rhythm_explicit(lydocument.cursor(cursor))
Exemple #42
0
def rhythm_implicit_per_line(cursor):
    ly.rhythm.rhythm_implicit_per_line(lydocument.cursor(cursor))
Exemple #43
0
def rhythm_remove(cursor):
    ly.rhythm.rhythm_remove(lydocument.cursor(cursor))
Exemple #44
0
def rhythm_remove_fraction_scaling(cursor):
    ly.rhythm.rhythm_remove_fraction_scaling(lydocument.cursor(cursor))
Exemple #45
0
def rhythm_undot(cursor):
    ly.rhythm.rhythm_undot(lydocument.cursor(cursor))
Exemple #46
0
def rhythm_halve(cursor):
    ly.rhythm.rhythm_halve(lydocument.cursor(cursor))
Exemple #47
0
def rhythm_explicit(cursor):
    ly.rhythm.rhythm_explicit(lydocument.cursor(cursor))
Exemple #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)
Exemple #49
0
def rhythm_copy(cursor):
    _clipboard[:] = ly.rhythm.rhythm_extract(lydocument.cursor(cursor))
Exemple #50
0
def rhythm_remove(cursor):
    ly.rhythm.rhythm_remove(lydocument.cursor(cursor))
Exemple #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)
Exemple #52
0
def rhythm_paste(cursor):
    ly.rhythm.rhythm_overwrite(lydocument.cursor(cursor), _clipboard)
Exemple #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)
Exemple #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]
Exemple #55
0
def rhythm_double(cursor):
    ly.rhythm.rhythm_double(lydocument.cursor(cursor))
Exemple #56
0
def rhythm_implicit_per_line(cursor):
    ly.rhythm.rhythm_implicit_per_line(lydocument.cursor(cursor))