27 #include "types.h" |
27 #include "types.h" |
28 #include "gui.h" |
28 #include "gui.h" |
29 #include "file.h" |
29 #include "file.h" |
30 #include "gldraw.h" |
30 #include "gldraw.h" |
31 #include "configDialog.h" |
31 #include "configDialog.h" |
|
32 #include "moc_download.cpp" |
32 |
33 |
33 cfg (String, net_downloadpath, ""); |
34 cfg (String, net_downloadpath, ""); |
34 cfg (Bool, net_guesspaths, true); |
35 cfg (Bool, net_guesspaths, true); |
35 cfg (Bool, net_autoclose, false); |
36 cfg (Bool, net_autoclose, false); |
36 |
37 |
37 constexpr const char* PartDownloader::k_OfficialURL, |
38 constexpr const char *PartDownloader::k_UnofficialURL; |
38 *PartDownloader::k_UnofficialURL; |
39 |
39 |
40 // ============================================================================= |
40 // ============================================================================= |
41 // ----------------------------------------------------------------------------- |
41 // ----------------------------------------------------------------------------- |
42 void PartDownloader::k_download() |
42 void PartDownloader::k_download() { |
43 { str path = getDownloadPath(); |
43 str path = getDownloadPath(); |
44 |
44 if (path == "" || QDir (path).exists() == false) { |
45 if (path == "" || QDir (path).exists() == false) |
45 critical (PartDownloader::tr ("You need to specify a valid path for " |
46 { critical (PartDownloader::tr ("You need to specify a valid path for " |
46 "downloaded files in the configuration to download paths.")); |
47 "downloaded files in the configuration to download paths.")); |
47 |
48 |
48 (new ConfigDialog (ConfigDialog::DownloadTab, null))->exec(); |
49 (new ConfigDialog (ConfigDialog::DownloadTab, null))->exec(); |
49 return; |
50 return; |
50 } |
51 } |
51 |
52 |
52 PartDownloader* dlg = new PartDownloader; |
53 PartDownloader* dlg = new PartDownloader; |
53 dlg->exec(); |
54 dlg->exec(); |
54 } |
55 } |
55 |
56 |
56 // ============================================================================= |
57 // ============================================================================= |
57 // ----------------------------------------------------------------------------- |
58 // ----------------------------------------------------------------------------- |
58 str PartDownloader::getDownloadPath() { |
59 str PartDownloader::getDownloadPath() |
59 str path = net_downloadpath; |
60 { str path = net_downloadpath; |
60 |
61 |
61 #if DIRSLASH_CHAR != '/' |
62 #if DIRSLASH_CHAR != '/' |
62 path.replace (DIRSLASH, "/"); |
63 path.replace (DIRSLASH, "/"); |
63 #endif |
64 #endif |
64 |
65 |
65 return path; |
66 return path; |
66 } |
67 } |
67 |
68 |
68 // ============================================================================= |
69 // ============================================================================= |
69 // ----------------------------------------------------------------------------- |
70 // ----------------------------------------------------------------------------- |
70 PartDownloader::PartDownloader (QWidget* parent) : QDialog (parent) { |
71 PartDownloader::PartDownloader (QWidget* parent) : QDialog (parent) |
71 ui = new Ui_DownloadFrom; |
72 { ui = new Ui_DownloadFrom; |
72 ui->setupUi (this); |
73 ui->setupUi (this); |
73 ui->fname->setFocus(); |
74 ui->fname->setFocus(); |
74 ui->progress->horizontalHeader()->setResizeMode (PartLabelColumn, QHeaderView::Stretch); |
75 ui->progress->horizontalHeader()->setResizeMode (PartLabelColumn, QHeaderView::Stretch); |
75 |
76 |
76 m_downloadButton = new QPushButton (tr ("Download")); |
77 m_downloadButton = new QPushButton (tr ("Download")); |
77 ui->buttonBox->addButton (m_downloadButton, QDialogButtonBox::ActionRole); |
78 ui->buttonBox->addButton (m_downloadButton, QDialogButtonBox::ActionRole); |
78 getButton (Abort)->setEnabled (false); |
79 getButton (Abort)->setEnabled (false); |
79 |
80 |
80 connect (ui->source, SIGNAL (currentIndexChanged (int)), this, SLOT (sourceChanged (int))); |
81 connect (ui->source, SIGNAL (currentIndexChanged (int)), this, SLOT (sourceChanged (int))); |
81 connect (ui->buttonBox, SIGNAL (clicked (QAbstractButton*)), this, SLOT (buttonClicked (QAbstractButton*))); |
82 connect (ui->buttonBox, SIGNAL (clicked (QAbstractButton*)), this, SLOT (buttonClicked (QAbstractButton*))); |
82 } |
83 } |
83 |
84 |
84 // ============================================================================= |
85 // ============================================================================= |
85 // ----------------------------------------------------------------------------- |
86 // ----------------------------------------------------------------------------- |
86 PartDownloader::~PartDownloader() { |
87 PartDownloader::~PartDownloader() |
87 delete ui; |
88 { delete ui; |
88 } |
89 } |
89 |
90 |
90 // ============================================================================= |
91 // ============================================================================= |
91 // ----------------------------------------------------------------------------- |
92 // ----------------------------------------------------------------------------- |
92 str PartDownloader::getURL() const { |
93 str PartDownloader::getURL() const |
93 const Source src = getSource(); |
94 { const Source src = getSource(); |
94 str dest; |
95 str dest; |
95 |
96 |
96 switch (src) { |
97 switch (src) |
97 case PartsTracker: |
98 { case PartsTracker: |
98 dest = ui->fname->text(); |
99 dest = ui->fname->text(); |
99 modifyDest (dest); |
100 modifyDest (dest); |
100 return str (k_UnofficialURL) + dest; |
101 return str (k_UnofficialURL) + dest; |
101 |
102 |
102 case CustomURL: |
103 case CustomURL: |
103 return ui->fname->text(); |
104 return ui->fname->text(); |
104 } |
105 } |
105 |
106 |
106 // Shouldn't happen |
107 // Shouldn't happen |
107 return ""; |
108 return ""; |
108 } |
109 } |
109 |
110 |
110 // ============================================================================= |
111 // ============================================================================= |
111 // ----------------------------------------------------------------------------- |
112 // ----------------------------------------------------------------------------- |
112 void PartDownloader::modifyDest (str& dest) const { |
113 void PartDownloader::modifyDest (str& dest) const |
113 dest = dest.simplified(); |
114 { dest = dest.simplified(); |
114 |
115 |
115 // If the user doesn't want us to guess, stop right here. |
116 // If the user doesn't want us to guess, stop right here. |
116 if (net_guesspaths == false) |
117 if (net_guesspaths == false) |
117 return; |
118 return; |
118 |
119 |
119 // Ensure .dat extension |
120 // Ensure .dat extension |
120 if (dest.right (4) != ".dat") { |
121 if (dest.right (4) != ".dat") |
121 /* Remove the existing extension, if any. It may be we're here over a |
122 { // Remove the existing extension, if any. It may be we're here over a |
122 typo in the .dat extension. */ |
123 // typo in the .dat extension. |
123 const int dotpos = dest.lastIndexOf ("."); |
124 const int dotpos = dest.lastIndexOf ("."); |
|
125 |
124 if (dotpos != -1 && dotpos >= dest.length() - 4) |
126 if (dotpos != -1 && dotpos >= dest.length() - 4) |
125 dest.chop (dest.length() - dotpos); |
127 dest.chop (dest.length() - dotpos); |
126 |
128 |
127 dest += ".dat"; |
129 dest += ".dat"; |
128 } |
130 } |
129 |
131 |
130 /* If the part starts with s\ or s/, then use parts/s/. Same goes with |
132 // If the part starts with s\ or s/, then use parts/s/. Same goes with |
131 48\ and p/48/. */ |
133 // 48\ and p/48/. |
132 if (dest.left (2) == "s\\" || dest.left (2) == "s/") { |
134 if (dest.left (2) == "s\\" || dest.left (2) == "s/") |
133 dest.remove (0, 2); |
135 { dest.remove (0, 2); |
134 dest.prepend ("parts/s/"); |
136 dest.prepend ("parts/s/"); |
135 } elif (dest.left (3) == "48\\" || dest.left (3) == "48/") { |
137 } elif (dest.left (3) == "48\\" || dest.left (3) == "48/") |
136 dest.remove (0, 3); |
138 |
|
139 { dest.remove (0, 3); |
137 dest.prepend ("p/48/"); |
140 dest.prepend ("p/48/"); |
138 } |
141 } |
139 |
142 |
140 /* Try determine where to put this part. We have four directories: |
143 /* Try determine where to put this part. We have four directories: |
141 parts/, parts/s/, p/, and p/48/. If we haven't already specified |
144 parts/, parts/s/, p/, and p/48/. If we haven't already specified |
142 either parts/ or p/, we need to add it automatically. Part files |
145 either parts/ or p/, we need to add it automatically. Part files |
143 are numbers wit a possible u prefix for parts with unknown number |
146 are numbers wit a possible u prefix for parts with unknown number |
144 which can be followed by any of: |
147 which can be followed by any of: |
145 - c** (composites) |
148 - c** (composites) |
146 - d** (formed stickers) |
149 - d** (formed stickers) |
147 - p** (patterns) |
150 - p** (patterns) |
148 - a lowercase alphabetic letter for variants |
151 - a lowercase alphabetic letter for variants |
149 |
152 |
150 Subfiles (usually) have an s** prefix, in which case we use parts/s/. |
153 Subfiles (usually) have an s** prefix, in which case we use parts/s/. |
151 Note that the regex starts with a '^' so it won't catch already fully |
154 Note that the regex starts with a '^' so it won't catch already fully |
152 given part file names. */ |
155 given part file names. */ |
153 str partRegex = "^u?[0-9]+(c[0-9][0-9]+)*(d[0-9][0-9]+)*[a-z]?(p[0-9a-z][0-9a-z]+)*"; |
156 str partRegex = "^u?[0-9]+(c[0-9][0-9]+)*(d[0-9][0-9]+)*[a-z]?(p[0-9a-z][0-9a-z]+)*"; |
154 str subpartRegex = partRegex + "s[0-9][0-9]+"; |
157 str subpartRegex = partRegex + "s[0-9][0-9]+"; |
155 |
158 |
156 partRegex += "\\.dat$"; |
159 partRegex += "\\.dat$"; |
157 subpartRegex += "\\.dat$"; |
160 subpartRegex += "\\.dat$"; |
158 |
161 |
159 if (QRegExp (subpartRegex).exactMatch (dest)) |
162 if (QRegExp (subpartRegex).exactMatch (dest)) |
160 dest.prepend ("parts/s/"); |
163 dest.prepend ("parts/s/"); |
|
164 |
161 elif (QRegExp (partRegex).exactMatch (dest)) |
165 elif (QRegExp (partRegex).exactMatch (dest)) |
162 dest.prepend ("parts/"); |
166 dest.prepend ("parts/"); |
163 elif (dest.left (6) != "parts/" && dest.left (2) != "p/") |
167 elif (dest.left (6) != "parts/" && dest.left (2) != "p/") |
164 dest.prepend ("p/"); |
168 dest.prepend ("p/"); |
165 } |
169 } |
166 |
170 |
167 // ============================================================================= |
171 // ============================================================================= |
168 // ----------------------------------------------------------------------------- |
172 // ----------------------------------------------------------------------------- |
169 PartDownloader::Source PartDownloader::getSource() const { |
173 PartDownloader::Source PartDownloader::getSource() const |
170 return (Source) ui->source->currentIndex(); |
174 { return (Source) ui->source->currentIndex(); |
171 } |
175 } |
172 |
176 |
173 // ============================================================================= |
177 // ============================================================================= |
174 // ----------------------------------------------------------------------------- |
178 // ----------------------------------------------------------------------------- |
175 void PartDownloader::sourceChanged (int i) { |
179 void PartDownloader::sourceChanged (int i) |
176 if (i == CustomURL) |
180 { if (i == CustomURL) |
177 ui->fileNameLabel->setText (tr ("URL:")); |
181 ui->fileNameLabel->setText (tr ("URL:")); |
178 else |
182 else |
179 ui->fileNameLabel->setText (tr ("File name:")); |
183 ui->fileNameLabel->setText (tr ("File name:")); |
180 } |
184 } |
181 |
185 |
182 // ============================================================================= |
186 // ============================================================================= |
183 // ----------------------------------------------------------------------------- |
187 // ----------------------------------------------------------------------------- |
184 void PartDownloader::buttonClicked (QAbstractButton* btn) { |
188 void PartDownloader::buttonClicked (QAbstractButton* btn) |
185 if (btn == getButton (Close)) { |
189 { if (btn == getButton (Close)) |
186 reject(); |
190 { reject(); |
187 } elif (btn == getButton (Abort)) { |
191 } elif (btn == getButton (Abort)) |
188 setAborted (true); |
192 |
189 |
193 { setAborted (true); |
190 for (PartDownloadRequest* req : m_requests) |
194 |
|
195 for (PartDownloadRequest * req : m_requests) |
191 req->abort(); |
196 req->abort(); |
192 } elif (btn == getButton (Download)) { |
197 } elif (btn == getButton (Download)) |
193 str dest = ui->fname->text(); |
198 { str dest = ui->fname->text(); |
194 setPrimaryFile (null); |
199 setPrimaryFile (null); |
195 setAborted (false); |
200 setAborted (false); |
196 |
201 |
197 if (getSource() == CustomURL) |
202 if (getSource() == CustomURL) |
198 dest = basename (getURL()); |
203 dest = basename (getURL()); |
199 |
204 |
200 modifyDest (dest); |
205 modifyDest (dest); |
201 |
206 |
202 if (QFile::exists (PartDownloader::getDownloadPath() + DIRSLASH + dest)) { |
207 if (QFile::exists (PartDownloader::getDownloadPath() + DIRSLASH + dest)) |
203 const str overwritemsg = fmt (tr ("%1 already exists in download directory. Overwrite?"), dest); |
208 { const str overwritemsg = fmt (tr ("%1 already exists in download directory. Overwrite?"), dest); |
204 |
|
205 if (!confirm (tr ("Overwrite?"), overwritemsg)) |
209 if (!confirm (tr ("Overwrite?"), overwritemsg)) |
206 return; |
210 return; |
207 } |
211 } |
208 |
212 |
209 m_downloadButton->setEnabled (false); |
213 m_downloadButton->setEnabled (false); |
210 ui->progress->setEnabled (true); |
214 ui->progress->setEnabled (true); |
211 ui->fname->setEnabled (false); |
215 ui->fname->setEnabled (false); |
212 ui->source->setEnabled (false); |
216 ui->source->setEnabled (false); |
213 downloadFile (dest, getURL(), true); |
217 downloadFile (dest, getURL(), true); |
217 } |
221 } |
218 } |
222 } |
219 |
223 |
220 // ============================================================================= |
224 // ============================================================================= |
221 // ----------------------------------------------------------------------------- |
225 // ----------------------------------------------------------------------------- |
222 void PartDownloader::downloadFile (str dest, str url, bool primary) { |
226 void PartDownloader::downloadFile (str dest, str url, bool primary) |
223 const int row = ui->progress->rowCount(); |
227 { const int row = ui->progress->rowCount(); |
224 |
228 |
225 // Don't download files repeadetly. |
229 // Don't download files repeadetly. |
226 if (m_filesToDownload.find (dest) != -1u) |
230 if (m_filesToDownload.find (dest) != -1u) |
227 return; |
231 return; |
228 |
232 |
229 modifyDest (dest); |
233 modifyDest (dest); |
230 print ("DOWNLOAD: %1 -> %2\n", url, PartDownloader::getDownloadPath() + DIRSLASH + dest); |
234 print ("DOWNLOAD: %1 -> %2\n", url, PartDownloader::getDownloadPath() + DIRSLASH + dest); |
231 PartDownloadRequest* req = new PartDownloadRequest (url, dest, primary, this); |
235 PartDownloadRequest* req = new PartDownloadRequest (url, dest, primary, this); |
232 |
236 |
233 m_filesToDownload << dest; |
237 m_filesToDownload << dest; |
234 m_requests << req; |
238 m_requests << req; |
235 ui->progress->insertRow (row); |
239 ui->progress->insertRow (row); |
236 req->setTableRow (row); |
240 req->setTableRow (row); |
237 req->updateToTable(); |
241 req->updateToTable(); |
238 } |
242 } |
239 |
243 |
240 // ============================================================================= |
244 // ============================================================================= |
241 // ----------------------------------------------------------------------------- |
245 // ----------------------------------------------------------------------------- |
242 void PartDownloader::checkIfFinished() { |
246 void PartDownloader::checkIfFinished() |
243 bool failed = aborted(); |
247 { bool failed = aborted(); |
244 |
248 |
245 // If there is some download still working, we're not finished. |
249 // If there is some download still working, we're not finished. |
246 for (PartDownloadRequest* req : m_requests) { |
250 for (PartDownloadRequest* req : m_requests) |
247 if (!req->isFinished()) |
251 { if (!req->isFinished()) |
248 return; |
252 return; |
249 |
253 |
250 if (req->state() == PartDownloadRequest::Failed) |
254 if (req->state() == PartDownloadRequest::Failed) |
251 failed = true; |
255 failed = true; |
252 } |
256 } |
253 |
257 |
254 for (PartDownloadRequest* req : m_requests) |
258 for (PartDownloadRequest* req : m_requests) |
255 delete req; |
259 delete req; |
256 |
260 |
257 m_requests.clear(); |
261 m_requests.clear(); |
258 |
262 |
259 // Update everything now |
263 // Update everything now |
260 if (primaryFile()) { |
264 if (primaryFile()) |
261 LDFile::setCurrent (primaryFile()); |
265 { LDFile::setCurrent (primaryFile()); |
262 reloadAllSubfiles(); |
266 reloadAllSubfiles(); |
263 g_win->fullRefresh(); |
267 g_win->fullRefresh(); |
264 g_win->R()->resetAngles(); |
268 g_win->R()->resetAngles(); |
265 } |
269 } |
266 |
270 |
267 if (net_autoclose && !failed) { |
271 if (net_autoclose && !failed) |
268 // Close automatically if desired. |
272 { // Close automatically if desired. |
269 accept(); |
273 accept(); |
270 } else { |
274 } |
271 // Allow the prompt be closed now. |
275 else |
|
276 { // Allow the prompt be closed now. |
272 getButton (Abort)->setEnabled (false); |
277 getButton (Abort)->setEnabled (false); |
273 getButton (Close)->setEnabled (true); |
278 getButton (Close)->setEnabled (true); |
274 } |
279 } |
275 } |
280 } |
276 |
281 |
277 // ============================================================================= |
282 // ============================================================================= |
278 // ----------------------------------------------------------------------------- |
283 // ----------------------------------------------------------------------------- |
279 QPushButton* PartDownloader::getButton (PartDownloader::Button i) { |
284 QPushButton* PartDownloader::getButton (PartDownloader::Button i) |
280 typedef QDialogButtonBox QDBB; |
285 { typedef QDialogButtonBox QDBB; |
281 alias btnbox = ui->buttonBox; |
286 alias btnbox = ui->buttonBox; |
282 |
287 |
283 switch (i) { |
288 switch (i) |
284 case Download: |
289 { case Download: |
285 return m_downloadButton; |
290 return m_downloadButton; |
286 |
291 |
287 case Abort: |
292 case Abort: |
288 return qobject_cast<QPushButton*> (btnbox->button (QDBB::Abort)); |
293 return qobject_cast<QPushButton*> (btnbox->button (QDBB::Abort)); |
289 |
294 |
290 case Close: |
295 case Close: |
291 return qobject_cast<QPushButton*> (btnbox->button (QDBB::Close)); |
296 return qobject_cast<QPushButton*> (btnbox->button (QDBB::Close)); |
292 } |
297 } |
293 |
298 |
294 return null; |
299 return null; |
295 } |
300 } |
296 |
301 |
297 // ============================================================================= |
302 // ============================================================================= |
298 // ----------------------------------------------------------------------------- |
303 // ----------------------------------------------------------------------------- |
328 // ----------------------------------------------------------------------------- |
335 // ----------------------------------------------------------------------------- |
329 PartDownloadRequest::~PartDownloadRequest() {} |
336 PartDownloadRequest::~PartDownloadRequest() {} |
330 |
337 |
331 // ============================================================================= |
338 // ============================================================================= |
332 // ----------------------------------------------------------------------------- |
339 // ----------------------------------------------------------------------------- |
333 void PartDownloadRequest::updateToTable() { |
340 void PartDownloadRequest::updateToTable() |
334 const int labelcol = PartDownloader::PartLabelColumn, |
341 { const int labelcol = PartDownloader::PartLabelColumn, |
335 progcol = PartDownloader::ProgressColumn; |
342 progcol = PartDownloader::ProgressColumn; |
336 QTableWidget* table = m_prompt->ui->progress; |
343 QTableWidget* table = m_prompt->ui->progress; |
337 QProgressBar* prog; |
344 QProgressBar* prog; |
338 |
345 |
339 switch (m_state) { |
346 switch (m_state) |
340 case Requesting: |
347 { case Requesting: |
341 case Downloading: |
348 case Downloading: |
342 prog = qobject_cast<QProgressBar*> (table->cellWidget (tableRow(), progcol)); |
349 prog = qobject_cast<QProgressBar*> (table->cellWidget (tableRow(), progcol)); |
343 |
350 |
344 if (!prog) { |
351 if (!prog) |
345 prog = new QProgressBar; |
352 { prog = new QProgressBar; |
346 table->setCellWidget (tableRow(), progcol, prog); |
353 table->setCellWidget (tableRow(), progcol, prog); |
347 } |
354 } |
348 |
355 |
349 prog->setRange (0, m_bytesTotal); |
356 prog->setRange (0, m_bytesTotal); |
350 prog->setValue (m_bytesRead); |
357 prog->setValue (m_bytesRead); |
351 break; |
358 break; |
352 |
359 |
353 case Finished: |
360 case Finished: |
354 case Failed: |
361 case Failed: |
355 { |
362 { QLabel* lb = new QLabel ( (m_state == Finished) ? "<b><span style=\"color: #080\">FINISHED</span></b>" : |
356 QLabel* lb = new QLabel ((m_state == Finished) ? "<b><span style=\"color: #080\">FINISHED</span></b>" : |
363 "<b><span style=\"color: #800\">FAILED</span></b>"); |
357 "<b><span style=\"color: #800\">FAILED</span></b>"); |
|
358 lb->setAlignment (Qt::AlignCenter); |
364 lb->setAlignment (Qt::AlignCenter); |
359 table->setCellWidget (tableRow(), progcol, lb); |
365 table->setCellWidget (tableRow(), progcol, lb); |
360 } |
366 } |
361 break; |
367 break; |
362 } |
368 } |
363 |
369 |
364 QLabel* lb = qobject_cast<QLabel*> (table->cellWidget (tableRow(), labelcol)); |
370 QLabel* lb = qobject_cast<QLabel*> (table->cellWidget (tableRow(), labelcol)); |
365 if (m_firstUpdate) { |
371 |
366 lb = new QLabel (fmt ("<b>%1</b>", m_dest), table); |
372 if (m_firstUpdate) |
|
373 { lb = new QLabel (fmt ("<b>%1</b>", m_dest), table); |
367 table->setCellWidget (tableRow(), labelcol, lb); |
374 table->setCellWidget (tableRow(), labelcol, lb); |
368 } |
375 } |
369 |
376 |
370 // Make sure that the cell is big enough to contain the label |
377 // Make sure that the cell is big enough to contain the label |
371 if (table->columnWidth (labelcol) < lb->width()) |
378 if (table->columnWidth (labelcol) < lb->width()) |
372 table->setColumnWidth (labelcol, lb->width()); |
379 table->setColumnWidth (labelcol, lb->width()); |
373 |
380 |
374 m_firstUpdate = false; |
381 m_firstUpdate = false; |
375 } |
382 } |
376 |
383 |
377 // ============================================================================= |
384 // ============================================================================= |
378 // ----------------------------------------------------------------------------- |
385 // ----------------------------------------------------------------------------- |
379 void PartDownloadRequest::downloadFinished() { |
386 void PartDownloadRequest::downloadFinished() |
380 if (m_reply->error() != QNetworkReply::NoError) { |
387 { if (m_reply->error() != QNetworkReply::NoError) |
381 if (m_primary && !m_prompt->aborted()) |
388 { if (m_primary && !m_prompt->aborted()) |
382 critical (m_reply->errorString()); |
389 critical (m_reply->errorString()); |
383 |
390 |
384 m_state = Failed; |
391 m_state = Failed; |
385 } elif (state() != Failed) |
392 } elif (state() != Failed) |
386 m_state = Finished; |
393 |
387 |
394 m_state = Finished; |
|
395 |
388 m_bytesRead = m_bytesTotal; |
396 m_bytesRead = m_bytesTotal; |
389 updateToTable(); |
397 updateToTable(); |
390 |
398 |
391 if (m_fp) { |
399 if (m_fp) |
392 m_fp->close(); |
400 { m_fp->close(); |
393 delete m_fp; |
401 delete m_fp; |
394 m_fp = null; |
402 m_fp = null; |
395 |
403 |
396 if (m_state == Failed) |
404 if (m_state == Failed) |
397 QFile::remove (m_fpath); |
405 QFile::remove (m_fpath); |
398 } |
406 } |
399 |
407 |
400 if (m_state != Finished) { |
408 if (m_state != Finished) |
401 m_prompt->checkIfFinished(); |
409 { m_prompt->checkIfFinished(); |
402 return; |
410 return; |
403 } |
411 } |
404 |
412 |
405 // Try to load this file now. |
413 // Try to load this file now. |
406 LDFile* f = openDATFile (m_fpath, false); |
414 LDFile* f = openDATFile (m_fpath, false); |
|
415 |
407 if (!f) |
416 if (!f) |
408 return; |
417 return; |
409 |
418 |
410 f->setImplicit (!m_primary); |
419 f->setImplicit (!m_primary); |
411 |
420 |
412 // Iterate through this file and check for errors. If there's any that stems |
421 // Iterate through this file and check for errors. If there's any that stems |
413 // from unknown file references, try resolve that by downloading the reference. |
422 // from unknown file references, try resolve that by downloading the reference. |
414 // This is why downloading a part may end up downloading multiple files, as |
423 // This is why downloading a part may end up downloading multiple files, as |
415 // it resolves dependencies. |
424 // it resolves dependencies. |
416 for (LDObject* obj : f->objects()) { |
425 for (LDObject* obj : f->objects()) |
417 LDError* err = dynamic_cast<LDError*> (obj); |
426 { LDError* err = dynamic_cast<LDError*> (obj); |
|
427 |
418 if (!err || err->fileRef().isEmpty()) |
428 if (!err || err->fileRef().isEmpty()) |
419 continue; |
429 continue; |
420 |
430 |
421 str dest = err->fileRef(); |
431 str dest = err->fileRef(); |
422 m_prompt->modifyDest (dest); |
432 m_prompt->modifyDest (dest); |
423 m_prompt->downloadFile (dest, str (PartDownloader::k_UnofficialURL) + dest, false); |
433 m_prompt->downloadFile (dest, str (PartDownloader::k_UnofficialURL) + dest, false); |
424 } |
434 } |
425 |
435 |
426 if (m_primary) { |
436 if (m_primary) |
427 addRecentFile (m_fpath); |
437 { addRecentFile (m_fpath); |
428 m_prompt->setPrimaryFile (f); |
438 m_prompt->setPrimaryFile (f); |
429 } |
439 } |
430 |
440 |
431 m_prompt->checkIfFinished(); |
441 m_prompt->checkIfFinished(); |
432 } |
442 } |
433 |
443 |
434 // ============================================================================= |
444 // ============================================================================= |
435 // ----------------------------------------------------------------------------- |
445 // ----------------------------------------------------------------------------- |
436 void PartDownloadRequest::downloadProgress (int64 recv, int64 total) { |
446 void PartDownloadRequest::downloadProgress (int64 recv, int64 total) |
437 m_bytesRead = recv; |
447 { m_bytesRead = recv; |
438 m_bytesTotal = total; |
448 m_bytesTotal = total; |
439 m_state = Downloading; |
449 m_state = Downloading; |
440 updateToTable(); |
450 updateToTable(); |
441 } |
451 } |
442 |
452 |
443 // ============================================================================= |
453 // ============================================================================= |
444 // ----------------------------------------------------------------------------- |
454 // ----------------------------------------------------------------------------- |
445 void PartDownloadRequest::readyRead() { |
455 void PartDownloadRequest::readyRead() |
446 if (state() == Failed) |
456 { if (state() == Failed) |
447 return; |
457 return; |
448 |
458 |
449 if (m_fp == null) { |
459 if (m_fp == null) |
450 m_fpath.replace ("\\", "/"); |
460 { m_fpath.replace ("\\", "/"); |
451 |
461 |
452 // We have already asked the user whether we can overwrite so we're good |
462 // We have already asked the user whether we can overwrite so we're good |
453 // to go here. |
463 // to go here. |
454 m_fp = new QFile (m_fpath.toLocal8Bit()); |
464 m_fp = new QFile (m_fpath.toLocal8Bit()); |
455 if (!m_fp->open (QIODevice::WriteOnly)) { |
465 |
456 critical (fmt (tr ("Couldn't open %1 for writing: %2"), m_fpath, strerror (errno))); |
466 if (!m_fp->open (QIODevice::WriteOnly)) |
|
467 { critical (fmt (tr ("Couldn't open %1 for writing: %2"), m_fpath, strerror (errno))); |
457 m_state = Failed; |
468 m_state = Failed; |
458 m_reply->abort(); |
469 m_reply->abort(); |
459 updateToTable(); |
470 updateToTable(); |
460 m_prompt->checkIfFinished(); |
471 m_prompt->checkIfFinished(); |
461 return; |
472 return; |
462 } |
473 } |
463 } |
474 } |
464 |
475 |
465 m_fp->write (m_reply->readAll()); |
476 m_fp->write (m_reply->readAll()); |
466 } |
477 } |
467 |
478 |
468 // ============================================================================= |
479 // ============================================================================= |
469 // ----------------------------------------------------------------------------- |
480 // ----------------------------------------------------------------------------- |
470 bool PartDownloadRequest::isFinished() const { |
481 bool PartDownloadRequest::isFinished() const |
471 return m_state == Finished || m_state == Failed; |
482 { return m_state == Finished || m_state == Failed; |
472 } |
483 } |
473 |
484 |
474 // ============================================================================= |
485 // ============================================================================= |
475 // ----------------------------------------------------------------------------- |
486 // ----------------------------------------------------------------------------- |
476 const PartDownloadRequest::State& PartDownloadRequest::state() const { |
487 const PartDownloadRequest::State& PartDownloadRequest::state() const |
477 return m_state; |
488 { return m_state; |
478 } |
489 } |
479 |
490 |
480 // ============================================================================= |
491 // ============================================================================= |
481 // ----------------------------------------------------------------------------- |
492 // ----------------------------------------------------------------------------- |
482 void PartDownloadRequest::abort() { |
493 void PartDownloadRequest::abort() |
483 m_reply->abort(); |
494 { m_reply->abort(); |
484 } |
495 } |
485 |
496 |
486 // ============================================================================= |
497 // ============================================================================= |
487 // ----------------------------------------------------------------------------- |
498 // ----------------------------------------------------------------------------- |
488 DEFINE_ACTION (DownloadFrom, 0) { |
499 DEFINE_ACTION (DownloadFrom, 0) |
489 PartDownloader::k_download(); |
500 { PartDownloader::k_download(); |
490 } |
501 } |
491 #include "moc_download.cpp" |
|