I'm redesigning the thing so downloading of remote files would be optional.

This commit is contained in:
Victorious Children Studios 2023-12-17 22:28:27 +02:00
parent d766371266
commit 5e7052b3ab
5 changed files with 430 additions and 35 deletions

View file

@ -4,6 +4,7 @@
import os import os
import json import json
import time import time
import fnmatch
import hashlib import hashlib
import urllib.request import urllib.request
import urllib.parse import urllib.parse
@ -60,19 +61,19 @@ def down(win, website, filename, fsize=100000):
# If it is a blend file, we are in trouble. # If it is a blend file, we are in trouble.
if filename.endswith(".blend"): # if filename.endswith(".blend"):
dp = go(win, website, "/blend"+filename) # dp = go(win, website, "/blend"+filename)
dplen = len(dp.get("files", {})) # dplen = len(dp.get("files", {}))
for f in dp.get("files", {}): # for f in dp.get("files", {}):
try: # try:
hashis = hashlib.md5(open(win.project+f,'rb').read()).hexdigest() # hashis = hashlib.md5(open(win.project+f,'rb').read()).hexdigest()
except: # except:
hashis = "" # hashis = ""
if hashis != dp.get("files", {}).get(f, {}).get("md5"): # if hashis != dp.get("files", {}).get(f, {}).get("md5"):
win.current["http-server"]["message"] = f[f.rfind("/")+1:] # win.current["http-server"]["message"] = f[f.rfind("/")+1:]
filesize = dp.get("files", {}).get(f, {}).get("filesize") # filesize = dp.get("files", {}).get(f, {}).get("filesize")
print("trying to get:", f) # print("trying to get:", f)
pp = down(win, website, f, filesize) # pp = down(win, website, f, filesize)
# Making folder for the files # Making folder for the files
@ -99,6 +100,96 @@ def down(win, website, filename, fsize=100000):
savef.close() savef.close()
def get_folder_info(win, folders, cur):
# This function gets an information of what files should be changed. And outputs
# the found data into the the global win thing, so it could accessed later.
# Making sure we have the infrastructure.
print("Getting Update Info About Folders")
website = win.analytics["remote-server-url"]
if "remote-folder-data" not in win.current:
win.current["remote-folder-data"] = {}
if cur not in win.current["remote-folder-data"]:
win.current["remote-folder-data"][cur] = {"missing":{},
"changed":{}}
def sort_file(filename, files, f):
filedata = files.get(f, {})
try:
hashis = hashlib.md5(open(win.project+filename,'rb').read()).hexdigest()
except:
hashis = ""
if not os.path.exists(win.project+filename):
win.current["remote-folder-data"][cur]["missing"][filename] = filedata
elif hashis != filedata.get("md5"):
filedata["to_download"] = True
win.current["remote-folder-data"][cur]["changed"][filename] = filedata
# Part one: Getting all the data about the files.
for foldername in folders:
try:
answer = go(win, website, "/list"+foldername)
files = list(answer.get("files", {}).keys())
for f in fnmatch.filter(files, folders.get(foldername, "*")):
# Now we need to figure out whether we have the file
# , whether we don't even have it ,
# or whether we have a different version.
fullfilename = foldername+"/"+f
sort_file(fullfilename, answer.get("files", {}), f)
except Exception as e:
error = "Error: "+ str(e)
print(error)
# Part two: Unwrapping all the blend dependancies data.
# Here we are going to store blend file that were checked already.
win.current["remote-folder-data"][cur]["blend_checked"] = []
# A function checking if we still have some unchecked .blends
def not_checked():
for t in ["missing", "changed"]:
for i in win.current["remote-folder-data"][cur][t]:
if i not in win.current["remote-folder-data"][cur]["blend_checked"] and i.endswith(".blend"):
return i
return False
nc = not_checked()
while nc:
dp = go(win, website, "/blend"+nc)
for f in dp.get("files", {}):
try:
sort_file(f,
dp.get("files", {}),
f[f.rfind("/")+1:])
except Exception as e:
print(e)
win.current["remote-folder-data"][cur]["blend_checked"].append(nc)
nc = not_checked()
for t in ["missing", "changed"]:
print(t+":")
for i in win.current["remote-folder-data"][cur][t]:
print(" "+i)
def get_folders(win): def get_folders(win):
# This function will get specified subfolders # This function will get specified subfolders
@ -244,6 +335,7 @@ def get_files(win):
try: try:
hashis = hashlib.md5(open(win.project+filename,'rb').read()).hexdigest() hashis = hashlib.md5(open(win.project+filename,'rb').read()).hexdigest()
except: except:
print("missing", filename)
hashis = "" hashis = ""
if hashis != answer.get("files", {}).get(i, {}).get("md5"): if hashis != answer.get("files", {}).get(i, {}).get("md5"):
@ -386,3 +478,193 @@ def layer(win, call):
10,) 10,)
return surface return surface
def prompt_layer(win, call):
# 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()
# So it's going to be like a little window in the center of the VCStudio
# with a simple UI. Probably like 2 things. Folder and a projectname.
UI_color.set(layer, win, "node_background")
UI_elements.roundrect(layer, win,
win.current["w"]/2-350,
100,
700,
win.current["h"]-200,
10)
# Exit button
def do():
win.current["calls"][call]["var"] = False
UI_elements.roundrect(layer, win,
win.current["w"]/2+310,
win.current["h"]-140,
40,
40,
10,
button=do,
icon="cancel",
tip=talk.text("cancel"))
# Clipping everything
UI_elements.roundrect(layer, win,
win.current["w"]/2-350,
100,
700,
win.current["h"]-260,
10,
fill=False)
layer.clip()
clip = [
win.current["w"]/2-350,
100,
700,
win.current["h"]-260]
# Setting up the scroll
if "http-prompt" not in win.scroll:
win.scroll["http-prompt"] = 0
cur = win.current["remote-folder-data"]["prompt"]
current_Y = 0
# Missing files
if "missing_active" not in win.current["remote-folder-data"][cur]:
win.current["remote-folder-data"][cur]["missing_active"] = False
icon = "closed"
if win.current["remote-folder-data"][cur]["missing_active"]:
icon = "open"
def do():
win.current["remote-folder-data"][cur]["missing_active"] = not win.current["remote-folder-data"][cur]["missing_active"]
UI_elements.roundrect(layer, win,
win.current["w"]/2-340,
110 + current_Y + win.scroll["http-prompt"],
680,
40,
10,
button=do,
icon=icon,
tip=talk.text("MissingFiles"))
UI_color.set(layer, win, "text_normal")
layer.set_font_size(20)
layer.move_to(win.current["w"]/2-290,
current_Y + win.scroll["http-prompt"] + 135)
layer.show_text(talk.text("MissingFiles")+" ( "+str(len(win.current["remote-folder-data"][cur]["missing"]))+" ) ")
current_Y += 50
if win.current["remote-folder-data"][cur]["missing_active"]:
for f in win.current["remote-folder-data"][cur]["missing"]:
UI_color.set(layer, win, "text_normal")
layer.set_font_size(20)
layer.move_to(win.current["w"]/2-270,
current_Y + win.scroll["http-prompt"] + 135)
layer.show_text(f)
current_Y += 50
# Updated files
if "changed_active" not in win.current["remote-folder-data"][cur]:
win.current["remote-folder-data"][cur]["changed_active"] = True
icon = "closed"
if win.current["remote-folder-data"][cur]["changed_active"]:
icon = "open"
def do():
win.current["remote-folder-data"][cur]["changed_active"] = not win.current["remote-folder-data"][cur]["changed_active"]
UI_elements.roundrect(layer, win,
win.current["w"]/2-340,
110 + current_Y + win.scroll["http-prompt"],
680,
40,
10,
button=do,
icon=icon,
tip=talk.text("ChangedFiles"))
UI_color.set(layer, win, "text_normal")
layer.set_font_size(20)
layer.move_to(win.current["w"]/2-290,
current_Y + win.scroll["http-prompt"] + 135)
layer.show_text(talk.text("ChangedFiles")+" ( "+str(len(win.current["remote-folder-data"][cur]["changed"]))+" ) ")
current_Y += 50
if win.current["remote-folder-data"][cur]["changed_active"]:
for f in win.current["remote-folder-data"][cur]["changed"]:
fdata = win.current["remote-folder-data"][cur]["changed"][f]
icon = "unchecked"
if fdata["to_download"]:
icon = "checked"
def do():
fdata["to_download"] = not fdata["to_download"]
UI_elements.roundrect(layer, win,
win.current["w"]/2-315,
110 + current_Y + win.scroll["http-prompt"],
660,
40,
10,
button=do,
icon=icon)
UI_color.set(layer, win, "text_normal")
layer.set_font_size(20)
layer.move_to(win.current["w"]/2-270,
current_Y + win.scroll["http-prompt"] + 135)
layer.show_text(f)
current_Y += 50
UI_elements.scroll_area(layer, win, "http-prompt",
int(win.current["w"]/2-350),
100,
700,
win.current["h"]-260,
current_Y,
bar=True,
mmb=True,
url="http-server-prompt"
)
return surface

View file

@ -116,7 +116,6 @@ class handler(BaseHTTPRequestHandler):
"files":{}} "files":{}}
for i in walk[2]: for i in walk[2]:
fd = fileinfo(folder+"/"+i) fd = fileinfo(folder+"/"+i)
data["files"][i] = fd data["files"][i] = fd
@ -127,6 +126,30 @@ class handler(BaseHTTPRequestHandler):
self.end_headers() self.end_headers()
self.wfile.write(senddata) self.wfile.write(senddata)
# THIS WAS A GOOD IDEA ON PAPER, BUT WITH A 100 GB PROJECT
# IT TOOK FOREVER TO DO THIS FOR ONE PART OF THIS PROJECT.
# elif self.path.startswith("/tree/"):
# foldername = self.path[5:]
# folder = PROJECT+foldername
# walk = list(os.walk(folder))
# data = {"folders":[],
# "files":{}}
# for i in walk:
# fol = i[0].replace(PROJECT, "")[1:]
# data["folders"].append(fol)
# for fil in i[2]:
# fd = fileinfo(PROJECT+"/"+fol+"/"+fil)
# data["files"][fol+"/"+fil] = fd
# senddata = json.dumps(data).encode("utf-8")
# self.start_page(200)
# self.send_header('Content-type', 'application/json')
# self.end_headers()
# self.wfile.write(senddata)
elif self.path.startswith("/blend/"): elif self.path.startswith("/blend/"):
filename = self.path[6:] filename = self.path[6:]

View file

@ -285,3 +285,6 @@ remote-update-initial-tip = [Download initial project files and replace
the ones on the computer with the ones on the computer with
the downloaded files.] the downloaded files.]
remote-server-url = [The hostname of the remote server.] remote-server-url = [The hostname of the remote server.]
MissingFiles = [Missing Files]
ChangedFiles = [Changed Files]
RemoteAssetUpdates = [Remote Asset Updates]

View file

@ -4,6 +4,7 @@
# This a console project manager. # This a console project manager.
import os import os
import threading
# GTK module ( Graphical interface # GTK module ( Graphical interface
import gi import gi
@ -144,21 +145,23 @@ def layer(win):
def do(): def do():
win.current["asset_cur_folder"] = cur win.current["asset_cur_folder"] = cur
# Why? # FUNCTIONS PER THINGS
if win.current["asset_cur_folder"] == "idea":
fl = "reference"
elif win.current["asset_cur_folder"] == "texture":
fl = "tex"
elif win.current["asset_cur_folder"] == "render":
fl = "renders"
else:
fl = ""
# Remote Server Stuff # # Why?
if win.analytics["from-remote-server"]: # if win.current["asset_cur_folder"] == "idea":
def after(win, var): # fl = "reference"
UI_elements.reload_images(win) # elif win.current["asset_cur_folder"] == "texture":
studio_dialogs.http_client_dialog(win, "http-client", after, http_client.get_files, "/dev/"+win.cur+"/"+fl) # fl = "tex"
# elif win.current["asset_cur_folder"] == "render":
# fl = "renders"
# else:
# fl = ""
# # Remote Server Stuff
# if win.analytics["from-remote-server"]:
# def after(win, var):
# UI_elements.reload_images(win)
# studio_dialogs.http_client_dialog(win, "http-client", after, http_client.get_files, "/dev/"+win.cur+"/"+fl)
UI_elements.roundrect(layer, win, UI_elements.roundrect(layer, win,
@ -172,6 +175,48 @@ def layer(win):
tip=talk.text(folds[cur])) tip=talk.text(folds[cur]))
# Little Remote Server thing
if win.analytics["from-remote-server"]:
if "remote-folder-data" not in win.current:
win.current["remote-folder-data"] = {}
if win.cur not in win.current["remote-folder-data"]:
win.current["remote-folder-data"][win.cur] = {"missing":{},
"changed":{}}
def do():
def after(win, var):
UI_elements.reload_images(win)
win.current["remote-folder-data"]["prompt"] = win.cur
studio_dialogs.http_client_update_prompt(win, "http-client-prompt", after)
UI_elements.roundrect(layer, win,
win.current["w"]/4+60,
350,
40,
40,
10,
do,
"multiuser",
tip=talk.text("RemoteAssetUpdates"))
if win.current["remote-folder-data"][win.cur]["missing"] or win.current["remote-folder-data"][win.cur]["changed"]:
count = str(len(win.current["remote-folder-data"][win.cur]["missing"])+len(win.current["remote-folder-data"][win.cur]["changed"]))
UI_color.set(layer, win, "progress_active")
UI_elements.roundrect(layer, win,
win.current["w"]/4+60+25,
350,
len(count)*12+6,
25,
5)
layer.fill()
UI_color.set(layer, win, "text_normal")
layer.set_font_size(20)
layer.move_to(win.current["w"]/4+60+28,370)
layer.show_text(count)
# Preview # Preview
@ -439,12 +484,37 @@ def layer(win):
"/dev"+win.cur+"/", "/dev"+win.cur+"/",
name+".blend") name+".blend")
# This is executed on the first frame when you click onto an asset.
if win.current["in-asset-remote-server"]: if win.current["in-asset-remote-server"]:
# First we gonna change the active folder to view the Blend files.
# This is important for the function for the remote server.
win.current["asset_cur_folder"] = "blender"
# Let's also check for updates on the file
# Remote Server Stuff # Remote Server Stuff
if win.analytics["from-remote-server"]: if win.analytics["from-remote-server"]:
def after(win, var):
UI_elements.reload_images(win) # Checking date [ FOLDER NAME ] [ FILES TO CHECK FOR ]
studio_dialogs.http_client_dialog(win, "http-client", after, http_client.get_asset_files, "/dev/"+win.cur+"/") check_folders = {"/dev"+win.cur : "*",
"/ast/"+acur : name+"*",
"/dev"+win.cur+"/renders" : "*",
"/dev"+win.cur+"/reference" : "*",
"/dev"+win.cur+"/tex" : "*",
}
check_updates = threading.Thread(target=http_client.get_folder_info,
args=(win, check_folders, win.cur, ))
check_updates.setDaemon(True)
check_updates.start()
win.current["in-asset-remote-server"] = False win.current["in-asset-remote-server"] = False

View file

@ -365,3 +365,20 @@ def http_client_dialog(win, name, call, function, args=""):
function_run = threading.Thread(target=function, args=(win,)) function_run = threading.Thread(target=function, args=(win,))
function_run.setDaemon(True) function_run.setDaemon(True)
function_run.start() function_run.start()
def http_client_update_prompt(win, name, call):
# This function is going to be the UI for http-client.
if name not in win.current["calls"]:
win.current["calls"][name] = {
"var" :None, # This is the variable that we are waiting for
"call":call, # This is what it's going to run when it's done
"url" :"http-server-prompt",
"back":win.url,# This is where it's going to come back when it's done
"draw":http_client.prompt_layer
}
# Let's clear the LMB just in case
win.previous["LMB"] = False