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 |
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 // ============================================================================= |
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) |