# -*- coding: ISO-8859-1 -*-
""" capellaScript -- (c) Paul Villiger
>>> Quick Format

    Mit diesem Skript können folgende Layouteinstellungen verändert werden:
    - Seitenrand, oben/unten/links/rechts
    - Abstand von Systemen, über 1stem System/zwischen
    - Abstand der Notenzeilen, oben/unten
    - Abstand Notenlinien, normal/schmal/Pageobjekt
    - Vertikale Ausrichtung
    - linker Einzug
    - Titel, Komponist, Fusszeile  (Zeilenumbruch mit '|' )
    Die einzelnen Werte müssen vollständig sein und mit '/' getrennt werden
    Die eingegebenen Werte werden zwischengespeichert.

    Mit der Option Stapelverarbeitung kann ein ganzer Ordner geändert werden.

    Rückmeldungen bitte an mailto:villpaul(a)bluewin.ch
<<<

History: 15.11.04 - Erste Ausgabe
         16.11.04 - Fehler bei Abbruch
         30.11.04 - Bei Systemklammern wurden Pageobjekte nicht generiert
                    Bem: Die Reihenfolge der Elemente unter "score" ist anscheinend zwingend
                  - Seitenausgleich korrigiert
         17.05.06 - Stapelverarbeitung
         18.05.06 - Stapelverarbeitung mit Zielverzeichnis
         15.03.09 - Abbruch bei Seitenrand mit führender Null: '08'
                

"""
# default settings; diese Werte bei Bedarf anpassen
               # face
               #                  # height
               #                  #     # weight
               #                  #     #      # italic
               #                  #     #      #        # horizontal align
defTitle    = ['Times New Roman', '24', '700', 'false', 'center']
defComposer = ['Times New Roman', '10', '400', 'false', 'right']
defFootNote = ['Times New Roman', '8',  '400', 'true',  'right']



from xml.dom.minidom import NodeList, Node, Element
from caplib.capDOM import ScoreChange
import tempfile, string, new

def latin1_d(u):
    return u.decode('Latin-1')

def gotoChild(self, name, new=False):
    newEl = None
    if new:
        pass
    else:
        for child in self.childNodes:
            if child.nodeType == child.ELEMENT_NODE and child.tagName == name:
                newEl = child
                break
    if newEl == None:
        newEl = doc.createElement(name)
        self.appendChild(newEl)
    return newEl
Node.gotoChild = new.instancemethod(gotoChild,None,Node)


options = ScriptOptions() 
opt = options.get()
qfBorderDist = opt.get('qfBorderDist','20/20/20/20')
qfSystemDist = opt.get('qfSystemDist','12/4')
qfStaffDist = opt.get('qfStaffDist','6/6')
qfLineDist = opt.get('qfLineDist','1.8/1.2/1.8')
qfIndent = opt.get('qfIndent','auto/0')
qfVertAdj = opt.get('qfVertAdj','0')
qfFootNote = opt.get('qfFootNote','Paul Villiger, 15.11.2004')
qfTitle = opt.get('qfTitle','Titel')
qfComposer = opt.get('qfComposer','Komponist')

qfBorderCheck = opt.get('qfBorderCheck','True')
qfSystemCheck = opt.get('qfSystemCheck','True')
qfStaffCheck = opt.get('qfStaffCheck','True')
qfLineCheck = opt.get('qfLineCheck','True')
qfIndentCheck = opt.get('qfIndentCheck','True')
qfVertAdjCheck = opt.get('qfVertAdjCheck','True')
qfFootNoteCheck = opt.get('qfFootNoteCheck','True')
qfTitleCheck = opt.get('qfTitleCheck','True')
qfComposerCheck = opt.get('qfComposerCheck','True')

borderDist = Edit(qfBorderDist, width = 18, padding = 8)
systemDist = Edit(qfSystemDist, width = 18, padding = 8)
staffDist  = Edit(qfStaffDist, width = 18, padding = 8)
lineDist   = Edit(qfLineDist, width = 18, padding = 8)
indent     = Edit(qfIndent, width = 18, padding = 8)
vertAdj    = ComboBox(['kein Ausgleich','alle ausser letzte Seite', 'alle Seiten'], width = 18, padding = 8)
footNote   = Edit(qfFootNote, width = 18, padding =8)
title      = Edit(qfTitle, width = 18, padding =8)
composer   = Edit(qfComposer, width = 18, padding =8)

borderCheck = CheckBox('',value=eval(qfBorderCheck))
systemCheck = CheckBox('',value=eval(qfSystemCheck))
staffCheck = CheckBox('',value=eval(qfStaffCheck))
lineCheck = CheckBox('',value=eval(qfLineCheck))
indentCheck = CheckBox('',value=eval(qfIndentCheck))
vertAdjCheck = CheckBox('',value=eval(qfVertAdjCheck))
footNoteCheck = CheckBox('',value=eval(qfFootNoteCheck))
titleCheck = CheckBox('',value=eval(qfTitleCheck))
composerCheck = CheckBox('',value=eval(qfComposerCheck))
batchConversion = CheckBox('', value = False)

dlg = Dialog('*** Quick-Format ***',VBox([HBox([borderCheck,Label('Rand (mm): oben/unten/links/rechts',width=32),borderDist]),
                                     HBox([systemCheck,Label('Abstand System (Zw): über erstem/zwischen',width=32),systemDist]),
                                     HBox([staffCheck,Label('Abstand Zeile (Zw): oben/unten',width=32),staffDist]),
                                     HBox([lineCheck,Label('Abstand Notenlinien (mm): normal/klein/Seite',width=32),lineDist]),
                                     HBox([indentCheck,Label('Einzug ("auto" oder Zahl): 1. Zeile/Rest',width=32),indent]),
                                     HBox([vertAdjCheck,Label('Vertikale Ausrichtung',width=32),vertAdj]),
                                     HBox([titleCheck,Label('Titel',width=32),title]),
                                     HBox([composerCheck,Label('Komponist',width=32),composer]),
                                     HBox([footNoteCheck,Label('Fusszeile',width=32),footNote]),
                                     Label('  '),
                                     VBox([HBox([batchConversion, Label('Stapelverarbeitung von mehreren Dateien', width = 50)]),
                                           Label('1) Bitte zuvor alle cap-Dateien aus Zielverzeichnis schliessen !!!'),
                                           Label('2) Sind die Dateien gesichert ???')], text = ' '),
                                     Label('  ')]
                                    , padding = 5))
            
if dlg.run():
    
    opt['qfBorderDist'] = borderDist.value()
    opt['qfSystemDist'] = systemDist.value()
    opt['qfStaffDist'] = staffDist.value()
    opt['qfLineDist'] = lineDist.value()
    opt['qfIndent'] = indent.value()
    opt['qfVertAdj'] = vertAdj.value()
    opt['qfFootNote'] = footNote.value()
    opt['qfTitle'] = title.value()
    opt['qfComposer'] = composer.value()
    
    opt['qfBorderCheck'] = borderCheck.value()
    opt['qfSystemCheck'] = systemCheck.value()
    opt['qfStaffCheck'] = staffCheck.value()
    opt['qfLineCheck'] = lineCheck.value()
    opt['qfIndentCheck'] = indentCheck.value()
    opt['qfVertAdjCheck'] = vertAdjCheck.value()
    opt['qfFootNoteCheck'] = footNoteCheck.value()
    opt['qfTitleCheck'] = titleCheck.value()
    opt['qfComposerCheck'] = composerCheck.value()
    options.set(opt)

    borderDist = string.split(borderDist.value(),'/')    
    systemDist = string.split(systemDist.value(),'/')    
    staffDist = string.split(staffDist.value(),'/')    
    lineDist = string.split(lineDist.value(),'/')
    indent = string.split(indent.value(),'/')
    vertAdj = ['none','exceptLast','all'][vertAdj.value()]
    footNote = latin1_d(footNote.value())
    footNote = footNote.replace('|',chr(10))        # Zeilenumbruch mit '|'
    title = latin1_d(title.value())
    title = title.replace('|',chr(10))        
    composer = latin1_d(composer.value())
    composer = composer.replace('|',chr(10))        

    borderCheck = borderCheck.value()
    systemCheck = systemCheck.value()
    staffCheck = staffCheck.value()
    lineCheck = lineCheck.value()
    indentCheck = indentCheck.value()
    vertAdjCheck = vertAdjCheck.value()
    footNoteCheck = footNoteCheck.value()
    titleCheck = titleCheck.value()
    composerCheck = composerCheck.value()
    batchConversion = batchConversion.value()
    continueScript = True

    if batchConversion:
        dlg = FileDialog()
        dlg.__init__(bOpen=False)
        dlg.setTitle('Bitte Quellordner auswählen')
        dlg.addFilter('capella-Dateien', '*.cap;*.capx')
        dlg.setStartFile('$$XX.cap')
        if dlg.run():
            capFile=dlg.filePath()
            capDir, capName = os.path.split(capFile)
        else:
            continueScript = False

        dlg = FileDialog()
        dlg.__init__(bOpen=False)
        dlg.setTitle('Bitte Zielordner auswählen')
        dlg.addFilter('capella-Dateien', '*.cap;*.capx')
        dlg.setStartFile('$$XX.cap')
        if continueScript and dlg.run():
            destFile=dlg.filePath()
            destDir, destName = os.path.split(destFile)
        else:
            continueScript = False

else:
    continueScript = False
    


def changeDoc(score):
    layout = score.gotoChild('layout')
    
    # Abstand Seitenrand
    if borderCheck:
        pages = layout.gotoChild('pages')
        pages.setAttribute('top',borderDist[0])
        pages.setAttribute('bottom',borderDist[1])
        pages.setAttribute('left',borderDist[2])
        pages.setAttribute('right',borderDist[3])

    # Abstand System
    distances = layout.gotoChild('distances')
    if systemCheck:
        systems = distances.gotoChild('systems')
        systems.setAttribute('top',systemDist[0])
        systems.setAttribute('between',systemDist[1])
    
    # Abstand Notenlinien
    if lineCheck:
        staffLines = distances.gotoChild('staffLines')
        staffLines.setAttribute('normal',lineDist[0])
        staffLines.setAttribute('small',lineDist[1])
        staffLines.setAttribute('pageObj',lineDist[2])

    # Abstand Notenzeilen
    if staffCheck:
        staves = layout.gotoChild('staves')
        for staffLayout in staves.getElementsByTagName('staffLayout'):
            slDistances = staffLayout.gotoChild('distances')
            slDistances.setAttribute('top',staffDist[0])
            slDistances.setAttribute('bottom',staffDist[1])

        # Alle Extradistanzen zurücksetzen
        for staff in score.getElementsByTagName('staff'):
            for extraDistance in staff.getElementsByTagName('extraDistance'):
                extraDistance.setAttribute('top','0')
                extraDistance.setAttribute('bottom','0')
    # linker Einzug
    if indentCheck:
        for i in range(len(indent)):
            if indent[i] == 'auto':
                indent[i] = '-1'
        systems = score.gotoChild('systems')
        i = 0
        for system in systems.getElementsByTagName('system'):
            if i == 0:
                system.setAttribute('leftIndent',indent[0])
                i = 1
            else:
                system.setAttribute('leftIndent',indent[1])
                
    # Vertical Adjustement                
    if vertAdjCheck:
        systems = distances.gotoChild('systems')
        systems.setAttribute('pageJustified',vertAdj)
        # capella interpretiert 'none' als 'exceptLast'
        if vertAdj == 'none':
            systems.removeAttribute('pageJustified')
        
    # PageObjects generieren wenn nicht vorhanden
    if footNoteCheck or titleCheck or composerCheck:
        if score.getElementsByTagName('pageObjects').length == 0:
            pageObjects = doc.createElement('pageObjects')
            layout = score.gotoChild('layout')
            next = layout.nextSibling
            score.insertBefore(pageObjects,next)
        
    # Fusszeile
    if footNoteCheck:
        # (A4 Breite - Rand links - Rand rechts) / Linienabstand PageObjekt
        if defFootNote[4] == 'right':
            x = (210.0 - int(borderDist[2]) - int(borderDist[3])) / eval(lineDist[2])
        elif defFootNote[4] == 'center':
            x = (210.0 - int(borderDist[2]) - int(borderDist[3])) / (2.0 * eval(lineDist[2]))
        else:
            x = 0.0
            
        # (A4 Höhe - Rand oben - Rand unten + 2.5) / Linienabstand PageObjekt
        y = (297.0 - int(borderDist[0]) - int(borderDist[1]) + 2.5 ) / eval(lineDist[2])

        pageObjects = score.gotoChild('pageObjects')

        drawObj = pageObjects.gotoChild('drawObj',True)
        text = drawObj.gotoChild('text')
        text.setAttribute('x',str(x))
        text.setAttribute('y',str(y))
        text.setAttribute('align',defFootNote[4])
        
        font = text.gotoChild('font')
        font.setAttribute('face',defFootNote[0])
        font.setAttribute('height',defFootNote[1])
        font.setAttribute('weight',defFootNote[2])
        font.setAttribute('italic',defFootNote[3])
        font.setAttribute('pitchAndFamily','0')
        
        content = text.gotoChild('content')
        textNode = doc.createTextNode(footNote)
        content.appendChild(textNode)

    # Titel
    if titleCheck:
        # (A4 Breite - Rand links - Rand rechts) / Linienabstand PageObjekt
        if defTitle[4] == 'right':
            x = (210.0 - int(borderDist[2]) - int(borderDist[3])) / eval(lineDist[2])
        elif defTitle[4] == 'center':
            x = (210.0 - int(borderDist[2]) - int(borderDist[3])) / (2.0 * eval(lineDist[2]))
        else:
            x = 0.0
            
        # 
        y = eval(defTitle[1]) / 7.0

        pageObjects = score.gotoChild('pageObjects')

        drawObj = pageObjects.gotoChild('drawObj',True)
        text = drawObj.gotoChild('text')
        text.setAttribute('x',str(x))
        text.setAttribute('y',str(y))
        text.setAttribute('align',defTitle[4])
        
        font = text.gotoChild('font')
        font.setAttribute('face',defTitle[0])
        font.setAttribute('height',defTitle[1])
        font.setAttribute('weight',defTitle[2])
        font.setAttribute('italic',defTitle[3])
        font.setAttribute('pitchAndFamily','0')
        
        content = text.gotoChild('content')
        textNode = doc.createTextNode(title)
        content.appendChild(textNode)

        basic = drawObj.gotoChild('basic')
        basic.setAttribute('oddPagesExceptFirst','false')
        basic.setAttribute('evenPages','false')
        # basic.setAttribute('behindNotes','true')

    # Komponist
    if composerCheck:
        # (A4 Breite - Rand links - Rand rechts) / Linienabstand PageObjekt
        if defComposer[4] == 'right':
            x = (210.0 - int(borderDist[2]) - int(borderDist[3])) / eval(lineDist[2])
        elif defComposer[4] == 'center':
            x = (210.0 - int(borderDist[2]) - int(borderDist[3])) / (2.0 * eval(lineDist[2]))
        else:
            x = 0.0
            
        # 
        y = 2.5 * eval(defTitle[1]) / 7.0

        pageObjects = score.gotoChild('pageObjects')

        drawObj = pageObjects.gotoChild('drawObj',True)
        text = drawObj.gotoChild('text')
        text.setAttribute('x',str(x))
        text.setAttribute('y',str(y))
        text.setAttribute('align',defComposer[4])
        
        font = text.gotoChild('font')
        font.setAttribute('face',defComposer[0])
        font.setAttribute('height',defComposer[1])
        font.setAttribute('weight',defComposer[2])
        font.setAttribute('italic',defComposer[3])
        font.setAttribute('pitchAndFamily','0')
        
        content = text.gotoChild('content')
        textNode = doc.createTextNode(composer)
        content.appendChild(textNode)

        basic = drawObj.gotoChild('basic')
        basic.setAttribute('oddPagesExceptFirst','false')
        basic.setAttribute('evenPages','false')
        # basic.setAttribute('behindNotes','true')


class ScoreChange(ScoreChange):

    def changeScore(self, score):
        global scriptAction, doc
        doc = score.parentNode
        changeDoc(score)
        

if continueScript:
    if batchConversion:
        
        dirlist = os.listdir(capDir)
        dirlist.sort()

        for capFile in dirlist:
            head, tail = os.path.splitext(capFile)
            if tail.lower() not in  ['.cap','.capx']:
                continue
            isXML = False
            if tail.lower() == '.capx':
                isXML = True

            
            capFileName = os.path.join(capDir,capFile)
            destFileName = os.path.join(destDir,capFile)
            if not os.path.isfile(capFileName):
                continue
            
            openScore(capFileName)
            if activeScore():
                tempInput = tempfile.mktemp('.capx')
                tempOutput = tempfile.mktemp('.capx')
                activeScore().write(tempInput)

                ScoreChange(tempInput, tempOutput)

                activeScore().read(tempOutput)
                os.remove(tempInput)
                os.remove(tempOutput)

                activeScore().write(destFileName, xml = not isXML)
            
            closeActiveScore()


    elif activeScore():

        activeScore().registerUndo("Quick Format")
        tempInput = tempfile.mktemp('.capx')
        tempOutput = tempfile.mktemp('.capx')
        activeScore().write(tempInput)

        ScoreChange(tempInput, tempOutput)

        activeScore().read(tempOutput)
        os.remove(tempInput)
        os.remove(tempOutput)

