src/PartDownloader.cc

changeset 642
751a8df42842
parent 639
851634b85893
child 644
93dcd1a0e4bd
equal deleted inserted replaced
641:425b169a82aa 642:751a8df42842
71 // ============================================================================= 71 // =============================================================================
72 // 72 //
73 PartDownloader::PartDownloader (QWidget* parent) : QDialog (parent) 73 PartDownloader::PartDownloader (QWidget* parent) : QDialog (parent)
74 { 74 {
75 setInterface (new Ui_DownloadFrom); 75 setInterface (new Ui_DownloadFrom);
76 getInterface()->setupUi (this); 76 interface()->setupUi (this);
77 getInterface()->fname->setFocus(); 77 interface()->fname->setFocus();
78 getInterface()->progress->horizontalHeader()->setResizeMode (PartLabelColumn, QHeaderView::Stretch); 78 interface()->progress->horizontalHeader()->setResizeMode (PartLabelColumn, QHeaderView::Stretch);
79 79
80 setDownloadButton (new QPushButton (tr ("Download"))); 80 setDownloadButton (new QPushButton (tr ("Download")));
81 getInterface()->buttonBox->addButton (getDownloadButton(), QDialogButtonBox::ActionRole); 81 interface()->buttonBox->addButton (downloadButton(), QDialogButtonBox::ActionRole);
82 getButton (Abort)->setEnabled (false); 82 getButton (Abort)->setEnabled (false);
83 83
84 connect (getInterface()->source, SIGNAL (currentIndexChanged (int)), 84 connect (interface()->source, SIGNAL (currentIndexChanged (int)),
85 this, SLOT (sourceChanged (int))); 85 this, SLOT (sourceChanged (int)));
86 connect (getInterface()->buttonBox, SIGNAL (clicked (QAbstractButton*)), 86 connect (interface()->buttonBox, SIGNAL (clicked (QAbstractButton*)),
87 this, SLOT (buttonClicked (QAbstractButton*))); 87 this, SLOT (buttonClicked (QAbstractButton*)));
88 } 88 }
89 89
90 // ============================================================================= 90 // =============================================================================
91 // 91 //
92 PartDownloader::~PartDownloader() 92 PartDownloader::~PartDownloader()
93 { 93 {
94 delete getInterface(); 94 delete interface();
95 } 95 }
96 96
97 // ============================================================================= 97 // =============================================================================
98 // 98 //
99 QString PartDownloader::getURL() const 99 QString PartDownloader::getURL() const
102 QString dest; 102 QString dest;
103 103
104 switch (src) 104 switch (src)
105 { 105 {
106 case PartsTracker: 106 case PartsTracker:
107 dest = getInterface()->fname->text(); 107 dest = interface()->fname->text();
108 modifyDestination (dest); 108 modifyDestination (dest);
109 return g_unofficialLibraryURL + dest; 109 return g_unofficialLibraryURL + dest;
110 110
111 case CustomURL: 111 case CustomURL:
112 return getInterface()->fname->text(); 112 return interface()->fname->text();
113 } 113 }
114 114
115 // Shouldn't happen 115 // Shouldn't happen
116 return ""; 116 return "";
117 } 117 }
180 180
181 // ============================================================================= 181 // =============================================================================
182 // 182 //
183 PartDownloader::Source PartDownloader::getSource() const 183 PartDownloader::Source PartDownloader::getSource() const
184 { 184 {
185 return (Source) getInterface()->source->currentIndex(); 185 return (Source) interface()->source->currentIndex();
186 } 186 }
187 187
188 // ============================================================================= 188 // =============================================================================
189 // 189 //
190 void PartDownloader::sourceChanged (int i) 190 void PartDownloader::sourceChanged (int i)
191 { 191 {
192 if (i == CustomURL) 192 if (i == CustomURL)
193 getInterface()->fileNameLabel->setText (tr ("URL:")); 193 interface()->fileNameLabel->setText (tr ("URL:"));
194 else 194 else
195 getInterface()->fileNameLabel->setText (tr ("File name:")); 195 interface()->fileNameLabel->setText (tr ("File name:"));
196 } 196 }
197 197
198 // ============================================================================= 198 // =============================================================================
199 // 199 //
200 void PartDownloader::buttonClicked (QAbstractButton* btn) 200 void PartDownloader::buttonClicked (QAbstractButton* btn)
205 } 205 }
206 elif (btn == getButton (Abort)) 206 elif (btn == getButton (Abort))
207 { 207 {
208 setAborted (true); 208 setAborted (true);
209 209
210 for (PartDownloadRequest* req : getRequests()) 210 for (PartDownloadRequest* req : requests())
211 req->abort(); 211 req->abort();
212 } 212 }
213 elif (btn == getButton (Download)) 213 elif (btn == getButton (Download))
214 { 214 {
215 QString dest = getInterface()->fname->text(); 215 QString dest = interface()->fname->text();
216 setPrimaryFile (null); 216 setPrimaryFile (null);
217 setAborted (false); 217 setAborted (false);
218 218
219 if (getSource() == CustomURL) 219 if (getSource() == CustomURL)
220 dest = basename (getURL()); 220 dest = basename (getURL());
226 const QString overwritemsg = fmt (tr ("%1 already exists in download directory. Overwrite?"), dest); 226 const QString overwritemsg = fmt (tr ("%1 already exists in download directory. Overwrite?"), dest);
227 if (!confirm (tr ("Overwrite?"), overwritemsg)) 227 if (!confirm (tr ("Overwrite?"), overwritemsg))
228 return; 228 return;
229 } 229 }
230 230
231 getDownloadButton()->setEnabled (false); 231 downloadButton()->setEnabled (false);
232 getInterface()->progress->setEnabled (true); 232 interface()->progress->setEnabled (true);
233 getInterface()->fname->setEnabled (false); 233 interface()->fname->setEnabled (false);
234 getInterface()->source->setEnabled (false); 234 interface()->source->setEnabled (false);
235 downloadFile (dest, getURL(), true); 235 downloadFile (dest, getURL(), true);
236 getButton (Close)->setEnabled (false); 236 getButton (Close)->setEnabled (false);
237 getButton (Abort)->setEnabled (true); 237 getButton (Abort)->setEnabled (true);
238 getButton (Download)->setEnabled (false); 238 getButton (Download)->setEnabled (false);
239 } 239 }
241 241
242 // ============================================================================= 242 // =============================================================================
243 // 243 //
244 void PartDownloader::downloadFile (QString dest, QString url, bool primary) 244 void PartDownloader::downloadFile (QString dest, QString url, bool primary)
245 { 245 {
246 const int row = getInterface()->progress->rowCount(); 246 const int row = interface()->progress->rowCount();
247 247
248 // Don't download files repeadetly. 248 // Don't download files repeadetly.
249 if (getFilesToDownload().indexOf (dest) != -1) 249 if (filesToDownload().indexOf (dest) != -1)
250 return; 250 return;
251 251
252 modifyDestination (dest); 252 modifyDestination (dest);
253 log ("DOWNLOAD: %1 -> %2\n", url, PartDownloader::getDownloadPath() + DIRSLASH + dest);
254 PartDownloadRequest* req = new PartDownloadRequest (url, dest, primary, this); 253 PartDownloadRequest* req = new PartDownloadRequest (url, dest, primary, this);
255 254 m_filesToDownload << dest;
256 pushToFilesToDownload (dest); 255 m_requests << req;
257 pushToRequests (req); 256 interface()->progress->insertRow (row);
258 getInterface()->progress->insertRow (row);
259 req->setTableRow (row); 257 req->setTableRow (row);
260 req->updateToTable(); 258 req->updateToTable();
261 } 259 }
262 260
263 // ============================================================================= 261 // =============================================================================
265 void PartDownloader::checkIfFinished() 263 void PartDownloader::checkIfFinished()
266 { 264 {
267 bool failed = isAborted(); 265 bool failed = isAborted();
268 266
269 // If there is some download still working, we're not finished. 267 // If there is some download still working, we're not finished.
270 for (PartDownloadRequest* req : getRequests()) 268 for (PartDownloadRequest* req : requests())
271 { 269 {
272 if (!req->isFinished()) 270 if (!req->isFinished())
273 return; 271 return;
274 272
275 if (req->getState() == PartDownloadRequest::EFailed) 273 if (req->state() == PartDownloadRequest::EFailed)
276 failed = true; 274 failed = true;
277 } 275 }
278 276
279 for (PartDownloadRequest* req : getRequests()) 277 for (PartDownloadRequest* req : requests())
280 delete req; 278 delete req;
281 279
282 clearRequests(); 280 m_requests.clear();
283 281
284 // Update everything now 282 // Update everything now
285 if (getPrimaryFile()) 283 if (primaryFile() != null)
286 { 284 {
287 LDDocument::setCurrent (getPrimaryFile()); 285 LDDocument::setCurrent (primaryFile());
288 reloadAllSubfiles(); 286 reloadAllSubfiles();
289 g_win->doFullRefresh(); 287 g_win->doFullRefresh();
290 g_win->R()->resetAngles(); 288 g_win->R()->resetAngles();
291 } 289 }
292 290
308 QPushButton* PartDownloader::getButton (PartDownloader::Button i) 306 QPushButton* PartDownloader::getButton (PartDownloader::Button i)
309 { 307 {
310 switch (i) 308 switch (i)
311 { 309 {
312 case Download: 310 case Download:
313 return getDownloadButton(); 311 return downloadButton();
314 312
315 case Abort: 313 case Abort:
316 return qobject_cast<QPushButton*> (getInterface()->buttonBox->button (QDialogButtonBox::Abort)); 314 return qobject_cast<QPushButton*> (interface()->buttonBox->button (QDialogButtonBox::Abort));
317 315
318 case Close: 316 case Close:
319 return qobject_cast<QPushButton*> (getInterface()->buttonBox->button (QDialogButtonBox::Close)); 317 return qobject_cast<QPushButton*> (interface()->buttonBox->button (QDialogButtonBox::Close));
320 } 318 }
321 319
322 return null; 320 return null;
323 } 321 }
324 322
325 // ============================================================================= 323 // =============================================================================
326 // 324 //
327 PartDownloadRequest::PartDownloadRequest (QString url, QString dest, bool primary, PartDownloader* parent) : 325 PartDownloadRequest::PartDownloadRequest (QString url, QString dest, bool primary, PartDownloader* parent) :
328 QObject (parent), 326 QObject (parent),
329 m_State (ERequesting), 327 m_state (ERequesting),
330 m_Prompt (parent), 328 m_prompt (parent),
331 m_URL (url), 329 m_url (url),
332 m_Destinaton (dest), 330 m_destinaton (dest),
333 m_FilePath (PartDownloader::getDownloadPath() + DIRSLASH + dest), 331 m_filePath (PartDownloader::getDownloadPath() + DIRSLASH + dest),
334 m_NAM (new QNetworkAccessManager), 332 m_networkManager (new QNetworkAccessManager),
335 m_FirstUpdate (true), 333 m_isFirstUpdate (true),
336 m_Primary (primary), 334 m_isPrimary (primary),
337 m_FilePointer (null) 335 m_filePointer (null)
338 { 336 {
339 // Make sure that we have a valid destination. 337 // Make sure that we have a valid destination.
340 QString dirpath = dirname (getFilePath()); 338 QString dirpath = dirname (filePath());
341 339
342 QDir dir (dirpath); 340 QDir dir (dirpath);
343 341
344 if (!dir.exists()) 342 if (!dir.exists())
345 { 343 {
347 345
348 if (!dir.mkpath (dirpath)) 346 if (!dir.mkpath (dirpath))
349 critical (fmt (tr ("Couldn't create the directory %1!"), dirpath)); 347 critical (fmt (tr ("Couldn't create the directory %1!"), dirpath));
350 } 348 }
351 349
352 setReply (getNAM()->get (QNetworkRequest (QUrl (url)))); 350 setNetworkReply (networkManager()->get (QNetworkRequest (QUrl (url))));
353 connect (getReply(), SIGNAL (finished()), this, SLOT (downloadFinished())); 351 connect (networkReply(), SIGNAL (finished()), this, SLOT (downloadFinished()));
354 connect (getReply(), SIGNAL (readyRead()), this, SLOT (readyRead())); 352 connect (networkReply(), SIGNAL (readyRead()), this, SLOT (readyRead()));
355 connect (getReply(), SIGNAL (downloadProgress (qint64, qint64)), 353 connect (networkReply(), SIGNAL (downloadProgress (qint64, qint64)),
356 this, SLOT (downloadProgress (qint64, qint64))); 354 this, SLOT (downloadProgress (qint64, qint64)));
357 } 355 }
358 356
359 // ============================================================================= 357 // =============================================================================
360 // 358 //
363 // ============================================================================= 361 // =============================================================================
364 // 362 //
365 void PartDownloadRequest::updateToTable() 363 void PartDownloadRequest::updateToTable()
366 { 364 {
367 const int labelcol = PartDownloader::PartLabelColumn, 365 const int labelcol = PartDownloader::PartLabelColumn,
368 progcol = PartDownloader::ProgressColumn; 366 progcol = PartDownloader::ProgressColumn;
369 QTableWidget* table = getPrompt()->getInterface()->progress; 367 QTableWidget* table = prompt()->interface()->progress;
370 QProgressBar* prog; 368 QProgressBar* prog;
371 369
372 switch (getState()) 370 switch (state())
373 { 371 {
374 case ERequesting: 372 case ERequesting:
375 case EDownloading: 373 case EDownloading:
376 { 374 {
377 prog = qobject_cast<QProgressBar*> (table->cellWidget (getTableRow(), progcol)); 375 prog = qobject_cast<QProgressBar*> (table->cellWidget (tableRow(), progcol));
378 376
379 if (!prog) 377 if (!prog)
380 { 378 {
381 prog = new QProgressBar; 379 prog = new QProgressBar;
382 table->setCellWidget (getTableRow(), progcol, prog); 380 table->setCellWidget (tableRow(), progcol, prog);
383 } 381 }
384 382
385 prog->setRange (0, getBytesTotal()); 383 prog->setRange (0, numBytesTotal());
386 prog->setValue (getBytesRead()); 384 prog->setValue (numBytesRead());
387 } break; 385 } break;
388 386
389 case EFinished: 387 case EFinished:
390 case EFailed: 388 case EFailed:
391 { 389 {
392 const QString text = (getState() == EFinished) 390 const QString text = (state() == EFinished)
393 ? "<b><span style=\"color: #080\">FINISHED</span></b>" 391 ? "<b><span style=\"color: #080\">FINISHED</span></b>"
394 : "<b><span style=\"color: #800\">FAILED</span></b>"; 392 : "<b><span style=\"color: #800\">FAILED</span></b>";
395 393
396 QLabel* lb = new QLabel (text); 394 QLabel* lb = new QLabel (text);
397 lb->setAlignment (Qt::AlignCenter); 395 lb->setAlignment (Qt::AlignCenter);
398 table->setCellWidget (getTableRow(), progcol, lb); 396 table->setCellWidget (tableRow(), progcol, lb);
399 } break; 397 } break;
400 } 398 }
401 399
402 QLabel* lb = qobject_cast<QLabel*> (table->cellWidget (getTableRow(), labelcol)); 400 QLabel* lb = qobject_cast<QLabel*> (table->cellWidget (tableRow(), labelcol));
403 401
404 if (isFirstUpdate()) 402 if (isFirstUpdate())
405 { 403 {
406 lb = new QLabel (fmt ("<b>%1</b>", getDestinaton()), table); 404 lb = new QLabel (fmt ("<b>%1</b>", destinaton()), table);
407 table->setCellWidget (getTableRow(), labelcol, lb); 405 table->setCellWidget (tableRow(), labelcol, lb);
408 } 406 }
409 407
410 // Make sure that the cell is big enough to contain the label 408 // Make sure that the cell is big enough to contain the label
411 if (table->columnWidth (labelcol) < lb->width()) 409 if (table->columnWidth (labelcol) < lb->width())
412 table->setColumnWidth (labelcol, lb->width()); 410 table->setColumnWidth (labelcol, lb->width());
416 414
417 // ============================================================================= 415 // =============================================================================
418 // 416 //
419 void PartDownloadRequest::downloadFinished() 417 void PartDownloadRequest::downloadFinished()
420 { 418 {
421 if (getReply()->error() != QNetworkReply::NoError) 419 if (networkReply()->error() != QNetworkReply::NoError)
422 { 420 {
423 if (isPrimary() && !getPrompt()->isAborted()) 421 if (isPrimary() && !prompt()->isAborted())
424 critical (getReply()->errorString()); 422 critical (networkReply()->errorString());
425 423
426 setState (EFailed); 424 setState (EFailed);
427 } 425 }
428 elif (getState() != EFailed) 426 elif (state() != EFailed)
429 setState (EFinished); 427 setState (EFinished);
430 428
431 setBytesRead (getBytesTotal()); 429 setNumBytesRead (numBytesTotal());
432 updateToTable(); 430 updateToTable();
433 431
434 if (getFilePointer()) 432 if (filePointer())
435 { 433 {
436 getFilePointer()->close(); 434 filePointer()->close();
437 delete getFilePointer(); 435 delete filePointer();
438 setFilePointer (null); 436 setFilePointer (null);
439 437
440 if (getState() == EFailed) 438 if (state() == EFailed)
441 QFile::remove (getFilePath()); 439 QFile::remove (filePath());
442 } 440 }
443 441
444 if (getState() != EFinished) 442 if (state() != EFinished)
445 { 443 {
446 getPrompt()->checkIfFinished(); 444 prompt()->checkIfFinished();
447 return; 445 return;
448 } 446 }
449 447
450 // Try to load this file now. 448 // Try to load this file now.
451 LDDocument* f = openDocument (getFilePath(), false); 449 LDDocument* f = openDocument (filePath(), false);
452 450
453 if (!f) 451 if (!f)
454 return; 452 return;
455 453
456 f->setImplicit (!isPrimary()); 454 f->setImplicit (!isPrimary());
457 455
458 // Iterate through this file and check for errors. If there's any that stems 456 // Iterate through this file and check for errors. If there's any that stems
459 // from unknown file references, try resolve that by downloading the reference. 457 // from unknown file references, try resolve that by downloading the reference.
460 // This is why downloading a part may end up downloading multiple files, as 458 // This is why downloading a part may end up downloading multiple files, as
461 // it resolves dependencies. 459 // it resolves dependencies.
462 for (LDObject* obj : f->getObjects()) 460 for (LDObject* obj : f->objects())
463 { 461 {
464 LDError* err = dynamic_cast<LDError*> (obj); 462 LDError* err = dynamic_cast<LDError*> (obj);
465 463
466 if (!err || err->getFileReferenced().isEmpty()) 464 if (err == null || err->fileReferenced().isEmpty())
467 continue; 465 continue;
468 466
469 QString dest = err->getFileReferenced(); 467 QString dest = err->fileReferenced();
470 getPrompt()->modifyDestination (dest); 468 prompt()->modifyDestination (dest);
471 getPrompt()->downloadFile (dest, g_unofficialLibraryURL + dest, false); 469 prompt()->downloadFile (dest, g_unofficialLibraryURL + dest, false);
472 } 470 }
473 471
474 if (isPrimary()) 472 if (isPrimary())
475 { 473 {
476 addRecentFile (getFilePath()); 474 addRecentFile (filePath());
477 getPrompt()->setPrimaryFile (f); 475 prompt()->setPrimaryFile (f);
478 } 476 }
479 477
480 getPrompt()->checkIfFinished(); 478 prompt()->checkIfFinished();
481 } 479 }
482 480
483 // ============================================================================= 481 // =============================================================================
484 // 482 //
485 void PartDownloadRequest::downloadProgress (int64 recv, int64 total) 483 void PartDownloadRequest::downloadProgress (int64 recv, int64 total)
486 { 484 {
487 setBytesRead (recv); 485 setNumBytesRead (recv);
488 setBytesTotal (total); 486 setNumBytesTotal (total);
489 setState (EDownloading); 487 setState (EDownloading);
490 updateToTable(); 488 updateToTable();
491 } 489 }
492 490
493 // ============================================================================= 491 // =============================================================================
494 // 492 //
495 void PartDownloadRequest::readyRead() 493 void PartDownloadRequest::readyRead()
496 { 494 {
497 if (getState() == EFailed) 495 if (state() == EFailed)
498 return; 496 return;
499 497
500 if (getFilePointer() == null) 498 if (filePointer() == null)
501 { 499 {
502 replaceInFilePath ("\\", "/"); 500 m_filePath.replace ("\\", "/");
503 501
504 // We have already asked the user whether we can overwrite so we're good 502 // We have already asked the user whether we can overwrite so we're good
505 // to go here. 503 // to go here.
506 setFilePointer (new QFile (getFilePath().toLocal8Bit())); 504 setFilePointer (new QFile (filePath().toLocal8Bit()));
507 505
508 if (!getFilePointer()->open (QIODevice::WriteOnly)) 506 if (!filePointer()->open (QIODevice::WriteOnly))
509 { 507 {
510 critical (fmt (tr ("Couldn't open %1 for writing: %2"), getFilePath(), strerror (errno))); 508 critical (fmt (tr ("Couldn't open %1 for writing: %2"), filePath(), strerror (errno)));
511 setState (EFailed); 509 setState (EFailed);
512 getReply()->abort(); 510 networkReply()->abort();
513 updateToTable(); 511 updateToTable();
514 getPrompt()->checkIfFinished(); 512 prompt()->checkIfFinished();
515 return; 513 return;
516 } 514 }
517 } 515 }
518 516
519 getFilePointer()->write (getReply()->readAll()); 517 filePointer()->write (networkReply()->readAll());
520 } 518 }
521 519
522 // ============================================================================= 520 // =============================================================================
523 // 521 //
524 bool PartDownloadRequest::isFinished() const 522 bool PartDownloadRequest::isFinished() const
525 { 523 {
526 return getState() == EFinished || getState() == EFailed; 524 return state() == EFinished || state() == EFailed;
527 } 525 }
528 526
529 // ============================================================================= 527 // =============================================================================
530 // 528 //
531 void PartDownloadRequest::abort() 529 void PartDownloadRequest::abort()
532 { 530 {
533 getReply()->abort(); 531 networkReply()->abort();
534 } 532 }
535 533
536 // ============================================================================= 534 // =============================================================================
537 // 535 //
538 DEFINE_ACTION (DownloadFrom, 0) 536 DEFINE_ACTION (DownloadFrom, 0)

mercurial