# This file is part of the Coral project.
# Please read the copyright notice in the LICENSE file.

# -*- coding: UTF-8 -*-
#
# savediagram - script to save XMI-DI diagrams to file
#
# SYNOPSIS
#
# Explained in usage()
#
# DESCRIPTION
#
# savediagram is a simple script that saves diagrams to files.
# It requires graphics support
# filename: the name of your XMI file
#
# AUTHORS
#
# Marcus Alanen <maalanen@abo.fi> 2004
#


def getSupportedFormats():
    """Returns a list of three-tuples (mimetype,extension,description)
    describing the supported output image formats"""
    
    return [
        ("application/eps","eps","EPS - Encapsulated PostScript (*.eps)"),
        ("application/postscript","ps","PS - PostScript (*.ps)"),
        ("image/png","png","PNG - Portable Network Graphics (*.png)"),
        ("image/svg+xml","svg","SVG - Scalable Vector Graphics (*.svg)"),
        ]


def saveDiagram(xmidi_elements, filename, editorSet, imagetype = "png"):
    """Saves the graphics of the given XMI-DI elements into filename.
    EditorSet is used to focus on the diagram.
    The given imagetype is a type supported by Coral's savediagram.
    """
    import coral
    DI=coral.lang.XMIDI20
    from coral.modeler.coralmodeler import CoralModeler
    import coral.modeler.xselection

    if not xmidi_elements:
        return
    diagram = None
    for e in xmidi_elements:
        d = e.__getRoot__()
        if d.__type__() == DI.Diagram:
            diagram = d
            break
    if not diagram:
        raise Exception("No XMI-DI elements with diagram!")

    coral.getTransactionManager().beginModifyCmd()
    try:
        editorSet.notifyFocusOn(diagram)
        CoralModeler.getInstance().getQtApp().processEvents()
    finally:
        coral.getTransactionManager().endModifyCmd()

    coll = coral.Sequence()
    for i in xmidi_elements:
        coll.append(i)
    x = coral.modeler.xselection.XSelection(coll, False)

    typestr = "image/" + imagetype
    for mt,ext,_ in getSupportedFormats():
        if imagetype==ext:
            typestr = mt
            break

    if imagetype == "ps":
        typestr = "application/postscript"
    elif imagetype == "eps":
        typestr = "application/eps"
    elif imagetype == "svg": # Helper for users
        typestr = "image/svg+xml"

    data = str(x.encodedData(typestr))
    
    f = file(filename, "wb")
    try:
        f.write(data)
    finally:
        f.close() 
   
def main(arguments):
    def usage():
        print "Usage: savediagram [ --help | --version | [-v] [-t format] filename diagram... ]"
        print "Options:"
        print "  --help         Display this information"
        print "  --version      Display version information and exit"
        print "  -t format      Save in given image format type, defaulting to png"
        print "  -p prefix      Replace prefix with the given value"
        print "  -v             Inverts selection of diagrams."
        print "                 Use this for saving all diagrams!"
        print ""
        print "The given filename is loaded and the diagrams with the given"
        print "names are saved into files. The filename is constructed as"
        print "\"filename-diagramname.format\"."
        print ""

    def version():
        import coral
        print "This is Coral version",coral.version, " (savediagram script)"
        
    import sys
    import getopt
    import coral
    import os

    try:
        opts, args = getopt.getopt(arguments, "hp:vt:", ["help", "version"])
    except getopt.GetoptError:
        usage()
        sys.exit(2)

    typesuffix = "png"
    inverted = False
    prefix = ""
    
    for o,a in opts:
        if o in ("-h", "--help"):
            usage()
            sys.exit(0)
        elif o in ("-p"):
            prefix = a
        elif o in ("-v"):
            inverted = True
        elif o in ("--version"):
            version()
            sys.exit(0)
        elif o in ("-t"):
            typesuffix = a
        else:
            usage()
            sys.exit(2)

    #
    # Display help blurb if no XMI file was given.
    # Note that this permits savediagram to be called without
    # any actual diagrams to be saved... Not particularly useful
    # for the end user, but might be useful for scripts
    #
    if len(args) < 1:
        usage()
        sys.exit(2)
        
    xmifile = args[0]
    if len(args) >= 2:
        diagrams = args[1:]
    else:
        diagrams = []
    
    import coral.modeler.modeler
    import coral.modeler.basicEdit
    import coral.modeler
    DI=coral.lang.XMIDI20
    import coral.log
    import re

    logger = coral.log.getLogger()

    mw = coral.modeler.modeler.ModelerWindow(show = False)
    st = coral.modeler.action.openProject(xmifile)

    fileprefix = os.path.basename(xmifile)
    fileprefix = re.sub(".xm(i|l)", "", fileprefix)
    fileprefix = re.sub(".XM(I|L)", "", fileprefix)

    if prefix:
        fileprefix = prefix
        
    d = dict.fromkeys(diagrams)

    candidates = {}
    for candidate in st.contents():
        if not candidate.__type__() == DI.Diagram:
            continue
        u = unicode(candidate.name).encode("UTF-8")
        if candidates.has_key(u):
            logger.warn("Warning multiple diagrams with the name " + u + "!")
            continue
        candidates[u] = candidate

    # Not inverted => must exist in both d and candidates
    # Inverted     => must not exist in d but does exist in candidates

    all_ok = True

    for name in candidates.keys():
        if not inverted:
            if name not in d:
                continue
            else:
                # ok
                pass
        else:
            if name not in d:
                # ok
                pass
            else:
                continue

        outputfile = fileprefix + "-" + name + "." + typesuffix
        try:
            logger.info("Saving diagram " + name + " to " + outputfile + "...")
            saveDiagram([candidates[name]], outputfile, mw.getDiagramEditorManager().editorSet, typesuffix)
        except:
            logger.warn("Could not save diagram \"" + name + "\"!")
            import traceback
            traceback.print_exc()
            all_ok = False

    if not inverted:
        for d in diagrams:
            if not candidates.has_key(d):
                # error
                logger.warn("No diagram by the name of " + d + " was found!")
                all_ok = False
    else:
        for d in diagrams:
            if not candidates.has_key(d):
                logger.warn("No diagram by the name of " + d + " was found! (ignored)")
                ###all_ok = False

    if not all_ok:
        sys.exit(2)
        
if __name__ == "__main__":
    import sys
    main(sys.argv[1:])
