1# -*- coding: utf-8 -*- 2from __future__ import unicode_literals 3 4import os 5import re 6import sys 7reload(sys) # Reload is a hack 8sys.setdefaultencoding('UTF8') 9 10sys.path.append(os.path.normpath(os.path.join(os.path.dirname(__file__), ".."))) 11 12try: 13 {}.iteritems 14 iteritems = lambda x: x.iteritems() 15 iterkeys = lambda x: x.iterkeys() 16except AttributeError: 17 iteritems = lambda x: x.items() 18 iterkeys = lambda x: x.keys() 19try: 20 unicode 21except NameError: 22 unicode = str 23 24import biplist 25from mac_alias import * 26from ds_store import * 27 28from colors import parseColor 29 30try: 31 from badge import badge 32except ImportError: 33 badge = None 34 35class DMGError(Exception): 36 pass 37 38 39def build_dmg(): 40 options = { 41 'icon': None, 42 'badge_icon': None, 43 'sidebar_width': 180, 44 'arrange_by': None, 45 'grid_offset': (0, 0), 46 'grid_spacing': 100.0, 47 'scroll_position': (0.0, 0.0), 48 'show_icon_preview': False, 49 'text_size': os.environ['iconTextSize'], 50 'icon_size': os.environ['iconSize'], 51 'include_icon_view_settings': 'auto', 52 'include_list_view_settings': 'auto', 53 'list_icon_size': 16.0, 54 'list_text_size': 12.0, 55 'list_scroll_position': (0, 0), 56 'list_sort_by': 'name', 57 'list_columns': ('name', 'date-modified', 'size', 'kind', 'date-added'), 58 'list_column_widths': { 59 'name': 300, 60 'date-modified': 181, 61 'date-created': 181, 62 'date-added': 181, 63 'date-last-opened': 181, 64 'size': 97, 65 'kind': 115, 66 'label': 100, 67 'version': 75, 68 'comments': 300, 69 }, 70 'list_column_sort_directions': { 71 'name': 'ascending', 72 'date-modified': 'descending', 73 'date-created': 'descending', 74 'date-added': 'descending', 75 'date-last-opened': 'descending', 76 'size': 'descending', 77 'kind': 'ascending', 78 'label': 'ascending', 79 'version': 'ascending', 80 'comments': 'ascending', 81 } 82 } 83 84 # Set up the finder data 85 bwsp = { 86 'ShowStatusBar': False, 87 'ContainerShowSidebar': False, 88 'PreviewPaneVisibility': False, 89 'SidebarWidth': options['sidebar_width'], 90 'ShowTabView': False, 91 'ShowToolbar': False, 92 'ShowPathbar': False, 93 'ShowSidebar': False 94 } 95 96 window_x = os.environ.get('windowX') 97 if window_x: 98 window_y = os.environ['windowY'] 99 bwsp['WindowBounds'] = '{{%s, %s}, {%s, %s}}' % (window_x, 100 window_y, 101 os.environ['windowWidth'], 102 os.environ['windowHeight']) 103 104 arrange_options = { 105 'name': 'name', 106 'date-modified': 'dateModified', 107 'date-created': 'dateCreated', 108 'date-added': 'dateAdded', 109 'date-last-opened': 'dateLastOpened', 110 'size': 'size', 111 'kind': 'kind', 112 'label': 'label', 113 } 114 115 icvp = { 116 'viewOptionsVersion': 1, 117 'backgroundType': 0, 118 'backgroundColorRed': 1.0, 119 'backgroundColorGreen': 1.0, 120 'backgroundColorBlue': 1.0, 121 'gridOffsetX': float(options['grid_offset'][0]), 122 'gridOffsetY': float(options['grid_offset'][1]), 123 'gridSpacing': float(options['grid_spacing']), 124 'arrangeBy': str(arrange_options.get(options['arrange_by'], 'none')), 125 'showIconPreview': options['show_icon_preview'] == True, 126 'showItemInfo': False, 127 'labelOnBottom': True, 128 'textSize': float(options['text_size']), 129 'iconSize': float(options['icon_size']), 130 'scrollPositionX': float(options['scroll_position'][0]), 131 'scrollPositionY': float(options['scroll_position'][1]) 132 } 133 134 columns = { 135 'name': 'name', 136 'date-modified': 'dateModified', 137 'date-created': 'dateCreated', 138 'date-added': 'dateAdded', 139 'date-last-opened': 'dateLastOpened', 140 'size': 'size', 141 'kind': 'kind', 142 'label': 'label', 143 'version': 'version', 144 'comments': 'comments' 145 } 146 147 default_widths = { 148 'name': 300, 149 'date-modified': 181, 150 'date-created': 181, 151 'date-added': 181, 152 'date-last-opened': 181, 153 'size': 97, 154 'kind': 115, 155 'label': 100, 156 'version': 75, 157 'comments': 300, 158 } 159 160 default_sort_directions = { 161 'name': 'ascending', 162 'date-modified': 'descending', 163 'date-created': 'descending', 164 'date-added': 'descending', 165 'date-last-opened': 'descending', 166 'size': 'descending', 167 'kind': 'ascending', 168 'label': 'ascending', 169 'version': 'ascending', 170 'comments': 'ascending', 171 } 172 173 lsvp = { 174 'viewOptionsVersion': 1, 175 'sortColumn': columns.get(options['list_sort_by'], 'name'), 176 'textSize': float(options['list_text_size']), 177 'iconSize': float(options['list_icon_size']), 178 'showIconPreview': options['show_icon_preview'], 179 'scrollPositionX': options['list_scroll_position'][0], 180 'scrollPositionY': options['list_scroll_position'][1], 181 'useRelativeDates': True, 182 'calculateAllSizes': False, 183 } 184 185 lsvp['columns'] = {} 186 cndx = {} 187 188 for n, column in enumerate(options['list_columns']): 189 cndx[column] = n 190 width = options['list_column_widths'].get(column, default_widths[column]) 191 asc = 'ascending' == options['list_column_sort_directions'].get(column, default_sort_directions[column]) 192 193 lsvp['columns'][columns[column]] = { 194 'index': n, 195 'width': width, 196 'identifier': columns[column], 197 'visible': True, 198 'ascending': asc 199 } 200 201 n = len(options['list_columns']) 202 for k in iterkeys(columns): 203 if cndx.get(k, None) is None: 204 cndx[k] = n 205 width = default_widths[k] 206 asc = 'ascending' == default_sort_directions[k] 207 208 lsvp['columns'][columns[column]] = { 209 'index': n, 210 'width': width, 211 'identifier': columns[column], 212 'visible': False, 213 'ascending': asc 214 } 215 216 n += 1 217 218 default_view = 'icon-view' 219 views = { 220 'icon-view': b'icnv', 221 'column-view': b'clmv', 222 'list-view': b'Nlsv', 223 'coverflow': b'Flwv' 224 } 225 226 icvl = (b'type', views.get(default_view, 'icnv')) 227 228 include_icon_view_settings = default_view == 'icon-view' \ 229 or options['include_icon_view_settings'] not in \ 230 ('auto', 'no', 0, False, None) 231 include_list_view_settings = default_view in ('list-view', 'coverflow') \ 232 or options['include_list_view_settings'] not in \ 233 ('auto', 'no', 0, False, None) 234 235 try: 236 background_bmk = None 237 238 background_color = os.environ.get('backgroundColor') 239 background_file = os.environ.get('backgroundFile') 240 241 if background_color: 242 c = parseColor(background_color).to_rgb() 243 244 icvp['backgroundType'] = 1 245 icvp['backgroundColorRed'] = float(c.r) 246 icvp['backgroundColorGreen'] = float(c.g) 247 icvp['backgroundColorBlue'] = float(c.b) 248 elif background_file: 249 alias = Alias.for_file(background_file) 250 background_bmk = Bookmark.for_file(background_file) 251 252 icvp['backgroundType'] = 2 253 icvp['backgroundImageAlias'] = biplist.Data(alias.to_bytes()) 254 255 image_dsstore = os.path.join(os.environ['volumePath'], '.DS_Store') 256 257 f = "icon_locations = {\n" + os.environ['iconLocations'] + "\n}" 258 exec (f, options, options) 259 260 with DSStore.open(image_dsstore, 'w+') as d: 261 d['.']['vSrn'] = ('long', 1) 262 d['.']['bwsp'] = bwsp 263 if include_icon_view_settings: 264 d['.']['icvp'] = icvp 265 if background_bmk: 266 d['.']['pBBk'] = background_bmk 267 if include_list_view_settings: 268 d['.']['lsvp'] = lsvp 269 d['.']['icvl'] = icvl 270 271 d['.background']['Iloc'] = (2560, 170) 272 d['.DS_Store']['Iloc'] = (2610, 170) 273 d['.fseventsd']['Iloc'] = (2660, 170) 274 d['.Trashes']['Iloc'] = (2710, 170) 275 d['.VolumeIcon.icns']['Iloc'] = (2760, 170) 276 277 for k, v in iteritems(options['icon_locations']): 278 d[k]['Iloc'] = v 279 except: 280 raise 281 282build_dmg()