# -*- coding: ISO-8859-1 -*-
""" capellaScript -- (c) Paul Villiger
>>> Plugin Bar Manager

    Zuweisen von Skripts an die Plugin-Knöpfe|
    Sichern und Wiederherstellen der Einstellungen |
    Download von plugins.dat und plugins-1.bmp|
    Installieren von plugins.dat|
    Testen von plugins.dat|
    ABgleichen von plugins.dat mit Download||
    Bitte Hinweise im Skripthandbuch beachten - wiki.sins942.ch
    

<<<

History: 04.06.2004 - Erste Ausgabe
         06.06.2004 - Am Dateiende dürfen keine Leerzeichen stehen
                      sonst stürzt das Skript beim direkten Aufruf ab
         07.07.2006 - Verzeichnisergleich nur mit Kleinbuchstaben (Win98)
         18.10.2007 - Anpassungen an capella 2008
         08.09.2009 - Sichern und laden von plugins.dat
         26.09.2010 - Erweiterung für capella 7

Das Skript muss im Capella Skriptverzeichnis liegen.
Für capella 2008 muss das Icon in das Skriptverzeichnis kopiert werden.

"""

import os, os.path, string, shutil, _winreg, datetime, traceback
from distutils.file_util import copy_file
import xml.dom.minidom, urllib2

programDir = getProgramDir()

if (6, 0, 0) > capVersion():
    scriptPath = os.path.join(programDir, 'scripts')
    pluginFileName = os.path.join(programDir, 'data', 'plugins.dat')
    pluginFilePath = os.path.join(programDir, 'data')
    pluginFileNameTemp = os.path.join(programDir, 'data', 'plugins_template.dat')
    pluginBmpName = os.path.join(programDir, 'data', 'toolbars', 'plugins-1.bmp')
    pluginCount = 8
    version6 = False
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')
    pluginFileName = os.path.join(homePath, 'capella', 'config', 'data', 'plugins.dat')
    pluginFilePath = os.path.join(homePath, 'capella', 'config', 'data')
    pluginFileNameTemp = os.path.join(homePath, 'capella', 'config', 'data', 'plugins_template.dat')
    pluginBmpName = os.path.join(homePath, 'capella', 'config', 'data', 'toolbars', 'plugins-1.bmp')
    pluginCount = 12
    version6 = True

if (7, 0, 0) <= capVersion():
    version7 = True
else:
    version7 = False


def downloadPluginsDat():
    try:
        u = 'http://www.sins942.ch/skripts/plugins-dat/plugins.dat'
        f = urllib2.urlopen(u)
        data = f.read(-1)
        pf = file(pluginFileNameTemp,'wb')
        pf.write(data)
        pf.flush()
        pf.close()
    except:
        messageBox('Fehler', 'Fehler beim herunterladen der Datei %s' % u)

def downloadPluginsBmp():
    path, name = os.path.split(pluginBmpName)
    if not os.path.isdir(path):
        os.mkdir(path)
    try:
        u = 'http://www.sins942.ch/skripts/plugins-dat/plugins-1.bmp'
        f = urllib2.urlopen(u)
        data = f.read(-1)
        pf = file(pluginBmpName,'wb')
        pf.write(data)
        pf.flush()
        pf.close()
    except:
        messageBox('Fehler', 'Fehler beim herunterladen der Datei %s' % u )



def readPluginsDat(pluginsDat):
    if os.path.isfile(pluginsDat):
        pass
    else:
        return False
    
    filePlugin = open(pluginsDat, 'r')
    textPlugin = filePlugin.read()
    filePlugin.close()

    if '<?xml' not in textPlugin:
        textPlugin = '<?xml version="1.0" encoding="ISO-8859-1"?>\n\r' + textPlugin

    try:
        domPlugin = xml.dom.minidom.parseString(textPlugin)
    except:
        messageBox('Fehler', 'Die Datei %s ist fehlerhaft!' % pluginsDat)
        return False
    
    return domPlugin

def writePluginsDat(pluginsDat, dom):
    fileOut = open(pluginsDat, 'w')
    fileOut.write( dom.toxml('ISO-8859-1') )
    fileOut.flush()
    fileOut.close()
    

def combinePluginsDat(new, orig):

    origChanged = False

    if not os.path.isfile(new):
        messageBox('Fehler', 'Die Datei %s ist nicht vorhanden! Bitte zuerst herunterladen.' % new)
        return

    domNew = readPluginsDat(new)
    if not domNew:
        messageBox('XML Fehler', 'Die Datei %s kann nicht gelesen werden!' % new)
        return
        
    if not os.path.isfile(orig):
        writePluginsDat(orig, domNew)
        messageBox('-- Hinweis --', 'Die Datei %s wurde eingerichtet, bitte capella neu starten' % orig)
        return

    domOrig = readPluginsDat(orig)
    if not domOrig:
        messageBox('XML Fehler', 'Die Datei %s kann nicht gelesen werden!' % orig)
        return


    groupOrig = None
    for group in domOrig.getElementsByTagName('group'):
        itemCount = len(group.getElementsByTagName('item'))
        if 12 <= itemCount < 30:
            groupOrig = group
            break
        if itemCount < 12:
            break
    
    if groupOrig:
        if not groupOrig.hasAttribute("name"):
            groupOrig.setAttribute("name", "Plugin Symbolleiste")

        # replace items without symbol attributes
        for itemOrig in groupOrig.getElementsByTagName('item'):
            path, itemFile = os.path.split(itemOrig.getAttribute('file'))

            for itemNew in domNew.getElementsByTagName('item'):
                path, fil = os.path.split(itemNew.getAttribute('file'))
                if itemFile == fil:
                    itemOrig.parentNode.replaceChild(itemNew.cloneNode(True), itemOrig)
                    break

        # replace original script group with entries from original file
        for group in domNew.getElementsByTagName('group'):
            itemCount = len(group.getElementsByTagName('item'))
            if 12 <= itemCount < 30:
                group.parentNode.replaceChild(groupOrig, group)
                origChanged = True
                break
            if itemCount < 12:
                break

    if origChanged:
        # plugins.dat wird geschrieben
        writePluginsDat(orig, domNew)
        messageBox('-- Hinweis --', 'Die Datei plugins.dat wurde geändert, bitte capella neu starten')
    else:
        messageBox('-- Hinweis --', 'Die Datei plugins.dat wurde nicht geändert.')
        

def updatePluginsDat(new, orig):
    # Diese Prozedur gleicht die Einträge von plugins.dat mit der Vorlage von Andreas Peier ab
    # Die Vorlage muss als Datei plugins_temp.dat vorhanden sein

    domNew = readPluginsDat(new)
    domOrig = readPluginsDat(orig)

    if domNew and domOrig:
        pass
    else:
        return

    dictNew = {}
    for item in domNew.getElementsByTagName('item'):
        fil = item.getAttribute('file')
        path, dat = os.path.split(fil)
        nam = item.getAttribute('name')
        if item.hasAttribute('symbol'):
            sym = item.getAttribute('symbol')
        else:
            sym = ''
        dictNew[dat] = [fil, nam, sym]            

    missingEntries = []
    for item in domOrig.getElementsByTagName('item'):
        fil = item.getAttribute('file')
        path, dat = os.path.split(fil)
        if dat in dictNew:
            item.setAttribute('file', dictNew[dat][0])
            item.setAttribute('name', dictNew[dat][1])
            item.setAttribute('symbol', dictNew[dat][2])
        else:
            missingEntries.append(fil.encode('latin2'))

    writePluginsDat(orig, domOrig)
    messageBox('-- Hinweis --', 'Die Datei plugins.dat wurde geändert, bitte capella neu starten')

    if len(missingEntries) > 0:
        messageBox('-- Hinweis --', 'Diese Einträge wurden nicht aktualisiert: %s ' % str(missingEntries))

def check4MissingScripts(pluginsDat):
    # Diese Prozedur prüft, ob alle Einträge in plugins.dat als Dateien vorhanden sind

    missingScripts = []
    dom = readPluginsDat(pluginsDat)
    if not dom:
        return
    for item in dom.getElementsByTagName('item'):
        fil = item.getAttribute('file')
        if not os.path.isfile(os.path.join(scriptPath, fil)):
            missingScripts.append(fil.encode('latin2'))

    if len(missingScripts) > 0:
        messageBox('-- Hinweis --', 'Diese Einträge sind nicht als Skripts vorhanden: %s ' % str(missingScripts))
    else:
        messageBox('-- Hinweis --', 'Keine Fehler in plugins.dat gefunden')


def selectScript():
    dlg = FileDialog()
    dlg.__init__(bOpen=True)
    dlg.setTitle('Python Skript auswählen')
    dlg.addFilter('Python Scripts', '*.py')
    currenScript = str(sys.argv[0])
    path, file = os.path.split(currenScript)
    dlg.setStartFile(os.path.join(scriptPath, file))
    dlg.setStartPath(path)
    if dlg.run():
        newSkript = dlg.filePath()
        if string.lower(scriptPath) in string.lower(newSkript):
            newSkript = newSkript[len(scriptPath)+1:]
        else:
            newSkript = ''
            messageBox('-- Hinweis --', 'Skript nicht im Capella Skriptverzeichnis',2)
        return newSkript
    else:
        return ''

def selectPluginsDat():
    dlg = FileDialog()
    dlg.__init__(bOpen=True)
    dlg.setTitle('Bitte plugins.dat auswählen')
    dlg.addFilter('capella Plugindatei', 'plugins*.dat')
    path, file = os.path.split(pluginFileName)
    dlg.setStartPath(path)
    dlg.setStartFile(file)
    if dlg.run():
        newPluginsDat = dlg.filePath()
        return newPluginsDat
    else:
        return ''

def selectIcons():
    dlg = FileDialog()
    dlg.__init__(bOpen=True)
    dlg.setTitle('Plugin Icons auswählen')
    dlg.addFilter('PNG-Dateien', '*.png')
    dlg.setStartFile(os.path.join(programDir,"data\\toolbars\\plugins-1.png"))
    if dlg.run():
        newIcon = dlg.filePath()
        return newIcon
    else:
        return ''

def getScripts(pluginsDat, v7):
    dom = readPluginsDat(pluginsDat)
    if not dom:
        return []
    
    if v7:
        scriptList = []
        count = 0

        for item in dom.getElementsByTagName('item'):
            scriptList.append(item.getAttribute('name').encode('latin2'))
            count += 1
            if count > 11:
                break
    else:
        scriptList = [""] * 12
        for item in dom.getElementsByTagName('item'):
            if item.hasAttribute('symbol'):
                sym = eval(item.getAttribute('symbol'))
                if sym <= 12:
                    if not scriptList[sym-1]:
                        scriptList[sym-1] = item.getAttribute('name').encode('latin2')

    return scriptList

def assignProgram(program, pluginsDat, v7):
    select = selectScript()
    if select and v7:
        dom = readPluginsDat(pluginsDat)
        count = 0
        for item in dom.getElementsByTagName('item'):
            count += 1
            if count == eval(program):
                item.setAttribute("file", select)
                pat, fil = os.path.split(select)
                name, ext = os.path.splitext(fil)
                item.setAttribute("name", name)
                for it in dom.getElementsByTagName('item'):
                    if it == item:
                        continue
                    if fil in it.getAttribute('file'):
                        item.setAttribute("name", it.getAttribute("name"))
                        if it.hasAttribute("symbol"):
                            item.setAttribute("symbol", it.getAttribute("symbol"))
                        else:
                            if item.hasAttribute("symbol"):
                                item.removeAttribute("symbol")
                        break
                break                    
        writePluginsDat(pluginsDat, dom)

    elif select:
        # vor version 7
        dom = readPluginsDat(pluginsDat)
        itemSel = None
        for item in dom.getElementsByTagName('item'):
            if item.hasAttribute("symbol"):
                sym = item.getAttribute("symbol")
                if sym == program:
                    itemSel = item
                    break
        if not itemSel:
            itemSel = dom.getElementsByTagName('item')[eval(program)]
            clone = itemSel.cloneNode(True)
            itemSel.parentNode.insertBefore(clone, itemSel)
            itemSel = clone

        itemSel.setAttribute("file", select)
        pat, fil = os.path.split(select)
        fil, ext = os.path.splitext(fil)
        itemSel.setAttribute("name", fil)
        itemSel.setAttribute("symbol", program)
        writePluginsDat(pluginsDat, dom)
        


(ver, sub, sr) = (5,1,5)
if capVersion() < (ver, sub, sr):
    messageBox('Fehler', 
               'Dieses Skript benötigt capella ab Version %d.%02d-%02d' % (ver, sub, sr),
                4)
else:

    pluginsChanged = False
    while True:  # Endlosschlaufe bis Abbruch (break)

        pluginList = getScripts(pluginFileName, version7)
        
        radProgram = Radio(pluginList,
                           value = 0,
                           text='Skriptauswahl',
                           padding = 8)

        if version7:
            radTask    = Radio(['Neues Skript auswählen',
                                'Plugindatei sichern',
                                'Plugindatei auswählen',
                                'Plugindatei testen',
                                'Plugindatei herunterladen --> Download',
                                'Plugindatei installieren <-- Download',
                                'Plugindatei aktualisieren mit Download',
                                'Skript beenden'], value = 0, text = 'Aktion')
        else:
            radTask    = Radio(['Neues Skript auswählen',
                                'Plugindatei sichern',
                                'Plugindatei auswählen',
                                'PluginDatei testen',
                                'Skript beenden'], value = 0, text = 'Aktion')

        vbox1 = VBox([radTask,
                      radProgram,
                      Label(' '),
                      Label('Bitte Hinweise im Skripthandbuch beachten - wiki.sins942.ch'),
                      Label(' ')
                      ])

        dlg = Dialog('  -- Plugin Bar Manager --', vbox1)

        if dlg.run():
            task = radTask.value()
            program = str(radProgram.value()+1)
            
            if task == 0:
                # Programm zuweisen
                assignProgram(program, pluginFileName, version7)
                
            elif task == 1:
                if os.path.isfile(pluginFileName):
                    # Save current plugins.dat to plugins_YYMMDDHHSS.dat
                    currentTime = datetime.datetime.now().strftime('%y%m%d%H%M')
                    filePath, fileName = os.path.split(pluginFileName)
                    fileHead, fileExt = os.path.splitext(fileName)
                    saveFileName = os.path.join(filePath, fileHead + '_' + currentTime + fileExt)
                    copy_file(pluginFileName, saveFileName)
                else:
                    messageBox('-- Hinweis --', 'Die Datei %s ist nicht vorhanden!' % pluginFileName) 
                    
            elif task == 2:
                # Select plugins.dat
                saveFileName = selectPluginsDat()
                if os.path.exists(saveFileName):
                    if pluginFileName <> saveFileName:
                        copy_file(saveFileName, pluginFileName)
                        pluginsChanged = True
            elif task == 3:
                if os.path.isfile(pluginFileName):
                    # Plugins.dat testen
                    check4MissingScripts(pluginFileName)
                else:
                    messageBox('-- Hinweis --', 'Die Datei %s ist nicht vorhanden!' % pluginFileName) 
            elif task == 4 and version7:
                # plugins.dat und plugins-1.bmp herunterladen
                downloadPluginsBmp()
                downloadPluginsDat()
            elif task == 5 and version7:
                # plugins.dat installieren
                combinePluginsDat(pluginFileNameTemp, pluginFileName)
            elif task == 6 and version7:
                # plugins.dat aktualisieren mit plugins_temp
                updatePluginsDat(pluginFileNameTemp, pluginFileName)
            else:
                # Skript beenden
                break # while
        else:
            break # while
        
    if pluginsChanged:
        if version6:
            messageBox('-- Hinweis --', 'Bitte Icon in Scriptverzeichnis kopieren\nund capella neu starten!     ',2)
        else:            
            messageBox('-- Hinweis --', 'Bitte Capella neu starten!     ',2)

# ENDE
pass



