【设计背景】
工作中一个维护型的项目采用opengl+gtk+sdl的方案进行设计实现的,其中GTK负责窗口的设计实现。
使用过Qt的同学都知道QtCreator设计助手(解脱了ui设计的问题),但是GTK没有这么幸运,看了组内历史的代码,随便一个窗口代码都是上千行的,一看源码其中UI的控件创建、控件size设计、控件的位置等就占据了将近1/3,这是多么尴尬的一件事情。
客户来一个窗口,开发人员需要手动编写ui代码然后编译验证,再测试、再调整,直到UI看起来不错位置,这样下来一个上午连一个ui窗口的显示工作都难以完成。
基于这种尴尬的场景,于是萌生了用python来自动化生成GTK的布局代码。
【设计原理】
我们都知道QtCreator设计文件*.ui本质上是一个xml文件,包含了用户拖拽控件的相对父子和布局Size关系。
xml文件可以通过python的lxml魔窟啊进行解析,然后记录其中的控件的类型和位置大小的信息即可,
然后将Qt控件类一一映射为GTK的控件,最后生成GTK的ui布局代码。
【设计代码】
- 解析ui文件,提取控件标识(Qt类型和 ID) & 控件信息
-
import os,sys import re from string import Template from xml.etree.ElementTree import ElementTree,Element ############################################################################### # @Function: description ############################################################################### def readFile(fname): with open(fname, 'rb') as f: return f.read() def writeFile(fname, data): with open(fname, 'wb') as fo: fo.write(data) ############################################################################### # @Function: read/write xml. ############################################################################### def read_xml(in_path): tree = ElementTree() tree.parse(in_path) return tree def write_xml(tree, out_path): tree.write(out_path, encoding="utf-8",xml_declaration=True) ############################################################################### # @Function: basic utils. ############################################################################### def if_match(node, kv_map): for key in kv_map: if node.get(key) != kv_map.get(key): return False return True ############################################################################### # @Function: various search actions. ############################################################################### def getElementsByTag(tree, path): return tree.findall(path) def getElementsByKey(nodelist, kv_map): result_nodes = [] for node in nodelist: if if_match(node, kv_map): result_nodes.append(node) return result_nodes ############################################################################### # @Function: various modify actions. ############################################################################### def removeAttribute(nodelist, kv_map): for node in nodelist: for key in kv_map: if key in node.attrib: del node.attrib[key] def addAttribute(nodelist, kv_map): for node in nodelist: for key in kv_map: node.set(key, kv_map.get(key)) def setAttribute(nodelist, text): for node in nodelist: node.text = text def createElement(tag, property_map, content): element = Element(tag, property_map) element.text = content return element def add_child_node(nodelist, element): for node in nodelist: node.append(element) def removeNodeByTagAndKey(nodelist, tag, kv_map): fo