source: trunk/tools/porting/src/portingrules.cpp@ 564

Last change on this file since 564 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 10.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the qt3to4 porting application of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "portingrules.h"
43#include "logger.h"
44#include "qtsimplexml.h"
45#include <QFile>
46#include <QFileInfo>
47#include <QDir>
48
49QT_BEGIN_NAMESPACE
50
51PortingRules *PortingRules::theInstance = 0;
52
53void PortingRules::createInstance(QString xmlFilePath)
54{
55 deleteInstance();
56 theInstance = new PortingRules(xmlFilePath);
57}
58
59PortingRules *PortingRules::instance()
60{
61 if(theInstance) {
62 return theInstance;
63 } else {
64 qWarning("Error: must create a PortingRules instance with createInstance() before calling instance()\n");
65 return 0;
66 }
67}
68
69void PortingRules::deleteInstance()
70{
71 if(theInstance) {
72 delete theInstance;
73 theInstance = 0;
74 }
75}
76
77PortingRules::PortingRules(QString xmlFilePath)
78{
79 parseXml(xmlFilePath);
80}
81
82QList<TokenReplacement*> PortingRules::getTokenReplacementRules()
83{
84 if(tokenRules.isEmpty())
85 addLogWarning(QLatin1String("Warning: token rules list is empty"));
86 return tokenRules;
87}
88
89QStringList PortingRules::getHeaderList(QtVersion qtVersion)
90{
91 if(qt3Headers.isEmpty() || qt4Headers.isEmpty())
92 addLogWarning(QLatin1String("Warning: headers list is empty"));
93
94 if (qtVersion==Qt3)
95 return qt3Headers;
96 else //Qt4
97 return qt4Headers;
98}
99
100QHash<QByteArray, QByteArray> PortingRules::getNeededHeaders()
101{
102 if(neededHeaders.isEmpty())
103 addLogWarning(QLatin1String("Warning: needed headers list is empty"));
104 return neededHeaders;
105}
106
107QStringList PortingRules::getInheritsQt()
108{
109 if(tokenRules.isEmpty())
110 addLogWarning(QLatin1String("Warning: inheritsQtClass list is empty"));
111 return inheritsQtClass;
112}
113
114QHash<QByteArray, QByteArray> PortingRules::getClassLibraryList()
115{
116 if(classLibraryList.isEmpty())
117 addLogWarning(QLatin1String("Warning: classLibraryList list is empty"));
118 return classLibraryList;
119}
120
121QHash<QByteArray, QByteArray> PortingRules::getHeaderReplacements()
122{
123 return headerReplacements;
124}
125
126/*
127 Loads rule xml file given by fileName, and sets up data structures.
128 The rules can generally be divided into to types, replacement rules and
129 info rules.
130
131 Replacement rules has the form Qt3Symobl -> Qt4Symbol
132 Info rules includes the NeedHeader, Qt3Header, Qt4Header, InhertitsQt
133 rule types.
134*/
135void PortingRules::parseXml(QString fileName)
136{
137 QtSimpleXml *xmlPointer = loadXml(fileName);
138 QtSimpleXml &xml = *xmlPointer;
139
140 int ruleCount = xml[QLatin1String("Rules")].numChildren();
141 ++ruleCount;
142
143 for(int rule=0; rule<ruleCount; ++rule) {
144 QtSimpleXml &currentRule = xml[QLatin1String("Rules")][rule];
145 QString ruleType = currentRule.attribute(QLatin1String("Type"));
146
147 if(isReplacementRule(ruleType)) {
148 QString qt3Symbol = currentRule[QLatin1String("Qt3")].text();
149 QString qt4Symbol = currentRule[QLatin1String("Qt4")].text();
150
151 QString disable = currentRule.attribute(QLatin1String("Disable"));
152 if(disable == QLatin1String("True") || disable == QLatin1String("true")) {
153 disableRule(currentRule);
154 continue;
155 }
156
157 if (isRuleDisabled(currentRule))
158 continue;
159
160 if(ruleType == QLatin1String("RenamedHeader")) {
161 headerReplacements.insert(qt3Symbol.toLatin1(), qt4Symbol.toLatin1());
162 } else if(ruleType == QLatin1String("RenamedClass") || ruleType == QLatin1String("RenamedToken") ) {
163 tokenRules.append(new ClassNameReplacement(
164 qt3Symbol.toLatin1(), qt4Symbol.toLatin1()));
165 } else if(ruleType == QLatin1String("RenamedEnumvalue") || ruleType == QLatin1String("RenamedType") ||
166 ruleType == QLatin1String("RenamedQtSymbol") ) {
167 checkScopeAddRule(currentRule);
168 }
169 } else if(ruleType == QLatin1String("NeedHeader")) {
170 const QByteArray className = currentRule[QLatin1String("Class")].text().toLatin1();
171 const QByteArray headerName = currentRule[QLatin1String("Header")].text().toLatin1();
172 neededHeaders.insert(className, headerName);
173 }
174 else if(ruleType == QLatin1String("qt3Header")) {
175 qt3Headers += currentRule.text();
176 }
177 else if(ruleType == QLatin1String("qt4Header")) {
178 qt4Headers += currentRule.text();
179 }
180 else if(ruleType == QLatin1String("InheritsQt")) {
181 inheritsQtClass += currentRule.text();
182 }
183 else if(ruleType == QLatin1String("Qt4Class")) {
184 // Get library name, make it lowercase and chop of the "Qt" prefix.
185 const QByteArray libraryName = currentRule[QLatin1String("Library")].text().toLatin1().toLower().mid(2);
186 classLibraryList.insert(currentRule[QLatin1String("Name")].text().toLatin1(), libraryName);
187 }
188 }
189
190 QString includeFile = xml[QLatin1String("Rules")][QLatin1String("Include")].text();
191
192 if(!includeFile.isNull()) {
193 QString resolvedIncludeFile = resolveFileName(fileName, includeFile);
194 if (!resolvedIncludeFile.isEmpty())
195 parseXml(resolvedIncludeFile);
196 }
197
198 delete xmlPointer;
199}
200
201/*
202 Check if the rule in currentRule describes a qualified name
203 (like QButton::ToggleState). If so, create a scoped ScopedTokenReplacement,
204 else create a GenericTokenReplacement
205*/
206void PortingRules::checkScopeAddRule(/*const */QtSimpleXml &currentRule)
207{
208 QByteArray oldToken = currentRule[QLatin1String("Qt3")].text().toLatin1();
209 QByteArray newToken = currentRule[QLatin1String("Qt4")].text().toLatin1();
210
211 if (oldToken.contains(QByteArray("::")))
212 tokenRules.append(new ScopedTokenReplacement(oldToken, newToken));
213 else
214 tokenRules.append(new GenericTokenReplacement(oldToken, newToken));
215}
216
217/*
218 Loads the xml-file given by fileName into a new'ed QtSimpleXml, which is
219 returned by pointer.
220*/
221QtSimpleXml *PortingRules::loadXml(const QString fileName) const
222{
223 QFile f(fileName);
224 if(!f.open(QIODevice::ReadOnly)) {
225 qFatal("Could not find rule file %s", fileName.toLatin1().constData());
226 }
227 QtSimpleXml *xml = new QtSimpleXml();
228 if(!xml->setContent(&f))
229 addLogError(QLatin1String("Xml parsing failed: ") + xml->errorString());
230
231 return xml;
232}
233
234/*
235 Resolves includeFilePath against currentFilePath. If currentFilePath
236 contains foo/bar.xml, and includeFilePath contains bar2.xml, the returned
237 result will be foo/bar2.xml. If includeFilePath is absolute, it is returned
238 unmodified.
239*/
240QString PortingRules::resolveFileName(const QString currentFilePath,
241 const QString includeFilePath) const
242{
243 if(QFileInfo(includeFilePath).isAbsolute())
244 return includeFilePath;
245 QString relativeDirectory = QFileInfo(currentFilePath).dir().dirName();
246 QString testFileName = relativeDirectory + QLatin1String("/") + includeFilePath;
247 if (QFile::exists(testFileName))
248 return testFileName;
249
250 return QString();
251}
252/*
253 Checks if a rule is a replacement rule.
254*/
255bool PortingRules::isReplacementRule(const QString ruleType) const
256{
257 return (ruleType == QLatin1String("RenamedHeader") || ruleType == QLatin1String("RenamedClass") ||
258 ruleType == QLatin1String("RenamedToken") || ruleType == QLatin1String("RenamedEnumvalue") ||
259 ruleType == QLatin1String("RenamedType") || ruleType == QLatin1String("RenamedQtSymbol") );
260}
261
262/*
263 Disables a replacement rule given by the replacementRule parameter
264*/
265void PortingRules::disableRule(QtSimpleXml &replacementRule)
266{
267 RuleDescription ruleDescription(replacementRule);
268 disabledRules.append(ruleDescription);
269}
270
271/*
272 Checks if a replacement rule is disabled or not
273*/
274bool PortingRules::isRuleDisabled(QtSimpleXml &replacementRule) const
275{
276 RuleDescription ruleDescription(replacementRule);
277 return disabledRules.contains(ruleDescription);
278}
279
280/*
281 Adds a warning to the global logger.
282*/
283void PortingRules::addLogWarning(const QString text) const
284{
285 Logger::instance()->addEntry(new PlainLogEntry(QLatin1String("Warning"), QLatin1String("Porting"), text));
286}
287
288/*
289 Adds an error to the global logger.
290*/
291void PortingRules::addLogError(const QString text) const
292{
293 Logger::instance()->addEntry(new PlainLogEntry(QLatin1String("Error"), QLatin1String("Porting"), text));
294}
295
296QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.