Last active
October 11, 2019 06:55
-
-
Save grassmunk/4b6887159e702761bbf6898a98e8ef62 to your computer and use it in GitHub Desktop.
Microsoft Theme Parser Beta for Chicago95
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# License GPL3 | |
# Parse Windows .theme files | |
# Notes: Does not work with theme names with spaces in the title | |
# To parse the config | |
import configparser | |
import sys | |
import os | |
# For icon conversion | |
import PIL.Image | |
import svgwrite | |
import os | |
import operator | |
import struct | |
from PIL import BmpImagePlugin, PngImagePlugin, Image | |
# Fix pixel2svg | |
import xml.etree.ElementTree as ET | |
import re | |
import subprocess | |
import fnmatch | |
# recolor | |
import shutil | |
p = os.path.join | |
## For ini file writting: | |
def get_filename(ini, name, var): | |
'''gets the icon''' | |
#ini is parsed config object | |
#name is the section | |
#var is the variable to get | |
if name in ini and (var in ini[name] or var.capitalize() in ini[name] or var.lower() in ini[name] or var.upper() in ini[name]): | |
if var in ini[name]: ico = ini[name][var] | |
if var.capitalize() in ini[name]: ico = ini[name][var.capitalize()] | |
if var.upper() in ini[name]: ico = ini[name][var.upper()] | |
if var.lower() in ini[name]: ico = ini[name][var.lower()] | |
elif "Software\\Classes\\"+name in ini and (var.capitalize() in ini["Software\\Classes\\"+name] or | |
var.lower() in ini["Software\\Classes\\"+name] or | |
var.upper() in ini["Software\\Classes\\"+name] or | |
var in ini["Software\\Classes\\"+name] ): | |
if var in ini["Software\\Classes\\"+name]: ico = ini["Software\\Classes\\"+name][var] | |
if var.capitalize() in ini["Software\\Classes\\"+name]: ico = ini["Software\\Classes\\"+name][var.capitalize()] | |
if var.upper() in ini["Software\\Classes\\"+name]: ico = ini["Software\\Classes\\"+name][var.upper()] | |
if var.lower() in ini["Software\\Classes\\"+name]: ico = ini["Software\\Classes\\"+name][var.lower()] | |
else: | |
return(False) | |
if ico == '': return(False) | |
if "%WinDir%" in ico: return(False) | |
if "%ThemeDir%" in ico: | |
ico = ico.replace("%ThemeDir%",'') | |
else: | |
if "\\" in ico: ico = ico.split("\\")[len(ico.split("\\"))-1] | |
if "," in ico: ico = ico.split(",")[0] | |
ico = ico.replace("\\","/") | |
return(ico) | |
def hexToRGB(h): | |
h = h.replace("#","") | |
return tuple(int(h[i:i+2], 16) for i in (0, 2, 4)) | |
def rgbaToRGB(tup): | |
return (tup[0],tup[1],tup[2]) | |
def convert_with_inkscape(svg_in, size, svg_out): | |
#print("\t\t[Inkscape Convert]", svg_in, size, svg_out) | |
try: | |
inkscape_path = subprocess.check_output(["which", "inkscape"]).strip() | |
except subprocess.CalledProcessError: | |
print("ERROR: You need inkscape installed to use this script.") | |
exit(1) | |
size = str(size) | |
args = [ | |
inkscape_path, | |
"--without-gui", | |
"-f", svg_in, | |
"--export-area-page", | |
"-w", size, | |
"-h", size, | |
"--export-png=" + svg_out | |
] | |
subprocess.check_call(args, stdout=subprocess.DEVNULL) | |
def fix_with_inkscape(color, tmpfile): | |
try: | |
inkscape_path = subprocess.check_output(["which", "inkscape"]).strip() | |
except subprocess.CalledProcessError: | |
print("ERROR: You need inkscape installed to use this script.") | |
exit(1) | |
#print("\t\t[Inkscape Convert]", svg_in, size, svg_out) | |
#cmd = "inkscape --select=" + rgbs[rgb] +" --verb EditSelectSameFillColor --verb SelectionCombine --verb SelectionUnion --verb FileSave --verb FileQuit "+ tmpfile | |
args = [ | |
inkscape_path, | |
"--select="+color, | |
"--verb", "EditSelectSameFillColor", | |
"--verb", "SelectionCombine", | |
"--verb", "SelectionUnion", | |
"--verb", "FileSave", | |
"--verb", "FileQuit", | |
tmpfile | |
] | |
subprocess.check_call(args, stderr=subprocess.DEVNULL ,stdout=subprocess.DEVNULL) | |
def findfiles(filenamed, where='.'): | |
# filename might contain / so we pasrse it here | |
which = filenamed | |
if len(filenamed.split("/")) >= 2: | |
(where,which) = os.path.split(filenamed) | |
rule = re.compile(fnmatch.translate(which), re.IGNORECASE) | |
return [name for name in os.listdir(where) if rule.match(name)] | |
def convert_icon(folder, filename, squaresize = 20, overlap = 0, tmp_file="./chicago95_tmp_file.svg" ): | |
## Convert Icons to PNG | |
# Lots of code lifter from pixel2svg | |
if folder[-1] not in "/": | |
folder = folder + "/" | |
if len(filename.split("/")) >= 2: | |
filename = os.path.split(filename)[0]+"/"+findfiles(filename)[0] | |
else: | |
filename = findfiles(filename)[0] | |
image = Image.open(filename) | |
if len(filename.split("/")) >= 2: filename = filename.split("/")[-1] | |
image = image.convert("RGBA") | |
(width, height) = image.size | |
#print("[pixel2svg] Image is {0}x{1}".format(width, height)) | |
rgb_values = list(image.getdata()) | |
#print("[pixel2svg] Converting image to RGBA") | |
#print("[pixel2svg] Image is {0}x{1}".format(width, height)) | |
rgb_values = list(image.getdata()) | |
#print("[pixel2svg] Read {0} pixels".format(len(rgb_values))) | |
svgdoc = svgwrite.Drawing(filename = os.path.splitext(folder+filename)[0] + ".svg", | |
size = ("{0}px".format(width * squaresize), | |
"{0}px".format(height * squaresize))) | |
print("\t[convert_icon] Converting '{0}'".format(folder+filename),"to '{0}'".format(svgdoc.filename)) | |
# If --overlap is given, use a slight overlap to prevent inaccurate SVG rendering | |
rectangle_size = ("{0}px".format(squaresize + overlap), | |
"{0}px".format(squaresize + overlap)) | |
rowcount = 0 | |
while rowcount < height: | |
#print("[pixel2svg] Processing pixel row {0} of {1}".format(rowcount + 1, height)) | |
colcount = 0 | |
while colcount < width: | |
rgb_tuple = rgb_values.pop(0) | |
# Omit transparent pixels | |
if rgb_tuple[3] > 0: | |
rectangle_posn = ("{0}px".format(colcount * squaresize), | |
"{0}px".format(rowcount * squaresize)) | |
rectangle_fill = svgwrite.rgb(rgb_tuple[0], rgb_tuple[1], rgb_tuple[2]) | |
alpha = rgb_tuple[3]; | |
if alpha == 255: | |
svgdoc.add(svgdoc.rect(insert = rectangle_posn, | |
size = rectangle_size, | |
fill = rectangle_fill)) | |
else: | |
svgdoc.add(svgdoc.rect(insert = rectangle_posn, | |
size = rectangle_size, | |
fill = rectangle_fill, | |
opacity = alpha/float(255))) | |
colcount = colcount + 1 | |
rowcount = rowcount + 1 | |
svgdoc.save() | |
# Now we need to clean up the pixel file created | |
#print("[fix] Creating tmp file", tmp_file) | |
cmd = "inkscape -l "+ tmp_file +" \"{0}\"".format(svgdoc.filename) | |
#print("[fix] Executing command:", cmd) | |
os.system(cmd) | |
#print("[fix] Parsing", tmp_file) | |
SVG_NS = "http://www.w3.org/2000/svg" | |
svg = ET.parse(tmp_file) | |
rects = svg.findall('.//{%s}rect' % SVG_NS) | |
rgbs = {} | |
#print('[fix] Getting colors and ids') | |
for rect in rects: | |
rect_id = rect.attrib['id'] | |
rgb = rect.attrib['fill'] | |
if rgb not in rgbs: | |
rgbs[rgb] = rect_id | |
#for rgb in rgbs: | |
# print('\t[id]', rgbs[rgb], rgb) | |
print("\t[convert_icon] Joining same colors\n\t[pixel2svg]!!! Inkscape will open and close here a {0} times".format(len(rgbs))) | |
count = 0 | |
for rgb in rgbs: | |
if len(rgbs) >= 150: | |
print("\t\t[pixel2svg] File has too many colors, skipping") | |
break | |
count = count + 1 | |
print('\t\t[',count,'/',len(rgbs),str(round((float(count)/float(len(rgbs))*100),0))+'%] Working on', rgbs[rgb], rgb) | |
fix_with_inkscape( rgbs[rgb] , tmp_file ) | |
#print('[fix] Moving tmp file', tmp_file, 'to original file', svgdoc.filename) | |
cmd = 'mv '+tmp_file+' "'+ svgdoc.filename +'"' | |
os.system(cmd) | |
return(svgdoc.filename) | |
def convert_cursor(folder,icon_name,output_file): | |
if len(icon_name.split("/")) >= 2: | |
icon_name = os.path.split(icon_name)[0]+"/"+findfiles(icon_name)[0] | |
else: | |
icon_name = findfiles(icon_name)[0] | |
try: | |
convert_path = subprocess.check_output(["which", "convert"]).strip() | |
except subprocess.CalledProcessError: | |
print("ERROR: You need imagemagick installed to use this script.") | |
exit(1) | |
if folder[-1] not in "/": | |
folder = folder + "/" | |
output_file = folder+output_file + ".png" | |
args = [ | |
convert_path, | |
icon_name, | |
output_file | |
] | |
subprocess.check_call(args, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL ) | |
def convert_ani(folder, ani_file, output_file): | |
if folder[-1] not in "/": | |
folder = folder + "/" | |
file_name = ani_file | |
if len(file_name.split("/")) >= 2: | |
file_name = os.path.split(file_name)[0]+"/"+findfiles(file_name)[0] | |
else: | |
file_name = findfiles(file_name)[0] | |
ico_counter = 1 | |
name = file_name[:-4] | |
f = open(file_name,'rb') | |
ani_file = f.read() | |
f.close() | |
bytes = bytearray(ani_file) | |
file_len = len(bytes) | |
for i in range(0,file_len): | |
if i + 4 <= file_len and (bytes[i] == 0x69 and bytes[i+1] == 0x63 and bytes[i+2] == 0x6f and bytes[i+3] == 0x6e ): | |
new_icon_name = folder+output_file + "_{:02}".format(ico_counter) + ".ico" | |
ico_counter += 1 | |
new_file = bytearray() | |
j = 8 | |
while(i+j+4 <= file_len): | |
if bytes[i+j+1] == 0x69 and bytes[i+1] == 0x63 and bytes[i+2] == 0x6f and bytes[i+3] == 0x6e: | |
f = open(new_icon_name,"wb") | |
f.write(new_file) | |
f.close() | |
try: | |
convert_cursor(folder, new_icon_name, new_icon_name.split("/")[-1][:-4]) | |
except subprocess.CalledProcessError as e: | |
#ignore these for now | |
pass | |
os.system("rm "+ new_icon_name) | |
if os.path.isfile(new_icon_name[:-4]+"-0.png"): | |
os.system("mv " + new_icon_name[:-4]+"-0.png " + new_icon_name[:-4]+".png") | |
break | |
if j == 10: | |
new_file.append(0x01) | |
else: | |
new_file.append(bytes[i+j]) | |
j += 1 | |
i += j | |
f = open(new_icon_name,"wb") | |
f.write(new_file) | |
f.close() | |
try: | |
convert_cursor(folder, new_icon_name, new_icon_name.split("/")[-1][:-4]) | |
except subprocess.CalledProcessError as e: | |
#ignore these for now | |
pass | |
os.system("rm "+ new_icon_name) | |
if os.path.isfile(new_icon_name[:-4]+"-0.png"): | |
os.system("mv " + new_icon_name[:-4]+"-0.png " + new_icon_name[:-4]+".png") | |
return(ico_counter) | |
print("Microsoft Theme file parser") | |
if len(sys.argv) < 2: | |
print("Usage:",sys.argv[0]," theme_file") | |
sys.exit(-1) | |
config = configparser.RawConfigParser(interpolation=None) | |
config.optionxform = str | |
theme = sys.argv[1] | |
print("[Parser] Parsing Theme File:", theme) | |
config.read(theme) | |
theme_name = theme.replace(".theme",'') | |
theme_name = theme_name.replace(".Theme",'') | |
## Get the icons | |
print("\t[+] Grabbing Icons") | |
icons = {} | |
# Computer | |
icons["computer_ico"] = get_filename(config,"CLSID\\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\DefaultIcon","DefaultValue") | |
# Documents | |
icons["documents_ico"] = get_filename(config,"CLSID\\{450D8FBA-AD25-11D0-98A8-0800361B1103}\\DefaultIcon","DefaultValue") | |
# Network | |
icons["network_ico"] = get_filename(config,"CLSID\\{208D2C60-3AEA-1069-A2D7-08002B30309D}\\DefaultIcon","DefaultValue") | |
# Recycle | |
icons["recycle_full"] = get_filename(config,"CLSID\\{645FF040-5081-101B-9F08-00AA002F954E}\\DefaultIcon","Full") | |
icons["recycle_empty"] = get_filename(config,"CLSID\\{645FF040-5081-101B-9F08-00AA002F954E}\\DefaultIcon","Empty") | |
## Colors | |
print("\t[+] Grabbing Colors") | |
if "Control Panel\Colors" in config: | |
config_colors = config["Control Panel\Colors"] | |
colors = {} | |
for color in config_colors: | |
r = int(config_colors[color].split()[0]) | |
g = int(config_colors[color].split()[1]) | |
b = int(config_colors[color].split()[2]) | |
colors[color] = '#{:02x}{:02x}{:02x}'.format(r,g,b) | |
## Get the cursors | |
print("\t[+] Grabbing Cursors") | |
if "Control Panel\Cursors" in config: | |
config_cursors = config["Control Panel\Cursors"] | |
cursors = {} | |
for cursor in config_cursors: | |
cursors[cursor] = get_filename(config,"Control Panel\Cursors",cursor) | |
## Get the wallpaper | |
print("\t[+] Grabbing Wallpaper") | |
wallpaper = get_filename(config,"Control Panel\Desktop","Wallpaper") | |
## Get Sound files | |
print("\t[+] Grabbing Sounds") | |
sound_names = [ | |
"AppEvents\\Schemes\\Apps\\.Default\\AppGPFault\\.Current", | |
"AppEvents\\Schemes\\Apps\\.Default\\Close\\.Current", | |
"AppEvents\\Schemes\\Apps\\.Default\\.Default\\.Current", | |
"AppEvents\\Schemes\\Apps\\.Default\\MailBeep\\.Current", | |
"AppEvents\\Schemes\\Apps\\.Default\\Maximize\\.Current", | |
"AppEvents\\Schemes\\Apps\\.Default\\MenuCommand\\.Current", | |
"AppEvents\\Schemes\\Apps\\.Default\\MenuPopup\\.Current", | |
"AppEvents\\Schemes\\Apps\\.Default\\Minimize\\.Current", | |
"AppEvents\\Schemes\\Apps\\.Default\\Open\\.Current", | |
"AppEvents\\Schemes\\Apps\\.Default\\RestoreDown\\.Current", | |
"AppEvents\\Schemes\\Apps\\.Default\\RestoreUp\\.Current", | |
"AppEvents\\Schemes\\Apps\\.Default\\RingIn\\.Current", | |
"AppEvents\\Schemes\\Apps\\.Default\\Ringout\\.Current", | |
"AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current", | |
"AppEvents\\Schemes\\Apps\\.Default\\SystemDefault\\.Current", | |
"AppEvents\\Schemes\\Apps\\.Default\\SystemExclamation\\.Current", | |
"AppEvents\\Schemes\\Apps\\.Default\\SystemExit\\.Current", | |
"AppEvents\\Schemes\\Apps\\.Default\\SystemHand\\.Current", | |
"AppEvents\\Schemes\\Apps\\.Default\\SystemQuestion\\.Current", | |
"AppEvents\\Schemes\\Apps\\.Default\\SystemStart\\.Current", | |
"AppEvents\\Schemes\Apps\Explorer\EmptyRecycleBin\\.Current" | |
] | |
sounds = {} | |
for i in sound_names: | |
sound_name = i.split("\\")[-2] | |
if get_filename(config,i,"DefaultValue"): | |
wav_file = get_filename(config,i,"DefaultValue") | |
sounds[sound_name] = wav_file | |
print("\t[+] Icons:") | |
for i in icons: print("\t\t["+i+"]\t", icons[i]) | |
print("\t[+] Cursors:") | |
for i in cursors: print("\t\t["+i+"]\t", cursors[i]) | |
print("\t[+] Colors:") | |
for i in colors: print("\t\t["+i+"]\t", colors[i]) | |
print("\t[+] Wallpaper:\n\t\t", wallpaper) | |
print("\t[+] Sounds:") | |
for i in sounds: print("\t\t["+i+"]\t", sounds[i]) | |
## Whew we made it, now lets start processing these | |
# First we make a folder to put our new theme in | |
folder_name = theme_name + "_Chicago95" | |
print("[Theme] Creating new theme folders\n\tMaking folder:", folder_name) | |
os.mkdir(folder_name) | |
out_folder = folder_name+"/"+theme_name+"_" | |
#os.mkdir(out_folder+"Icons") | |
print("[DefaultIcon] Creating New Icons") | |
ricon_sizes = [16,22,24,32,48] | |
ricon_files = {"documents_ico": "folder-documents.png", | |
"network_ico" : "network-server.png", | |
"computer_ico" : "user-home.png", | |
"recycle_empty" : "user-trash.png", | |
"recycle_full": "user-trash-full.png"} | |
sicon_files = {"documents_ico": "folder-documents.svg", | |
"network_ico" : "network-server.svg", | |
"computer_ico" : "folder_home.svg", | |
"recycle_full" : "edittrash.svg", | |
"recycle_empty": "emptytrash.svg"} | |
inPath = os.path.expanduser("~/.icons/Chicago95") | |
outPath = out_folder+"Icons" | |
shutil.copytree(inPath,outPath,symlinks=True,ignore_dangling_symlinks=True) | |
for i in icons: | |
if not icons[i]: continue | |
converted_icon = convert_icon(outPath,icons[i]) | |
for size in ricon_sizes: | |
if size <= 32 and i == "documents_ico": continue | |
print("\t\tplaces/"+str(size)+"/"+ricon_files[i]) | |
sized_target = outPath+"/places/"+str(size)+"/"+ricon_files[i] | |
convert_with_inkscape( converted_icon, size, sized_target) | |
scaled_target = outPath+"/places/scalable/"+sicon_files[i] | |
#print(scaled_target) | |
shutil.copy(converted_icon, scaled_target) | |
# Now replace Icons | |
icon_theme_config = configparser.RawConfigParser(interpolation=None) | |
icon_theme_config.optionxform = str | |
icon_theme_config.read(outPath+"/index.theme") | |
icon_theme_config.set("Icon Theme","Name",theme_name) | |
with open(outPath+"/index.theme", 'w') as configfile: | |
icon_theme_config.write(configfile, space_around_delimiters=False) | |
print("[DefaultIcon] Done!") | |
# Parse Colors | |
# config | |
inPath = os.path.expanduser("~/.themes/Chicago95") | |
outPath = folder_name +"/"+theme_name+"_Theme" | |
remapColors = { | |
"#000080": colors['ActiveTitle'], #Active Window and Text Highlight - RED | |
"#dfdfdf": colors['Menu'], #highlight? - Does Nothing - Yellow | |
"#c0c0c0": colors['Menu'], #main window outline/buttons/bars color and inactive text - Green | |
"#ffffff": colors['Window'], #main window color inner and main text color - Blue | |
"#808080": colors['InactiveTitle'], #shadow window color (Inactive?) - turqoise | |
"#000000": colors['WindowText'], #Inactive window text color - Purple | |
} | |
print("[ControlPanel\Colors] Changing theme colors:") | |
for i in remapColors: | |
print("\t\tOriginal Color:",i,"New Color:",remapColors[i]) | |
#Make sure none of them overlap | |
for x in remapColors: | |
if remapColors[x] in remapColors: | |
if remapColors[x][-1].lower() == 'f': | |
remapColors[x] = remapColors[x][:6] + str(254) | |
else: | |
remapColors[x] = remapColors[x][:6] + str(int(remapColors[x][-1]) + 1) | |
if (os.path.isdir(outPath)): | |
shutil.rmtree(outPath) | |
os.makedirs(outPath) | |
for root,dirs,files in os.walk(inPath): | |
for dir in dirs: | |
fpath = p(root,dir) | |
nfpath = fpath.replace(inPath,outPath) | |
if not (os.path.isdir(nfpath)): | |
os.makedirs(nfpath) | |
for file in files: | |
fpath = p(root,file) | |
nfpath = fpath.replace(inPath,outPath) | |
lpath = fpath.replace(inPath + "/","") | |
ext = os.path.splitext(fpath)[1].lower() | |
if (ext == ".css") or (ext == ".scss") or (ext == ".xpm") or (ext == ".svg") or (ext == ".rc")\ | |
or (lpath == "gtk-2.0/gtkrc") or (lpath == "xfwm4/hidpi/themerc") or (lpath == "xfwm4/themerc"): | |
#print("[colors] editing text: " +fpath) | |
fileh = open(fpath,"r") | |
nfileh = open(nfpath,"w") | |
for line in fileh: | |
for color in remapColors: | |
colorV = remapColors[color] | |
line = line.replace(color.upper(),colorV.upper()) | |
line = line.replace(color.lower(),colorV.lower()) | |
nfileh.write(line) | |
fileh.close() | |
nfileh.close() | |
if (ext == ".png"): | |
#print("[colors] editing image: " +fpath) | |
img = Image.open(fpath) | |
img = img.convert("RGBA") | |
pixels = img.load() | |
width, height = img.size | |
for y in range(height): | |
for x in range(width): | |
pixel = pixels[x,y] | |
for color in remapColors: | |
colorV = remapColors[color] | |
rgbColor = hexToRGB(color) | |
rgbColorV = hexToRGB(colorV) | |
if (rgbaToRGB(pixel) == rgbColor): | |
pixels[x,y] = (rgbColorV[0],rgbColorV[1],rgbColorV[2],pixel[3]) | |
break | |
img.save(nfpath) | |
img.close() | |
if not (os.path.isfile(nfpath)): | |
shutil.copy(fpath,nfpath) | |
# Cursors | |
print("[ControlPanel\Cursors] Creating Cursors") | |
cursor_folder = out_folder + "Cursors" | |
inPath = os.path.expanduser("~/.icons/Chicago95_Cursor_Black") | |
shutil.copytree(inPath,cursor_folder,symlinks=True,ignore_dangling_symlinks=True) | |
cursor_folder = cursor_folder + "/src" | |
pointers = { | |
"Arrow" : "Arrow", | |
"Help" : "Help", | |
"AppStarting" : "AppStarting", | |
"Wait" : "Wait", | |
"NWPen" : "Handwriting", | |
"No" : "NO", | |
"SizeNS" : "BaseN", | |
"SizeWE" : "SizeWE", | |
"Crosshair" : "Crosshair", | |
"IBeam" : "IBeam", | |
"SizeNWSE" : "AngleNE", | |
"SizeNESW" : "AngleNW", | |
"SizeAll" : "SizeAll", | |
"UpArrow" : "UpArrow" | |
} | |
for i in pointers: | |
if i not in cursors or not cursors[i]: | |
continue | |
print("\t\tConverting",i,"to",pointers[i]) | |
theme_cursor = cursors[i] | |
x11_cursor = pointers[i] | |
if os.path.splitext(theme_cursor)[1] not in ".ani": | |
convert_cursor(cursor_folder, theme_cursor, x11_cursor) | |
else: | |
total = convert_ani(cursor_folder, theme_cursor, x11_cursor) | |
os.system("rm \""+cursor_folder+"/"+x11_cursor+".png\"") | |
with open(cursor_folder+"/"+x11_cursor+".conf") as f: | |
(g1, g2, g3, cursor_n) = f.readline().strip().split(" ") | |
write_conf = open(cursor_folder+"/"+x11_cursor+".conf", 'w') | |
for i in range(1,total): | |
cursor_string = g1+" "+g2+" "+g3+" "+x11_cursor+"_{:02}".format(i)+".png\n" | |
write_conf.write(cursor_string) | |
write_conf.close() | |
# All the cursors are done now, lets make a cursor folder | |
#subprocess.check_call("./"+cursor_folder+"/Build.sh",cwd="./"+cursor_folder,shell=True) | |
p = subprocess.Popen([os.getcwd()+"/"+cursor_folder+"/Build.sh"],cwd="./"+cursor_folder) | |
p.wait() | |
cur_theme_config = configparser.RawConfigParser(interpolation=None) | |
cur_theme_config.optionxform = str | |
cur_theme_config.read(out_folder + "Cursors"+"/index.theme") | |
cur_theme_config.set("Icon Theme","Name",theme_name) | |
with open(out_folder + "Cursors"+"/index.theme", 'w') as configfile: | |
cur_theme_config.write(configfile, space_around_delimiters=False) | |
os.system("rm -rf '"+out_folder + "Cursors"+"/cursors'") | |
os.system("mv "+cursor_folder+"/cursors "+out_folder + "Cursors"+"/cursors") | |
print("[ControlPanel\Cursors] Done") | |
print("[ControlPanel\Audio]") | |
os.mkdir(out_folder+"Audio") | |
for i in sounds: | |
if len(sounds[i].split("/")) >= 2: | |
sound = os.path.split(sounds[i])[0]+"/"+findfiles(sounds[i])[0] | |
else: | |
sound = findfiles(sounds[i])[0] | |
if os.path.exists(sound): | |
print("\t\tCopying:", i,sound) | |
if len(sound.split("/")) >= 2: | |
sound_out = sound.split("/")[-1] | |
else: | |
sound_out = sound | |
shutil.copy(sound,out_folder+"Audio/"+i+"_"+sound_out) | |
if wallpaper: | |
print("[Control Panel\Desktop]") | |
if len(wallpaper.split("/")) >= 2: | |
wallpaper = os.path.split(wallpaper)[0]+"/"+findfiles(wallpaper)[0] | |
else: | |
wallpaper = findfiles(wallpaper)[0] | |
shutil.copy(wallpaper,folder_name) | |
print("[Fonts]") | |
found = [] | |
for root, dirs, files in os.walk(os.getcwd()): | |
for local_file in files: | |
if (local_file.endswith(".ttf") or local_file.endswith(".TTF")) and local_file not in found: | |
print("\tCopying:",local_file) | |
shutil.copy(os.path.join(root,local_file),folder_name) | |
found.append(local_file) | |
print("[DONE]\n") | |
print("." * 80) | |
print("." * 80) | |
print("." * 80) | |
print("\n\tNewly created theme is available at {0}.\n\t To install copy:\n\t\t".format(folder_name) + | |
"{0} to ~/.icons\n\t\t".format(out_folder+"Icons") + | |
"{0} to ~/.icons\n\t\t".format(out_folder+"Cursors") + | |
"{0} to ~/.themes\n\t\t".format(out_folder+"Theme") + | |
"Audio Files are located in {0}\n\t\t".format(out_folder+"Audio") + | |
"Fonts and Wallpapers are located in {0}\n".format(folder_name) + | |
"\t\t\tTo install font, put the font file in ~/.fonts and run fc-cache -f -v\n" | |
) | |
print("One liner: cp -r "+out_folder+"Cursors ~/.icons;cp -r "+out_folder+"Icons ~/.icons;cp -r "+out_folder+"Theme ~/.theme") | |
print("." * 80) | |
print("." * 80) | |
print("." * 80) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment