1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357 |
- ####################################
- # #
- # COPYRIGHT NOTICE #
- # #
- # This file is a part of Victori- #
- # ous Children Studio Organizer. #
- # Or simply VCStudio. Copyright #
- # of J.Y.Amihud. But don't be sad #
- # because I released the entire #
- # project under a GNU GPL license. #
- # You may use Version 3 or later. #
- # See www.gnu.org/licenses if your #
- # copy has no License file. Please #
- # note. Ones I used the GPL v2 for #
- # it. It's no longer the case. #
- # #
- ####################################
- import os
- import datetime
- # 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 settings import fileformats
- from settings import oscalls
- from project_manager import pm_project
- #UI modules
- from UI import UI_elements
- from UI import UI_color
- # story
- from studio import story
- from studio import checklist
- from studio import analytics
- from studio import studio_dialogs
- from studio import schedule
- from studio import history
- def datetip(win, date):
- # Function that outputs basic analytics about a given date
- # in text form
- # TODO: This function is in a prototype stage. Meaning it's
- # not translated to multiple languages. This should be fixed.
- # See settings/talk.py file.
-
- text = date
- try:
- data = win.analytics["dates"][date]
- # Expected
- startdate = win.analytics["startdate"]
- deadline = win.analytics["deadline"]
- duration = win.analytics["duration"]
- new_date_format = "%Y/%m/%d"
- sd = datetime.datetime.strptime(startdate, new_date_format)
- nd = datetime.datetime.strptime(date , new_date_format)
-
- dn = nd - sd
- daysin = int(dn.days)
- expected = round(100 / duration * daysin, 2)
- text = text +"\n\nExpected: "+str(expected)+"%"
-
- # Actual
- frac = round(data.get("fractions", {}).get("project")*100, 2)
- text = text +"\nActual: "+str(frac)+"%"
- # Productivity
- productivity = int(round(frac - expected+100))
- text = text +"\n\nProductivity: "+str(productivity)+"%"
-
- except Exception as e:
- pass
-
- return text
- def layer(win):
- # This is very important. I makes live easier. LOL.
- win.current["shot_left_side_scroll_please_work_omg_wtf"] = True
-
- # Making the layer
- surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, win.current['w'],
- win.current['h'])
- layer = cairo.Context(surface)
-
-
- #text setting
- layer.select_font_face("Monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
-
- UI_color.set(layer, win, "dark_overdrop")
- layer.rectangle(
- 0,
- 0,
- win.current["w"],
- win.current["h"],
- )
- layer.fill()
-
-
-
- UI_color.set(layer, win, "node_background")
- UI_elements.roundrect(layer, win,
- win.current["w"]/4,
- 10,
- win.current["w"]/2,
- win.current["h"]-20,
- 10)
-
- ############################################################################
-
- # This is the Analitycs window. This time I want to do something crazy.
- # There will be 5 sections on the screen.
-
- ############################################################################
- # # # #
- # # # #
- # # PROGRESS BARS # #
- # # # #
- # # # #
- # # ####################################### # #
- # # # #
- # SCHEDULING # ANALYTICS GRAPH # MAIN #
- # # # CHECKLIS #
- # # # #
- # # ####################################### # #
- # # # #
- # # CALENDAR / DAY SELECTOR # #
- # # # #
- # # X # #
- ############################################################################
-
- # The idea is that you could be in Assets or Script Editor and drag the
- # tasks from the checklist down to Calendar and leave it there. So when you
- # move the task and mouse comes into the center part, you automatically
- # transferred to the analytics layer for untill you leave the task somewhere
- # or return it back to the checklist.
-
- # I want to do the same with the SCHEDULING. So you could simple drag it to
- # the Calendar to change it's date. Let's see how terribly hard will it be
- # to implement. Because I'm already fighting with the Scedules all day.
-
- ############################################################################
-
- ############## PROGRESS BARS #############
-
-
- timepassed = 0.0
- projectdone = 0.0
- chrdone = 0.0
- vehdone = 0.0
- locdone = 0.0
- objdone = 0.0
- rnddone = 0.0
-
- try:
- timepassed = win.analytics["timepassed"]
- projectdone = win.analytics["fraction"]
- chrdone = win.analytics["chr"]
- vehdone = win.analytics["veh"]
- locdone = win.analytics["loc"]
- objdone = win.analytics["obj"]
- rnddone = win.analytics["rnd"]
- except:
- pass
-
- # MAIN PROGRESS
- UI_elements.image(layer, win, "settings/themes/"\
- +win.settings["Theme"]+"/icons/star.png",
- win.current["w"]/4+10,
- 15,
- 40,
- 40)
-
- # Progressbar
- UI_color.set(layer, win, "progress_background")
- UI_elements.roundrect(layer, win,
- win.current["w"]/4+60,
- 25,
- win.current["w"]/2-80,
- 20,
- 10,
- tip="Today's requirement is: "+str(round(win.analytics.get("needed", 0)*100, 1))+"% ( "+str(round(win.analytics.get("star", 0)*100, 1))+"% of which is done )")
- UI_color.set(layer, win, "text_link")
- UI_elements.roundrect(layer, win,
- win.current["w"]/4+60,
- 25,
- (win.current["w"]/2-80)*min(win.analytics.get("star", 0), 1),
- 20,
- 10)
-
- # # Icon
- # UI_elements.image(layer, win, "settings/themes/"\
- # +win.settings["Theme"]+"/icons/analytics.png",
- # win.current["w"]/4+10,
- # 15,
- # 40,
- # 40)
-
- # # Progressbar
- # UI_color.set(layer, win, "progress_background")
- # UI_elements.roundrect(layer, win,
- # win.current["w"]/4+60,
- # 25,
- # win.current["w"]/2-80,
- # 20,
- # 10,
- # tip=str(round(projectdone*100, 1))+"%")
-
-
-
- # # Project Done
- # UI_color.set(layer, win, "progress_active")
- # UI_elements.roundrect(layer, win,
- # win.current["w"]/4+60,
- # 25,
- # (win.current["w"]/2-80)*projectdone,
- # 20,
- # 10)
-
- # TIME PASSED
-
- # Icon
- UI_elements.image(layer, win, "settings/themes/"\
- +win.settings["Theme"]+"/icons/schedule.png",
- win.current["w"]/4+10,
- 55,
- 40,
- 40)
-
- UI_color.set(layer, win, "progress_background")
- UI_elements.roundrect(layer, win,
- win.current["w"]/4+60,
- 65,
- win.current["w"]/2-80,
- 20,
- 10,
- tip="Time: "+str(round(timepassed*100, 1))+"% Project: "+str(round(projectdone*100, 1))+"%")
-
- # Timepassed
- UI_color.set(layer, win, "progress_time")
- UI_elements.roundrect(layer, win,
- win.current["w"]/4+60,
- 65,
- (win.current["w"]/2-80)*timepassed,
- 20,
- 10)
- # Project Done
- UI_color.set(layer, win, "progress_active")
- UI_elements.roundrect(layer, win,
- win.current["w"]/4+60,
- 65,
- (win.current["w"]/2-80)*projectdone,
- 20,
- 10)
-
-
- # SCENES DONE ( RND )
-
- # Icon
- UI_elements.image(layer, win, "settings/themes/"\
- +win.settings["Theme"]+"/icons/shot.png",
- win.current["w"]/4+10,
- 95,
- 40,
- 40)
-
- UI_color.set(layer, win, "shot_5")
- UI_elements.roundrect(layer, win,
- win.current["w"]/4+60,
- 105,
- win.current["w"]/2-80,
- 20,
- 10,
- tip=str(round(rnddone*100, 1))+"%",
- fill=False)
- layer.stroke()
-
- # Scenes
- UI_color.set(layer, win, "shot_5")
- UI_elements.roundrect(layer, win,
- win.current["w"]/4+60,
- 105,
- (win.current["w"]/2-80)*rnddone,
- 20,
- 10)
-
- # CHR DONE
-
- # Icon
- UI_elements.image(layer, win, "settings/themes/"\
- +win.settings["Theme"]+"/icons/chr.png",
- win.current["w"]/4+10,
- 135,
- 40,
- 40)
-
- UI_color.set(layer, win, "shot_1")
- UI_elements.roundrect(layer, win,
- win.current["w"]/4+60,
- 145,
- win.current["w"]/4-80,
- 20,
- 10,
- tip=str(round(chrdone*100, 1))+"%",
- fill=False)
- layer.stroke()
-
- # progress
- UI_color.set(layer, win, "shot_1")
- UI_elements.roundrect(layer, win,
- win.current["w"]/4+60,
- 145,
- (win.current["w"]/4-80)*chrdone,
- 20,
- 10)
-
- # VEH DONE
-
- # Icon
- UI_elements.image(layer, win, "settings/themes/"\
- +win.settings["Theme"]+"/icons/veh.png",
- win.current["w"]/2,
- 135,
- 40,
- 40)
-
- UI_color.set(layer, win, "shot_2")
- UI_elements.roundrect(layer, win,
- win.current["w"]/2+60,
- 145,
- win.current["w"]/4-80,
- 20,
- 10,
- tip=str(round(vehdone*100, 1))+"%",
- fill=False)
- layer.stroke()
-
- # progress
- UI_color.set(layer, win, "shot_2")
- UI_elements.roundrect(layer, win,
- win.current["w"]/2+60,
- 145,
- (win.current["w"]/4-80)*vehdone,
- 20,
- 10)
-
- # LOC DONE
-
- # Icon
- UI_elements.image(layer, win, "settings/themes/"\
- +win.settings["Theme"]+"/icons/loc.png",
- win.current["w"]/4+10,
- 175,
- 40,
- 40)
-
- UI_color.set(layer, win, "shot_3")
- UI_elements.roundrect(layer, win,
- win.current["w"]/4+60,
- 185,
- win.current["w"]/4-80,
- 20,
- 10,
- tip=str(round(locdone*100, 1))+"%",
- fill=False)
- layer.stroke()
-
- # progress
- UI_color.set(layer, win, "shot_3")
- UI_elements.roundrect(layer, win,
- win.current["w"]/4+60,
- 185,
- (win.current["w"]/4-80)*locdone,
- 20,
- 10)
-
- # OBJ DONE
-
- # Icon
- UI_elements.image(layer, win, "settings/themes/"\
- +win.settings["Theme"]+"/icons/obj.png",
- win.current["w"]/2,
- 175,
- 40,
- 40)
-
- UI_color.set(layer, win, "shot_4")
- UI_elements.roundrect(layer, win,
- win.current["w"]/2+60,
- 185,
- win.current["w"]/4-80,
- 20,
- 10,
- tip=str(round(objdone*100, 1))+"%",
- fill=False)
- layer.stroke()
-
- # progress
- UI_color.set(layer, win, "shot_4")
- UI_elements.roundrect(layer, win,
- win.current["w"]/2+60,
- 185,
- (win.current["w"]/4-80)*objdone,
- 20,
- 10)
-
- ############### THE GRAPH ##################
-
- # This graph going to show the entire time of the whole project from
- # StartDate till Deadline. It will fill up with data overtime.
-
- # We are going to have a couple of modes.
-
- # Regular mode: Showing actuall values represented on the graph
- # it's going to be a diagonal line if the work was done
- # linearly.
- # Normalized : This this a graph of true values compared to time. So let's
- # say at a second day you had to be only at 3%. Being at 3% will
- # make graph show 100%. The expected value is linear from 0%
- # to 100% over the whole project.
- # Pulse mode : This mode will give a graph compared to the previous day.
- # if on a given day there was a gib jump in percentage there
- # will be a big spike on the graph.
-
- # Let's make a mode selector.
-
- if "analytics_middle_graph_mode" not in win.current:
- win.current["analytics_middle_graph_mode"] = "linear"
-
- for num, thing in enumerate(["linear", "analytics", "pulse"]): # By icons
-
- if win.current["analytics_middle_graph_mode"] == thing:
-
- UI_color.set(layer, win, "progress_time")
- UI_elements.roundrect(layer, win,
- win.current["w"]/4+10+(40*num),
- 225,
- 40,
- 40,
- 10)
-
- def do():
- win.current["analytics_middle_graph_mode"] = thing
- del win.current["graph_cashe"]
-
- UI_elements.roundrect(layer, win,
- win.current["w"]/4+10+(40*num),
- 225,
- 40,
- 40,
- 10,
- do,
- thing)
-
- # And before we start a little settings icon.
-
- # Documentation entry
- def do():
- def after(win, var):
- pass
-
- studio_dialogs.help(win, "help", after, SEARCH=talk.text("documentation_analytics"))
-
- UI_elements.roundrect(layer, win,
- win.current["w"]/4*3-110,
- 225,
- 40,
- 40,
- 10,
- do,
- "question")
-
- # Settings
- def do():
- win.url = "settings_layer"
-
- UI_elements.roundrect(layer, win,
- win.current["w"]/4*3-60,
- 225,
- 40,
- 40,
- 10,
- do,
- "settings",
- talk.text("Settings"))
-
- # Now let's make a filter by type. As you maybe already know appart from
- # the main progress I'm reading all the other things too. Every progress
- # bar on the screen should have a corrisponding graph. But sometimes if
- # paths go too far appart, this aint helpfull. So a filter is required to
- # switch a category on and off.
-
- if "analytics_middle_graph_switch" not in win.current:
- win.current["analytics_middle_graph_switch"] = {
- "project":[True,"analytics", "progress_active"],
- "checklist":[True,"checklist", "node_videofile"],
- "rnd":[True,"shot", "shot_5"],
- "chr":[True,"chr", "shot_1"],
- "veh":[True,"veh", "shot_2"], # Name in data : [ Active, Icon name, color ]
- "loc":[True,"loc", "shot_3"],
- "obj":[True,"obj", "shot_4"]
- }
-
- cat = win.current["analytics_middle_graph_switch"]
- mode = win.current["analytics_middle_graph_mode"]
-
- for num, thing in enumerate(cat):
-
- if cat[thing][0]:
-
- UI_color.set(layer, win, cat[thing][2])
- UI_elements.roundrect(layer, win,
- win.current["w"]/4+160+(40*num),
- 225,
- 38,
- 40,
- 10,
- fill=False)
- layer.stroke()
-
- def do():
- cat[thing][0] = not cat[thing][0]
- del win.current["graph_cashe"]
-
- UI_elements.roundrect(layer, win,
- win.current["w"]/4+160+(40*num),
- 225,
- 38,
- 40,
- 10,
- do,
- cat[thing][1])
-
- # Let's set up some very handy values
- new_date_format = "%Y/%m/%d"
- startdate = win.analytics["startdate"]
- deadline = win.analytics["deadline"]
- duration = win.analytics["duration"]
-
- # Let's setup the little graph layer. So nothing come out of the frame.
-
- x = win.current["w"]/4
- y = 280
- width = win.current["w"] / 2
- height = 100
-
- # Now let's make a layer.
-
- # CURRENT DATE
- today = datetime.datetime.strftime(datetime.datetime.today(), new_date_format)
-
-
- if "graph_cashe" not in win.current:
-
-
- # Making the layer
- graphsurface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width), int(height))
- node = cairo.Context(graphsurface)
- node.select_font_face("Monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
-
-
- # Background
- #UI_color.set(node, win, "dark_overdrop")
- #node.rectangle(0,0,width, height)
- #node.fill()
-
- # helping line
- UI_color.set(node, win, "progress_time")
-
- if mode == "analytics":
-
- node.move_to(0, height/2)
- node.line_to(width, height/2)
-
- elif mode == "pulse":
-
- ty = height / duration
- node.move_to(0, height/2-ty)
- node.line_to(width, height/2-ty)
-
- else:
-
- node.move_to(0, height)
- node.line_to(width, 0)
-
- node.stroke()
-
- todayX = 0
-
- for num, thing in enumerate(reversed(cat)):
-
- if cat[thing][0]:
-
- UI_color.set(node, win, cat[thing][2])
-
- if mode == "linear":
- node.move_to(0, height)
- else:
- node.move_to(0, height/2)
-
- pfrac = 0
-
- dates = win.analytics["dates"]
- for date in dates:
-
- # Let's calculate the X position of a given part on a graph
-
- sd = datetime.datetime.strptime(startdate, new_date_format)
- nd = datetime.datetime.strptime(date , new_date_format)
-
- dn = nd - sd
- dn = int(dn.days)
-
- graphX = width / duration * dn
- if date == today:
- todayX = graphX
-
- # Let's calculate the Y position of a given part on a graph
-
- if "fractions" in dates[date]:
- fracs = dates[date]["fractions"]
-
- if mode == "linear":
- gfraction = fracs[thing]
- graphY = height - height * gfraction
- node.line_to(graphX, graphY)
- elif mode == "analytics":
- gfraction = fracs[thing]
- tfraction = dn / duration
- gfraction = gfraction / tfraction / 2
- graphY = height - height * gfraction
- node.line_to(graphX, graphY)
- else:
- gfraction = fracs[thing]
- gfraction = gfraction - pfrac
- graphY = height - height * gfraction - height / 2
- node.line_to(graphX, graphY)
-
- pfrac = fracs[thing]
-
- node.stroke()
- # Today
- UI_color.set(node, win, "button_clicked")
- node.move_to(todayX, 0)
- node.line_to(todayX, height)
- node.stroke()
-
- win.current["graph_cashe"] = graphsurface
-
- # Dynamic elements of the graph!
- # I sense a possible bug here, since I will draw these on top
- # of a prebaked image. And something sometimes might not align
- # properly. I don't know how to deal with it quite yet, perhaps
- # you can try fixing the issue. LOL.
- # Bottom Graph position on the top graph.
- try:
- posX = width / (duration*50) * win.scroll["days"]
- posX2 = (width / (duration*50) * (win.scroll["days"]+width))-posX
- except:
- posX = 0
- posX2 = 20
- UI_color.set(layer, win, "dark_overdrop")
- UI_elements.roundrect(layer, win,
- x-posX,
- y,
- posX2,
- height,
- 5,
- fill=True)
- layer.stroke()
- # Mouse drag thingy
- if x < win.current["mx"] < x+width\
- and y < win.current["my"] < y+height:
- if win.current["LMB"]:
- win.scroll["days"] = 0- (( win.current["mx"] - x ) / width * (duration*50)) + (width/2)
- sd = datetime.datetime.strptime(startdate, new_date_format)
- daysin = int(round( duration / width * (x-win.current["mx"])))*-1
- td = datetime.timedelta(days=daysin)
- hoverdate = sd + td
- hoverdate = hoverdate.strftime(new_date_format)
-
- UI_elements.tooltip(win, datetip(win, hoverdate))
- UI_color.set(layer, win, "progress_background")
- layer.move_to(win.current["mx"], y)
- layer.line_to(win.current["mx"], y+height)
- layer.stroke()
-
- # Outputting the layer
- layer.set_source_surface(win.current["graph_cashe"], x, y)
- layer.paint()
-
- # Let's force graph to refresh on each click
- if not win.current["LMB"] and win.previous["LMB"]:
- try:
- del win.current["graph_cashe"]
- except:
- pass
-
- ############### SCHEDULING / DATE SELECTION ################
-
-
- # So here I want to put a dialog that in the Blender-Organizer legacy was
- # in the center of the frame. I thought here it makes a bit more sense. Tho
- # I will remove the graph from it. I have a very good graph on the top from
- # it. And in my opinion this is enough. In you think otherwise let me know.
- # or fork VCStudio and implement it yourself. See what I can do with free-
- # software. I can just tell you to do everything yourself. Imaging doing this
- # when developing proprietery software.
-
- # Anyway back to the thing. I do want to draw schedules inside the days cells.
- # and by their colors. RED or GREY or PURPLE or GREEN you will have an idea of
- # how much stuff is done and how much stuff is not yet done. A kind of second
- # graph, so to speak. But representing differnt kind of data.
-
-
- # OKAY. SETTINGS.
-
- if "schedule_analytics_settings" not in win.current:
- win.current["schedule_analytics_settings"] = {
- "checked":False,
- "multiuser":False
- }
-
- for num, button in enumerate(win.current["schedule_analytics_settings"]):
-
- if win.current["schedule_analytics_settings"][button]:
-
- UI_color.set(layer, win, "progress_time")
- UI_elements.roundrect(layer, win,
- x+10+(40*num),
- y+height+10,
- 40,
- 40,
- 10)
-
- def do():
- win.current["schedule_analytics_settings"][button] = not win.current["schedule_analytics_settings"][button]
-
- UI_elements.roundrect(layer, win,
- x+10+(40*num),
- y+height+10,
- 40,
- 40,
- 10,
- do,
- button)
-
-
- UI_elements.text(layer, win, "current_date_setting",
- x+100,
- y+height+10,
- 200,
- 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(layer, win,
- x+260,
- y+height+10,
- 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(layer, win,
- x+260,
- y+height+10,
- 40,
- 40,
- 10,
- button=do,
- icon="cancel",
- tip=talk.text("cancel"))
-
-
- y = y + height + 60
- height = win.current["h"]-500
-
- # Making the layer
- graphsurface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width), int(height))
- node = cairo.Context(graphsurface)
- node.select_font_face("Monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
-
-
-
-
- if "days" not in win.scroll:
- win.scroll["days"] = 0 - win.analytics["dayspassed"]*50 + width / 2 - 25
-
- current_X = 0
-
- prevyear = [startdate.split("/")[0], win.scroll["days"]]
- prevmonth = [startdate.split("/")[1], win.scroll["days"]]
- prevday = "1997/07/30"
- pfrac = {}
-
- for doffset in range(duration+1): # FOR ALL DAYS. NO MATTER IF THEY ARE IN DATA
-
- sd = datetime.datetime.strptime(startdate, new_date_format)
- theday = datetime.datetime.strftime(sd+datetime.timedelta(days=doffset), new_date_format)
-
-
- nowyear = [theday.split("/")[0], current_X+win.scroll["days"]]
- nowmonth = [theday.split("/")[1], current_X+win.scroll["days"]]
-
- # Focusing if selected
-
- if win.current["date"] != win.previous["date"] and win.current["date"] == theday:
- win.scroll["days"] = 0 - current_X + width / 2 - 25
-
- # YEARS
-
- if nowyear[0] != prevyear[0]:
- UI_color.set(node, win, "dark_overdrop")
- UI_elements.roundrect(node, win,
- 5+prevyear[1]+2,
- 0,
- nowyear[1] - prevyear[1]-7,
- 20,
- 10)
-
-
- UI_color.set(node, win, "text_normal")
- node.set_font_size(15)
- node.move_to(
- max(prevyear[1] + 200, min(width/2-23, nowyear[1]- 200)),
- 15,
- )
- node.show_text(prevyear[0])
-
- prevyear = nowyear
-
- # MONTHS
-
- if nowmonth[0] != prevmonth[0]:
- UI_color.set(node, win, "dark_overdrop")
- UI_elements.roundrect(node, win,
- 5+prevmonth[1]+2,
- 22,
- nowmonth[1]-prevmonth[1]-7,
- 20,
- 10)
-
- UI_color.set(node, win, "text_normal")
- node.set_font_size(15)
- node.move_to(
- max(prevmonth[1] + 12, min(width/2-12, nowmonth[1]- 35)),
- 38,
- )
- node.show_text(prevmonth[0])
-
- prevmonth = nowmonth
-
- # DAYS
- if -50 < current_X+win.scroll["days"] < width:
-
- UI_color.set(node, win, "dark_overdrop")
- UI_elements.roundrect(node, win,
- 5+current_X+win.scroll["days"],
- 44,
- 40,
- 20,
- 10)
-
- UI_color.set(node, win, "text_normal")
- node.set_font_size(15)
- node.move_to(
- 15+current_X+win.scroll["days"],
- 59,
- )
- node.show_text(theday.split("/")[2])
-
- UI_color.set(node, win, "dark_overdrop")
- if theday >= today:
- if theday == today:
- UI_color.set(node, win, "button_clicked")
- UI_elements.roundrect(node, win,
- 5+current_X+win.scroll["days"],
- 67,
- 40,
- height-67,
- 10)
-
- if win.current["date"] == theday:
- UI_color.set(node, win, "progress_background")
- UI_elements.roundrect(node, win,
- 5+current_X+win.scroll["days"],
- 67,
- 40,
- height-67,
- 10,
- fill=False)
- node.stroke()
-
- # STARTDATE & DEADLINE
-
- elif theday in [startdate, deadline]:
- UI_color.set(node, win, "node_badfile")
- UI_elements.roundrect(node, win,
- 5+current_X+win.scroll["days"],
- 67,
- 40,
- height-67,
- 10,
- fill=False)
- node.stroke()
-
- # SELECTION BUTTON
-
- def do():
-
-
-
- if win.current["tool"] == "schedule":
-
- # If it's a scheduling.
-
- path, back, cur, schedulepath, username = win.current["grab_data"].copy()
- path = path.replace(win.project, "")
- path = path[path.find(cur)+len(cur):]
-
- if theday not in win.analytics["dates"]:
- win.analytics["dates"][theday] = {}
-
- name = cur[cur.rfind("/")+1:]
- acur = cur.replace(name, "").replace("/", "")
-
- if acur in ["chr", "veh", "loc","obj"]:
- itemtype = "assets"
- elif not acur:
- itemtype = "files"
- else:
- itemtype = "scenes"
-
- if itemtype not in win.analytics["dates"][theday]:
- win.analytics["dates"][theday][itemtype] = {}
-
- if cur not in win.analytics["dates"][theday][itemtype]:
- win.analytics["dates"][theday][itemtype][cur] = []
- #print("test 1")
- win.analytics["dates"][theday][itemtype][cur].append(
- ["00:00:00",
- "schedule",
- path,
- "[Un-Checked]",
- schedulepath,
- username]
- )
- #print("test 2")
- # RETURNING BACK TO NORMAL
-
- win.url = back
- win.current["tool"] = "selection"
- analytics.save(win.project, win.analytics)
- win.analytics = analytics.load(win.project)
- win.checklists = {}
-
- # Multiuser sycning
- win.multiuser["request"] = "analytics"
-
- #print("test 3")
-
- else:
- win.current["date"] = theday
- win.text["current_date_setting"]["text"] = theday
-
- UI_elements.roundrect(node, win,
- 5+current_X+win.scroll["days"],
- 67,
- 40,
- height-67,
- 10,
- button=do,
- offset=[x,y],
- fill=False,
- tip=datetip(win, theday))
- node.stroke()
- ##################### BOTTOM GRAPH #######################
- # Blender-Organizer legacy had two graphs. One smaller
- # that shows all the project from start to finish
- # ( Implemented above ) and one bigger. That shows a
- # Zoomed in version of the graph. Back then I made it
- # executing the same code twice. Which was fine. Since
- # I had to make a change only ones. Now it's a bit of a
- # problem to do so. Since the graph above is baked. And
- # need to be able to navigate with in the bottom graph.
- # So instead I'm going to redo the graph, but since we
- # are re-doing it. I orignally wanted to do a different
- # design. But it ended up looking confusing. It needs lines!
- # Roundrects will not do.
-
- for num, thing in enumerate(reversed(cat)):
- if cat[thing][0]:
- UI_color.set(node, win, cat[thing][2])
- try:
- sd = datetime.datetime.strptime(startdate, new_date_format)
- nd = datetime.datetime.strptime(theday , new_date_format)
-
- dn = nd - sd
- dn = int(dn.days)
- fracs = win.analytics["dates"][theday]["fractions"]
- Pfracs = win.analytics["dates"][prevday]["fractions"]
-
- gfraction = fracs[thing]
- if mode == "linear":
-
- graphY = ((height-80) - (height-80) * gfraction)+60
-
- elif mode == "analytics":
- tfraction = dn / duration
- gfraction = gfraction / tfraction / 2
- graphY = ((height-80) - (height-80) * gfraction)+60
-
- else:
- try:
- gfraction = fracs[thing]
- gfraction = gfraction - Pfracs[thing]
- except:
- gfraction = 0
- graphY = ((height-80) - (height-80) * gfraction - (height-80) / 2)+60
- PgraphY = pfrac.get(thing, graphY)
- pfrac[thing] = graphY
-
- node.move_to(current_X+win.scroll["days"]-25,
- PgraphY)
- node.line_to(current_X+win.scroll["days"]+25,
- graphY)
- node.stroke()
-
-
-
-
-
- except Exception as e:
- if theday < today and theday not in win.analytics["dates"]:
- UI_color.set(node, win, "node_badfile")
- UI_elements.roundrect(node, win,
- 5+current_X+win.scroll["days"],
- 67,
- 40,
- height-67,
- 10,
- fill=False)
- node.stroke()
-
-
-
-
-
- # Now here I want to draw the representations of scheduled
- # tasks that are inside
- # Icons of what was done at the day
- icons_stuff = {"assets":"obj",
- "scenes":"shot",
- "files":"checklist"}
- icons = []
- for t in icons_stuff:
- if t in win.analytics["dates"].get(theday, {}) and t != "assets":
- icons.append(icons_stuff[t])
- elif t in win.analytics["dates"].get(theday, {}):
- for at in ["chr", "obj", "loc", "veh"]:
- for stuff in win.analytics["dates"].get(theday, {})[t]:
- if at in stuff and at not in icons:
- icons.append(at)
- for nicon, icon in enumerate(icons):
- UI_elements.image(node, win, "settings/themes/"\
- +win.settings["Theme"]+"/icons/"+icon+".png",
- 6+current_X+win.scroll["days"],
- height-(50*nicon)-50,
- 40,
- 40)
- # Stars! If the day was exceptional.
- try:
- if win.analytics["needed"] <= fracs.get("project", 0) - Pfracs.get("project", 0) and theday <= today:
- stars = (fracs.get("project", 0) - Pfracs.get("project", 0)) / win.analytics["needed"]
- for star in range(int(round(stars))):
- UI_elements.image(node, win, "settings/themes/"\
- +win.settings["Theme"]+"/icons/star.png",
- 6+current_X+win.scroll["days"],
- height-(50*(nicon+star-1))-150,
- 40,
- 40)
- except:
- pass
-
-
- # Schedules
-
- sch = []
- if theday in win.analytics["dates"]:
- date = win.analytics["dates"][theday]
-
- for i in ["files", "assets", "scenes"]:
- if i in date:
- for item in date[i]:
- for stuff in date[i][item]:
- if stuff[1] == "schedule":
-
- if not win.current["schedule_analytics_settings"]["multiuser"]:
- if win.settings["Username"] != stuff[-1]:
- continue
- if "[Checked]" in stuff:
- if win.current["schedule_analytics_settings"]["checked"]:
- sch.append(True)
- else:
- sch.append(False)
- for n, s in enumerate(sch):
- UI_color.set(node, win, "node_background")
- if theday < today:
- UI_color.set(node, win, "node_badfile")
- elif theday > today:
- UI_color.set(node, win, "node_asset")
- if s:
- UI_color.set(node, win, "node_blendfile")
-
- UI_elements.roundrect(node, win,
- 8+current_X+win.scroll["days"],
- 70+13*n,
- 35,
- 8,
- 5)
-
-
-
- current_X = current_X + 50
- prevday = theday
-
- UI_color.set(node, win, "dark_overdrop")
- UI_elements.roundrect(node, win,
- 5+prevyear[1]+2,
- 0,
- nowyear[1] - prevyear[1]-4 + 50,
- 20,
- 10)
-
-
- UI_color.set(node, win, "text_normal")
- node.set_font_size(15)
- node.move_to(
- max(prevyear[1] + 200, min(width/2-23, nowyear[1]- 200)),
- 15,
- )
- node.show_text(prevyear[0])
-
- UI_color.set(node, win, "dark_overdrop")
- UI_elements.roundrect(node, win,
- 5+prevmonth[1]+2,
- 22,
- nowmonth[1]-prevmonth[1]-4 + 50,
- 20,
- 10)
-
- UI_color.set(node, win, "text_normal")
- node.set_font_size(15)
- node.move_to(
- max(prevmonth[1] + 12, min(width/2-12, nowmonth[1]- 35)),
- 38,
- )
- node.show_text(prevmonth[0])
-
- # Outputting the layer
- layer.set_source_surface(graphsurface, x, y)
- layer.paint()
-
- # Scroll
- UI_elements.scroll_area(layer, win, "days",
- x,
- y,
- width,
- height+30,
- current_X,
- bar=True,
- mmb=True,
- sideways=True)
-
-
- ############## CHECKLIST ################
-
- if win.current["tool"] == "schedule":
-
- # If the tool is scheduling I want to make sure that the user sees where
- # he needs to place the task. A higlight.
-
- UI_color.set(layer, win, "progress_background")
- UI_elements.roundrect(layer, win,
- x,
- y+67,
- width,
- height-67,
- 10,
- fill=False)
- layer.stroke()
-
- path, back, cur, schedulepath, username = win.current["grab_data"].copy()
-
-
-
- checklist.draw(layer, win, path, back)
-
- UI_color.set(layer, win, "node_background")
- UI_elements.roundrect(layer, win,
- win.current["mx"],
- win.current["my"],
- 40,
- 40,
- 10)
-
- UI_elements.image(layer, win,
- "settings/themes/"+win.settings["Theme"]+"/icons/schedule.png",
- win.current["mx"],
- win.current["my"],
- 40,
- 40)
-
-
-
- elif os.path.exists(win.project+"/set/project.progress"):
- checklist.draw(layer, win, win.project+"/set/project.progress", back=win.url)
-
- elif os.path.exists(win.project+"/project.progress"):
- checklist.draw(layer, win, win.project+"/project.progress", back=win.url)
-
-
- # In the analytics window there will a choise of whether to see schedules. Or to
- # see history.
-
- if "analytics_left_panel" not in win.current:
- win.current["analytics_left_panel"] = "schedule"
-
-
- UI_color.set(layer, win, "node_background")
- UI_elements.roundrect(layer, win,
- 10,
- 10,
- win.current["w"]/4-20,
- 50,
- 10)
-
- for num, thing in enumerate(["schedule", "history"]):
- if win.current["analytics_left_panel"] == thing:
-
- UI_color.set(layer, win, "progress_time")
- UI_elements.roundrect(layer, win,
- 20+(40*num),
- 15,
- 40,
- 40,
- 10)
-
- def do():
- win.current["analytics_left_panel"] = thing
-
- UI_elements.roundrect(layer, win,
- 20+(40*num),
- 15,
- 40,
- 40,
- 10,
- do,
- thing)
-
- ##### SCHEDULE ######
-
- if win.current["analytics_left_panel"] == "schedule":
- schedule.draw(layer, win)
-
- ##### HISTORY #######
-
- else:
- history.draw(layer, win)
-
- # CANCEl
-
- def do():
- win.url = "story_editor"
- win.assets = {}
- win.current["asset_file_selected"] = ""
-
- UI_elements.roundrect(layer, win,
- win.current["w"]-40-win.current["w"]/4,
- win.current["h"]-50,
- 40,
- 40,
- 10,
- button=do,
- icon="cancel",
- tip=talk.text("cancel"))
-
- # Short cut ESC
- if 65307 in win.current["keys"] and not win.textactive:
- do()
-
-
- return surface
|