patchdownloader.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #include "models/patchdownloader.h"
  2. #include "models/settings.h"
  3. #include "models/filesystem.h"
  4. #include <QUrlQuery>
  5. void PatchDownloader::init() {
  6. for (const QString& patch: patches_) {
  7. Downloader* patch_downloader = new Downloader(this);
  8. patch_downloaders_[patch] = patch_downloader;
  9. patch_downloaders_status_[patch_downloader] = Downloader::Status();
  10. QObject::connect(patch_downloader, &Downloader::progressChanged, this, &PatchDownloader::onDownloaderProgressChanged);
  11. QObject::connect(patch_downloader, &Downloader::downloadFinished, this, &PatchDownloader::onDownloaderFinished);
  12. }
  13. }
  14. PatchDownloader::~PatchDownloader()
  15. {
  16. for (const QString& patch: patches_) {
  17. patch_downloaders_[patch]->deleteLater();
  18. }
  19. }
  20. PatchDownloader::PatchDownloader() {
  21. // Does nothing
  22. }
  23. void PatchDownloader::startPatchDownloaderChain() {
  24. if (started_) {
  25. qCritical() << "PatchDwnlder: Tried to start patch downloader chain while other was already running!";
  26. }
  27. emit started();
  28. started_ = true;
  29. checkForUpdates();
  30. downloadDatabases();
  31. started_ = false;
  32. emit finished();
  33. }
  34. void PatchDownloader::onDownloaderProgressChanged(Downloader* context, Downloader::Status progress) {
  35. patch_downloaders_status_[context] = progress;
  36. Downloader::Status cumulative_status;
  37. for (const Downloader::Status& status: patch_downloaders_status_.values()) {
  38. cumulative_status = cumulative_status + status;
  39. }
  40. emit progressChanged(cumulative_status);
  41. }
  42. void PatchDownloader::onDownloaderFinished(Downloader* context) {
  43. context->targetFile->close();
  44. context->targetFile->deleteLater();
  45. context->targetFile = nullptr;
  46. Settings::setValue("DatabaseNeedInstall/" + patch_downloaders_.key(context), true);
  47. }
  48. void PatchDownloader::checkForUpdates() {
  49. qDebug() << __FUNCTION__ << "Started check for updates!";
  50. QUrlQuery query; // query for building GET-request aka patch-version
  51. for (const QString& patch: patches_) {
  52. query.addQueryItem(patch, "100");
  53. }
  54. QUrl target_url;
  55. target_url.setUrl(Settings::getValue("Network/patch_updates_url").toString());
  56. target_url.setQuery(query);
  57. QByteArray target_array;
  58. Downloader downloader;
  59. downloader.setUrl(target_url);
  60. downloader.targetBytearray = &target_array;
  61. downloader.start();
  62. downloader.waitForDownloaded();
  63. if (target_array.isEmpty()) {
  64. qWarning() << __FUNCTION__ << "Cannot check for updates, target_array is empty!";
  65. return;
  66. }
  67. qDebug() << __FUNCTION__ << "Check for updates result: " << target_array;
  68. QStringList patch_info = QString(target_array).split('|');
  69. if (patch_info.size() != patches_.size()) {
  70. qCritical() << __FUNCTION__ << "Incorrect patches number! Data: " << patch_info;
  71. return;
  72. }
  73. for (int i = 0; i < patches_.size(); ++i) {
  74. const QString patch = patches_[i];
  75. const QStringList patch_data = patch_info[i].split(":::");
  76. if (patch_data.size() != 3) {
  77. qCritical() << __FUNCTION__ << "Incorrect patch entry size! Entry: " << patch_data;
  78. return;
  79. }
  80. QString patch_filename = Settings::getValue("General/PatchDownloadDir").toString() + "/" + patch + ".db";
  81. Settings::setValue("PatchDatabases/" + patch + "/url", patch_data[0]);
  82. Settings::setValue("PatchDatabases/" + patch + "/hashsum", patch_data[1]);
  83. Settings::setValue("PatchDatabases/" + patch + "/datetime", patch_data[2]);
  84. Settings::setValue("PatchDatabases/" + patch + "/path", patch_filename);
  85. }
  86. }
  87. void PatchDownloader::downloadDatabases() {
  88. for (const QString& patch: patches_) {
  89. QString target_filename = Settings::getValue("PatchDatabases/" + patch + "/path").toString();
  90. qDebug() << __FUNCTION__ << patch << ": Checking if there's need to download patch";
  91. if (!needDownloadDatabase(patch)) {
  92. qInfo() << patch << ": file " << target_filename << " is up-to-date, no need to download";
  93. continue;
  94. }
  95. FileSystem::createFilePath(target_filename);
  96. QFile* target_file = new QFile(target_filename);
  97. if (!target_file->open(QIODevice::ReadWrite | QIODevice::Truncate)) {
  98. qWarning() << __FUNCTION__ << patch << "Cannot open file " << target_filename;
  99. continue;
  100. }
  101. qInfo() << __FUNCTION__ << patch << ": beginning download of file " << target_filename;
  102. patch_downloaders_[patch]->setUrl(Settings::getValue("PatchDatabases/" + patch + "/url").toUrl());
  103. patch_downloaders_[patch]->targetFile = target_file;
  104. patch_downloaders_[patch]->start();
  105. }
  106. for (Downloader* patch_downloader: patch_downloaders_) {
  107. patch_downloader->waitForDownloaded();
  108. }
  109. }
  110. bool PatchDownloader::needDownloadDatabase(QString db_name)
  111. {
  112. QString patch_filename = Settings::getValue("PatchDatabases/" + db_name + "/path").toString();
  113. QString current_file_hash = FileSystem::fileHash(patch_filename);
  114. QString required_file_hash = Settings::getValue("PatchDatabases/" + db_name + "/hashsum").toString();
  115. return Settings::getValue("DatabaseDownload/" + db_name).toBool() && (current_file_hash != required_file_hash);
  116. }