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