57
|
1 /****************************************************************************
|
|
2 **
|
|
3 ** Copyright (C) 2009 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 ** $QT_BEGIN_LICENSE:LGPL$
|
|
9 ** Commercial Usage
|
|
10 ** Licensees holding valid Qt Commercial licenses may use this file in
|
|
11 ** accordance with the Qt Commercial License Agreement provided with the
|
|
12 ** Software or, alternatively, in accordance with the terms contained in
|
|
13 ** a written agreement between you and Nokia.
|
|
14 **
|
|
15 ** GNU Lesser General Public License Usage
|
|
16 ** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
17 ** General Public License version 2.1 as published by the Free Software
|
|
18 ** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
19 ** packaging of this file. Please review the following information to
|
|
20 ** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
21 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
22 **
|
|
23 ** In addition, as a special exception, Nokia gives you certain
|
|
24 ** additional rights. These rights are described in the Nokia Qt LGPL
|
|
25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
|
|
26 ** 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 are unsure which license is appropriate for your use, please
|
|
37 ** contact the sales department at qt-sales@nokia.com.
|
|
38 ** $QT_END_LICENSE$
|
|
39 **
|
|
40 ****************************************************************************/
|
|
41
|
|
42 #include "rcc.h"
|
|
43 #include "qcorecmdlineargs_p.h"
|
|
44
|
|
45 #include <QDebug>
|
|
46 #include <QDir>
|
|
47 #include <QFile>
|
|
48 #include <QFileInfo>
|
|
49 #include <QTextStream>
|
|
50
|
|
51 QT_BEGIN_NAMESPACE
|
|
52
|
|
53 void showHelp(const QString &argv0, const QString &error)
|
|
54 {
|
|
55 fprintf(stderr, "Qt resource compiler\n");
|
|
56 if (!error.isEmpty())
|
|
57 fprintf(stderr, "%s: %s\n", qPrintable(argv0), qPrintable(error));
|
|
58 fprintf(stderr, "Usage: %s [options] <inputs>\n\n"
|
|
59 "Options:\n"
|
|
60 " -o file write output to file rather than stdout\n"
|
|
61 " -name name create an external initialization function with name\n"
|
|
62 " -threshold level threshold to consider compressing files\n"
|
|
63 " -compress level compress input files by level\n"
|
|
64 " -root path prefix resource access path with root path\n"
|
|
65 " -no-compress disable all compression\n"
|
|
66 " -binary output a binary file for use as a dynamic resource\n"
|
|
67 " -namespace turn off namespace macros\n"
|
|
68 " -project Output a resource file containing all\n"
|
|
69 " files from the current directory\n"
|
|
70 " -version display version\n"
|
|
71 " -help display this information\n",
|
|
72 qPrintable(argv0));
|
|
73 }
|
|
74
|
|
75 void dumpRecursive(const QDir &dir, QTextStream &out)
|
|
76 {
|
|
77 QFileInfoList entries = dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot
|
|
78 | QDir::NoSymLinks);
|
|
79 foreach (QFileInfo entry, entries) {
|
|
80 if (entry.isDir()) {
|
|
81 dumpRecursive(entry.filePath(), out);
|
|
82 } else {
|
|
83 out << QLatin1String("<file>")
|
|
84 << entry.filePath()
|
|
85 << QLatin1String("</file>\n");
|
|
86 }
|
|
87 }
|
|
88 }
|
|
89
|
|
90 int createProject(const QString &outFileName)
|
|
91 {
|
|
92 QDir currentDir = QDir::current();
|
|
93 QString currentDirName = currentDir.dirName();
|
|
94 if (currentDirName.isEmpty())
|
|
95 currentDirName = QLatin1String("root");
|
|
96
|
|
97 QFile file;
|
|
98 bool isOk = false;
|
|
99 if (outFileName.isEmpty()) {
|
|
100 isOk = file.open(stdout, QFile::WriteOnly | QFile::Text);
|
|
101 } else {
|
|
102 file.setFileName(outFileName);
|
|
103 isOk = file.open(QFile::WriteOnly | QFile::Text);
|
|
104 }
|
|
105 if (!isOk) {
|
|
106 fprintf(stderr, "Unable to open %s: %s\n",
|
|
107 outFileName.isEmpty() ? qPrintable(outFileName) : "standard output",
|
|
108 qPrintable(file.errorString()));
|
|
109 return 1;
|
|
110 }
|
|
111
|
|
112 QTextStream out(&file);
|
|
113 out << QLatin1String("<!DOCTYPE RCC><RCC version=\"1.0\">\n"
|
|
114 "<qresource>\n");
|
|
115
|
|
116 // use "." as dir to get relative file pathes
|
|
117 dumpRecursive(QDir(QLatin1String(".")), out);
|
|
118
|
|
119 out << QLatin1String("</qresource>\n"
|
|
120 "</RCC>\n");
|
|
121
|
|
122 return 0;
|
|
123 }
|
|
124
|
|
125 int runRcc(int argc, char *argv[])
|
|
126 {
|
|
127 QString outFilename;
|
|
128 bool helpRequested = false;
|
|
129 bool list = false;
|
|
130 bool projectRequested = false;
|
|
131 QStringList filenamesIn;
|
|
132
|
|
133 QStringList args = qCmdLineArgs(argc, argv);
|
|
134
|
|
135 RCCResourceLibrary library;
|
|
136
|
|
137 //parse options
|
|
138 QString errorMsg;
|
|
139 for (int i = 1; i < args.count() && errorMsg.isEmpty(); i++) {
|
|
140 if (args[i].isEmpty())
|
|
141 continue;
|
|
142 if (args[i][0] == QLatin1Char('-')) { // option
|
|
143 QString opt = args[i];
|
|
144 if (opt == QLatin1String("-o")) {
|
|
145 if (!(i < argc-1)) {
|
|
146 errorMsg = QLatin1String("Missing output name");
|
|
147 break;
|
|
148 }
|
|
149 outFilename = args[++i];
|
|
150 } else if (opt == QLatin1String("-name")) {
|
|
151 if (!(i < argc-1)) {
|
|
152 errorMsg = QLatin1String("Missing target name");
|
|
153 break;
|
|
154 }
|
|
155 library.setInitName(args[++i]);
|
|
156 } else if (opt == QLatin1String("-root")) {
|
|
157 if (!(i < argc-1)) {
|
|
158 errorMsg = QLatin1String("Missing root path");
|
|
159 break;
|
|
160 }
|
|
161 library.setResourceRoot(QDir::cleanPath(args[++i]));
|
|
162 if (library.resourceRoot().isEmpty()
|
|
163 || library.resourceRoot().at(0) != QLatin1Char('/'))
|
|
164 errorMsg = QLatin1String("Root must start with a /");
|
|
165 } else if (opt == QLatin1String("-compress")) {
|
|
166 if (!(i < argc-1)) {
|
|
167 errorMsg = QLatin1String("Missing compression level");
|
|
168 break;
|
|
169 }
|
|
170 library.setCompressLevel(args[++i].toInt());
|
|
171 } else if (opt == QLatin1String("-threshold")) {
|
|
172 if (!(i < argc-1)) {
|
|
173 errorMsg = QLatin1String("Missing compression threshold");
|
|
174 break;
|
|
175 }
|
|
176 library.setCompressThreshold(args[++i].toInt());
|
|
177 } else if (opt == QLatin1String("-binary")) {
|
|
178 library.setFormat(RCCResourceLibrary::Binary);
|
|
179 } else if (opt == QLatin1String("-namespace")) {
|
|
180 // library.setUseNameSpace(!library.useNameSpace());
|
|
181 library.setUseNameSpace(false);
|
|
182 } else if (opt == QLatin1String("-verbose")) {
|
|
183 library.setVerbose(true);
|
|
184 } else if (opt == QLatin1String("-list")) {
|
|
185 list = true;
|
|
186 } else if (opt == QLatin1String("-version") || opt == QLatin1String("-v")) {
|
|
187 fprintf(stderr, "Qt Resource Compiler version %s\n", QT_VERSION_STR);
|
|
188 return 1;
|
|
189 } else if (opt == QLatin1String("-help") || opt == QLatin1String("-h")) {
|
|
190 helpRequested = true;
|
|
191 } else if (opt == QLatin1String("-no-compress")) {
|
|
192 library.setCompressLevel(-2);
|
|
193 } else if (opt == QLatin1String("-project")) {
|
|
194 projectRequested = true;
|
|
195 } else {
|
|
196 errorMsg = QString::fromLatin1("Unknown option: '%1'").arg(args[i]);
|
|
197 }
|
|
198 } else {
|
|
199 if (!QFile::exists(args[i])) {
|
|
200 qWarning("%s: File does not exist '%s'",
|
|
201 qPrintable(args[0]), qPrintable(args[i]));
|
|
202 return 1;
|
|
203 }
|
|
204 filenamesIn.append(args[i]);
|
|
205 }
|
|
206 }
|
|
207
|
|
208 if (projectRequested && !helpRequested) {
|
|
209 return createProject(outFilename);
|
|
210 }
|
|
211
|
|
212 if (!filenamesIn.size() || !errorMsg.isEmpty() || helpRequested) {
|
|
213 showHelp(args[0], errorMsg);
|
|
214 return 1;
|
|
215 }
|
|
216 QFile errorDevice;
|
|
217 errorDevice.open(stderr, QIODevice::WriteOnly|QIODevice::Text);
|
|
218
|
|
219 if (library.verbose())
|
|
220 errorDevice.write("Qt resource compiler\n");
|
|
221
|
|
222 library.setInputFiles(filenamesIn);
|
|
223
|
|
224 if (!library.readFiles(list, errorDevice))
|
|
225 return 1;
|
|
226
|
|
227 // open output
|
|
228 QFile out;
|
|
229 QIODevice::OpenMode mode = QIODevice::WriteOnly;
|
|
230 if (library.format() == RCCResourceLibrary::C_Code)
|
|
231 mode |= QIODevice::Text;
|
|
232
|
|
233 if (outFilename.isEmpty() || outFilename == QLatin1String("-")) {
|
|
234 // using this overload close() only flushes.
|
|
235 out.open(stdout, mode);
|
|
236 } else {
|
|
237 out.setFileName(outFilename);
|
|
238 if (!out.open(mode)) {
|
|
239 const QString msg = QString::fromUtf8("Unable to open %1 for writing: %2\n").arg(outFilename).arg(out.errorString());
|
|
240 errorDevice.write(msg.toUtf8());
|
|
241 return 1;
|
|
242 }
|
|
243 }
|
|
244
|
|
245 // do the task
|
|
246 if (list) {
|
|
247 const QStringList data = library.dataFiles();
|
|
248 for (int i = 0; i < data.size(); ++i) {
|
|
249 out.write(qPrintable(QDir::cleanPath(data.at(i))));
|
|
250 out.write("\n");
|
|
251 }
|
|
252 return 0;
|
|
253 }
|
|
254
|
|
255 return library.output(out, errorDevice) ? 0 : 1;
|
|
256 }
|
|
257
|
|
258 QT_END_NAMESPACE
|
|
259
|
|
260 int main(int argc, char *argv[])
|
|
261 {
|
|
262 return QT_PREPEND_NAMESPACE(runRcc)(argc, argv);
|
|
263 }
|