123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644 |
- # THIS FILE IS A PART OF VCStudio
- # PYTHON 3
- import os
- import datetime
- import threading
- # GTK module ( Graphical interface
- import gi
- gi.require_version('Gtk', '3.0')
- from gi.repository import Gtk
- from gi.repository import GLib
- from gi.repository import Gdk
- import cairo
- # Own modules
- from settings import settings
- from settings import talk
- from project_manager import pm_project
- from studio import analytics
- from studio import studio_nodes
- from studio import studio_dialogs
- from studio import story
- from studio import analytics
- from studio import checklist
- #UI modules
- from UI import UI_elements
- from UI import UI_color
- ################################################################################
- # This file is going to hande HISTORY. Both recoring and showing. I suppose in
- # future when I gonna implement Networking Multiuser support. History will be
- # handling some of it too. Will see. ( I might forget about this comment and it's
- # already implemented, who knows. )
- ################################################################################
- def record(win, filename, task, checklist=[] ):
-
- ############################################################################
-
- # This function will write the history file. Or incase connecting to multiuser
- # will also notify the server of a task being done. This file probably going
- # to change quite usually. Because I might start writting in more or less
- # stuff. So keep an eye on it.
-
- # Now since this will touch the multiuser and I can't guarantee that all
- # users will have the same version. The multiuser part of this should insure
- # stable backward compatibility with all verisons of VCStudio.
-
- # BUT THERE IS NO WARRANTY! So who knows if exidentaly break something for
- # the old versions. So keeping up to date quite advisable. Or at least keep
- # the same version of VCStudio across all the computers involved in multiuser.
-
- ############################################################################
-
- ################### CHECKLIST OF IMPEMENTED DATATYPES ######################
-
- # [V] [Openned] # WHEN BLEND FILE IS OPENNED [ settings/oscalls.py ]
- # [V] [Linked] # AS LINKED ASSET INTO BLEND [ studio/studio_shot_linkLayer.py ]
- # [V] [Edited] # WHEN EDITED STORY [ studio/studio_scriptLayer.py ]
- # [V] [Updated] # WHEN CONFIGURED STUFF [ studio/studio_asset_configureLayer.py ]
- # [V] [Added] # WHEN ADDING A BLEND FILE [ settings/oscalls.py ]
- # [V] [Added Asset] # WHEN ADDING AN ASSET [ studio/studio_asset_selectLayer.py ]
- # [V] [Checked] # WHEN [V] IN CHECKLIST [ studio/checklist.py ]
- # [V] [Un-Checked] # WHEN [ ] IN CHECKLIST [ studio/checklist.py ]
-
- ############################################################################
-
- ############### PARSING THE URLS ##############
-
- print("HISTORY-RAW: ", filename, task, checklist)
-
- # Fisrt of all let's remove the project's url
- filename = filename.replace(win.project, "").replace("//", "/")
-
- # Now let's find a type
- t = "files"
- item = filename
- if filename.startswith("/rnd"):
- t = "scenes"
- item = filename.replace("/rnd", "")
- filename = filename[filename.rfind("/"):]
- item = item[:item.rfind(filename)]
-
- elif filename.startswith("/ast") or filename.startswith("/dev"):
- t = "assets"
-
- if filename.startswith("/ast"):
- filename = "[asset_blend]"
- item = item.replace(".blend", "").replace("/ast", "")
-
- elif filename.startswith("/dev"):
- f = filename[filename.rfind("/"):]
- item = filename.replace(f, "").replace("/dev", "")
- filename = f
- else:
- filename = filename[filename.rfind("/"):]
-
- item = item.replace("//", "/")
- filename = filename.replace("//", "/")
-
- # Somebody please look at this. Maybe there is more clever way to record
- # editing of scenes. I don't know.
- if task == "[Edited]":
- item = filename
-
- print("HISTORY: ", t, item, filename, task, checklist)
-
-
- ########### WRITING TO THE ANANLYTICS ###########
-
- new_date_format = "%Y/%m/%d"
- date = datetime.datetime.strftime(datetime.datetime.today(), new_date_format)
-
- seconds_format = "%H:%M:%S"
- time = datetime.datetime.strftime(datetime.datetime.now(), seconds_format)
-
- username = win.settings["Username"]
-
- # Now since we have our DATE and TIME we can start writing.
-
-
- if date not in win.analytics["dates"]:
- win.analytics["dates"][date] = {}
- if t not in win.analytics["dates"][date]:
- win.analytics["dates"][date][t] = {}
- if item not in win.analytics["dates"][date][t]:
- win.analytics["dates"][date][t][item] = []
-
- # APPENDNING
- if not checklist:
- win.analytics["dates"][date][t][item].append(
- [
- time,
- "history",
- filename,
- task,
- username
- ]
- )
- else:
- win.analytics["dates"][date][t][item].append(
- [
- time,
- "history",
- filename,
- task,
- checklist,
- username
- ]
- )
-
- # REFRASHING
-
- analytics.save(win.project, win.analytics)
- win.analytics = analytics.load(win.project)
-
- # Multiuser sycning
- win.multiuser["request"] = "analytics"
-
- def draw(outlayer, win):
-
- x = 10
- y = 70
- width = win.current["w"] / 4 - 20
- height = win.current["h"] - 80
-
-
- # Now let's make a layer.
-
- # Making the layer
- surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width), int(height))
- layer = cairo.Context(surface)
- layer.select_font_face("Monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
-
- # Clip
- UI_elements.roundrect(layer, win,
- 0,
- 0,
- width,
- height,
- 10,
- fill=False)
- layer.clip()
-
- # Background
- #UI_color.set(layer, win, "dark_overdrop")
- #layer.rectangle(0,0,width, height)
- #layer.fill()
-
- new_date_format = "%Y/%m/%d"
- today = datetime.datetime.strftime(datetime.datetime.today(), new_date_format)
-
- if win.cur == "/set" :
- UI_elements.text(outlayer, win, "current_date_setting",
- width-100-(width-6*40),
- 15,
- (width-6*40),
- 40,
- set_text=win.current["date"])
-
- if win.text["current_date_setting"]["text"] != win.current["date"]\
- and analytics.ifdate(win.text["current_date_setting"]["text"]):
- def do():
- win.current["date"] = win.text["current_date_setting"]["text"]
- win.textactive = ""
-
- UI_elements.roundrect(outlayer, win,
- width-140,
- 15,
- 40,
- 40,
- 10,
- button=do,
- icon="ok",
- tip=talk.text("checked"))
-
- elif win.current["date"] != today:
- def do():
- win.current["date"] = today
- win.text["current_date_setting"]["text"] = today
- win.textactive = ""
-
- UI_elements.roundrect(outlayer, win,
- width-140,
- 15,
- 40,
- 40,
- 10,
- button=do,
- icon="cancel",
- tip=talk.text("cancel"))
-
-
- if "history" not in win.scroll:
- win.scroll["history"] = 0
-
- current_Y = 0
-
- # OKAY I GUESS SINCE HISTORY IS RELATIVELLY SIMPLE (LOL) I WILL PARSE IT
- # STRAIGHT. Without making a whole lot of parsing. Because with schedules
- # it resulted in some rather hilarious stuff.
-
- if "history_selection" not in win.current:
- win.current["history_selection"] = {
- "date":win.current["date"],
- "item":False,
- "user":False
- }
-
- dates = win.analytics["dates"]
-
-
- for date in dates:
-
- if (not win.cur or win.cur == "/set" )and date != win.current["date"]:
- continue
-
- theday = date
- date = dates[date]
-
- # Now let's parse throught it. I guess.
-
- for i in ["files", "assets", "scenes"]:
- if i in date:
- for item in date[i]:
-
- # This is our individual items. I want to create a folder
- # with USERS inside it. So you could see who done what.
-
-
-
- if win.cur.count("/") > 1:
- tmp = win.cur.replace("/","",1).split("/")
- acur, name = tmp[0], tmp[1]
- else:
- name = win.cur[win.cur.rfind("/")+1:]
- acur = ""
-
- if win.cur not in item and win.cur != "/set":
- continue
-
-
- name = item[item.rfind("/")+1:]
- acur = item.replace(name, "").replace("/", "")
-
- found = {}
-
- for stuff in date[i][item]:
- if stuff[1] == "history":
- if stuff[-1] not in found:
- found[stuff[-1]] = []
- if stuff[3] in ["[Checked]", "[Un-Checked]"]:
- found[stuff[-1]].append([stuff[0],stuff[2],stuff[3],stuff[4]])
- else:
- found[stuff[-1]].append([stuff[0],stuff[2],stuff[3],[]])
-
- if found:
- # Now let's output our findings
- UI_color.set(layer, win, "node_background")
- UI_elements.roundrect(layer, win,
- 0,
- win.scroll["history"] + current_Y,
- width,
- 50,
- 10)
-
-
-
- # ICON
- if i == "scenes" and win.cur == "/set":
-
- if item.count("/") > 1:
-
- UI_elements.image(layer, win,
- "settings/themes/"+win.settings["Theme"]+"/icons/shot.png",
- 5, win.scroll["history"] + current_Y+5, 40, 40)
- else:
-
- UI_elements.image(layer, win,
- "settings/themes/"+win.settings["Theme"]+"/icons/scene.png",
- 5, win.scroll["history"] + current_Y+5, 40, 40)
- elif i == "assets" and win.cur == "/set":
-
- if os.path.exists(os.getcwd()+"/settings/themes/"+win.settings["Theme"]+"/icons/"+acur+".png"):
-
- UI_elements.image(layer, win,
- "settings/themes/"+win.settings["Theme"]+"/icons/"+acur+".png",
- 5, win.scroll["history"] + current_Y+5, 40, 40)
- else:
-
- UI_elements.image(layer, win,
- "settings/themes/"+win.settings["Theme"]+"/icons/"+name+".png",
- 5, win.scroll["history"] + current_Y+5, 40, 40)
-
- name = talk.text(name.replace("/", ""))
- else:
- UI_elements.image(layer, win,
- "settings/themes/"+win.settings["Theme"]+"/icons/history.png",
- 5, win.scroll["history"] + current_Y+5, 40, 40)
-
- # MAIN TASK
- UI_color.set(layer, win, "text_normal")
- layer.set_font_size(20)
- layer.move_to(
- 50,
- win.scroll["history"] + current_Y+30,
- )
- if win.cur == "/set":
- if "chr" not in item and "veh" not in item and "loc" not in item and "obj" not in item and "set" not in item:
- layer.show_text(item.replace("/","",1).replace("/", " | "))
- else:
- layer.show_text(name.replace("project.progress", win.analytics["name"]))
- else:
- layer.show_text(theday)
- # Selection button
-
- def do():
-
- win.current["history_selection"]["item"] = item
- win.current["history_selection"]["date"] = theday
- win.current["history_selection"]["user"] = False
-
- UI_elements.roundrect(layer, win,
- 0,
- win.scroll["history"] + current_Y,
- width,
- 50,
- 10,
- button=do,
- fill=False,
- offset=[x,y])
- layer.stroke()
-
- if win.current["history_selection"]["item"] == item\
- and win.current["history_selection"]["date"] == theday:
-
- UI_color.set(layer, win, "progress_background")
- UI_elements.roundrect(layer, win,
- 0,
- win.scroll["history"] + current_Y,
- width,
- 50,
- 10,
- fill=False)
- layer.stroke()
-
- current_Y = current_Y + 60
-
- # It a history is selected you could open up the list
- # of users that worked on a given task.
-
- for user in found:
-
- UI_color.set(layer, win, "node_background")
- UI_elements.roundrect(layer, win,
- 20,
- win.scroll["history"] + current_Y,
- width-20,
- 50,
- 10)
-
- UI_elements.image(layer, win,
- "settings/themes/"+win.settings["Theme"]+"/icons/user.png",
- 25, win.scroll["history"] + current_Y+5, 40, 40)
-
- # NAME OF THE USER
-
- UI_color.set(layer, win, "text_normal")
- layer.set_font_size(20)
- layer.move_to(
- 70,
- win.scroll["history"] + current_Y+30,
- )
- layer.show_text(user)
-
- # SELECTION BOX
-
- def do():
-
- win.current["history_selection"]["user"] = user
-
- UI_elements.roundrect(layer, win,
- 20,
- win.scroll["history"] + current_Y,
- width-20,
- 50,
- 10,
- button=do,
- fill=False,
- offset=[x,y])
- layer.stroke()
-
- # IF THE USER IS SELECTED
-
- if win.current["history_selection"]["user"] == user:
-
- UI_color.set(layer, win, "progress_background")
- UI_elements.roundrect(layer, win,
- 20,
- win.scroll["history"] + current_Y,
- width-20,
- 50,
- 10,
- fill=False)
- layer.stroke()
-
- current_Y = current_Y + 60
-
- for stuff in found[user]:
-
- UI_color.set(layer, win, "node_background")
- UI_elements.roundrect(layer, win,
- 40,
- win.scroll["history"] + current_Y,
- width-40,
- 50,
- 10)
-
-
- # Here if both category and the user are
- # selected I need to parse the data of
- # the history to present it to you.
-
- operation_icons = {
- "[Openned]":"blender",
- "[Linked]":"file_link",
- "[Edited]":"scene",
- "[Updated]":"update",
- "[Added]":"new",
- "[Added Asset]":"asset_new",
- "[Checked]":"checked",
- "[Un-Checked]":"unchecked"
- }
-
-
- try:
- icon = operation_icons[stuff[2]]
- except:
- icon = "history"
-
- UI_elements.image(layer, win,
- "settings/themes/"+win.settings["Theme"]+"/icons/"+icon+".png",
- 45, win.scroll["history"] + current_Y+5, 40, 40)
-
- # Next will be to add some text about
- # what exactly was done here. And I know
- # that we are already super inside. I
- # mean indentation. If somebody want's
- # to reduse a few spaces. They are
- # welcome to try.
-
- # Let's split the the history entries to
- # 2 types. Checklists and everything else.
-
- # CHECKLISTS
- if "Checked" in stuff[2]:
-
- # Let's get task and url
- try:
- task = stuff[-1][-1]
- fullurl = ""
- for e in stuff[-1][:-1]:
- fullurl = fullurl+e+" > "
- except:
- tasl = ""
- fullurl = ""
-
-
- # MAIN TASK
- UI_color.set(layer, win, "text_normal")
- layer.set_font_size(20)
- layer.move_to(
- 80,
- win.scroll["history"] + current_Y+24,
- )
- layer.show_text(task)
-
-
- # TASK URL INSIDE THE CHECKLIST
-
- if fullurl:
- UI_color.set(layer, win, "text_normal")
- layer.set_font_size(10)
- layer.move_to(
- 90+len(task)*12,
- win.scroll["history"] + current_Y+24,
- )
- layer.show_text(fullurl)
-
- else:
- # If it's not a checklist. I just want
- # to output what it is and what action
- # happened to it.
-
- task = stuff[1].replace("/", " ")
- if task == "[asset_blend]":
- task = " Asset Blend File"
-
- # WHAT
- UI_color.set(layer, win, "text_normal")
- layer.set_font_size(20)
- layer.move_to(
- 80,
- win.scroll["history"] + current_Y+24,
- )
- layer.show_text(task)
-
-
- # WHAT WAS DONE
-
- UI_color.set(layer, win, "text_normal")
- layer.set_font_size(10)
- layer.move_to(
- 90+len(task)*12,
- win.scroll["history"] + current_Y+24,
- )
- layer.show_text(stuff[2])
-
- UI_color.set(layer, win, "text_normal")
- layer.set_font_size(15)
- layer.move_to(
- 92,
- win.scroll["history"] + current_Y+41,
- )
- layer.show_text(stuff[0])
-
- # Okay and the last thing. The button of
- # when it's clicked. For example to get
- # to the item. Or to find the task in
- # the checklist. For what ever reason.
-
- def do():
-
- # Let's make the auto-selecting of
- # the checklists. OMG I really have
- # no space left to type. OMG. What
- # is this.
-
- if "Checked" in stuff[2]:
-
- # AAAAAAAAAAAAAAAAAAAAAAAAAAAA
- # How am I supposed to tell thi-
- # ngs? OMG.
-
- if "schedule_task_selected" not in win.current:
- win.current["schedule_task_selected"] = []
-
- win.current["schedule_task_selected"] = \
- [[[stuff[0], "schedule", stuff[1], stuff[2], stuff[3]], 0], item]
-
- # Now since we did this weird
- # what ever the mack. Let's make so
- # it's going to the asset.
-
- if i == "assets":
- goto = "assets"
- elif i == "scenes":
- goto = "script"
- else:
- goto = "analytics"
-
- win.url = goto
- win.cur = item
- win.current["asset_left_panel"] = "history"
-
- if stuff[2] != "[Added Asset]":
-
- UI_elements.roundrect(layer, win,
- 40,
- win.scroll["history"] + current_Y,
- width-40,
- 50,
- 10,
- button=do,
- fill=False,
- offset=[x,y])
- layer.stroke()
-
-
- current_Y = current_Y + 60
- else:
- current_Y = current_Y + 60
- else:
- current_Y = current_Y + 60
-
- # Outputting the layer
- outlayer.set_source_surface(surface, x, y)
- outlayer.paint()
-
- # Scroll
- UI_elements.scroll_area(outlayer, win, "history",
- x+0,
- y+50,
- width,
- height-50,
- current_Y,
- bar=True,
- mmb=True)
|