def addWindowsIconFromIcons(): icon_group = 1 image_id = 1 images = [] result_filename = OutputDirectories.getResultFullpath() for icon_path in Options.getIconPaths(): with open(icon_path, "rb") as icon_file: # Read header and icon entries. header = readFromFile(icon_file, IconDirectoryHeader) icons = [ readFromFile(icon_file, IconDirectoryEntry) for icon in range(header.count) ] # Image data are to be scanned from places specified icon entries for icon in icons: icon_file.seek(icon.image_offset, 0) images.append(icon_file.read(icon.image_size)) parts = [convertStructureToBytes(header)] for icon in icons: parts.append( convertStructureToBytes( IconGroupDirectoryEntry( width=icon.width, height=icon.height, colors=icon.colors, reserved=icon.reserved, planes=icon.planes, bit_count=icon.bit_count, image_size=icon.image_size, id=image_id, ))) image_id += 1 addResourceToFile( target_filename=result_filename, data=b"".join(parts), resource_kind=RT_GROUP_ICON, lang_id=0, res_name=icon_group, logger=postprocessing_logger, ) for count, image in enumerate(images, 1): addResourceToFile( target_filename=result_filename, data=image, resource_kind=RT_ICON, lang_id=0, res_name=count, logger=postprocessing_logger, )
def addWindowsIconFromIcons(): icon_group = 1 image_id = 1 images = [] result_filename = OutputDirectories.getResultFullpath() for icon_spec in Options.getIconPaths(): if "#" in icon_spec: icon_path, icon_index = icon_spec.rsplit("#", 1) icon_index = int(icon_index) else: icon_path = icon_spec icon_index = None with open(icon_path, "rb") as icon_file: # Read header and icon entries. header = readFromFile(icon_file, IconDirectoryHeader) icons = [ readFromFile(icon_file, IconDirectoryEntry) for _i in range(header.count) ] if icon_index is not None: if icon_index > len(icons): postprocessing_logger.sysexit( "Error, referenced icon index %d in file %r with only %d icons." % (icon_index, icon_path, len(icons))) icons[:] = icons[icon_index:icon_index + 1] postprocessing_logger.info("Adding %d icon(s) from icon file %r." % (len(icons), icon_spec)) # Image data are to be scanned from places specified icon entries for icon in icons: icon_file.seek(icon.image_offset, 0) images.append(icon_file.read(icon.image_size)) parts = [convertStructureToBytes(header)] for icon in icons: parts.append( convertStructureToBytes( IconGroupDirectoryEntry( width=icon.width, height=icon.height, colors=icon.colors, reserved=icon.reserved, planes=icon.planes, bit_count=icon.bit_count, image_size=icon.image_size, id=image_id, ))) image_id += 1 addResourceToFile( target_filename=result_filename, data=b"".join(parts), resource_kind=RT_GROUP_ICON, lang_id=0, res_name=icon_group, logger=postprocessing_logger, ) for count, image in enumerate(images, 1): addResourceToFile( target_filename=result_filename, data=image, resource_kind=RT_ICON, lang_id=0, res_name=count, logger=postprocessing_logger, )
def _addWindowsIconFromIcons(onefile): # Relatively detailed handling, pylint: disable=too-many-locals icon_group = 1 image_id = 1 images = [] result_filename = OutputDirectories.getResultFullpath(onefile=onefile) for icon_spec in Options.getIconPaths(): if "#" in icon_spec: icon_path, icon_index = icon_spec.rsplit("#", 1) icon_index = int(icon_index) else: icon_path = icon_spec icon_index = None icon_path = os.path.normcase(icon_path) if not icon_path.endswith(".ico"): postprocessing_logger.info( "File '%s' is not in Windows icon format, converting to it." % icon_path) if icon_index is not None: postprocessing_logger.sysexit( "Cannot specify indexes with non-ico format files in '%s'." % icon_spec) icon_build_path = os.path.join( OutputDirectories.getSourceDirectoryPath(onefile=onefile), "icons", ) makePath(icon_build_path) converted_icon_path = os.path.join( icon_build_path, "icon-%d.ico" % image_id, ) convertImageToIconFormat( logger=postprocessing_logger, image_filename=icon_spec, icon_filename=converted_icon_path, ) icon_path = converted_icon_path with open(icon_path, "rb") as icon_file: # Read header and icon entries. header = readFromFile(icon_file, IconDirectoryHeader) icons = [ readFromFile(icon_file, IconDirectoryEntry) for _i in range(header.count) ] if icon_index is not None: if icon_index > len(icons): postprocessing_logger.sysexit( "Error, referenced icon index %d in file '%s' with only %d icons." % (icon_index, icon_path, len(icons))) icons[:] = icons[icon_index:icon_index + 1] postprocessing_logger.info( "Adding %d icon(s) from icon file '%s'." % (len(icons), icon_spec)) # Image data are to be scanned from places specified icon entries for icon in icons: icon_file.seek(icon.image_offset, 0) images.append(icon_file.read(icon.image_size)) parts = [convertStructureToBytes(header)] for icon in icons: parts.append( convertStructureToBytes( IconGroupDirectoryEntry( width=icon.width, height=icon.height, colors=icon.colors, reserved=icon.reserved, planes=icon.planes, bit_count=icon.bit_count, image_size=icon.image_size, id=image_id, ))) image_id += 1 addResourceToFile( target_filename=result_filename, data=b"".join(parts), resource_kind=RT_GROUP_ICON, lang_id=0, res_name=icon_group, logger=postprocessing_logger, ) for count, image in enumerate(images, 1): addResourceToFile( target_filename=result_filename, data=image, resource_kind=RT_ICON, lang_id=0, res_name=count, logger=postprocessing_logger, )
def createPlistInfoFile(logger, onefile): # Many details, pylint: disable=too-many-locals import plistlib if Options.isStandaloneMode(): bundle_dir = os.path.dirname( OutputDirectories.getStandaloneDirectoryPath()) else: bundle_dir = os.path.dirname( OutputDirectories.getResultRunFilename(onefile=onefile)) result_filename = OutputDirectories.getResultFullpath(onefile=onefile) app_name = Options.getMacOSAppName() or os.path.basename(result_filename) signed_app_name = Options.getMacOSSignedAppName() or app_name app_version = Options.getMacOSAppVersion() or "1.0" # TODO: We want an OrderedDict probably for stability. infos = OrderedDict([ ("CFBundleDisplayName", app_name), ("CFBundleName", app_name), ("CFBundleIdentifier", signed_app_name), ("CFBundleExecutable", app_name), ("CFBundleInfoDictionaryVersion", "6.0"), ("CFBundlePackageType", "APPL"), ("CFBundleShortVersionString", app_version), ]) icon_paths = Options.getIconPaths() if icon_paths: assert len(icon_paths) == 1 icon_path = icon_paths[0] # Convert to single macOS .icns file if necessary if not icon_path.endswith(".icns"): logger.info( "File '%s' is not in macOS icon format, converting to it." % icon_path) icon_build_path = os.path.join( OutputDirectories.getSourceDirectoryPath(onefile=onefile), "icons", ) makePath(icon_build_path) converted_icon_path = os.path.join( icon_build_path, "Icons.icns", ) convertImageToIconFormat( logger=logger, image_filename=icon_path, icon_filename=converted_icon_path, ) icon_path = converted_icon_path icon_name = os.path.basename(icon_path) resources_dir = os.path.join(bundle_dir, "Resources") makePath(resources_dir) copyFile(icon_path, os.path.join(resources_dir, icon_name)) infos["CFBundleIconFile"] = icon_name # Console mode, which is why we have to use bundle in the first place typically. if Options.shallDisableConsoleWindow(): infos["NSHighResolutionCapable"] = True else: infos["LSBackgroundOnly"] = True for resource_name, resource_desc in Options.getMacOSAppProtectedResourcesAccesses( ): if resource_name in infos: logger.sysexit("Duplicate value for '%s' is not allowed." % resource_name) infos[resource_name] = resource_desc filename = os.path.join(bundle_dir, "Info.plist") if str is bytes: plist_contents = plistlib.writePlistToString(infos) else: plist_contents = plistlib.dumps(infos) with openTextFile(filename=filename, mode="wb") as plist_file: plist_file.write(plist_contents)