Exemple #1
0
def loadProject(project, zip=None):
    """
    Loads a project.
    @param project: the filename of the project to open.
    @param zip: whether the project is a zipped or not.
    @return: an array of errors, empty if None.
    """

    mw = mainWindow()
    errors = []

    ####################################################################################################################
    # Read and store everything in a dict

    log("\nLoading {} ({})".format(project, "ZIP" if zip else "not zip"))
    if zip:
        files = loadFilesFromZip(project)

        # Decode files
        for f in files:
            if f[-4:] not in [".xml", "opml"]:
                files[f] = files[f].decode("utf-8")

    else:
        # Project path
        dir = os.path.dirname(project)

        # Folder containing file: name of the project file (without .msk extension)
        folder = os.path.splitext(os.path.basename(project))[0]

        # The full path towards the folder containing files
        path = os.path.join(dir, folder, "")

        files = {}
        for dirpath, dirnames, filenames in os.walk(path):
            p = dirpath.replace(path, "")
            for f in filenames:
                # mode = "r" + ("b" if f[-4:] in [".xml", "opml"] else "")
                if f[-4:] in [".xml", "opml"]:
                    with open(os.path.join(dirpath, f), "rb") as fo:
                        files[os.path.join(p, f)] = fo.read()
                else:
                    with open(os.path.join(dirpath, f), "r", encoding="utf8") as fo:
                        files[os.path.join(p, f)] = fo.read()

        # Saves to cache (only if we loaded from disk and not zip)
        global cache
        cache = files

        # FIXME: watch directory for changes

    # Sort files by keys
    files = OrderedDict(sorted(files.items()))

    ####################################################################################################################
    # Settings

    if "settings.txt" in files:
        settings.load(files["settings.txt"], fromString=True, protocol=0)
    else:
        errors.append("settings.txt")

    # Just to be sure
    settings.saveToZip = zip
    settings.defaultTextType = "md"

    ####################################################################################################################
    # Labels

    mdl = mw.mdlLabels
    mdl.appendRow(QStandardItem(""))  # Empty = No labels
    if "labels.txt" in files:
        log("\nReading labels:")
        for s in files["labels.txt"].split("\n"):
            if not s:
                continue

            m = re.search(r"^(.*?):\s*(.*)$", s)
            txt = m.group(1)
            col = m.group(2)
            log("* Add status: {} ({})".format(txt, col))
            icon = iconFromColorString(col)
            mdl.appendRow(QStandardItem(icon, txt))

    else:
        errors.append("labels.txt")

    ####################################################################################################################
    # Status

    mdl = mw.mdlStatus
    mdl.appendRow(QStandardItem(""))  # Empty = No status
    if "status.txt" in files:
        log("\nReading Status:")
        for s in files["status.txt"].split("\n"):
            if not s:
                continue
            log("* Add status:", s)
            mdl.appendRow(QStandardItem(s))
    else:
        errors.append("status.txt")

    ####################################################################################################################
    # Infos

    mdl = mw.mdlFlatData
    if "infos.txt" in files:
        md, body = parseMMDFile(files["infos.txt"], asDict=True)

        row = []
        for name in ["Title", "Subtitle", "Serie", "Volume", "Genre", "License", "Author", "Email"]:
            row.append(QStandardItem(md.get(name, "")))

        mdl.appendRow(row)

    else:
        errors.append("infos.txt")

    ####################################################################################################################
    # Summary

    mdl = mw.mdlFlatData
    if "summary.txt" in files:
        md, body = parseMMDFile(files["summary.txt"], asDict=True)

        row = []
        for name in ["Situation", "Sentence", "Paragraph", "Page", "Full"]:
            row.append(QStandardItem(md.get(name, "")))

        mdl.appendRow(row)

    else:
        errors.append("summary.txt")

    ####################################################################################################################
    # Plots

    mdl = mw.mdlPlots
    if "plots.xml" in files:
        log("\nReading plots:")
        # xml = bytearray(files["plots.xml"], "utf-8")
        root = ET.fromstring(files["plots.xml"])

        for plot in root:
            # Create row
            row = getStandardItemRowFromXMLEnum(plot, Plot)

            # Log
            log("* Add plot: ", row[0].text())

            # Characters
            if row[Plot.characters.value].text():
                IDs = row[Plot.characters.value].text().split(",")
                item = QStandardItem()
                for ID in IDs:
                    item.appendRow(QStandardItem(ID.strip()))
                row[Plot.characters.value] = item

            # Subplots
            for step in plot:
                row[Plot.steps.value].appendRow(
                    getStandardItemRowFromXMLEnum(step, PlotStep)
                )

            # Add row to the model
            mdl.appendRow(row)

    else:
        errors.append("plots.xml")

    ####################################################################################################################
    # World

    mdl = mw.mdlWorld
    if "world.opml" in files:
        log("\nReading World:")
        # xml = bytearray(files["plots.xml"], "utf-8")
        root = ET.fromstring(files["world.opml"])
        body = root.find("body")

        for outline in body:
            row = getOutlineItem(outline, World)
            mdl.appendRow(row)

    else:
        errors.append("world.opml")

    ####################################################################################################################
    # Characters

    mdl = mw.mdlCharacter
    log("\nReading Characters:")
    for f in [f for f in files if "characters" in f]:
        md, body = parseMMDFile(files[f])
        c = mdl.addCharacter()
        c.lastPath = f

        color = False
        for desc, val in md:

            # Base infos
            if desc in characterMap.values():
                key = [key for key, value in characterMap.items() if value == desc][0]
                index = c.index(key.value)
                mdl.setData(index, val)

            # Character color
            elif desc == "Color" and not color:
                c.setColor(QColor(val))
                # We remember the first time we found "Color": it is the icon color.
                # If "Color" comes a second time, it is a Character's info.
                color = True

            # Character's infos
            else:
                c.infos.append(CharacterInfo(c, desc, val))

        log("* Adds {} ({})".format(c.name(), c.ID()))

    ####################################################################################################################
    # Texts
    # We read outline form the outline folder. If revisions are saved, then there's also a revisions.xml which contains
    # everything, but the outline folder takes precedence (in cases it's been edited outside of manuksript.

    mdl = mw.mdlOutline
    log("\nReading outline:")
    paths = [f for f in files if "outline" in f]
    outline = OrderedDict()

    # We create a structure of imbricated OrderedDict to store the whole tree.
    for f in paths:
        split = f.split(os.path.sep)[1:]
        # log("* ", split)

        last = ""
        parent = outline
        parentLastPath = "outline"
        for i in split:
            if last:
                parent = parent[last]
                parentLastPath = os.path.join(parentLastPath, last)
            last = i

            if not i in parent:
                # If not last item, then it is a folder
                if i != split[-1]:
                    parent[i] = OrderedDict()

                # If file, we store it
                else:
                    parent[i] = files[f]

                # We store f to add it later as lastPath
                parent[i + ":lastPath"] = os.path.join(parentLastPath, i)



    # We now just have to recursively add items.
    addTextItems(mdl, outline)

    # Adds revisions
    if "revisions.xml" in files:
        root = ET.fromstring(files["revisions.xml"])
        appendRevisions(mdl, root)

    # Check IDS
    mdl.rootItem.checkIDs()

    return errors
Exemple #2
0
def loadProject(project, zip=None):
    """
    Loads a project.
    @param project: the filename of the project to open.
    @param zip: whether the project is a zipped or not.
    @return: an array of errors, empty if None.
    """

    mw = mainWindow()
    errors = []

    ####################################################################################################################
    # Read and store everything in a dict

    log("\nLoading {} ({})".format(project, "ZIP" if zip else "not zip"))
    if zip:
        files = loadFilesFromZip(project)

        # Decode files
        for f in files:
            if f[-4:] not in [".xml", "opml"]:
                files[f] = files[f].decode("utf-8")

    else:
        # Project path
        dir = os.path.dirname(project)

        # Folder containing file: name of the project file (without .msk extension)
        folder = os.path.splitext(os.path.basename(project))[0]

        # The full path towards the folder containing files
        path = os.path.join(dir, folder, "")

        files = {}
        for dirpath, dirnames, filenames in os.walk(path):
            p = dirpath.replace(path, "")
            for f in filenames:
                # mode = "r" + ("b" if f[-4:] in [".xml", "opml"] else "")
                if f[-4:] in [".xml", "opml"]:
                    with open(os.path.join(dirpath, f), "rb") as fo:
                        files[os.path.join(p, f)] = fo.read()
                else:
                    with open(os.path.join(dirpath, f), "r", encoding="utf8") as fo:
                        files[os.path.join(p, f)] = fo.read()

        # Saves to cache (only if we loaded from disk and not zip)
        global cache
        cache = files
        
        # FIXME: watch directory for changes

    # Sort files by keys
    files = OrderedDict(sorted(files.items()))

    ####################################################################################################################
    # Settings

    if "settings.txt" in files:
        settings.load(files["settings.txt"], fromString=True, protocol=0)
    else:
        errors.append("settings.txt")

    # Just to be sure
    settings.saveToZip = zip

    ####################################################################################################################
    # Labels

    mdl = mw.mdlLabels
    mdl.appendRow(QStandardItem(""))  # Empty = No labels
    if "labels.txt" in files:
        log("\nReading labels:")
        for s in files["labels.txt"].split("\n"):
            if not s:
                continue

            m = re.search(r"^(.*?):\s*(.*)$", s)
            txt = m.group(1)
            col = m.group(2)
            log("* Add status: {} ({})".format(txt, col))
            icon = iconFromColorString(col)
            mdl.appendRow(QStandardItem(icon, txt))

    else:
        errors.append("labels.txt")

    ####################################################################################################################
    # Status

    mdl = mw.mdlStatus
    mdl.appendRow(QStandardItem(""))  # Empty = No status
    if "status.txt" in files:
        log("\nReading Status:")
        for s in files["status.txt"].split("\n"):
            if not s:
                continue
            log("* Add status:", s)
            mdl.appendRow(QStandardItem(s))
    else:
        errors.append("status.txt")

    ####################################################################################################################
    # Infos

    mdl = mw.mdlFlatData
    if "infos.txt" in files:
        md, body = parseMMDFile(files["infos.txt"], asDict=True)

        row = []
        for name in ["Title", "Subtitle", "Serie", "Volume", "Genre", "License", "Author", "Email"]:
            row.append(QStandardItem(md.get(name, "")))

        mdl.appendRow(row)

    else:
        errors.append("infos.txt")

    ####################################################################################################################
    # Summary

    mdl = mw.mdlFlatData
    if "summary.txt" in files:
        md, body = parseMMDFile(files["summary.txt"], asDict=True)

        row = []
        for name in ["Situation", "Sentence", "Paragraph", "Page", "Full"]:
            row.append(QStandardItem(md.get(name, "")))

        mdl.appendRow(row)

    else:
        errors.append("summary.txt")

    ####################################################################################################################
    # Plots

    mdl = mw.mdlPlots
    if "plots.xml" in files:
        log("\nReading plots:")
        # xml = bytearray(files["plots.xml"], "utf-8")
        root = ET.fromstring(files["plots.xml"])

        for plot in root:
            # Create row
            row = getStandardItemRowFromXMLEnum(plot, Plot)

            # Log
            log("* Add plot: ", row[0].text())

            # Characters
            if row[Plot.characters.value].text():
                IDs = row[Plot.characters.value].text().split(",")
                item = QStandardItem()
                for ID in IDs:
                    item.appendRow(QStandardItem(ID.strip()))
                row[Plot.characters.value] = item

            # Subplots
            for step in plot:
                row[Plot.steps.value].appendRow(
                    getStandardItemRowFromXMLEnum(step, PlotStep)
                )

            # Add row to the model
            mdl.appendRow(row)

    else:
        errors.append("plots.xml")

    ####################################################################################################################
    # World

    mdl = mw.mdlWorld
    if "world.opml" in files:
        log("\nReading World:")
        # xml = bytearray(files["plots.xml"], "utf-8")
        root = ET.fromstring(files["world.opml"])
        body = root.find("body")

        for outline in body:
            row = getOutlineItem(outline, World)
            mdl.appendRow(row)

    else:
        errors.append("world.opml")

    ####################################################################################################################
    # Characters

    mdl = mw.mdlCharacter
    log("\nReading Characters:")
    for f in [f for f in files if "characters" in f]:
        md, body = parseMMDFile(files[f])
        c = mdl.addCharacter()
        c.lastPath = f

        color = False
        for desc, val in md:

            # Base infos
            if desc in characterMap.values():
                key = [key for key, value in characterMap.items() if value == desc][0]
                index = c.index(key.value)
                mdl.setData(index, val)

            # Character color
            elif desc == "Color" and not color:
                c.setColor(QColor(val))
                # We remember the first time we found "Color": it is the icon color.
                # If "Color" comes a second time, it is a Character's info.
                color = True

            # Character's infos
            else:
                c.infos.append(CharacterInfo(c, desc, val))

        log("* Adds {} ({})".format(c.name(), c.ID()))

    ####################################################################################################################
    # Texts
    # We read outline form the outline folder. If revisions are saved, then there's also a revisions.xml which contains
    # everything, but the outline folder takes precedence (in cases it's been edited outside of manuksript.

    mdl = mw.mdlOutline
    log("\nReading outline:")
    paths = [f for f in files if "outline" in f]
    outline = OrderedDict()

    # We create a structure of imbricated OrderedDict to store the whole tree.
    for f in paths:
        split = f.split(os.path.sep)[1:]
        # log("* ", split)

        last = ""
        parent = outline
        parentLastPath = "outline"
        for i in split:
            if last:
                parent = parent[last]
                parentLastPath = os.path.join(parentLastPath, last)
            last = i

            if not i in parent:
                # If not last item, then it is a folder
                if i != split[-1]:
                    parent[i] = OrderedDict()

                # If file, we store it
                else:
                    parent[i] = files[f]

                # We store f to add it later as lastPath
                parent[i + ":lastPath"] = os.path.join(parentLastPath, i)



    # We now just have to recursively add items.
    addTextItems(mdl, outline)

    # Adds revisions
    if "revisions.xml" in files:
        root = ET.fromstring(files["revisions.xml"])
        appendRevisions(mdl, root)

    # Check IDS
    mdl.rootItem.checkIDs()

    return errors