Mercurial > projects > qtd
comparison tools/duic/driver.cpp @ 1:e78566595089
initial import
author | mandel |
---|---|
date | Mon, 11 May 2009 16:01:50 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:36fb74dc547d | 1:e78566595089 |
---|---|
1 /**************************************************************************** | |
2 ** | |
3 ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). | |
4 ** Contact: Qt Software Information (qt-info@nokia.com) | |
5 ** | |
6 ** This file is part of the tools applications of the Qt Toolkit. | |
7 ** | |
8 ** Commercial Usage | |
9 ** Licensees holding valid Qt Commercial licenses may use this file in | |
10 ** accordance with the Qt Commercial License Agreement provided with the | |
11 ** Software or, alternatively, in accordance with the terms contained in | |
12 ** a written agreement between you and Nokia. | |
13 ** | |
14 ** | |
15 ** GNU General Public License Usage | |
16 ** Alternatively, this file may be used under the terms of the GNU | |
17 ** General Public License versions 2.0 or 3.0 as published by the Free | |
18 ** Software Foundation and appearing in the file LICENSE.GPL included in | |
19 ** the packaging of this file. Please review the following information | |
20 ** to ensure GNU General Public Licensing requirements will be met: | |
21 ** http://www.fsf.org/licensing/licenses/info/GPLv2.html and | |
22 ** http://www.gnu.org/copyleft/gpl.html. In addition, as a special | |
23 ** exception, Nokia gives you certain additional rights. These rights | |
24 ** are described in the Nokia Qt GPL Exception version 1.3, included in | |
25 ** the file GPL_EXCEPTION.txt in this package. | |
26 ** | |
27 ** Qt for Windows(R) Licensees | |
28 ** As a special exception, Nokia, as the sole copyright holder for Qt | |
29 ** Designer, grants users of the Qt/Eclipse Integration plug-in the | |
30 ** right for the Qt/Eclipse Integration to link to functionality | |
31 ** provided by Qt Designer and its related libraries. | |
32 ** | |
33 ** If you are unsure which license is appropriate for your use, please | |
34 ** contact the sales department at qt-sales@nokia.com. | |
35 ** | |
36 ****************************************************************************/ | |
37 | |
38 #include "driver.h" | |
39 #include "uic.h" | |
40 #include "ui4.h" | |
41 | |
42 #include <QtCore/QRegExp> | |
43 #include <QtCore/QFileInfo> | |
44 #include <QtCore/QDebug> | |
45 | |
46 QT_BEGIN_NAMESPACE | |
47 | |
48 Driver::Driver() | |
49 : m_stdout(stdout, QFile::WriteOnly | QFile::Text) | |
50 { | |
51 m_output = &m_stdout; | |
52 } | |
53 | |
54 Driver::~Driver() | |
55 { | |
56 } | |
57 | |
58 QString Driver::findOrInsertWidget(DomWidget *ui_widget) | |
59 { | |
60 if (!m_widgets.contains(ui_widget)) | |
61 m_widgets.insert(ui_widget, unique(ui_widget->attributeName(), ui_widget->attributeClass())); | |
62 | |
63 return m_widgets.value(ui_widget); | |
64 } | |
65 | |
66 QString Driver::findOrInsertSpacer(DomSpacer *ui_spacer) | |
67 { | |
68 if (!m_spacers.contains(ui_spacer)) { | |
69 const QString name = ui_spacer->hasAttributeName() ? ui_spacer->attributeName() : QString(); | |
70 m_spacers.insert(ui_spacer, unique(name, QLatin1String("QSpacerItem"))); | |
71 } | |
72 | |
73 return m_spacers.value(ui_spacer); | |
74 } | |
75 | |
76 QString Driver::findOrInsertLayout(DomLayout *ui_layout) | |
77 { | |
78 if (!m_layouts.contains(ui_layout)) { | |
79 const QString name = ui_layout->hasAttributeName() ? ui_layout->attributeName() : QString(); | |
80 m_layouts.insert(ui_layout, unique(name, ui_layout->attributeClass())); | |
81 } | |
82 | |
83 return m_layouts.value(ui_layout); | |
84 } | |
85 | |
86 QString Driver::findOrInsertLayoutItem(DomLayoutItem *ui_layoutItem) | |
87 { | |
88 switch (ui_layoutItem->kind()) { | |
89 case DomLayoutItem::Widget: | |
90 return findOrInsertWidget(ui_layoutItem->elementWidget()); | |
91 case DomLayoutItem::Spacer: | |
92 return findOrInsertSpacer(ui_layoutItem->elementSpacer()); | |
93 case DomLayoutItem::Layout: | |
94 return findOrInsertLayout(ui_layoutItem->elementLayout()); | |
95 case DomLayoutItem::Unknown: | |
96 break; | |
97 } | |
98 | |
99 Q_ASSERT( 0 ); | |
100 | |
101 return QString(); | |
102 } | |
103 | |
104 QString Driver::findOrInsertActionGroup(DomActionGroup *ui_group) | |
105 { | |
106 if (!m_actionGroups.contains(ui_group)) | |
107 m_actionGroups.insert(ui_group, unique(ui_group->attributeName(), QLatin1String("QActionGroup"))); | |
108 | |
109 return m_actionGroups.value(ui_group); | |
110 } | |
111 | |
112 QString Driver::findOrInsertAction(DomAction *ui_action) | |
113 { | |
114 if (!m_actions.contains(ui_action)) | |
115 m_actions.insert(ui_action, unique(ui_action->attributeName(), QLatin1String("QAction"))); | |
116 | |
117 return m_actions.value(ui_action); | |
118 } | |
119 | |
120 QString Driver::findOrInsertName(const QString &name) | |
121 { | |
122 return unique(name); | |
123 } | |
124 | |
125 QString Driver::normalizedName(const QString &name) | |
126 { | |
127 QString result = name; | |
128 result.replace(QRegExp(QLatin1String("[^a-zA-Z_0-9]")), QString(QLatin1Char('_'))); | |
129 return result; | |
130 } | |
131 | |
132 QString Driver::unique(const QString &instanceName, const QString &className) | |
133 { | |
134 QString name; | |
135 bool alreadyUsed = false; | |
136 | |
137 if (instanceName.size()) { | |
138 int id = 1; | |
139 name = instanceName; | |
140 name = normalizedName(name); | |
141 QString base = name; | |
142 | |
143 while (m_nameRepository.contains(name)) { | |
144 alreadyUsed = true; | |
145 name = base + QString::number(id++); | |
146 } | |
147 } else if (className.size()) { | |
148 name = unique(qtify(className)); | |
149 } else { | |
150 name = unique(QLatin1String("var")); | |
151 } | |
152 | |
153 if (alreadyUsed && className.size()) { | |
154 fprintf(stderr, "Warning: name %s is already used\n", qPrintable(instanceName)); | |
155 } | |
156 | |
157 m_nameRepository.insert(name, true); | |
158 return name; | |
159 } | |
160 | |
161 QString Driver::qtify(const QString &name) | |
162 { | |
163 QString qname = name; | |
164 | |
165 if (qname.at(0) == QLatin1Char('Q') || qname.at(0) == QLatin1Char('K')) | |
166 qname = qname.mid(1); | |
167 | |
168 int i=0; | |
169 while (i < qname.length()) { | |
170 if (qname.at(i).toLower() != qname.at(i)) | |
171 qname[i] = qname.at(i).toLower(); | |
172 else | |
173 break; | |
174 | |
175 ++i; | |
176 } | |
177 | |
178 return qname; | |
179 } | |
180 | |
181 static bool isAnsiCCharacter(const QChar& c) | |
182 { | |
183 return (c.toUpper() >= QLatin1Char('A') && c.toUpper() <= QLatin1Char('Z')) | |
184 || c.isDigit() || c == QLatin1Char('_'); | |
185 } | |
186 | |
187 QString Driver::headerFileName() const | |
188 { | |
189 QString name = m_option.outputFile; | |
190 | |
191 if (name.isEmpty()) { | |
192 name = QLatin1String("ui_"); // ### use ui_ as prefix. | |
193 name.append(m_option.inputFile); | |
194 } | |
195 | |
196 return headerFileName(name); | |
197 } | |
198 | |
199 QString Driver::headerFileName(const QString &fileName) | |
200 { | |
201 if (fileName.isEmpty()) | |
202 return headerFileName(QLatin1String("noname")); | |
203 | |
204 QFileInfo info(fileName); | |
205 QString baseName = info.baseName(); | |
206 // Transform into a valid C++ identifier | |
207 if (!baseName.isEmpty() && baseName.at(0).isDigit()) | |
208 baseName.prepend(QLatin1Char('_')); | |
209 for (int i = 0; i < baseName.size(); ++i) { | |
210 QChar c = baseName.at(i); | |
211 if (!isAnsiCCharacter(c)) { | |
212 // Replace character by its unicode value | |
213 QString hex = QString::number(c.unicode(), 16); | |
214 baseName.replace(i, 1, QLatin1Char('_') + hex + QLatin1Char('_')); | |
215 i += hex.size() + 1; | |
216 } | |
217 } | |
218 return baseName.toUpper() + QLatin1String("_H"); | |
219 } | |
220 | |
221 bool Driver::printDependencies(const QString &fileName) | |
222 { | |
223 Q_ASSERT(m_option.dependencies == true); | |
224 | |
225 m_option.inputFile = fileName; | |
226 | |
227 Uic tool(this); | |
228 return tool.printDependencies(); | |
229 } | |
230 | |
231 bool Driver::uic(const QString &fileName, DomUI *ui, QTextStream *out) | |
232 { | |
233 m_option.inputFile = fileName; | |
234 | |
235 QTextStream *oldOutput = m_output; | |
236 | |
237 m_output = out != 0 ? out : &m_stdout; | |
238 | |
239 Uic tool(this); | |
240 bool rtn = false; | |
241 #ifdef QT_UIC_D_GENERATOR | |
242 rtn = tool.write(ui); | |
243 #else | |
244 Q_UNUSED(ui); | |
245 fprintf(stderr, "uic: option to generate d code not compiled in [%s:%d]\n", | |
246 __FILE__, __LINE__); | |
247 #endif | |
248 | |
249 m_output = oldOutput; | |
250 | |
251 return rtn; | |
252 } | |
253 | |
254 bool Driver::uic(const QString &fileName, QTextStream *out) | |
255 { | |
256 QFile f; | |
257 if (fileName.isEmpty()) | |
258 f.open(stdin, QIODevice::ReadOnly); | |
259 else { | |
260 f.setFileName(fileName); | |
261 if (!f.open(QIODevice::ReadOnly)) | |
262 return false; | |
263 } | |
264 | |
265 m_option.inputFile = fileName; | |
266 | |
267 QTextStream *oldOutput = m_output; | |
268 bool deleteOutput = false; | |
269 | |
270 if (out) { | |
271 m_output = out; | |
272 } else { | |
273 #ifdef Q_WS_WIN | |
274 // As one might also redirect the output to a file on win, | |
275 // we should not create the textstream with QFile::Text flag. | |
276 // The redirected file is opened in TextMode and this will | |
277 // result in broken line endings as writing will replace \n again. | |
278 m_output = new QTextStream(stdout, QIODevice::WriteOnly); | |
279 #else | |
280 m_output = new QTextStream(stdout, QIODevice::WriteOnly | QFile::Text); | |
281 #endif | |
282 deleteOutput = true; | |
283 } | |
284 | |
285 Uic tool(this); | |
286 bool rtn = tool.write(&f); | |
287 f.close(); | |
288 | |
289 if (deleteOutput) | |
290 delete m_output; | |
291 | |
292 m_output = oldOutput; | |
293 | |
294 return rtn; | |
295 } | |
296 | |
297 void Driver::reset() | |
298 { | |
299 Q_ASSERT( m_output == 0 ); | |
300 | |
301 m_option = Option(); | |
302 m_output = 0; | |
303 m_problems.clear(); | |
304 | |
305 QStringList m_problems; | |
306 | |
307 m_widgets.clear(); | |
308 m_spacers.clear(); | |
309 m_layouts.clear(); | |
310 m_actionGroups.clear(); | |
311 m_actions.clear(); | |
312 m_nameRepository.clear(); | |
313 m_pixmaps.clear(); | |
314 } | |
315 | |
316 void Driver::insertPixmap(const QString &pixmap) | |
317 { | |
318 m_pixmaps.insert(pixmap, true); | |
319 } | |
320 | |
321 bool Driver::containsPixmap(const QString &pixmap) const | |
322 { | |
323 return m_pixmaps.contains(pixmap); | |
324 } | |
325 | |
326 DomWidget *Driver::widgetByName(const QString &name) const | |
327 { | |
328 return m_widgets.key(name); | |
329 } | |
330 | |
331 DomSpacer *Driver::spacerByName(const QString &name) const | |
332 { | |
333 return m_spacers.key(name); | |
334 } | |
335 | |
336 DomLayout *Driver::layoutByName(const QString &name) const | |
337 { | |
338 return m_layouts.key(name); | |
339 } | |
340 | |
341 DomActionGroup *Driver::actionGroupByName(const QString &name) const | |
342 { | |
343 return m_actionGroups.key(name); | |
344 } | |
345 | |
346 DomAction *Driver::actionByName(const QString &name) const | |
347 { | |
348 return m_actions.key(name); | |
349 } | |
350 | |
351 QT_END_NAMESPACE |