5360c496872dd5f9948b3d8d28ca07c99e4bedcb
[jalview.git] / utils / macos_dmg / jalview_customise_dsstore.py
1 #!/usr/bin/env python3
2 # Adapted from custom_dsstore.py by the Jalview team 2024
3 # Copyright (c) 2013-2017 The Bitcoin Core developers
4 # Distributed under the MIT software license, see the accompanying
5 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 import ds_store
7 import pprint
8 import mac_alias
9 import argparse
10 import json
11
12 parser = argparse.ArgumentParser(
13   prog = "jalview_custom_dsstore.py",
14   description = "Take an existing DS_Store file and change the volume name and add path to background image"
15   )
16 parser.add_argument("-i", "--input", help="The existing styled DS_Store file", dest="input")
17 parser.add_argument("-o", "--output", help="The output DS_Store file", dest="output")
18 parser.add_argument("-v", "--volumename", help="The name of the output DS_Store volume", dest="volumename")
19 parser.add_argument("-b", "--backgroundfile", help="The background image filename to use", dest="backgroundfile", default="background.png")
20 parser.add_argument("-d", "--backgrounddir", help="The background image hidden dirname to use", dest="backgrounddir", default=".background")
21 parser.add_argument("-c", "--config", help="YAML configuration for window and icon sizes and positions", dest="config")
22 parser.add_argument("-m", "--dmg", help="The filename of the DMG file", dest="dmg", default="Jalview_macos.dmg")
23 parser.add_argument("--dump", help="Display contents of the input DS_Store to stdout", action="store_true", dest="dump")
24 parser.add_argument("-q", "--quiet", help="Don't print messages to stdout", action="store_true", dest="quiet")
25 parser.add_argument("-f", "--filenames", help="List of comma-separated filenames to show information for --dump", dest="filenames", default="")
26
27 args = parser.parse_args()
28
29 def myprint(string):
30   if (not args.quiet):
31     print(string)
32
33 def mypprint(string):
34   if (not args.quiet):
35     pprint.pprint(string)
36
37 if (args.dump and not args.input):
38   exit("When --dump used, an --input must be given")
39
40 if (args.dump):
41   with ds_store.DSStore.open(args.input, 'r+') as d:
42     print(f"d=")
43     print(pprint.pformat(d['.']['bwsp'], width=1))
44
45     for key in ["bwsp", "icvp","Iloc"]:
46       try:
47         print(f"d['.']['{key}']=")
48         pprint.pprint(str(d['.'][key]), width=1)
49       except:
50         print(f"No info for d['.']['{key}']")
51
52     a = mac_alias.Alias.from_bytes( d['.']['icvp']['backgroundImageAlias'] )
53     print("backgroundImageAlias:")
54     print("alias.volume="+pprint.pformat(a.volume))
55     print("alias.target="+pprint.pformat(a.target))
56
57     for data in d:
58       try:
59         data = str(data)
60         pprint.pprint(f"d['{data}']="+d[data], width=1)
61       except:
62         print(f"No info for d['{data}']")
63 #    for filename in args.filenames.split(","):
64 #      if (filename):
65 #        for f in d.find(filename):
66 #          myprint(f"d['{f}']=", d[f])
67 #        else:
68 #          myprint(f"# No filename '{filename}' found in DS_Store '{args.input}'")
69     exit(0)
70
71 if (args.output and not (args.input or args.config)):
72   exit("Need --input FILENAME or --config FILENAME to produce an --output")
73
74 if (not args.output):
75   exit("Provide --output FILENAME to output DS_Store")
76
77 if (not args.volumename):
78   exit("Provide a volume name with --volumename NAME")
79
80 if (not args.backgroundfile):
81   exit("Provide a background image filename (just the file, no path) with --backgroundfile FILENAME")
82
83 package_name_ns = args.volumename
84 configfilename = args.config
85 config = None
86 if (configfilename):
87   configfile = open(configfilename, 'r')
88   config = json.load(configfile)
89
90 inputds = ds_store.DSStore.open(args.input)
91 outputds = ds_store.DSStore.open(args.output, 'w+')
92
93
94 bwsp = {}
95
96 for key in "ShowStatusBar SidebarWidthTenElevenOrLater ShowToolbar ShowTabView ContainerShowSidebar WindowBounds ShowSidebar ShowPathbar".split():
97   bwsp[key] = inputds['.']['bwsp'][key]
98   myprint(f"Setting bwsp['{key}'] to '"+str(inputds['.']['bwsp'][key])+"'")
99
100 outputds['.']['bwsp'] = bwsp
101
102 icvp = {}
103
104 #alias = mac_alias.Alias.from_bytes(inputds['.']['icvp']['backgroundImageAlias'])
105 #alias.volume.name = args.volumename
106 #alias.volume.posix_path = '/Volumes/' + args.volumename
107 #alias.volume.disk_image_alias.target.filename = args.volumename + '.dmg'
108 #alias.volume.disk_image_alias.target.carbon_path = 'Macintosh HD:Users:\x00Jalview:\x00' + args.volumename + ':\x00' + args.volumename + '.dmg'
109 #alias.volume.disk_image_alias.target.posix_path = '/Users/Jalview/' + args.volumename + '.dmg'
110 #alias.target.carbon_path = args.volumename + ':' + args.backgrounddir + ':\x00' + args.backgroundfile
111 #alias.target.posix_path = '/Volumes/' + args.volumename + '/' + args.backgrounddir
112 #alias.target.filename = args.backgroundfile
113
114
115 alias = mac_alias.Alias.from_bytes(inputds['.']['icvp']['backgroundImageAlias'])
116
117 alias.volume.name = args.volumename
118 alias.volume.posix_path = "/Volumes/" + args.volumename
119
120 alias.volume.disk_image_alias.volume.name = "Macintosh HD"
121 alias.volume.disk_image_alias.volume.posix_path = "/"
122
123 alias.volume.disk_image_alias.target.filename = args.dmg
124 alias.volume.disk_image_alias.target.folder_name = "Downloads"
125 alias.volume.disk_image_alias.target.carbon_path = f'Macintosh HD:Users:Jalview:Downloads:{args.dmg}'
126 alias.volume.disk_image_alias.target.posix_path = f'/Users/jalview/Downloads/{args.dmg}'
127
128 alias.target.filename = args.backgroundfile
129 alias.target.folder_name = args.backgrounddir
130 alias.target.carbon_path = f'{args.volumename}:{args.backgrounddir}:{args.backgroundfile}'
131 alias.target.posix_path = f'/{args.backgrounddir}/{args.backgroundfile}'
132
133 icvp['backgroundImageAlias'] = alias.to_bytes()
134
135 for key in "backgroundColorRed backgroundColorBlue backgroundColorGreen gridSpacing gridOffsetX gridOffsetY showItemInfo viewOptionsVersion arrangeBy textSize labelOnBottom backgroundType showIconPreview iconSize".split():
136   icvp[key] = inputds['.']['icvp'][key]
137   myprint(f"Setting icvp['{key}'] to '"+str(inputds['.']['icvp'][key])+"'")
138
139 outputds['.']['icvp'] = icvp
140
141 # copy filenames properties? not working, using JSON config file
142 #for filename in args.filenames.split(","):
143 #  outputds[filename]['Iloc'] = inputds[filename]['Iloc']
144
145 outputds['.']['vSrn'] = ('long', 1)
146
147 if config:
148   for fileinfo in config['files']:
149     outputds[fileinfo['name']]['Iloc'] = (fileinfo['xpos'], fileinfo['ypos'])
150
151 outputds.flush()
152 outputds.close()
153 inputds.close()