检查Qt项目的 .ui 文件引用图标资源是否存在的脚本程序

一个项目中遇到一个问题,项目更新升级过程中,有一些模块比较长时间没有维护了,其中.ui文件引用的.qrc中的图标资源已经不存在了,就会导致程序运行的过程中无法显示图标。因为一个个排查太费时间,也容易漏,所有写了一个 Python 脚本来检查这个是不是有问题,将有问题的图标引用进行输出。

检查流程如下:

graph LR A([开始])-->B[输入要检查的目录] B-->C[扫描目录] C-->D{ui文件?} subgraph check F[0.解析UI文件]-->M[1.迭代iconset节点] M-->G[2.读取resource属性] G-->I[3.解析指向的qrc文件] M-->H[4.读取normaloff标签节点] I-->J{{5.normaloff<br>指向的资源文件<br>在qrc文件中?}} H-->J J--是<7.检查下一个>-->M J--否-->N[6.打印不存在的引用] M--8.没有iconset节点了-->L(9.结束) end D--是-->F L-->D D--否<下一个>-->D

代码实现很简单,只是检查了引用的图标是否在qrc文件中,没有进一步检查图标文件是否存在,这是不完善的地方。因为Qt的代码中也可以通过setIcon(const QIcon& icon)接口来设置图标,所以这里也检查不到。要解决这个问题,需要检查所有代码文件。

代码如下:

import os
import xml.etree.ElementTree as ET


def get_iconset_path(ui_file, resource):
    ui_dir = os.path.dirname(ui_file)
    qrc_file = os.path.join(ui_dir, resource)
    return os.path.normpath(qrc_file)

def parse_qrc(qrc_file):
    # 使用 cache 缓存已经解析过的文件
    if hasattr(parse_qrc, 'cache') == False:
        setattr(parse_qrc, 'cache', dict())
    if qrc_file in parse_qrc.cache:
        return parse_qrc.cache[qrc_file]
    # 解析 qrc 文件
    try:
        tree = ET.parse(qrc_file)
    except IOError as err:
        print('\033[95m解析出错:{}\033[0m'.format(err))
        return []
    except BaseException as err:
        print('\033[95m解析异常:{}\033[0m'.format(err))
        return []
    
    root = tree.getroot()

    result = []
    for qresource in root.iter('qresource'):
        # 获取 prefix 属性
        prefix = qresource.get('prefix', '/')
        for file in qresource.iter('file'):
            rc_file = os.path.join(prefix, file.text).replace('\\', '/')
            # print(rc_file)
            result.append(':'+rc_file)
    # 存入缓存
    parse_qrc.cache[qrc_file] = result
    return result




def check_iconset(dir, ui_file):
    """ 对 ui 文件进行检查,输出图标不存在的部分
    :param dir: 遍历的目录,以便只输出文件名时候截取前面部分
    :param ui_file: 要检查的 ui 文件
    """
    print('check file:', os.path.relpath(ui_file, dir))
    tree = ET.parse(ui_file)
    root = tree.getroot()
    # 遍历所有iconset标签节点
    for iconset in root.iter('iconset'):
        # 获取resource属性并打印
        resource = iconset.get('resource')
        if resource is None:
            # print(iconset.text)
            continue
        qrc_file = get_iconset_path(ui_file, resource)
        # print('Resource:', qrc_file)
        result = parse_qrc(qrc_file)
        # print(result)

        # 判断节点下是否有normaloff标签节点
        normaloff = iconset.find('normaloff')
        if normaloff is not None:
            # 输出normaloff标签节点的内容
            # print('Normaloff:', normaloff.text)
            # 判断是否存在,如果不存在就输出
            if normaloff.text not in result:
                print('\033[31m\tnot found:{}\033[0m'.format(normaloff.text))


def walk_dir(directory):
    """ 对文件夹进行遍历处理
    """
    for root, _, files in os.walk(directory):
        for file in files:
            if file.endswith(".ui"):
                ui_file = os.path.join(root, file)
                check_iconset(directory, ui_file)


# 指定目录作为参数调用方法
directory = input("请输入目录路径:")
walk_dir(directory)

其他参考

posted @ 2023-09-19 14:52  乌合之众  阅读(32)  评论(0编辑  收藏  举报
clear