def save(self): """ Save this theme. """ domdoc = minidom.Document() try: theme_element = domdoc.createElement("theme") theme_element.setAttribute("name", self._name) theme_element.setAttribute("format", str(self.THEME_FORMAT)) domdoc.appendChild(theme_element) for name, _type, _default in self.attributes: if name == "color_scheme_basename": element = domdoc.createElement("color_scheme") text = domdoc.createTextNode(self.color_scheme_basename) element.appendChild(text) theme_element.appendChild(element) elif name == "key_label_overrides": overrides_element = \ domdoc.createElement("key_label_overrides") theme_element.appendChild(overrides_element) tuples = self.key_label_overrides for key_id, values in list(tuples.items()): element = domdoc.createElement("key") element.setAttribute("id", key_id) element.setAttribute("label", values[0]) element.setAttribute("group", values[1]) overrides_element.appendChild(element) else: value = getattr(self, name) if _type == "s": pass elif _type == "i": value = str(value) elif _type == "d": value = str(round(float(value), 2)) elif _type == "ad": value = ", ".join(str(d) for d in value) else: assert (False) # attribute of unknown type element = domdoc.createElement(name) text = domdoc.createTextNode(value) element.appendChild(text) theme_element.appendChild(element) pretty_xml = toprettyxml(domdoc) with open_utf8(self._filename, "w") as _file: if sys.version_info.major >= 3: _file.write(pretty_xml) else: _file.write(pretty_xml.encode("UTF-8")) except Exception as xxx_todo_changeme2: (ex) = xxx_todo_changeme2 raise Exceptions.ThemeFileError(_("Error saving ") + self._filename, chained_exception=ex) finally: domdoc.unlink()
def save(self): """ Save this theme. """ domdoc = minidom.Document() try: theme_element = domdoc.createElement("theme") theme_element.setAttribute("name", self._name) theme_element.setAttribute("format", str(self.THEME_FORMAT)) domdoc.appendChild(theme_element) for name, _type, _default in self.attributes: if name == "color_scheme_basename": element = domdoc.createElement("color_scheme") text = domdoc.createTextNode(self.color_scheme_basename) element.appendChild(text) theme_element.appendChild(element) elif name == "key_label_overrides": overrides_element = \ domdoc.createElement("key_label_overrides") theme_element.appendChild(overrides_element) tuples = self.key_label_overrides for key_id, values in list(tuples.items()): element = domdoc.createElement("key") element.setAttribute("id", key_id) element.setAttribute("label", values[0]) element.setAttribute("group", values[1]) overrides_element.appendChild(element) else: value = getattr(self, name) if _type == "s": pass elif _type == "i": value = str(value) elif _type == "d": value = str(round(float(value), 2)) elif _type == "ad": value = ", ".join(str(d) for d in value) else: assert(False) # attribute of unknown type element = domdoc.createElement(name) text = domdoc.createTextNode(value) element.appendChild(text) theme_element.appendChild(element) pretty_xml = toprettyxml(domdoc) with open_utf8(self._filename, "w") as _file: if sys.version_info.major >= 3: _file.write(pretty_xml) else: _file.write(pretty_xml.encode("UTF-8")) except Exception as xxx_todo_changeme2: (ex) = xxx_todo_changeme2 raise Exceptions.ThemeFileError(_("Error saving ") + self._filename, chained_exception = ex) finally: domdoc.unlink()
def _read_countries(self): with open_utf8("/usr/share/xml/iso-codes/iso_3166.xml") as f: dom = minidom.parse(f).documentElement for node in dom.getElementsByTagName("iso_3166_entry"): country_code = self._get_attr(node, "alpha_2_code") country_name = self._get_attr(node, "name") if country_code and country_name: self._countries[country_code.upper()] = country_name
def _load_svg_keys(self, filename): filename = os.path.join(self._root_layout_dir, filename) try: with open_utf8(filename) as svg_file: svg_dom = minidom.parse(svg_file).documentElement svg_nodes = self._parse_svg(svg_dom) svg_nodes = {node.id: node for node in svg_nodes} except Exceptions.LayoutFileError as ex: raise Exceptions.LayoutFileError( "error loading '{}'".format(filename), chained_exception=(ex)) return svg_nodes
def _load_svg_keys(self, filename): filename = os.path.join(self._root_layout_dir, filename) try: with open_utf8(filename) as svg_file: svg_dom = minidom.parse(svg_file).documentElement svg_nodes = self._parse_svg(svg_dom) svg_nodes = {node.id : node for node in svg_nodes} except Exceptions.LayoutFileError as ex: raise Exceptions.LayoutFileError( "error loading '{}'".format(filename), chained_exception = (ex)) return svg_nodes
def _read_languages(self): with open_utf8("/usr/share/xml/iso-codes/iso_639.xml") as f: dom = minidom.parse(f).documentElement for node in dom.getElementsByTagName("iso_639_entry"): lang_code = self._get_attr(node, "iso_639_1_code") if not lang_code: lang_code = self._get_attr(node, "iso_639_2T_code") lang_name = self._get_attr(node, "name", "") if lang_code and lang_name: self._languages[lang_code] = lang_name
def _load_svg_keys(self, filename): filename = os.path.join(self._root_layout_dir, filename) try: with open_utf8(filename) as svg_file: svg_dom = minidom.parse(svg_file).documentElement svg_keys = self._parse_svg(svg_dom) except Exception as xxx_todo_changeme1: (exception) = xxx_todo_changeme1 raise Exceptions.LayoutFileError(_("Error loading ") + filename, chained_exception=exception) return svg_keys
def _load_svg_keys(self, filename): filename = os.path.join(self._root_layout_dir, filename) try: with open_utf8(filename) as svg_file: svg_dom = minidom.parse(svg_file).documentElement svg_keys = self._parse_svg(svg_dom) except Exception as xxx_todo_changeme1: (exception) = xxx_todo_changeme1 raise Exceptions.LayoutFileError(_("Error loading ") + filename, chained_exception = exception) return svg_keys
def load(filename, is_system=False): """ Load a color scheme and return it as a new instance. """ color_scheme = None f = open_utf8(filename) try: dom = minidom.parse(f).documentElement name = dom.attributes["name"].value # check layout format format = ColorScheme.COLOR_SCHEME_FORMAT_LEGACY if dom.hasAttribute("format"): format = Version.from_string(dom.attributes["format"].value) if format >= ColorScheme.COLOR_SCHEME_FORMAT_TREE: # tree format? items = ColorScheme._parse_dom_node(dom, None, {}) else: _logger.warning(_format( \ "Loading legacy color scheme format '{old_format}', " "please consider upgrading to current format " "'{new_format}': '{filename}'", old_format = format, new_format = ColorScheme.COLOR_SCHEME_FORMAT, filename = filename)) items = ColorScheme._parse_legacy_color_scheme(dom) if not items is None: root = Root() root.set_items(items) color_scheme = ColorScheme() color_scheme.name = name color_scheme._filename = filename color_scheme.is_system = is_system color_scheme._root = root #print(root.dumps()) except xml.parsers.expat.ExpatError as ex: _logger.error( _format( "Error loading color scheme '{filename}'. " "{exception}: {cause}", filename=filename, exception=type(ex).__name__, cause=unicode_str(ex))) finally: f.close() return color_scheme
def load(filename, is_system=False): """ Load a color scheme and return it as a new instance. """ color_scheme = None f = open_utf8(filename) try: dom = minidom.parse(f).documentElement name = dom.attributes["name"].value # check layout format format = ColorScheme.COLOR_SCHEME_FORMAT_LEGACY if dom.hasAttribute("format"): format = Version.from_string(dom.attributes["format"].value) if format >= ColorScheme.COLOR_SCHEME_FORMAT_TREE: # tree format? items = ColorScheme._parse_dom_node(dom, None, {}) else: _logger.warning(_format( \ "Loading legacy color scheme format '{old_format}', " "please consider upgrading to current format " "'{new_format}': '{filename}'", old_format = format, new_format = ColorScheme.COLOR_SCHEME_FORMAT, filename = filename)) items = ColorScheme._parse_legacy_color_scheme(dom) if not items is None: root = Root() root.set_items(items) color_scheme = ColorScheme() color_scheme.name = name color_scheme._filename = filename color_scheme.is_system = is_system color_scheme._root = root #print(root.dumps()) except xml.parsers.expat.ExpatError as ex: _logger.error(_format("Error loading color scheme '{filename}'. " "{exception}: {cause}", filename = filename, exception = type(ex).__name__, cause = unicode_str(ex))) finally: f.close() return color_scheme
def _load_layout(self, layout_filename, parent_item=None): self._svg_cache = {} layout = None try: f = open_utf8(layout_filename) except FileNotFoundError as ex: _logger.warning("Failed to open '{}': {}".format( layout_filename, unicode_str(ex))) return None # make sure unlink is called with minidom.parse(f).documentElement as dom: # check layout format, no format version means legacy layout format = self.LAYOUT_FORMAT_LEGACY if dom.hasAttribute("format"): format = Version.from_string(dom.attributes["format"].value) self._format = format root = LayoutPanel() # root, representing the 'keyboard' tag root.set_id("__root__") # id for debug prints # Init included root with the parent item's svg filename. # -> Allows to skip specifying svg filenames in includes. if parent_item: root.filename = parent_item.filename if format >= self.LAYOUT_FORMAT_LAYOUT_TREE: self._parse_dom_node(dom, root) layout = root else: _logger.warning( _format( "Loading legacy layout, format '{}'. " "Please consider upgrading to current format '{}'", format, self.LAYOUT_FORMAT)) items = self._parse_legacy_layout(dom) if items: root.set_items(items) layout = root f.close() self._svg_cache = {} # Free the memory return layout
def get_layout_svg_filenames(filename): results = [] domdoc = None with open_utf8(filename) as f: domdoc = minidom.parse(f).documentElement if domdoc: filenames = {} for node in LayoutLoaderSVG._iter_dom_nodes(domdoc): if LayoutLoaderSVG.is_layout_node(node): if node.hasAttribute("filename"): fn = node.attributes["filename"].value filenames[fn] = fn layout_dir, name = os.path.split(filename) results = [] for fn in list(filenames.keys()): dir, name = os.path.split(fn) results.append(os.path.join(layout_dir, name)) return results
def _load_layout(self, layout_filename, parent_item = None): self._svg_cache = {} layout = None f = open_utf8(layout_filename) # make sure unlink is called with minidom.parse(f).documentElement as dom: # check layout format, no format version means legacy layout format = self.LAYOUT_FORMAT_LEGACY if dom.hasAttribute("format"): format = Version.from_string(dom.attributes["format"].value) self._format = format root = LayoutPanel() # root, representing the 'keyboard' tag root.set_id("__root__") # id for debug prints # Init included root with the parent item's svg filename. # -> Allows to skip specifying svg filenames in includes. if parent_item: root.filename = parent_item.filename if format >= self.LAYOUT_FORMAT_LAYOUT_TREE: self._parse_dom_node(dom, root) layout = root else: _logger.warning(_format("Loading legacy layout, format '{}'. " "Please consider upgrading to current format '{}'", format, self.LAYOUT_FORMAT)) items = self._parse_legacy_layout(dom) if items: root.set_items(items) layout = root f.close() self._svg_cache = {} # Free the memory return layout
def load(filename, is_system=False): """ Load a theme and return a new theme object. """ result = None _file = open_utf8(filename) try: domdoc = minidom.parse(_file).documentElement try: theme = Theme() node = domdoc.attributes.get("format") format = Version.from_string(node.value) \ if node else Theme.THEME_FORMAT_INITIAL theme.name = domdoc.attributes["name"].value # "color_scheme" is the base file name of the color scheme text = utils.xml_get_text(domdoc, "color_scheme") if not text is None: theme.color_scheme_basename = text # get key label overrides nodes = domdoc.getElementsByTagName("key_label_overrides") if nodes: overrides = nodes[0] tuples = {} for override in overrides.getElementsByTagName("key"): key_id = override.attributes["id"].value node = override.attributes.get("label") label = node.value if node else "" node = override.attributes.get("group") group = node.value if node else "" tuples[key_id] = (label, group) theme.key_label_overrides = tuples # read all other members for name, _type, _default in Theme.attributes: if not name in [ "color_scheme_basename", "key_label_overrides" ]: value = utils.xml_get_text(domdoc, name) if not value is None: if _type == "i": value = int(value) if _type == "d": value = float(value) if _type == "ad": value = [float(s) for s in value.split(",")] # upgrade to current file format if format < Theme.THEME_FORMAT_1_1: # direction was 0..360, ccw # is now -180..180, cw if name == "key_gradient_direction": value = -(value % 360) if value <= -180: value += 360 setattr(theme, name, value) theme._filename = filename theme.is_system = is_system theme.system_exists = is_system result = theme finally: domdoc.unlink() except (Exceptions.ThemeFileError, xml.parsers.expat.ExpatError) as ex: _logger.error( _format( "Error loading theme '{filename}'. " "{exception}: {cause}", filename=filename, exception=type(ex).__name__, cause=unicode_str(ex))) result = None finally: _file.close() return result
def copy_layout(src_filename, dst_filename): src_dir = os.path.dirname(src_filename) dst_dir, name_ext = os.path.split(dst_filename) dst_basename, ext = os.path.splitext(name_ext) _logger.info(_format("copying layout '{}' to '{}'", src_filename, dst_filename)) domdoc = None svg_filenames = {} fallback_layers = {} with open_utf8(src_filename) as f: domdoc = minidom.parse(f) keyboard_node = domdoc.documentElement # check layout format format = LayoutLoaderSVG.LAYOUT_FORMAT_LEGACY if keyboard_node.hasAttribute("format"): format = Version.from_string(keyboard_node.attributes["format"].value) keyboard_node.attributes["id"] = dst_basename if format < LayoutLoaderSVG.LAYOUT_FORMAT_LAYOUT_TREE: raise Exceptions.LayoutFileError( \ _format("copy_layouts failed, unsupported layout format '{}'.", format)) else: # replace the basename of all svg filenames for node in LayoutLoaderSVG._iter_dom_nodes(keyboard_node): if LayoutLoaderSVG.is_layout_node(node): if node.hasAttribute("filename"): filename = node.attributes["filename"].value # Create a replacement layer name for the unlikely # case that the svg-filename doesn't contain a # layer section (as in path/basename-layer.ext). fallback_layer_name = fallback_layers.get(filename, "Layer" + str(len(fallback_layers))) fallback_layers[filename] = fallback_layer_name # replace the basename of this filename new_filename = LayoutLoaderSVG._replace_basename( \ filename, dst_basename, fallback_layer_name) node.attributes["filename"].value = new_filename svg_filenames[filename] = new_filename if domdoc: # write the new layout file with open_utf8(dst_filename, "w") as f: xml = toprettyxml(domdoc) if sys.version_info.major == 2: # python 2? xml = xml.encode("UTF-8") f.write(xml) # copy the svg files for src, dst in list(svg_filenames.items()): dir, name = os.path.split(src) if not dir: src = os.path.join(src_dir, name) dir, name = os.path.split(dst) if not dir: dst = os.path.join(dst_dir, name) _logger.info(_format("copying svg file '{}' to '{}'", \ src, dst)) shutil.copyfile(src, dst)
def copy_layout(src_filename, dst_filename): src_dir = os.path.dirname(src_filename) dst_dir, name_ext = os.path.split(dst_filename) dst_basename, ext = os.path.splitext(name_ext) _logger.info( _format("copying layout '{}' to '{}'", src_filename, dst_filename)) domdoc = None svg_filenames = {} fallback_layers = {} try: with open_utf8(src_filename) as f: domdoc = minidom.parse(f) keyboard_node = domdoc.documentElement # check layout format format = LayoutLoaderSVG.LAYOUT_FORMAT_LEGACY if keyboard_node.hasAttribute("format"): format = Version.from_string( keyboard_node.attributes["format"].value) keyboard_node.attributes["id"] = dst_basename if format < LayoutLoaderSVG.LAYOUT_FORMAT_LAYOUT_TREE: raise Exceptions.LayoutFileError( \ _format("copy_layouts failed, unsupported layout format '{}'.", format)) else: # replace the basename of all svg filenames for node in LayoutLoaderSVG._iter_dom_nodes(keyboard_node): if LayoutLoaderSVG.is_layout_node(node): if node.hasAttribute("filename"): filename = node.attributes["filename"].value # Create a replacement layer name for the unlikely # case that the svg-filename doesn't contain a # layer section (as in path/basename-layer.ext). fallback_layer_name = fallback_layers.get( filename, "Layer" + str(len(fallback_layers))) fallback_layers[filename] = fallback_layer_name # replace the basename of this filename new_filename = LayoutLoaderSVG._replace_basename( \ filename, dst_basename, fallback_layer_name) node.attributes[ "filename"].value = new_filename svg_filenames[filename] = new_filename if domdoc: XDGDirs.assure_user_dir_exists(config.get_user_layout_dir()) # write the new layout file with open_utf8(dst_filename, "w") as f: xml = toprettyxml(domdoc) if sys.version_info.major == 2: # python 2? xml = xml.encode("UTF-8") f.write(xml) # copy the svg files for src, dst in list(svg_filenames.items()): dir, name = os.path.split(src) if not dir: src = os.path.join(src_dir, name) dir, name = os.path.split(dst) if not dir: dst = os.path.join(dst_dir, name) _logger.info(_format("copying svg file '{}' to '{}'", \ src, dst)) shutil.copyfile(src, dst) except OSError as ex: _logger.error("copy_layout failed: " + \ unicode_str(ex)) except Exceptions.LayoutFileError as ex: _logger.error(unicode_str(ex))
def load(filename, is_system=False): """ Load a theme and return a new theme object. """ result = None _file = open_utf8(filename) try: domdoc = minidom.parse(_file).documentElement try: theme = Theme() node = domdoc.attributes.get("format") format = Version.from_string(node.value) \ if node else Theme.THEME_FORMAT_INITIAL theme.name = domdoc.attributes["name"].value # "color_scheme" is the base file name of the color scheme text = utils.xml_get_text(domdoc, "color_scheme") if not text is None: theme.color_scheme_basename = text # get key label overrides nodes = domdoc.getElementsByTagName("key_label_overrides") if nodes: overrides = nodes[0] tuples = {} for override in overrides.getElementsByTagName("key"): key_id = override.attributes["id"].value node = override.attributes.get("label") label = node.value if node else "" node = override.attributes.get("group") group = node.value if node else "" tuples[key_id] = (label, group) theme.key_label_overrides = tuples # read all other members for name, _type, _default in Theme.attributes: if not name in ["color_scheme_basename", "key_label_overrides"]: value = utils.xml_get_text(domdoc, name) if not value is None: if _type == "i": value = int(value) if _type == "d": value = float(value) if _type == "ad": value = [float(s) for s in value.split(",")] # upgrade to current file format if format < Theme.THEME_FORMAT_1_1: # direction was 0..360, ccw # is now -180..180, cw if name == "key_gradient_direction": value = -(value % 360) if value <= -180: value += 360 setattr(theme, name, value) theme._filename = filename theme.is_system = is_system theme.system_exists = is_system result = theme finally: domdoc.unlink() except (Exceptions.ThemeFileError, xml.parsers.expat.ExpatError) as ex: _logger.error(_format("Error loading theme '{filename}'. " "{exception}: {cause}", filename = filename, exception = type(ex).__name__, cause = unicode_str(ex))) result = None finally: _file.close() return result