comparison base/ResourceFinder.cpp @ 742:c10cb8782576 coreaudio_tests

Merge from branch "default"
author Chris Cannam
date Sun, 01 Jul 2012 11:53:00 +0100
parents 66c3f4e060e9
children e802e550a1f2
comparison
equal deleted inserted replaced
666:4efa7429cd85 742:c10cb8782576
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Sonic Visualiser
5 An audio file viewer and annotation editor.
6 Centre for Digital Music, Queen Mary, University of London.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version. See the file
12 COPYING included with this distribution for more information.
13 */
14
15 /*
16 This is a modified version of a source file from the
17 Rosegarden MIDI and audio sequencer and notation editor.
18 This file copyright 2005-2011 Chris Cannam and the Rosegarden
19 development team.
20 */
21
22 #include "ResourceFinder.h"
23
24 #include <QDir>
25 #include <QFileInfo>
26 #include <QStringList>
27 #include <QProcess>
28 #include <QCoreApplication>
29
30 #include <cstdlib>
31 #include <iostream>
32
33 /**
34 Resource files may be found in three places:
35
36 * Bundled into the application as Qt4 resources. These may be
37 opened using Qt classes such as QFile, with "fake" file paths
38 starting with a colon. For example ":icons/fileopen.png".
39
40 * Installed with the package, or in the user's equivalent home
41 directory location. For example,
42
43 - on Linux, in /usr/share/<appname> or /usr/local/share/<appname>
44 - on Linux, in $HOME/.local/share/<appname>
45
46 - on OS/X, in /Library/Application Support/<appname>
47 - on OS/X, in $HOME/Library/Application Support/<appname>
48
49 - on Windows, in %ProgramFiles%/<company>/<appname>
50 - on Windows, in (where?) something from http://msdn.microsoft.com/en-us/library/dd378457%28v=vs.85%29.aspx ?
51
52 These locations are searched in reverse order (user-installed
53 copies take priority over system-installed copies take priority
54 over bundled copies). Also, /usr/local takes priority over /usr.
55 */
56
57 QStringList
58 ResourceFinder::getSystemResourcePrefixList()
59 {
60 // returned in order of priority
61
62 QStringList list;
63
64 #ifdef Q_OS_WIN32
65 char *programFiles = getenv("ProgramFiles");
66 if (programFiles && programFiles[0]) {
67 list << QString("%1/%2/%3")
68 .arg(programFiles)
69 .arg(qApp->organizationName())
70 .arg(qApp->applicationName());
71 } else {
72 list << QString("C:/Program Files/%1/%2")
73 .arg(qApp->organizationName())
74 .arg(qApp->applicationName());
75 }
76 #else
77 #ifdef Q_OS_MAC
78 list << QString("/Library/Application Support/%1")
79 .arg(qApp->applicationName());
80 #else
81 list << QString("/usr/local/share/%1")
82 .arg(qApp->applicationName());
83 list << QString("/usr/share/%1")
84 .arg(qApp->applicationName());
85 #endif
86 #endif
87
88 return list;
89 }
90
91 QString
92 ResourceFinder::getUserResourcePrefix()
93 {
94 #ifdef Q_OS_WIN32
95 char *homedrive = getenv("HOMEDRIVE");
96 char *homepath = getenv("HOMEPATH");
97 QString home;
98 if (homedrive && homepath) {
99 home = QString("%1%2").arg(homedrive).arg(homepath);
100 } else {
101 home = QDir::home().absolutePath();
102 }
103 if (home == "") return "";
104 return QString("%1/.%2").arg(home).arg(qApp->applicationName()); //!!! wrong
105 #else
106 char *home = getenv("HOME");
107 if (!home || !home[0]) return "";
108 #ifdef Q_OS_MAC
109 return QString("%1/Library/Application Support/%2")
110 .arg(home)
111 .arg(qApp->applicationName());
112 #else
113 return QString("%1/.local/share/%2")
114 .arg(home)
115 .arg(qApp->applicationName());
116 #endif
117 #endif
118 }
119
120 QStringList
121 ResourceFinder::getResourcePrefixList()
122 {
123 // returned in order of priority
124
125 QStringList list;
126
127 QString user = getUserResourcePrefix();
128 if (user != "") list << user;
129
130 list << getSystemResourcePrefixList();
131
132 list << ":"; // bundled resource location
133
134 return list;
135 }
136
137 QString
138 ResourceFinder::getResourcePath(QString resourceCat, QString fileName)
139 {
140 // We don't simply call getResourceDir here, because that returns
141 // only the "installed file" location. We also want to search the
142 // bundled resources and user-saved files.
143
144 QStringList prefixes = getResourcePrefixList();
145
146 if (resourceCat != "") resourceCat = "/" + resourceCat;
147
148 for (QStringList::const_iterator i = prefixes.begin();
149 i != prefixes.end(); ++i) {
150
151 QString prefix = *i;
152
153 SVDEBUG << "ResourceFinder::getResourcePath: Looking up file \"" << fileName << "\" for category \"" << resourceCat << "\" in prefix \"" << prefix << "\"" << endl;
154
155 QString path =
156 QString("%1%2/%3").arg(prefix).arg(resourceCat).arg(fileName);
157 if (QFileInfo(path).exists() && QFileInfo(path).isReadable()) {
158 std::cerr << "Found it!" << std::endl;
159 return path;
160 }
161 }
162
163 return "";
164 }
165
166 QString
167 ResourceFinder::getResourceDir(QString resourceCat)
168 {
169 // Returns only the "installed file" location
170
171 QStringList prefixes = getSystemResourcePrefixList();
172
173 if (resourceCat != "") resourceCat = "/" + resourceCat;
174
175 for (QStringList::const_iterator i = prefixes.begin();
176 i != prefixes.end(); ++i) {
177
178 QString prefix = *i;
179 QString path = QString("%1%2").arg(prefix).arg(resourceCat);
180 if (QFileInfo(path).exists() &&
181 QFileInfo(path).isDir() &&
182 QFileInfo(path).isReadable()) {
183 return path;
184 }
185 }
186
187 return "";
188 }
189
190 QString
191 ResourceFinder::getResourceSavePath(QString resourceCat, QString fileName)
192 {
193 QString dir = getResourceSaveDir(resourceCat);
194 if (dir == "") return "";
195
196 return dir + "/" + fileName;
197 }
198
199 QString
200 ResourceFinder::getResourceSaveDir(QString resourceCat)
201 {
202 // Returns the "user" location
203
204 QString user = getUserResourcePrefix();
205 if (user == "") return "";
206
207 if (resourceCat != "") resourceCat = "/" + resourceCat;
208
209 QDir userDir(user);
210 if (!userDir.exists()) {
211 if (!userDir.mkpath(user)) {
212 std::cerr << "ResourceFinder::getResourceSaveDir: ERROR: Failed to create user resource path \"" << user << "\"" << std::endl;
213 return "";
214 }
215 }
216
217 if (resourceCat != "") {
218 QString save = QString("%1%2").arg(user).arg(resourceCat);
219 QDir saveDir(save);
220 if (!saveDir.exists()) {
221 if (!userDir.mkpath(save)) {
222 std::cerr << "ResourceFinder::getResourceSaveDir: ERROR: Failed to create user resource path \"" << save << "\"" << std::endl;
223 return "";
224 }
225 }
226 return save;
227 } else {
228 return user;
229 }
230 }
231
232 QStringList
233 ResourceFinder::getResourceFiles(QString resourceCat, QString fileExt)
234 {
235 QStringList results;
236 QStringList prefixes = getResourcePrefixList();
237
238 QStringList filters;
239 filters << QString("*.%1").arg(fileExt);
240
241 for (QStringList::const_iterator i = prefixes.begin();
242 i != prefixes.end(); ++i) {
243
244 QString prefix = *i;
245 QString path;
246
247 if (resourceCat != "") {
248 path = QString("%1/%2").arg(prefix).arg(resourceCat);
249 } else {
250 path = prefix;
251 }
252
253 QDir dir(path);
254 if (!dir.exists()) continue;
255
256 dir.setNameFilters(filters);
257 QStringList entries = dir.entryList
258 (QDir::Files | QDir::Readable, QDir::Name);
259
260 for (QStringList::const_iterator j = entries.begin();
261 j != entries.end(); ++j) {
262 results << QString("%1/%2").arg(path).arg(*j);
263 }
264 }
265
266 return results;
267 }
268
269 bool
270 ResourceFinder::unbundleResource(QString resourceCat, QString fileName)
271 {
272 QString path = getResourcePath(resourceCat, fileName);
273
274 if (!path.startsWith(':')) return true;
275
276 // This is the lowest-priority alternative path for this
277 // resource, so we know that there must be no installed copy.
278 // Install one to the user location.
279 SVDEBUG << "ResourceFinder::unbundleResource: File " << fileName << " is bundled, un-bundling it" << endl;
280 QString target = getResourceSavePath(resourceCat, fileName);
281 QFile file(path);
282 if (!file.copy(target)) {
283 std::cerr << "ResourceFinder::unbundleResource: ERROR: Failed to un-bundle resource file \"" << fileName << "\" to user location \"" << target << "\"" << std::endl;
284 return false;
285 }
286
287 QFile chmod(target);
288 chmod.setPermissions(QFile::ReadOwner |
289 QFile::ReadUser | /* for potential platform-independence */
290 QFile::ReadGroup |
291 QFile::ReadOther |
292 QFile::WriteOwner|
293 QFile::WriteUser); /* for potential platform-independence */
294
295 return true;
296 }
297