From a2703dc7355e0264b023baba9ef6cd287f32a957 Mon Sep 17 00:00:00 2001 From: "Jeison Yehuda Amihud (Blender Dumbass)" Date: Tue, 5 Jan 2021 20:11:11 +0000 Subject: [PATCH] ODT export The UI and the ODT exporter it self. --- studio/story.py | 324 ++++++++++++++++++++++++++++++++++++ studio/studio_storyLayer.py | 16 ++ 2 files changed, 340 insertions(+) diff --git a/studio/story.py b/studio/story.py index 1a6f9c9..9e7c2bd 100644 --- a/studio/story.py +++ b/studio/story.py @@ -5,6 +5,15 @@ import os import datetime import json +# This is for the export. We need a window for it. Maybe I will make my own. +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk +import zipfile +import re + + +from settings import talk from studio import checklist #import checklist @@ -806,3 +815,318 @@ def redo(win): # And let's refresh story win.story = load(win.project) + +def export_to_odt(win): + + # This function will export the story to the ODT format. The ODT format is + # basically a zip file. With images and other stuff. And a context.xml file + # where you have all the styles and the text with task of style. This is + # very handy since we need to only make a simple text document with a folder + # of images. + + # First let's call a file save dialog. I'm going to use the standard Gtk + # one. Maybe will make my own. + + folderchooser = Gtk.FileChooserDialog(talk.text("export_tooltip"), + None, + Gtk.FileChooserAction.SAVE, + (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, + Gtk.STOCK_SAVE, Gtk.ResponseType.OK)) + folderchooser.set_default_response(Gtk.ResponseType.OK) + response = folderchooser.run() + if response == Gtk.ResponseType.OK: + savefilename = folderchooser.get_filename() + else: + folderchooser.destroy() + return + folderchooser.destroy() + + + # We are going to start the folder for this converion. For this in the + # new_file directory we have an example ODT file. It's basically a zip + # file that we want to use. Let's unzip it. + + referencefile = "/new_file/reference.odt" + + # Let's clear the folder from previouw parsing if such exists. + + try: + os.system("rm -rf /tmp/odt_export") + except: + pass + + # And make the folder again. + os.makedirs("/tmp/odt_export") + + # Now let's unzip our contents into there. + + ref = zipfile.ZipFile(os.getcwd()+referencefile, "r") + ref.extractall("/tmp/odt_export") + ref.close() + + # Now there will be the Pictures directory that contains the test image + # of Moria standing in front of the window and looking at the racetrack. + # we don't need it. But we need the folder it self. + + try: + os.remove("/tmp/odt_export/Pictures/1000020100000780000004380D1DEC99F7A147C7.png") + except: + pass + + # By the way. If you want to look at this image. Just into the reference.odt + # you will see it there in the text. + + + # Now we going to start writing to the context.xml file. So let's open it. + + save = open("/tmp/odt_export/content.xml", "w") + + # First stuff that we are going to write are the headers. So LibreOffice + # will not start going nutz. And saying how corrupter the file is. + + save.write('''''') + + # Now let's write the name of the project + + save.write(''+win.analytics["name"]+'') + + # Now let's write the director's name + + save.write(''+win.analytics["director"]+'') + + # Now let's write the comment + + save.write(''+win.analytics["status"]+'') + + # Now let's write scenes them selves. We don't want all scene but only + # ones in the main chain. So we are ignoring the scenes that are meant for + # tests and such. + + + lastarrow = 'start' + for i in win.story["arrows"]: + if lastarrow == "end": + break + for arrow in win.story["arrows"]: + if arrow[0] == lastarrow: + lastarrow = arrow[1] + if arrow[1] != "end": + + # Here is our scene name. + save.write(''+arrow[1][1]+'') + save.write('') + + # We need to get all the assets of the scene and write them + # net under the scene name. + + assets = get_assets(win, arrow[1][1]) + + for cur in ["chr", "veh", "loc", "obj"]: + t = talk.text(cur)+": " + for a in assets: + + if cur in a: + t = t +a[a.rfind("/")+1:]+", " + t = t[:-2] + + if t != talk.text(cur): + save.write(''+t+'') + + # Now let's actually write the text of the scene in there. + scene = win.story["scenes"][arrow[1][1]]["shots"] + + save.write('') + save.write('') + + for block in scene: + + + # For just text parts. + if block[0] == "text_block": + style = "T3" + else: + + # If It's a shot. I want the shot color marking + + shotis = block[1] + + rcolors = [ + "shot_1", + "shot_2", + "shot_3", + "shot_4", + "shot_5" + ] + + # Getting the color. It's not always works. + + if "shot_colors" not in win.story: + win.story["shot_colors"] = {} + + surl = "/"+arrow[1][1]+"/"+shotis + + if surl not in win.story["shot_colors"]: + + win.story["shot_colors"][surl] = rcolors[len(win.story["shot_colors"]) % len(rcolors)] + + style = win.story["shot_colors"][surl] + + # Now let's itterate over the text in the block. + + for text in block[-1]: + + # For just regular parts we have our regular text + + if text[0] == "text" or text[0] == "link": + + for line in re.split("(\n)",text[-1]): + + if line == "\n": + save.write('') + save.write('') + + else: + save.write(''+line+'') + + # For frases it's a bit different + + elif text[0] == "frase": + + # We gonna close the simle text part. + save.write('') + + # We gonna make a new line + save.write('') + + # We gonna write the name of the speaker + save.write(''+text[1][-1]+'') + + # Then we open the text type + save.write('') + + # Then we write the frase + + for line in re.split("(\n)",text[-1]): + if line == "\n": + save.write('') + save.write('') + + else: + save.write(''+line+'') + + # Then we close the frase + save.write('') + + # And open back the other one + save.write('') + + + # Now let's make images work. Okay. So there is our + # images folder. We need to copy our image to there + # first. + + elif text[0] == "image": + + # The image could be relative or absolute. + + tmpurl = text[-1].replace("/", "_") + + if os.path.exists(win.project+text[-1]): + f = open(win.project+text[-1], "rb") + else: + f = open(text[-1], "rb") + + s = open("/tmp/odt_export/Pictures/"+tmpurl, "wb") + s.write(f.read()) + f.close() + s.close() + + # Now we have a copy of the image in the + # file. We need to draw it. + + save.write('') + save.write('') + save.write('') + save.write('') + save.write('') + + # There is a problem tho. We need to write + # the existance of this file into another + # place. if we don't do that. LibreOffice will + # think that the ODT is broken. So it will fix + # it and all gonna be great. Still not the best + # experience for the users. Please somebody + # figure it out. + + + + save.write('') + + # After every scene is want a little line in the bottom + save.write('') + save.write('') + save.write('') + + + else: + break + + + + + + + + + + # Now let's close the file + + save.write('') + save.close() + + + + # And now let's make the odt file in the given savefilename place + + def zip_odt(src, dst): + zf = zipfile.ZipFile("%s.odt" % (dst), "w", zipfile.ZIP_DEFLATED) #changed file extension + abs_src = os.path.abspath(src) + for dirname, subdirs, files in os.walk(src): + for filename in files: + absname = os.path.abspath(os.path.join(dirname, filename)) + arcname = absname[len(abs_src) + 1:] + zf.write(absname, arcname) + zf.close() + + zip_odt("/tmp/odt_export", savefilename) + + +def get_assets(win, scene): + + # This funtion will get the assets from any given scene. + + assets = [] + + + + # Now let's read through the scene. + + for shot in win.story["scenes"][scene]["shots"]: + + + # Let's read the shot + for asset in shot[-1]: + # Ignore text + if asset[0] == "text": + continue + + # It's it's a staight up link. Just add it. + if asset[0] == "link" and asset[1] not in assets: + assets.append(asset[1]) + + # It's a link in a frase. + if asset[0] == "frase" and asset[1][0] == "link" and asset[1][1] not in assets: + assets.append(asset[1][1]) + + + return assets diff --git a/studio/studio_storyLayer.py b/studio/studio_storyLayer.py index 542700c..dcea13e 100644 --- a/studio/studio_storyLayer.py +++ b/studio/studio_storyLayer.py @@ -551,6 +551,22 @@ def layer(win): url="story_editor") + # Export to ODT + def do(): + story.export_to_odt(win) + + UI_elements.roundrect(layer, win, + 5, + 555, + 40, + 40, + 10, + do, + "export", + talk.text("export_tooltip"), + url="story_editor") + + # Bottom # Multiuser