Skip to content

Commit f3c7a30

Browse files
authored
Add option for OC snapshot
1 parent 1df123e commit f3c7a30

File tree

1 file changed

+197
-16
lines changed

1 file changed

+197
-16
lines changed

Scripts/plistwindow.py

Lines changed: 197 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,8 @@ def __init__(self, controller, root, **kw):
354354
file_menu.add_command(label="Save As ({}Shift+S)".format(sign), command=self.controller.save_plist_as)
355355
file_menu.add_command(label="Duplicate ({}D)".format(sign), command=self.controller.duplicate_plist)
356356
file_menu.add_separator()
357+
file_menu.add_command(label="OC Snapshot ({}R)".format(sign), command=self.oc_snapshot)
358+
file_menu.add_separator()
357359
file_menu.add_command(label="Convert Window ({}T)".format(sign), command=self.controller.show_convert)
358360
file_menu.add_command(label="Strip Comments ({}M)".format(sign), command=self.strip_comments)
359361
file_menu.add_separator()
@@ -384,6 +386,176 @@ def __init__(self, controller, root, **kw):
384386
self._tree.pack(side="bottom", fill="both", expand=True)
385387
self.entry_popup = None
386388

389+
def walk_kexts(self,path,parent=""):
390+
kexts = []
391+
for x in os.listdir(path):
392+
if x.startswith("."):
393+
continue
394+
if not x.lower().endswith(".kext"):
395+
continue
396+
kdir = os.path.join(path,x)
397+
if not os.path.isdir(kdir):
398+
continue
399+
kdict = {
400+
"Comment":"",
401+
"Enabled":True,
402+
"MatchKernel":"",
403+
"BundlePath":parent+"/"+x if len(parent) else x
404+
}
405+
# Should be valid-ish - let's check for a binary
406+
binpath = os.path.join(kdir,"Contents","MacOS",os.path.splitext(x)[0])
407+
if os.path.exists(binpath):
408+
kdict["ExecutablePath"] = "Contents/MacOS/"+os.path.splitext(x)[0]
409+
# Get the Info.plist
410+
if os.path.exists(os.path.join(kdir,"Contents","Info.plist")):
411+
kdict["PlistPath"] = "Contents/Info.plist"
412+
elif os.path.exists(os.path.join(kdir,"Info.plist")):
413+
kdict["PlistPath"] = "Info.plist"
414+
if not kdict.get("PlistPath") and not kdict.get("ExecutablePath"):
415+
continue
416+
# Should have something here
417+
kexts.append(kdict)
418+
# Check if we have a PlugIns folder
419+
pdir = kdir+"/Contents/PlugIns"
420+
if os.path.exists(pdir) and os.path.isdir(pdir):
421+
kexts.extend(self.walk_kexts(pdir,parent+"/Contents/PlugIns/"+x))
422+
return kexts
423+
424+
def oc_snapshot(self, event = None):
425+
oc_folder = fd.askdirectory(title="Select OC Folder:")
426+
if not len(oc_folder):
427+
return
428+
429+
# Verify folder structure - should be as follows:
430+
# OC
431+
# +- ACPI
432+
# | +- Custom
433+
# | +- SSDT.aml
434+
# +- Drivers
435+
# | +- EfiDriver.efi
436+
# +- Kexts
437+
# | +- Something.kext
438+
# +- config.plist
439+
440+
oc_acpi = os.path.join(oc_folder,"ACPI","Custom")
441+
oc_drivers = os.path.join(oc_folder,"Drivers")
442+
oc_kexts = os.path.join(oc_folder,"Kexts")
443+
444+
for x in [oc_acpi,oc_drivers,oc_kexts]:
445+
if not os.path.exists(x):
446+
self.bell()
447+
mb.showerror("Incorrect OC Folder Struction", "{} does not exist.".format(x), parent=self)
448+
return
449+
if not os.path.isdir(x):
450+
self.bell()
451+
mb.showerror("Incorrect OC Folder Struction", "{} exists, but is not a directory.".format(x), parent=self)
452+
return
453+
454+
# Folders are valid - lets work through each section
455+
456+
# ACPI is first, we'll iterate the .aml files we have and add what is missing
457+
# while also removing what exists in the plist and not in the folder.
458+
# If something exists in the table already, we won't touch it. This leaves the
459+
# enabled and comment properties untouched.
460+
#
461+
# Let's make sure we have the ACPI -> Add sections in our config
462+
463+
tree_dict = self.nodes_to_values()
464+
# We're going to replace the whole list
465+
if not "ACPI" in tree_dict or not isinstance(tree_dict["ACPI"],dict):
466+
tree_dict["ACPI"] = {"Add":[]}
467+
if not "Add" in tree_dict["ACPI"] or not isinstance(tree_dict["ACPI"]["Add"],list):
468+
tree_dict["ACPI"]["Add"] = []
469+
# Now we walk the existing add values
470+
new_acpi = [x for x in os.listdir(oc_acpi) if x.lower().endswith(".aml") and not x.startswith(".")]
471+
add = tree_dict["ACPI"]["Add"]
472+
for aml in new_acpi:
473+
if aml.lower() in [x.get("Path","").lower() for x in add]:
474+
# Found it - skip
475+
continue
476+
# Doesn't exist, add it
477+
add.append({
478+
"Enabled":True,
479+
"Comment":aml,
480+
"Path":aml
481+
})
482+
new_add = []
483+
for aml in add:
484+
if not aml.get("Path","").lower() in [x.lower() for x in new_acpi]:
485+
# Not there, skip
486+
continue
487+
new_add.append(aml)
488+
tree_dict["ACPI"]["Add"] = new_add
489+
490+
# Next we need to walk the .efi drivers - in basically the same exact manner
491+
if not "UEFI" in tree_dict or not isinstance(tree_dict["UEFI"],dict):
492+
tree_dict["UEFI"] = {"Drivers":[]}
493+
if not "Drivers" in tree_dict["UEFI"] or not isinstance(tree_dict["UEFI"]["Drivers"],list):
494+
tree_dict["UEFI"]["Drivers"] = []
495+
# Now we walk the existing values
496+
new_efi = [x for x in os.listdir(oc_drivers) if x.lower().endswith(".efi") and not x.startswith(".")]
497+
add = tree_dict["UEFI"]["Drivers"]
498+
for efi in new_efi:
499+
if efi.lower() in [x.lower() for x in add]:
500+
# Found it - skip
501+
continue
502+
# Doesn't exist, add it
503+
add.append(efi)
504+
new_add = []
505+
for efi in add:
506+
if not efi.lower() in [x.lower() for x in new_efi]:
507+
# Not there, skip
508+
continue
509+
new_add.append(efi)
510+
tree_dict["UEFI"]["Drivers"] = new_add
511+
512+
# Now we need to walk the kexts
513+
if not "Kernel" in tree_dict or not isinstance(tree_dict["Kernel"],dict):
514+
tree_dict["Kernel"] = {"Add":[]}
515+
if not "Add" in tree_dict["Kernel"] or not isinstance(tree_dict["Kernel"]["Add"],list):
516+
tree_dict["Kernel"]["Add"] = []
517+
kext_list = self.walk_kexts(oc_kexts)
518+
kexts = tree_dict["Kernel"]["Add"]
519+
for kext in kext_list:
520+
if kext["BundlePath"].lower() in [x.get("BundlePath","").lower() for x in kexts]:
521+
# Already have it, skip
522+
continue
523+
# We need it, it seems
524+
kexts.append(kext)
525+
new_kexts = []
526+
for kext in kexts:
527+
if not kext.get("BundlePath","").lower() in [x["BundlePath"].lower() for x in kext_list]:
528+
# Not there, skip it
529+
continue
530+
new_kexts.append(kext)
531+
tree_dict["Kernel"]["Add"] = new_kexts
532+
533+
# Now we remove the original tree - then replace it
534+
undo_list = []
535+
for x in self._tree.get_children():
536+
undo_list.append({
537+
"type":"remove",
538+
"cell":x,
539+
"from":self._tree.parent(x),
540+
"index":self._tree.index(x)
541+
})
542+
self._tree.detach(x)
543+
# Finally, we add the nodes back
544+
self.add_node(tree_dict)
545+
# Add all the root items to our undo list
546+
for child in self._tree.get_children():
547+
undo_list.append({
548+
"type":"add",
549+
"cell":child
550+
})
551+
self.add_undo(undo_list)
552+
# Ensure we're edited
553+
if not self.edited:
554+
self.edited = True
555+
self.title(self.title()+" - Edited")
556+
self.update_all_children()
557+
self.alternate_colors()
558+
387559
def get_check_type(self, cell=None, string=None):
388560
if not cell == None:
389561
t = self.get_padded_values(cell,1)[0]
@@ -1038,9 +1210,11 @@ def update_array_counts(self, target):
10381210
# Only updating the "text" field
10391211
self._tree.item(child,text=x)
10401212

1041-
def change_type(self, value):
1213+
def change_type(self, value, cell = None):
10421214
# Need to walk the values and pad
1043-
values = self.get_padded_values(self._tree.focus(), 3)
1215+
if cell == None:
1216+
cell = self._tree.focus()
1217+
values = self.get_padded_values(cell, 3)
10441218
# Verify we actually changed type
10451219
if values[0] == value:
10461220
# No change, bail
@@ -1050,15 +1224,14 @@ def change_type(self, value):
10501224
values[0] = value
10511225
# Remove children if needed
10521226
changes = []
1053-
for i in self._tree.get_children(self._tree.focus()):
1227+
for i in self._tree.get_children(cell):
10541228
changes.append({
10551229
"type":"remove",
10561230
"cell":i,
10571231
"from":self._tree.parent(i),
10581232
"index":self._tree.index(i)
10591233
})
10601234
self._tree.detach(i)
1061-
cell = self._tree.focus()
10621235
changes.append({
10631236
"type":"edit",
10641237
"cell":cell,
@@ -1074,10 +1247,10 @@ def change_type(self, value):
10741247
elif value.lower() == "boolean":
10751248
values[1] = "True"
10761249
elif value.lower() == "array":
1077-
self._tree.item(self._tree.focus(),open=True)
1250+
self._tree.item(cell,open=True)
10781251
values[1] = "0 children"
10791252
elif value.lower() == "dictionary":
1080-
self._tree.item(self._tree.focus(),open=True)
1253+
self._tree.item(cell,open=True)
10811254
values[1] = "0 key/value pairs"
10821255
elif value.lower() == "date":
10831256
values[1] = datetime.datetime.now().strftime("%b %d, %Y %I:%M:%S %p")
@@ -1086,7 +1259,7 @@ def change_type(self, value):
10861259
else:
10871260
values[1] = ""
10881261
# Set the values
1089-
self._tree.item(self._tree.focus(), values=values)
1262+
self._tree.item(cell, values=values)
10901263
if not self.edited:
10911264
self.edited = True
10921265
self.title(self.title()+" - Edited")
@@ -1173,6 +1346,7 @@ def merge_menu_preset(self, val = None):
11731346
# and ensuring the type
11741347
created = None
11751348
current_cell = ""
1349+
undo_list = []
11761350
for p,t in izip(paths,types):
11771351
found = False
11781352
needed_type = {"d":"Dictionary","a":"Array"}.get(t.lower(),"Dictionary")
@@ -1191,29 +1365,36 @@ def merge_menu_preset(self, val = None):
11911365
if not found:
11921366
# Need to add it
11931367
current_cell = self._tree.insert(current_cell,"end",text=p,values=(self.menu_code+" "+needed_type,"",self.drag_code,),open=True)
1194-
if created == None:
1195-
# Only get the top level item created
1196-
created = current_cell
1197-
1368+
undo_list.append({
1369+
"type":"add",
1370+
"cell":current_cell
1371+
})
11981372
# At this point - we should be able to add the final piece
11991373
# let's first make sure it doesn't already exist - if it does, we
12001374
# will overwrite it
1201-
'''current_type = self.get_check_type(current_cell).lower()
1375+
current_type = self.get_check_type(current_cell).lower()
12021376
if current_type == "dictionary":
12031377
# Scan through and make sure we have all the keys needed
12041378
for x in self._tree.get_children(current_cell):
12051379
name = self._tree.item(x,"text")
12061380
if name in value:
12071381
# Need to change this one
1208-
if len(self._tree.get_children(x)):
1209-
# Add some remove commands'''
1382+
for child in self._tree.get_children(x):
1383+
# Add some remove commands
1384+
undo_list.append({
1385+
"type":"remove",
1386+
"cell":child,
1387+
"from":x,
1388+
"index":self._tree.index(child)
1389+
})
12101390
last_cell = self.add_node(value,current_cell,"")
12111391
if created == None:
12121392
created = last_cell
1213-
self.add_undo({
1393+
undo_list.append({
12141394
"type":"add",
12151395
"cell":created
12161396
})
1397+
self.add_undo(undo_list)
12171398
if not self.edited:
12181399
self.edited = True
12191400
self.title(self.title()+" - Edited")
@@ -1432,4 +1613,4 @@ def alternate_colors(self, event = None):
14321613
tags.append("odd" if x % 2 else "even")
14331614
self._tree.item(item, tags=tags)
14341615
self._tree.tag_configure('odd', background='#E8E8E8')
1435-
self._tree.tag_configure('even', background='#DFDFDF')
1616+
self._tree.tag_configure('even', background='#DFDFDF')

0 commit comments

Comments
 (0)