Skip to content

Commit e6eb82a

Browse files
committed
支持APK包中二进制XML的编辑
1 parent 1f56917 commit e6eb82a

40 files changed

Lines changed: 16972 additions & 429 deletions

QResArscEditorUI.qrc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
<qresource prefix="/res">
33
<file>res/public-final.xml</file>
44
<file>res/locale.txt</file>
5+
<file>res/attrs.xml</file>
6+
<file>res/attrs_manifest.xml</file>
57
</qresource>
68
<qresource prefix="/icon">
79
<file>ico/save.png</file>

QtResArscEditor.vcxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,17 @@
118118
<ClCompile Include="src\common\utf8.cpp" />
119119
<ClCompile Include="src\GuidFactory.cpp" />
120120
<ClCompile Include="src\QAddLocaleDialog.cpp" />
121+
<ClCompile Include="src\QAndroidAttribute.cpp" />
122+
<ClCompile Include="src\QAndroidParser.cpp" />
121123
<ClCompile Include="src\QAppendDialog.cpp" />
122124
<ClCompile Include="src\QArscString.cpp" />
123125
<ClCompile Include="src\QEditDialog.cpp" />
126+
<ClCompile Include="src\QManifestParser.cpp" />
124127
<ClCompile Include="src\QPublicFinal.cpp" />
125128
<ClCompile Include="src\QResArscEditor.cpp" />
126129
<ClCompile Include="src\QResArscEditorUI.cpp" />
127130
<ClCompile Include="src\QResArscParser.cpp" />
131+
<ClCompile Include="src\QResXmlTree.cpp" />
128132
<ClCompile Include="src\QStringPool.cpp" />
129133
<ClCompile Include="src\QTablePackage.cpp" />
130134
<ClCompile Include="src\QTableType.cpp" />
@@ -137,6 +141,10 @@
137141
<QtMoc Include="src\QResArscParser.h" />
138142
</ItemGroup>
139143
<ItemGroup>
144+
<QtMoc Include="src\QAndroidAttribute.h" />
145+
<ClInclude Include="src\QAndroidParser.h" />
146+
<QtMoc Include="src\QManifestParser.h" />
147+
<ClInclude Include="src\QResXmlTree.h" />
140148
<ClInclude Include="src\QTablePackage.h" />
141149
</ItemGroup>
142150
<ItemGroup>

QtResArscEditor.vcxproj.filters

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,18 @@
8080
<ClCompile Include="src\QEditDialog.cpp">
8181
<Filter>Source Files</Filter>
8282
</ClCompile>
83+
<ClCompile Include="src\QManifestParser.cpp">
84+
<Filter>Source Files</Filter>
85+
</ClCompile>
86+
<ClCompile Include="src\QResXmlTree.cpp">
87+
<Filter>Source Files</Filter>
88+
</ClCompile>
89+
<ClCompile Include="src\QAndroidParser.cpp">
90+
<Filter>Source Files</Filter>
91+
</ClCompile>
92+
<ClCompile Include="src\QAndroidAttribute.cpp">
93+
<Filter>Source Files</Filter>
94+
</ClCompile>
8395
</ItemGroup>
8496
<ItemGroup>
8597
<ClInclude Include="src\GuidFactory.h">
@@ -130,6 +142,12 @@
130142
<ClInclude Include="src\QTablePackage.h">
131143
<Filter>Header Files</Filter>
132144
</ClInclude>
145+
<ClInclude Include="src\QAndroidParser.h">
146+
<Filter>Header Files</Filter>
147+
</ClInclude>
148+
<ClInclude Include="src\QResXmlTree.h">
149+
<Filter>Header Files</Filter>
150+
</ClInclude>
133151
</ItemGroup>
134152
<ItemGroup>
135153
<QtMoc Include="src\QResArscParser.h">
@@ -153,6 +171,12 @@
153171
<QtMoc Include="src\QEditDialog.h">
154172
<Filter>Header Files</Filter>
155173
</QtMoc>
174+
<QtMoc Include="src\QManifestParser.h">
175+
<Filter>Header Files</Filter>
176+
</QtMoc>
177+
<QtMoc Include="src\QAndroidAttribute.h">
178+
<Filter>Header Files</Filter>
179+
</QtMoc>
156180
</ItemGroup>
157181
<ItemGroup>
158182
<Natvis Include="src\common\sbtree.natvis">

main.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ void myMessageHandler(QtMsgType _type, const QMessageLogContext& _context, const
4747

4848
t_out << _msg << "\n";
4949
}
50-
5150
int main(int argc, char* argv[])
5251
{
5352
QApplication app(argc, argv);

res/attrs.xml

Lines changed: 10725 additions & 0 deletions
Large diffs are not rendered by default.

res/attrs_manifest.xml

Lines changed: 4152 additions & 0 deletions
Large diffs are not rendered by default.

src/QAndroidAttribute.cpp

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
#include "QAndroidAttribute.h"
2+
#include <QDebug>
3+
#include <QDomDocument>
4+
#include <QFile>
5+
#include <QRegularExpression>
6+
7+
void TAttributeFlags::appendFlag(const QDomNode& _node)
8+
{
9+
QDomNamedNodeMap t_attrMap = _node.attributes();
10+
if (t_attrMap.isEmpty())
11+
return;
12+
TAttributeFlag t_flag;
13+
t_flag.Name = t_attrMap.namedItem("name").nodeValue();
14+
QString t_svalue = t_attrMap.namedItem("value").nodeValue();
15+
if (t_svalue.startsWith("0x"))
16+
{
17+
t_flag.bit = true;
18+
t_flag.value = t_svalue.toUInt(nullptr, 16);
19+
}
20+
else
21+
{
22+
t_flag.bit = false;
23+
t_flag.value = (uint32_t)t_svalue.toInt(nullptr, 10);
24+
}
25+
flags.insert(t_flag, 0);
26+
flagValueMap.insert(t_flag.Name, t_flag.value);
27+
}
28+
uint32_t TAttributeFlags::string2value(const QString& _sname, const QString& _svalue)
29+
{
30+
uint32_t t_value = 0;
31+
QStringList t_sflags = _svalue.split("|", Qt::SkipEmptyParts);
32+
for (QStringList::iterator i = t_sflags.begin(); i != t_sflags.end(); ++i)
33+
{
34+
if (flagValueMap.contains(*i))
35+
t_value += flagValueMap[*i];
36+
else
37+
qDebug() << "Attribute:" << _sname << " unknow attr string:" << *i;
38+
}
39+
return t_value;
40+
}
41+
QString TAttributeFlags::value2string(const QString& _sname, uint32_t _value)
42+
{
43+
QString t_svalue;
44+
//从大到小来匹配标志位
45+
for (QMap<TAttributeFlag, int>::iterator i = flags.begin(); i != flags.end(); ++i)
46+
{
47+
const TAttributeFlag& t_flag = i.key();
48+
if (t_flag.bit && (_value & t_flag.value) == t_flag.value)
49+
{
50+
if (t_flag.value == 0 && t_svalue.length() > 0)
51+
break;
52+
t_svalue += t_flag.Name + "|";
53+
_value ^= t_flag.value;
54+
if (_value == 0)
55+
break;
56+
}
57+
}
58+
if (_value != 0)
59+
{
60+
for (QMap<TAttributeFlag, int>::iterator i = flags.begin(); i != flags.end(); ++i)
61+
{
62+
const TAttributeFlag& t_flag = i.key();
63+
if (!t_flag.bit && _value == t_flag.value)
64+
{
65+
t_svalue += t_flag.Name + "|";
66+
_value = 0;
67+
break;
68+
}
69+
}
70+
}
71+
qDebug() << "Attribute:" << _sname << " unknow attr value:" << _value;
72+
return t_svalue.mid(0, t_svalue.length() - 1);
73+
}
74+
QAndroidAttribute::QAndroidAttribute(QObject* _parent)
75+
:QObject(_parent)
76+
{
77+
initAttributes(":/res/res/attrs.xml");
78+
initAttributes(":/res/res/attrs_manifest.xml");
79+
}
80+
QAndroidAttribute::~QAndroidAttribute()
81+
{
82+
83+
}
84+
void QAndroidAttribute::initAttributes(const QString& _path)
85+
{
86+
QFile t_ReadFile(_path);
87+
if (!t_ReadFile.exists()) return;
88+
89+
if (!t_ReadFile.open(QFile::ReadOnly))
90+
return;
91+
QDomDocument t_domTree;
92+
if (!t_domTree.setContent(&t_ReadFile))
93+
{
94+
t_ReadFile.close();
95+
return;
96+
}
97+
QDomElement t_root = t_domTree.documentElement();
98+
QDomNode t_subNode = t_root.firstChild();
99+
while (!t_subNode.isNull())
100+
{
101+
analysisNode(t_subNode);
102+
t_subNode = t_subNode.nextSibling();
103+
}
104+
t_ReadFile.close();
105+
}
106+
void QAndroidAttribute::analysisNode(const QDomNode& _node)
107+
{
108+
QString t_nodeName = _node.nodeName();
109+
if (t_nodeName != "attr")
110+
{
111+
QDomNode t_subNode = _node.firstChild();
112+
while (!t_subNode.isNull())
113+
{
114+
analysisNode(t_subNode);
115+
t_subNode = t_subNode.nextSibling();
116+
}
117+
return;
118+
}
119+
if (!_node.hasChildNodes())
120+
return;
121+
QDomNamedNodeMap t_attrMap = _node.attributes();
122+
QString t_name = t_attrMap.namedItem("name").nodeValue();
123+
Q_ASSERT(!m_attrs.contains("android:" + t_name));
124+
TAttributeFlags t_flags;
125+
QDomNode t_flagNode = _node.firstChild();
126+
while (!t_flagNode.isNull())
127+
{
128+
t_flags.appendFlag(t_flagNode);
129+
t_flagNode = t_flagNode.nextSibling();
130+
}
131+
if (t_flags.flags.size() > 0)
132+
m_attrs.insert("android:" + t_name, t_flags);
133+
}
134+
uint32_t QAndroidAttribute::string2value(const QString& _sname, const QString& _svalue)
135+
{
136+
bool t_ok = true;
137+
uint32_t t_value;
138+
static QRegularExpression t_numberRegExp("^[0-9a-fA-FxX]{1,10}$");
139+
//只有非数值的字符串才去分析
140+
if (m_attrs.contains(_sname) && !t_numberRegExp.match(_svalue).hasMatch())
141+
t_value = m_attrs[_sname].string2value(_sname, _svalue);
142+
else if (_svalue.startsWith("0x", Qt::CaseInsensitive))
143+
t_value = _svalue.toUInt(&t_ok, 16);
144+
else
145+
t_value = _svalue.toUInt(&t_ok, 10);
146+
if (!t_ok)
147+
qDebug() << "Attribute:" << _sname << " unknow attr string:" << _svalue;
148+
return t_value;
149+
}
150+
QString QAndroidAttribute::value2string(const QString& _sname, uint32_t _value, bool _hex)
151+
{
152+
if (m_attrs.contains(_sname))
153+
return m_attrs[_sname].value2string(_sname, _value);
154+
else if (_hex)
155+
return QString("0x%1").arg(_value, 0, 16);
156+
else
157+
return QString::number(_value);
158+
}
159+
bool QAndroidAttribute::contains(const QString& _sname)
160+
{
161+
return m_attrs.contains(_sname);
162+
}
163+
QAndroidAttribute* g_androidAttribute;

src/QAndroidAttribute.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//********************************************************************
2+
// filename: F:\mygit\QtResArscEditor2\QAndroidAttribute.h
3+
// desc:
4+
//
5+
// created: wangdaye 15:1:2026 13:19
6+
//********************************************************************
7+
#ifndef QAndroidAttribute_h__
8+
#define QAndroidAttribute_h__
9+
#include <QMap>
10+
#include <QObject>
11+
#include <QString>
12+
13+
class QDomNode;
14+
15+
struct TAttributeFlag
16+
{
17+
QString Name;
18+
uint32_t value;
19+
bool bit; //按位匹配?
20+
bool operator < (const TAttributeFlag& _r) const
21+
{
22+
if (value != _r.value)
23+
return value > _r.value; //值大的排前面
24+
return Name < _r.Name;
25+
}
26+
};
27+
struct TAttributeFlags
28+
{
29+
QMap<TAttributeFlag, int> flags;
30+
QMap<QString, int> flagValueMap;
31+
void appendFlag(const QDomNode& _node);
32+
uint32_t string2value(const QString& _sname, const QString& _svalue);
33+
QString value2string(const QString& _sname, uint32_t _value);
34+
};
35+
class QAndroidAttribute : public QObject
36+
{
37+
Q_OBJECT
38+
public:
39+
QAndroidAttribute(QObject* _parent);
40+
~QAndroidAttribute();
41+
uint32_t string2value(const QString& _sname, const QString& _svalue);
42+
QString value2string(const QString& _sname, uint32_t _value, bool _hex);
43+
bool contains(const QString& _sname);
44+
private:
45+
void initAttributes(const QString& _path);
46+
void analysisNode(const QDomNode& _node);
47+
private:
48+
QMap<QString, TAttributeFlags> m_attrs;
49+
};
50+
extern QAndroidAttribute* g_androidAttribute;
51+
52+
#endif // QAndroidAttribute_h__

0 commit comments

Comments
 (0)