2020-12-13 04:06:44 +01:00
|
|
|
# THIS FILE IS A PART OF VCStudio
|
|
|
|
# PYTHON 3
|
|
|
|
|
|
|
|
# This a console project manager.
|
|
|
|
|
|
|
|
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
|
2020-12-14 04:21:25 +01:00
|
|
|
from studio import history
|
2020-12-13 04:06:44 +01:00
|
|
|
|
|
|
|
def layer(win):
|
|
|
|
|
|
|
|
|
|
|
|
# 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
|
|
|
|
|
|
|
|
# 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)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 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)
|
|
|
|
|
|
|
|
# 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)
|
|
|
|
|
|
|
|
# SCENES DONE ( RND )
|
|
|
|
|
|
|
|
# Icon
|
|
|
|
UI_elements.image(layer, win, "settings/themes/"\
|
2020-12-15 21:38:04 +01:00
|
|
|
+win.settings["Theme"]+"/icons/scene.png",
|
2020-12-13 04:06:44 +01:00
|
|
|
win.current["w"]/4+10,
|
|
|
|
95,
|
|
|
|
40,
|
|
|
|
40)
|
|
|
|
|
|
|
|
UI_color.set(layer, win, "progress_background")
|
|
|
|
UI_elements.roundrect(layer, win,
|
|
|
|
win.current["w"]/4+60,
|
|
|
|
105,
|
|
|
|
win.current["w"]/2-80,
|
|
|
|
20,
|
|
|
|
10)
|
|
|
|
|
|
|
|
# Scenes
|
|
|
|
UI_color.set(layer, win, "node_videofile")
|
|
|
|
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, "progress_background")
|
|
|
|
UI_elements.roundrect(layer, win,
|
|
|
|
win.current["w"]/4+60,
|
|
|
|
145,
|
|
|
|
win.current["w"]/4-80,
|
|
|
|
20,
|
|
|
|
10)
|
|
|
|
|
|
|
|
# progress
|
|
|
|
UI_color.set(layer, win, "node_asset")
|
|
|
|
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, "progress_background")
|
|
|
|
UI_elements.roundrect(layer, win,
|
|
|
|
win.current["w"]/2+60,
|
|
|
|
145,
|
|
|
|
win.current["w"]/4-80,
|
|
|
|
20,
|
|
|
|
10)
|
|
|
|
|
|
|
|
# progress
|
|
|
|
UI_color.set(layer, win, "node_imagefile")
|
|
|
|
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, "progress_background")
|
|
|
|
UI_elements.roundrect(layer, win,
|
|
|
|
win.current["w"]/4+60,
|
|
|
|
185,
|
|
|
|
win.current["w"]/4-80,
|
|
|
|
20,
|
|
|
|
10)
|
|
|
|
|
|
|
|
# progress
|
|
|
|
UI_color.set(layer, win, "node_blendfile")
|
|
|
|
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, "progress_background")
|
|
|
|
UI_elements.roundrect(layer, win,
|
|
|
|
win.current["w"]/2+60,
|
|
|
|
185,
|
|
|
|
win.current["w"]/4-80,
|
|
|
|
20,
|
|
|
|
10)
|
|
|
|
|
|
|
|
# progress
|
|
|
|
UI_color.set(layer, win, "node_badfile")
|
|
|
|
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"] = "pulse"
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
2020-12-25 15:20:34 +01:00
|
|
|
# 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")
|
|
|
|
|
2020-12-13 04:06:44 +01:00
|
|
|
# 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", "darker_parts"],
|
2020-12-15 21:38:04 +01:00
|
|
|
"rnd":[True,"scene", "node_videofile"],
|
2020-12-13 04:06:44 +01:00
|
|
|
"chr":[True,"chr", "node_asset"],
|
|
|
|
"veh":[True,"veh", "node_imagefile"], # Name in data : [ Active, Icon name, color ]
|
|
|
|
"loc":[True,"loc", "node_blendfile"],
|
|
|
|
"obj":[True,"obj", "node_badfile"]
|
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
|
|
|
40,
|
|
|
|
40,
|
|
|
|
10)
|
|
|
|
|
|
|
|
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,
|
|
|
|
40,
|
|
|
|
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 = (win.current["h"]-300)/2
|
|
|
|
|
|
|
|
# Now let's make a layer.
|
|
|
|
|
2020-12-14 04:21:25 +01:00
|
|
|
|
|
|
|
|
2020-12-13 04:06:44 +01:00
|
|
|
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_background")
|
|
|
|
|
|
|
|
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()
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
# 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()
|
|
|
|
|
|
|
|
win.current["graph_cashe"] = graphsurface
|
|
|
|
# Outputting the layer
|
|
|
|
layer.set_source_surface(win.current["graph_cashe"], x, y)
|
|
|
|
layer.paint()
|
2020-12-14 04:21:25 +01:00
|
|
|
|
|
|
|
# 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
|
2020-12-13 04:06:44 +01:00
|
|
|
|
|
|
|
############### 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)
|
|
|
|
|
|
|
|
# CURRENT DATE
|
|
|
|
today = datetime.datetime.strftime(datetime.datetime.today(), new_date_format)
|
|
|
|
|
|
|
|
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"]
|
2020-12-14 04:21:25 +01:00
|
|
|
win.textactive = ""
|
|
|
|
|
2020-12-13 04:06:44 +01:00
|
|
|
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
|
2020-12-14 04:21:25 +01:00
|
|
|
win.textactive = ""
|
2020-12-13 04:06:44 +01:00
|
|
|
|
|
|
|
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 = height - 100
|
|
|
|
|
|
|
|
# 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"]]
|
|
|
|
|
|
|
|
|
|
|
|
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:
|
|
|
|
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()
|
|
|
|
|
2020-12-14 04:21:25 +01:00
|
|
|
# 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()
|
|
|
|
|
2020-12-13 04:06:44 +01:00
|
|
|
# SELECTION BUTTON
|
|
|
|
|
|
|
|
def do():
|
2020-12-14 04:21:25 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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] = []
|
2020-12-15 21:38:04 +01:00
|
|
|
#print("test 1")
|
2020-12-14 04:21:25 +01:00
|
|
|
win.analytics["dates"][theday][itemtype][cur].append(
|
|
|
|
["00:00:00",
|
|
|
|
"schedule",
|
|
|
|
path,
|
|
|
|
"[Un-Checked]",
|
|
|
|
schedulepath,
|
|
|
|
username]
|
|
|
|
)
|
2020-12-15 21:38:04 +01:00
|
|
|
#print("test 2")
|
2020-12-14 04:21:25 +01:00
|
|
|
# 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 = {}
|
2021-01-03 00:33:34 +01:00
|
|
|
|
|
|
|
# Multiuser sycning
|
|
|
|
win.multiuser["request"] = "analytics"
|
|
|
|
|
2020-12-15 21:38:04 +01:00
|
|
|
#print("test 3")
|
2020-12-14 04:21:25 +01:00
|
|
|
|
|
|
|
else:
|
|
|
|
win.current["date"] = theday
|
|
|
|
win.text["current_date_setting"]["text"] = theday
|
|
|
|
|
2020-12-13 04:06:44 +01:00
|
|
|
UI_elements.roundrect(node, win,
|
|
|
|
5+current_X+win.scroll["days"],
|
|
|
|
67,
|
|
|
|
40,
|
|
|
|
height-67,
|
|
|
|
10,
|
|
|
|
button=do,
|
|
|
|
offset=[x,y],
|
|
|
|
fill=False)
|
|
|
|
node.stroke()
|
|
|
|
|
|
|
|
|
|
|
|
# Now here I want to draw the representations of scheduled
|
|
|
|
# tasks that are insife
|
|
|
|
|
|
|
|
sch = []
|
|
|
|
if theday in win.analytics["dates"]:
|
|
|
|
date = win.analytics["dates"][theday]
|
2020-12-15 21:38:04 +01:00
|
|
|
|
2020-12-13 04:06:44 +01:00
|
|
|
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":
|
2020-12-15 21:38:04 +01:00
|
|
|
|
2020-12-13 04:06:44 +01:00
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
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":
|
|
|
|
|
2020-12-14 04:21:25 +01:00
|
|
|
# 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()
|
2020-12-13 04:06:44 +01:00
|
|
|
|
2020-12-14 04:21:25 +01:00
|
|
|
path, back, cur, schedulepath, username = win.current["grab_data"].copy()
|
2020-12-13 04:06:44 +01:00
|
|
|
|
2020-12-15 21:38:04 +01:00
|
|
|
|
|
|
|
|
2020-12-13 04:06:44 +01:00
|
|
|
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)
|
|
|
|
|
2020-12-14 04:21:25 +01:00
|
|
|
|
|
|
|
# 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"
|
|
|
|
|
|
|
|
|
2020-12-13 04:06:44 +01:00
|
|
|
UI_color.set(layer, win, "node_background")
|
|
|
|
UI_elements.roundrect(layer, win,
|
|
|
|
10,
|
|
|
|
10,
|
|
|
|
win.current["w"]/4-20,
|
|
|
|
50,
|
|
|
|
10)
|
2020-12-14 04:21:25 +01:00
|
|
|
|
|
|
|
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
|
2020-12-13 04:06:44 +01:00
|
|
|
|
2020-12-14 04:21:25 +01:00
|
|
|
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)
|
2020-12-13 04:06:44 +01:00
|
|
|
|
|
|
|
# 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
|