Mercurial > hg > svcore
comparison data/fileio/RemoteFile.cpp @ 211:e2bbb58e6df6
Several changes related to referring to remote URLs for sessions and files:
* Pull file dialog wrapper functions out from MainWindow into FileFinder
* If a file referred to in a session is not found at its expected location,
try a few other alternatives (same location as the session file or same
location as the last audio file) before asking the user to locate it
* Allow user to give a URL when locating an audio file, not just locate on
the filesystem
* Make wave file models remember the "original" location (e.g. URL) of
the audio file, not just the actual location from which the data was
loaded (e.g. local copy of that URL) -- when saving a session, use the
original location so as not to refer to a temporary file
* Clean up incompletely-downloaded local copies of files
author | Chris Cannam |
---|---|
date | Thu, 11 Jan 2007 13:29:58 +0000 |
parents | a06afefe45ee |
children | ce6f65ab3327 |
comparison
equal
deleted
inserted
replaced
210:a06afefe45ee | 211:e2bbb58e6df6 |
---|---|
55 | 55 |
56 QString scheme = url.scheme().toLower(); | 56 QString scheme = url.scheme().toLower(); |
57 | 57 |
58 if (scheme == "http") { | 58 if (scheme == "http") { |
59 | 59 |
60 m_ok = true; | |
60 m_http = new QHttp(url.host(), url.port(80)); | 61 m_http = new QHttp(url.host(), url.port(80)); |
61 connect(m_http, SIGNAL(done(bool)), this, SLOT(done(bool))); | 62 connect(m_http, SIGNAL(done(bool)), this, SLOT(done(bool))); |
62 connect(m_http, SIGNAL(dataReadProgress(int, int)), | 63 connect(m_http, SIGNAL(dataReadProgress(int, int)), |
63 this, SLOT(dataReadProgress(int, int))); | 64 this, SLOT(dataReadProgress(int, int))); |
64 connect(m_http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)), | 65 connect(m_http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)), |
65 this, SLOT(responseHeaderReceived(const QHttpResponseHeader &))); | 66 this, SLOT(responseHeaderReceived(const QHttpResponseHeader &))); |
66 m_http->get(url.path(), m_localFile); | 67 m_http->get(url.path(), m_localFile); |
68 | |
69 } else if (scheme == "ftp") { | |
70 | |
67 m_ok = true; | 71 m_ok = true; |
68 | |
69 } else if (scheme == "ftp") { | |
70 | |
71 m_ftp = new QFtp; | 72 m_ftp = new QFtp; |
72 connect(m_ftp, SIGNAL(done(bool)), this, SLOT(done(bool))); | 73 connect(m_ftp, SIGNAL(done(bool)), this, SLOT(done(bool))); |
73 connect(m_ftp, SIGNAL(dataTransferProgress(qint64, qint64)), | 74 connect(m_ftp, SIGNAL(dataTransferProgress(qint64, qint64)), |
74 this, SLOT(dataTransferProgress(qint64, qint64))); | 75 this, SLOT(dataTransferProgress(qint64, qint64))); |
75 m_ftp->connectToHost(url.host(), url.port(21)); | 76 m_ftp->connectToHost(url.host(), url.port(21)); |
92 m_ftp->cd(*i); | 93 m_ftp->cd(*i); |
93 } else { | 94 } else { |
94 m_ftp->get(*i, m_localFile); | 95 m_ftp->get(*i, m_localFile); |
95 } | 96 } |
96 } | 97 } |
97 | |
98 m_ok = true; | |
99 } | 98 } |
100 | 99 |
101 if (m_ok) { | 100 if (m_ok) { |
102 m_progressDialog = new QProgressDialog(tr("Downloading %1...").arg(url.toString()), tr("Cancel"), 0, 100); | 101 m_progressDialog = new QProgressDialog(tr("Downloading %1...").arg(url.toString()), tr("Cancel"), 0, 100); |
103 m_progressDialog->hide(); | 102 m_progressDialog->hide(); |
109 } | 108 } |
110 } | 109 } |
111 | 110 |
112 RemoteFile::~RemoteFile() | 111 RemoteFile::~RemoteFile() |
113 { | 112 { |
114 delete m_ftp; | 113 cleanup(); |
115 delete m_http; | 114 } |
116 delete m_localFile; | 115 |
117 delete m_progressDialog; | 116 void |
118 } | 117 RemoteFile::cleanup() |
119 | 118 { |
120 bool | 119 // std::cerr << "RemoteFile::cleanup" << std::endl; |
121 RemoteFile::canHandleScheme(QUrl url) | 120 m_done = true; |
122 { | |
123 QString scheme = url.scheme().toLower(); | |
124 return (scheme == "http" || scheme == "ftp"); | |
125 } | |
126 | |
127 bool | |
128 RemoteFile::isAvailable() | |
129 { | |
130 while (!m_done && m_lastStatus == 0) { | |
131 QApplication::processEvents(); | |
132 } | |
133 return (m_lastStatus / 100 == 2); | |
134 } | |
135 | |
136 void | |
137 RemoteFile::wait() | |
138 { | |
139 while (!m_done) { | |
140 QApplication::processEvents(); | |
141 } | |
142 } | |
143 | |
144 bool | |
145 RemoteFile::isOK() const | |
146 { | |
147 return m_ok; | |
148 } | |
149 | |
150 bool | |
151 RemoteFile::isDone() const | |
152 { | |
153 return m_done; | |
154 } | |
155 | |
156 QString | |
157 RemoteFile::getLocalFilename() const | |
158 { | |
159 return m_localFilename; | |
160 } | |
161 | |
162 QString | |
163 RemoteFile::getErrorString() const | |
164 { | |
165 return m_errorString; | |
166 } | |
167 | |
168 void | |
169 RemoteFile::dataReadProgress(int done, int total) | |
170 { | |
171 dataTransferProgress(done, total); | |
172 } | |
173 | |
174 void | |
175 RemoteFile::responseHeaderReceived(const QHttpResponseHeader &resp) | |
176 { | |
177 m_lastStatus = resp.statusCode(); | |
178 if (m_lastStatus / 100 >= 4) { | |
179 m_errorString = QString("%1 %2") | |
180 .arg(resp.statusCode()).arg(resp.reasonPhrase()); | |
181 } | |
182 } | |
183 | |
184 void | |
185 RemoteFile::dataTransferProgress(qint64 done, qint64 total) | |
186 { | |
187 int percent = int((double(done) / double(total)) * 100.0 - 0.1); | |
188 emit progress(percent); | |
189 | |
190 m_progressDialog->setValue(percent); | |
191 m_progressDialog->show(); | |
192 } | |
193 | |
194 void | |
195 RemoteFile::cancelled() | |
196 { | |
197 delete m_http; | 121 delete m_http; |
198 m_http = 0; | 122 m_http = 0; |
199 delete m_ftp; | 123 delete m_ftp; |
200 m_ftp = 0; | 124 m_ftp = 0; |
201 delete m_progressDialog; | 125 delete m_progressDialog; |
202 m_progressDialog = 0; | 126 m_progressDialog = 0; |
203 delete m_localFile; | 127 delete m_localFile; |
204 m_localFile = 0; | 128 m_localFile = 0; |
129 } | |
130 | |
131 bool | |
132 RemoteFile::canHandleScheme(QUrl url) | |
133 { | |
134 QString scheme = url.scheme().toLower(); | |
135 return (scheme == "http" || scheme == "ftp"); | |
136 } | |
137 | |
138 bool | |
139 RemoteFile::isAvailable() | |
140 { | |
141 while (m_ok && (!m_done && m_lastStatus == 0)) { | |
142 QApplication::processEvents(); | |
143 } | |
144 bool available = true; | |
145 if (!m_ok) available = false; | |
146 else available = (m_lastStatus / 100 == 2); | |
147 std::cerr << "RemoteFile::isAvailable: " << (available ? "yes" : "no") | |
148 << std::endl; | |
149 return available; | |
150 } | |
151 | |
152 void | |
153 RemoteFile::wait() | |
154 { | |
155 while (m_ok && !m_done) { | |
156 QApplication::processEvents(); | |
157 } | |
158 } | |
159 | |
160 bool | |
161 RemoteFile::isOK() const | |
162 { | |
163 return m_ok; | |
164 } | |
165 | |
166 bool | |
167 RemoteFile::isDone() const | |
168 { | |
169 return m_done; | |
170 } | |
171 | |
172 QString | |
173 RemoteFile::getLocalFilename() const | |
174 { | |
175 return m_localFilename; | |
176 } | |
177 | |
178 QString | |
179 RemoteFile::getErrorString() const | |
180 { | |
181 return m_errorString; | |
182 } | |
183 | |
184 void | |
185 RemoteFile::dataReadProgress(int done, int total) | |
186 { | |
187 dataTransferProgress(done, total); | |
188 } | |
189 | |
190 void | |
191 RemoteFile::responseHeaderReceived(const QHttpResponseHeader &resp) | |
192 { | |
193 m_lastStatus = resp.statusCode(); | |
194 if (m_lastStatus / 100 >= 4) { | |
195 m_errorString = QString("%1 %2") | |
196 .arg(resp.statusCode()).arg(resp.reasonPhrase()); | |
197 std::cerr << "RemoteFile::responseHeaderReceived: " | |
198 << m_errorString.toStdString() << std::endl; | |
199 } else { | |
200 std::cerr << "RemoteFile::responseHeaderReceived: " | |
201 << m_lastStatus << std::endl; | |
202 } | |
203 } | |
204 | |
205 void | |
206 RemoteFile::dataTransferProgress(qint64 done, qint64 total) | |
207 { | |
208 if (!m_progressDialog) return; | |
209 | |
210 int percent = int((double(done) / double(total)) * 100.0 - 0.1); | |
211 emit progress(percent); | |
212 | |
213 if (percent > 0) { | |
214 m_progressDialog->setValue(percent); | |
215 m_progressDialog->show(); | |
216 } | |
217 } | |
218 | |
219 void | |
220 RemoteFile::cancelled() | |
221 { | |
222 deleteLocalFile(); | |
205 m_done = true; | 223 m_done = true; |
206 m_ok = false; | 224 m_ok = false; |
207 m_errorString = tr("Download cancelled"); | 225 m_errorString = tr("Download cancelled"); |
208 } | 226 } |
209 | 227 |
210 void | 228 void |
211 RemoteFile::done(bool error) | 229 RemoteFile::done(bool error) |
212 { | 230 { |
231 // std::cerr << "RemoteFile::done(" << error << ")" << std::endl; | |
232 | |
233 if (m_done) return; | |
234 | |
213 emit progress(100); | 235 emit progress(100); |
214 m_ok = !error; | |
215 | 236 |
216 if (error) { | 237 if (error) { |
217 if (m_http) { | 238 if (m_http) { |
218 m_errorString = m_http->errorString(); | 239 m_errorString = m_http->errorString(); |
219 } else if (m_ftp) { | 240 } else if (m_ftp) { |
220 m_errorString = m_ftp->errorString(); | 241 m_errorString = m_ftp->errorString(); |
221 } | 242 } |
222 } | 243 } |
223 | 244 |
224 if (m_lastStatus / 100 >= 4) { | 245 if (m_lastStatus / 100 >= 4) { |
225 m_ok = false; | 246 error = true; |
226 } | 247 } |
227 | 248 |
228 delete m_localFile; | 249 cleanup(); |
229 m_localFile = 0; | 250 |
230 | 251 if (!error) { |
231 delete m_progressDialog; | |
232 m_progressDialog = 0; | |
233 | |
234 if (m_ok) { | |
235 QFileInfo fi(m_localFilename); | 252 QFileInfo fi(m_localFilename); |
236 if (!fi.exists()) { | 253 if (!fi.exists()) { |
237 m_errorString = tr("Failed to create local file %1").arg(m_localFilename); | 254 m_errorString = tr("Failed to create local file %1").arg(m_localFilename); |
238 m_ok = false; | 255 error = true; |
239 } else if (fi.size() == 0) { | 256 } else if (fi.size() == 0) { |
240 m_errorString = tr("File contains no data!"); | 257 m_errorString = tr("File contains no data!"); |
241 m_ok = false; | 258 error = true; |
242 } | 259 } |
243 } | 260 } |
261 | |
262 if (error) { | |
263 deleteLocalFile(); | |
264 } | |
265 | |
266 m_ok = !error; | |
267 m_done = true; | |
268 } | |
269 | |
270 void | |
271 RemoteFile::deleteLocalFile() | |
272 { | |
273 // std::cerr << "RemoteFile::deleteLocalFile" << std::endl; | |
274 | |
275 cleanup(); | |
276 | |
277 if (m_localFilename == "") return; | |
278 | |
279 m_fileCreationMutex.lock(); | |
280 | |
281 if (!QFile(m_localFilename).remove()) { | |
282 std::cerr << "RemoteFile::deleteLocalFile: ERROR: Failed to delete file \"" << m_localFilename.toStdString() << "\"" << std::endl; | |
283 } else { | |
284 m_localFilename = ""; | |
285 } | |
286 | |
287 m_fileCreationMutex.unlock(); | |
288 | |
244 m_done = true; | 289 m_done = true; |
245 } | 290 } |
246 | 291 |
247 void | 292 void |
248 RemoteFile::showProgressDialog() | 293 RemoteFile::showProgressDialog() |
251 } | 296 } |
252 | 297 |
253 QString | 298 QString |
254 RemoteFile::createLocalFile(QUrl url) | 299 RemoteFile::createLocalFile(QUrl url) |
255 { | 300 { |
256 //!!! should we actually put up dialogs for these errors? or propagate an exception? | |
257 | |
258 QDir dir; | 301 QDir dir; |
259 try { | 302 try { |
260 dir = TempDirectory::getInstance()->getSubDirectoryPath("download"); | 303 dir = TempDirectory::getInstance()->getSubDirectoryPath("download"); |
261 } catch (DirectoryCreationFailed f) { | 304 } catch (DirectoryCreationFailed f) { |
262 std::cerr << "RemoteFile::createLocalFile: ERROR: Failed to create temporary directory: " << f.what() << std::endl; | 305 std::cerr << "RemoteFile::createLocalFile: ERROR: Failed to create temporary directory: " << f.what() << std::endl; |