# -*- coding: ISO-8859-1 -*-
""" capellaScript -- (c) Paul Villiger
>>> Cap2PDF

    Umwandeln von capella Dateien nach PDF|
    Bitte Anleitung lesen
    
<<<

History:    05.03.08 erste Ausgabe
            08.03.08 Filedialog hinzugefügt
            17.03.08 Warteschlaufe bis Datei konvertiert ist

Rückmeldungen bitte an  villpaul(a)bluewin.ch,
                        www.sin942.ch

"""

import _winreg, string, os.path, tempfile, time


pdfWriteFileName = os.path.join(tempfile.gettempdir(), 'pdfwrite.tmp') # Temporärdatei
pdfWriteFileName = os.path.join(getUserDataDir(), 'pdfwrite.tmp') # Capella Temporärdatei

keyHKLM = _winreg.HKEY_LOCAL_MACHINE
keyHKCU = _winreg.HKEY_CURRENT_USER

gswin32File = ''            # Pfad und Dateiname für gswin32.exe
gswin32Exe = 'gswin32c.exe'


def goToSubKey(key, subKey, newKey):
    newSubKey = ''
    try:
        r = _winreg.OpenKey(key, subKey, 0 ,_winreg.KEY_READ)

        try:
            subKeys, keys, modify = _winreg.QueryInfoKey(r)
            for s in range(subKeys):
                k = _winreg.EnumKey(r, s)
                if k == newKey:
                    newSubKey = subKey + '\\' + k
                    break

        except:
            messageBox('Cap2PDF','Exception reading registry: goToSubKey')
            
        _winreg.CloseKey(r)
    except:
        messageBox('Cap2PDF','Exception open registry: goToSubKey')
            
    return newSubKey
    

def getValue(key, subKey, valueName):
    returnValue = ''
    try:
        r = _winreg.OpenKey(key, subKey, 0 ,_winreg.KEY_READ)
        try:
            subKeys, keys, modify = _winreg.QueryInfoKey(r)
            for i in range(keys):
                name, value, type = _winreg.EnumValue(r, i)
                if name == valueName:
                    returnValue = value
                    break
        except:
            messageBox('Cap2PDF','Exception reading registry: getValue')

        _winreg.CloseKey(r)

    except:
        messageBox('Cap2PDF','Exception open registry: getValue')

    return returnValue

def setValue(key, subKey, name, value, printMsg = True, type = _winreg.REG_SZ):
    ok = True
    try:
        r = _winreg.OpenKey(key, subKey, 0 ,_winreg.KEY_SET_VALUE)
        try:
            _winreg.SetValueEx(r, name, 0, type, value )
        except:
            ok = False
            if printMsg:
                messageBox('Cap2PDF','Exception writing to registry: setValue')

        _winreg.CloseKey(r)
    except:
        ok = False
        if printMsg:
            messageBox('Cap2PDF','Exception open registry: setValue')

    return ok


def getSubKeys(key, subKey):
    returnValue = []
    try:
        r = _winreg.OpenKey(key, subKey, 0 ,_winreg.KEY_READ)

        try:
            subKeys, keys, modify = _winreg.QueryInfoKey(r)
            for i in range(subKeys):
                k = _winreg.EnumKey(r, i)
                returnValue.append(k)
        except:
            messageBox('Cap2PDF','Exception reading registry: getSubKeys')
        _winreg.CloseKey(r)
    except:
        messageBox('Cap2PDF','Exception open registry: getSubKeys')

    return returnValue
    


def getValues(key, subKey):
    returnValue = []
    try:
        r = _winreg.OpenKey(key, subKey, 0 ,_winreg.KEY_READ)

        try:
            subKeys, keys, modify = _winreg.QueryInfoKey(r)
            for i in range(keys):
                k = _winreg.EnumValue(r, i)
                returnValue.append(k)
        except:
            messageBox('Cap2PDF','Exception reading registry: getValues')
        _winreg.CloseKey(r)

    except:
        messageBox('Cap2PDF','Exception open registry: getValues')
    return returnValue

    
def searchSubKeys(key, sKey, search):
    r = _winreg.OpenKey(key, sKey, 0, _winreg.KEY_READ)
    subKeys, keys, modify = _winreg.QueryInfoKey(r)
    for s in range(subKeys):
        sk = _winreg.EnumKey(r, s)
        if str(search) == str(sk):
            _winreg.CloseKey(r)
            return sKey + '\\' + sk
        else:
            sk = searchSubKeys(key, sKey + '\\' + sk, search)
            if sk <> '':
                _winreg.CloseKey(r)
                return sk

    _winreg.CloseKey(r)
    return ''


################## Aufruf aus capella ####################
try:
    if activeScore():
        ok = True
except:
    print '*** Script muss aus capella aufgerufen werden!'
    ok = False

################## GHOSTSCRIPT ######################

# Ghostscript Version bestimmen
if ok:
    subKey = 'SOFTWARE'

    gsPath , gsDll = '', ''
    gsLib, gsFonts, gsResource = '', '', ''

    subKey = goToSubKey(keyHKLM, subKey, 'GPL Ghostscript')
    if not subKey:
        messageBox('Cpa2PDF', '*** GPL Ghostscript ist nicht installiert!')
        ok = False

    if ok:
        version = ''
        subKeys = getSubKeys(keyHKLM, subKey)
        for s in subKeys:
            version = max (version, s )  # die aktuelste Version wird ermittelt
        if not  version:
            ok = False
            messageBox('Cpa2PDF', '*** GPL Ghostscript keine Version gefunden!')
        

    # Ghostscript Verzeichnisse bestimmen
    if ok:
        subKey = goToSubKey(keyHKLM, subKey, version)

        gsDLL = getValue(keyHKLM, subKey, 'GS_DLL')
        gsPath , gsDll = os.path.split(gsDLL)
        
        gsLIB = getValue(keyHKLM, subKey, 'GS_LIB')
        gsLib, gsFonts, gsResource = string.split(gsLIB,';')
        
        gswin32File = os.path.join(gsPath, gswin32Exe)
    

def genPdfWriteFile(gsLib, gsFonts, outputFile):
    # PDFWrite Datei in Temp Verzeichnis generieren
    # 
    f = file(pdfWriteFileName, 'w')
    f.write('-I"%s";"%s"\n' % (gsLib, gsFonts) )
    f.write('-sDEVICE=pdfwrite\n')
    f.write('-r600\n')
    f.write('-dNOPAUSE\n')
    f.write('-dSAFER\n')
    f.write('-sPAPERSIZE=a4\n')
    f.write('-dCompatibilityLevel=1.4\n')
    f.write('-dPDFSETTINGS=/prepress\n')
    f.write('-dAutoRotatePages=/PageByPage\n')
    f.write('-sOutputFile="%s"\n' % (outputFile) )
    f.close()


################## PRINTER #######################
# Standard Drucker bestimmen

subKey = 'Software\Microsoft\Windows NT\CurrentVersion\Windows'
standardPrinter = ''
standardPrinter = getValue(keyHKCU, subKey, 'Device')
standardPrinterName = string.split(standardPrinter, ',')[0]
    

# verfügbare Drucker bestimmen

subKey = 'Software\Microsoft\Windows NT\CurrentVersion\Devices'
printerDevices = []
printerDevices = getValues(keyHKCU, subKey)

printerNames = []
for name, value, type in printerDevices:
    printerNames.append(name)



##################### Eingabedialog ###################
repeat = True
while repeat:
    repeat = False
    options = ScriptOptions() 
    opt = options.get()

    capellaDir = opt.get('capellaDir', 'Bitte Verzeichnis eintragen!')
    pdfSubDir  = opt.get('pdfSubDir', 'PDF')
    interruptCount = opt.get('interruptCount', '999')


    printerSelect = ComboBox(printerNames, width = 40, value = 0)
    dirSelect = Edit(capellaDir, width = 40)
    subDirSelect = Edit(pdfSubDir, width = 40)
    intCount = Edit(interruptCount, width = 40)
    actionSelect = Radio(['Druckerport aktualisieren', 'Verzeichnis auswählen', 'Nach PDF konvertieren'], value=2)
    overwritePDF = CheckBox('Bestehende PDF Dateien überschreiben', value = 0)

    dlg = Dialog('Cap2PDF',
                 VBox([
                     #Label('Druckerauswahl:'),
                       actionSelect,
                       Label('Verzeichnis mit capella Dateien'),
                       dirSelect,
                       Label('Unterverzeichnis mit PDF-Dateien'),
                       subDirSelect,
                       Label('Unterbrechung nach Anzahl Dateien'),
                       intCount,
                       overwritePDF,
                       Label(' ')
                       ], padding = 8)
                 )

    if ok and dlg.run():
    #    printerSelect = printerSelect.value()
    #    printerName = printerNames[printerSelect]
        printerUpdate = False
        overwritePDF = overwritePDF.value() == 1
        
        if actionSelect.value() == 0:
            printerUpdate = True
        elif actionSelect.value() == 1:
            repeat = True

            dlg = FileDialog()
            dlg.__init__(bOpen=False)
            dlg.setTitle('Cap2PDF Bitte Ordner auswählen')
            dlg.addFilter('capella-Dateien', '*.cap;*.capx')

            dlg.setStartFile('BitteNichtAendern.cap')

            abort = False
            if dlg.run():
                scoreFile=dlg.filePath()
                scoreDir, scoreName = os.path.split(scoreFile)
                opt['capellaDir'] = scoreDir

        elif actionSelect.value() == 2:
            dirSelect = dirSelect.value()
            opt['capellaDir'] = dirSelect
            if os.path.isdir(dirSelect):
                scoreDir = dirSelect
                try:
                    pdfDir = os.path.join(scoreDir,subDirSelect.value())
                    if not os.path.isdir(pdfDir):
                        os.mkdir(pdfDir)
                    opt['pdfSubDir'] = subDirSelect.value()
                    
                except:
                    ok = False
                    messageBox('Cpa2PDF', 'PDF Verzeichnis %s kann nicht angelegt werden!' % pdfDir )
                    
            else:
                ok = False
                messageBox('Cpa2PDF', 'Verzeichnis "%s" existiert nicht!' % dirSelect )
            intCount = intCount.value()
            if intCount.isdigit():
                interruptCount = intCount
                opt['interruptCount'] = interruptCount
            else:
                messageBox('Cpa2PDF', 'Für Unterbrechungszähler bitte nur Zahlen eingeben!' )
                ok = False

        options.set(opt)

    else:
        ok = False
        
    # ******* while E N D E **********

printerName = 'Cap2PDF'


################ Druckerport bestimmen

if ok:
    subKey  = 'SYSTEM\CurrentControlSet\Control\Print\Printers'
    printerPort = ''

    subKey = goToSubKey(keyHKLM, subKey, printerName)
    if not subKey:
        messageBox('Cap2PDF', '*** Drucker %s ist falsch eingerichtet!' % printerName)
        ok = False
    

if ok:
    printerPort = getValue(keyHKLM, subKey, 'Port')
    if not printerPort:
        messageBox('Cap2PDF', '*** Drucker %s ist falsch eingerichtet!' % printerName)
        ok = False
    

# Print Port Cap2PDF: finden
portSubKey = ''
printCommandSave = ''
printArgumentsSave = ''
printOutputSave = 0

if ok:    
    monitorSubKey = 'SYSTEM\CurrentControlSet\Control\Print\Monitors'
    portSubKey = searchSubKeys(keyHKLM, monitorSubKey, printerPort)


def updatePrinterMonitor():
    global gswin32File, pdfWriteFileName, keyHKLM, portSubKey
    
    if not setValue(keyHKLM, portSubKey, 'Command', gswin32File, printMsg = False):
        return False
    if not setValue(keyHKLM, portSubKey, 'Output', 0, False, _winreg.REG_DWORD):
        return False
    arguments = '@"%s" -c .setpdfwrite -f -' % (pdfWriteFileName)
    if not setValue(keyHKLM, portSubKey, 'Arguments', arguments, False):
        return False
    return True    

if ok and printerUpdate:
    if os.path.isfile(gswin32File):
        if updatePrinterMonitor():
            messageBox('Cap2PDF', 'Bitte Capella neu starten')
        else:
            messageBox('Cap2PDF', 'Fehler beim Schreiben in die Registry!\nAdministratorrechte erforderlich.')
    ok = False
    

# Druckerinstallation prüfen
if ok:    
    printCommandSave = getValue(keyHKLM, portSubKey, 'Command')
    printArgumentsSave = getValue(keyHKLM, portSubKey, 'Arguments')
    printOutputSave = getValue(keyHKLM, portSubKey, 'Output')
    if not (gswin32Exe in printCommandSave
            and pdfWriteFileName in printArgumentsSave
            and printOutputSave == 0):
        messageBox('Cap2PDF', 'Bitte Druckerport aktualisieren!', img=3)
        ok = False

    if ok and not os.path.isfile(gswin32File):
        messageBox('Cap2PDF', '*** Ghostscript EXE Pfad existiert nicht!')
        ok = False

################ Standard Drucker setzen wenn notwendig #################
if ok:
    if printerName <> standardPrinterName:
        subKey = 'Software\Microsoft\Windows NT\CurrentVersion\Windows'

        for name, value, type in printerDevices:
            if name == printerName:
                if not setValue(keyHKCU, subKey, 'Device', name + ',' + value, False):
                    messageBox('Cap2PDF', 'Standard Drucker kann nicht gesetzt werden!\nBitte Standard Drucker auf "%s" setzen oder \n Skript unter Adminrechten ausführen')
                    ok = False
                break


############################ Ausdruck ###########################
if ok:
    capExe = 'capella.exe'
    progDir = getProgramDir()
    capExe = 'capella.exe'

if ok:
    scores = os.listdir(scoreDir)
    scores.sort()

    count = 0
    for s in scores:
        head, tail = os.path.splitext(s)
        if string.lower(tail) in ['.cap', '.capx']:
            scoreFile = os.path.join(scoreDir, s)
            scorePDF = os.path.join(pdfDir, head + '.pdf')
            if os.path.isfile(scorePDF):
                if overwritePDF:
                    os.remove(scorePDF)
                else:
                    continue
                        

            # arguments = '@"%s" -c .setpdfwrite -f -' % (pdfWriteFileName)
            # setValue(keyHKLM, portSubKey, 'Arguments', arguments)

            genPdfWriteFile(gsLib, gsFonts, scorePDF)

            args = [' -p',  '"%s"' % (scoreFile) ]
            path = os.path.join(progDir, capExe)
            result = os.spawnv(os.P_WAIT, path, args)
            count += 1

            delayCount = 10
            while not os.path.isfile(scorePDF) and delayCount:
                time.sleep(2)
                delayCount -= 1

            if count % int(interruptCount) == 0:
                abbrechen = CheckBox('Umwandlung beenden?', value = 0)
                dlg = Dialog('Cap2PDF',
                             VBox([Label(' '),
                                   abbrechen,
                                   Label(' ')], padding = 8)
                             )
                if dlg.run():
                    if abbrechen.value() == 1:
                        break
                else:
                    break

    
# Standard Drucker wieder herstellen sofern notwendig
if standardPrinter:
    if printerName <> standardPrinterName:
        subKey = 'Software\Microsoft\Windows NT\CurrentVersion\Windows'
        setValue(keyHKCU, subKey, 'Device', standardPrinter, False)     




