# -*- coding: ISO-8859-1 -*-
""" capellaScript -- Paul Villiger
>>> Capella Style Editor

    Dieses Skript erlaubt das Editieren der Styles in der Datei "capella.dat". Folgende Aktionen stehen zur Verfügung:
    Style editieren - Style löschen - Style importieren - Speichern||
    Hinweise:|
    - Ein Style lässt sich duplizieren, wenn beim Editieren der "StyleName" geändert wird.
    - Beim Speichern wird die alte capella.dat Datei mit dem aktuellen Zeitstempel im Dateinamen gesichert.
    - Es können Dateien mit einzelnen oder mehreren Styledefinitionen (z.B. capella.dat) importiert werden.
      Bestehende Definitionen werden überschrieben, neue angehängt.
    - Die entsprechenden Notenfonts müssen vom Anwender importiert werden.
    - Die neuen oder geänderten Styles werden erst nach dem Neuladen von capella aktiv.

<<<
History:  20.03.2005 - Erstausgabe
          20.08.2005 - Styles sind neu aufsteigend sortiert
                     - erster Eintrag ist immer "capella-Standard"
          26.06.2010 - Anpssung an capella 6 und 7


Kommentare und Fehlermeldunge bitte an mailto:villpaul(a)bluewin.ch senden

"""

from xml.dom.minidom import NodeList, Node, Element
from caplib.capDOM import ScoreChange
import tempfile, os, os.path, string, new, _winreg
from datetime import *
from string import lower

programDir = getProgramDir()

if (6, 0, 0) > capVersion():
    scriptPath = os.path.join(programDir, 'scripts')
    datFileName = os.path.join(programDir, 'data', 'capella.dat')
else:
    r = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, r'Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders')
    homePath, x = _winreg.QueryValueEx(r, 'Personal')
    _winreg.CloseKey(r)
    scriptPath = os.path.join(homePath,'capella', 'scripts')
    datFileName = os.path.join(homePath, 'capella', 'config', 'data', 'capella.dat')

def mycmp(a,b):           # Vergleich ohne Gross/Klein
    return cmp(lower(a), lower(b))
        

class capellaData:

    def __init__(self):
        self.data = {}
        self.cont = True
        self.styles = {}

    def readDatFile(self):
        self.datFileName = datFileName
        datFile = file(self.datFileName,'r')
        self.dataList = datFile.readlines()
        datFile.close()

        schluessel = None
        for n in range(len(self.dataList)):
            s = self.dataList[n]
            s = string.strip(string.split(s,'/n')[0]) # Zeilenumbruch abschneiden
            s = string.strip(string.split(s,';')[0]) # Kommentar abschneiden
            if '[' in s and ']' in s:
                schluessel = string.strip(string.split(self.dataList[n],'[')[1])
                schluessel = string.strip(string.split(schluessel,']')[0])
                self.data[schluessel] = {}
            elif schluessel:
                if '=' in s:
                    s = string.split(s,'=')
                    self.data[schluessel][string.strip(s[0])] = string.strip(s[1])

        for schluessel in self.data.keys():
            if 'FontName' in self.data[schluessel] and 'FontFile' in self.data[schluessel]:
                self.styles[schluessel] = schluessel

    def readStyleFile(self):
        dlg = FileDialog()
        dlg.__init__(bOpen=True)
        dlg.setTitle('Capella Style-Definition auswählen')
        dlg.addFilter('Capella-Style', '*.txt')
        dlg.setStartFile('*.txt')
        if dlg.run():
            styleFileName = dlg.filePath()
        else:
            return

        datFile = file(styleFileName,'r')
        dataList = datFile.readlines()
        datFile.close()

        schluessel = None
        styles = {}
        for line in dataList:
            s = line
            s = string.strip(string.split(s,'/n')[0]) # Zeilenumbruch abschneiden
            s = string.strip(string.split(s,';')[0]) # Kommentar abschneiden
            if '[' in s and ']' in s:
                schluessel = string.strip(string.split(s, '[')[1])
                schluessel = string.strip(string.split(schluessel,']')[0])
                styles[schluessel] = {}
            elif schluessel:
                if '=' in s:
                    s = string.split(s,'=')
                    styles[schluessel][string.strip(s[0])] = string.strip(s[1])

        for schluessel in styles.keys():
            if 'FontName' in styles[schluessel] and 'FontFile' in styles[schluessel]:
                self.data[schluessel] = styles[schluessel]
                self.styles[schluessel] = schluessel

    def mainMenue(self):
        styleList = self.styles.keys()
        styleSelect = ComboBox(styleList, value = 0, width = 25)
        action = Radio(['Keine Aktion',
                        'Style editieren / duplizieren',
                        'Style löschen',
                        'Style importieren',
                        'Skript beenden mit Speichern',
                        'Skript beenden ohne Speichern'
                        ], value = 0)
        dlg = Dialog('--- Style Editor ---',
                     VBox([styleSelect,
                           Label(' '),
                           action,
                           Label(' ')]))
                
        if dlg.run():
            if action.value() == 0:
                pass
            elif action.value() == 1:   # Style editieren
                self.editStyle(styleList[styleSelect.value()])
            elif action.value() == 2:   # Style löschen
                self.deleteStyle(styleList[styleSelect.value()])
            elif action.value() == 3:   # Style importieren
                self.readStyleFile()
            elif action.value() == 4:   # Beenden mit Speichern
                self.cont = False
                self.writeDatFile()
            elif action.value() == 5:   # Beenden ohne Speichern
                self.cont = False
        else:
            self.cont = False
    

    def writeDatFile(self):
        now = datetime.now()
        nowStr = '%0000d%00d%00d%00d%00d%00d' % (now.year, now.month, now.day, now.hour, now.minute, now.second)
        head, tail = os.path.splitext(self.datFileName)
        saveFileName = head + '_' + nowStr + tail
        print self.datFileName, saveFileName
        os.rename(self.datFileName, saveFileName)

        datFile = file(self.datFileName,'w')
        state = 0
        for line in self.dataList:
            if state == 0:
                if '[Styles]' in line:
                    state = 1

                    datFile.write('[Styles]\n')
                    datFile.write('N=%s\n' % (str(len(self.styles))) )
                    styleList = self.styles.keys()
                    styleList.sort(mycmp)    # Styles alphabetisch sortieren
                    n = 1
                    for k in styleList:
                        if k == "capella-Standard":        # erster Eintrag soll "capella-Standard" sein
                            datFile.write('%s=%s\n' % ( str(n), k ))
                            n += 1
                    for k in styleList:      
                        if k <> "capella-Standard":        # restliche Einträge 
                            datFile.write('%s=%s\n' % ( str(n), k ))
                            n += 1
                    datFile.write('\n')
                    for k in styleList:
                        datFile.write('[%s]\n' % ( k ) )
                        styleDict = self.data[k]
                        for l in ['FontFile','FontName','NoteSpaces','HeadWidth','LineWidth','xStemDown','yStemDown','xStemUp','yStemUp','Bracket']:
                            datFile.write('%s=%s\n' % ( l, styleDict.get(l,'' ) ))
                        datFile.write('\n')

                else:
                    datFile.write(line)
            elif state == 1:
                if '[Rastrals]' in line:
                    state = 2
                    datFile.write(line)
            elif state == 2:
                datFile.write(line)
                
        datFile.flush()
        datFile.close()

    def deleteStyle(self,name):
        for k in self.styles.keys():
            if self.styles[k] == name:
                del self.styles[k]
                del self.data[k]
                break

    def copyStyle(self,name,new):
        if new not in self.data:
            self.data[new] = self.data[name]
            self.styles[new] = new

    def renameStyle(self,name,new):
        self.copyStyle(name,new)
        self.deleteStyle(name)

    def addNewStyle(self, name, dict):
        self.data[name] = dict
        self.styles[name] = name
        
        

    def editStyle(self, style):
        """
        [capella-Standard]
        FontFile=capella3
        FontName=capella3
        NoteSpaces=64,30,43       ; Einheit: 1/32 Zw.
        HeadWidth=512,384,307,307 ; brevis, ganze, halbe, viertel (Einheit: 1/256 Zw.)
        LineWidth=24,21,21        ; Hälse, Notenlinien, Taktstriche (Einheit: 1/256 Zw.)
        ;LineWidth=24,24,24       ;(Standard in capella 2002)
        xStemDown=0,0
        yStemDown=-43,-43
        xStemUp=307,307
        yStemUp=43,43
        Bracket=-16,-16,8,1,-24,-16,8,-16,30,-32,40,-48,30,-32,8,-4,-24,-4
        """        
        styleDict = self.data.get(style, {})
        w = 35
        styleName   = Edit(style, width = w)
        fontFile    = Edit(styleDict.get('FontFile'  ,'capella3'), width = w)
        fontName    = Edit(styleDict.get('FontName'  ,'capella3'), width = w)
        noteSpaces  = Edit(styleDict.get('NoteSpaces','64,30,43'), width = w)
        headWidth   = Edit(styleDict.get('HeadWidth' ,'512,384,307,307'), width = w)
        lineWidth   = Edit(styleDict.get('LineWidth' ,'24,21,21'), width = w)
        xStemDown   = Edit(styleDict.get('xStemDown' ,'0,0'), width = w)
        yStemDown   = Edit(styleDict.get('yStemDown' ,'-43,-43'), width = w)
        xStemUp     = Edit(styleDict.get('xStemUp'   ,'307,307'), width = w)
        yStemUp     = Edit(styleDict.get('yStemUp'   ,'43,43'), width = w)
        bracket     = Edit(styleDict.get('Bracket'   ,'-16,-16,8,1,-24,-16,8,-16,30,-32,40,-48,30,-32,8,-4,-24,-4'), width = w)
        w1 = 13
        dlg = Dialog('-- Edit Style:  ' + style + ' --',
                     VBox([HBox([Label('StyleName *)', width = w1), styleName ] ),
                           Label(' '),
                           HBox([Label('FontFile', width = w1),  fontFile  ] ),
                           HBox([Label('FontName', width = w1),  fontName  ] ),
                           HBox([Label('NoteSpaces', width = w1),noteSpaces] ),
                           HBox([Label('HeadWidth', width = w1), headWidth ] ),
                           HBox([Label('LineWidth', width = w1), lineWidth ] ),
                           HBox([Label('xStemDown', width = w1), xStemDown ] ),
                           HBox([Label('yStemDown', width = w1), yStemDown ] ),
                           HBox([Label('xStemUp', width = w1),   xStemUp   ] ),
                           HBox([Label('yStemUp', width = w1),   yStemUp   ] ),
                           HBox([Label('Bracket', width = w1),   bracket   ] ),
                           Label(' '),
                           Label('  *) Durch Ändern entsteht ein neuer Style'),
                           Label('  Die Beschreibung der Werte steht im Handbuch unter "Stil der Notendarstellung"'),
                           Label(' '),
                         ], padding = 4))
        if dlg.run():
            newStyleName            = styleName.value()
            newStyle = {}
            newStyle['FontFile'  ] = fontFile.value()
            newStyle['FontName'  ] = fontName.value()
            newStyle['NoteSpaces'] = noteSpaces.value()
            newStyle['HeadWidth' ] = headWidth.value()
            newStyle['LineWidth' ] = lineWidth.value()
            newStyle['xStemDown' ] = xStemDown.value()
            newStyle['yStemDown' ] = yStemDown.value()
            newStyle['xStemUp'   ] = xStemUp.value()
            newStyle['yStemUp'   ] = yStemUp.value()
            newStyle['Bracket'   ] = bracket.value()

            self.addNewStyle(newStyleName, newStyle)   # Style mit gleichem Namen wird ersetzt, sonst angehängt
                                     
        

cd = capellaData()
cd.readDatFile()

while cd.cont:
    cd.mainMenue()
    

