PageRenderTime 25ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/src/downloadwidget.cpp

https://gitlab.com/dianara/dianara-dev
C++ | 312 lines | 218 code | 63 blank | 31 comment | 12 complexity | 3f1400860587dc1ec7446fd033641172 MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. * This file is part of Dianara
  3. * Copyright 2012-2020 JanKusanagi JRR <jancoding@gmx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the
  17. * Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .
  19. */
  20. #include "downloadwidget.h"
  21. DownloadWidget::DownloadWidget(QString fileUrl,
  22. PumpController *pumpController,
  23. QWidget *parent) : QFrame(parent)
  24. {
  25. m_pumpController = pumpController;
  26. m_fileUrl = fileUrl;
  27. this->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
  28. m_downloading = false;
  29. m_aborted = false;
  30. QFont infoFont;
  31. infoFont.setPointSize(infoFont.pointSize() - 1);
  32. m_infoLabel = new QLabel(this);
  33. m_infoLabel->setAlignment(Qt::AlignCenter);
  34. m_infoLabel->setFont(infoFont);
  35. m_infoLabel->hide();
  36. m_openButton = new QPushButton(QIcon::fromTheme("document-open",
  37. QIcon(":/images/button-open.png")),
  38. tr("Open",
  39. "Verb, as in: Open the downloaded file"),
  40. this);
  41. m_openButton->setFlat(true);
  42. m_openButton->hide();
  43. connect(m_openButton, &QAbstractButton::clicked,
  44. this, &DownloadWidget::openAttachment);
  45. m_downloadButton = new QPushButton(QIcon::fromTheme("download",
  46. QIcon(":/images/button-download.png")),
  47. tr("Download"),
  48. this);
  49. m_downloadButton->setToolTip("<b></b>"
  50. + tr("Save the attached file to your folders"));
  51. m_downloadButton->setFlat(true);
  52. connect(m_downloadButton, &QAbstractButton::clicked,
  53. this, &DownloadWidget::downloadAttachment);
  54. m_progressBar = new QProgressBar(this);
  55. m_progressBar->setValue(0);
  56. m_progressBar->hide(); // Initially hidden
  57. m_cancelButton = new QPushButton(QIcon::fromTheme("dialog-cancel",
  58. QIcon(":/images/button-cancel.png")),
  59. tr("Cancel"),
  60. this);
  61. m_cancelButton->hide();
  62. connect(m_cancelButton, &QAbstractButton::clicked,
  63. this, &DownloadWidget::cancelDownload);
  64. m_layout = new QHBoxLayout();
  65. m_layout->addWidget(m_infoLabel);
  66. m_layout->addWidget(m_openButton);
  67. m_layout->addWidget(m_downloadButton);
  68. m_layout->addWidget(m_progressBar);
  69. m_layout->addWidget(m_cancelButton);
  70. this->setLayout(m_layout);
  71. qDebug() << "DownloadWidget created";
  72. }
  73. DownloadWidget::~DownloadWidget()
  74. {
  75. qDebug() << "DownloadWidget destroyed";
  76. }
  77. void DownloadWidget::resetWidget()
  78. {
  79. m_downloadButton->show();
  80. m_progressBar->hide();
  81. m_openButton->setToolTip(QString());
  82. m_openButton->hide();
  83. m_cancelButton->hide();
  84. m_networkReply->disconnect();
  85. m_networkReply->deleteLater();
  86. disconnect(m_pumpController, &PumpController::downloadCompleted,
  87. this, &DownloadWidget::completeDownload);
  88. disconnect(m_pumpController, &PumpController::downloadFailed,
  89. this, &DownloadWidget::onDownloadFailed);
  90. m_downloadedFile.close();
  91. m_downloading = false;
  92. m_aborted = false;
  93. }
  94. void DownloadWidget::updateSuggestedFilename(QString newFilename)
  95. {
  96. m_suggestedFilename = newFilename;
  97. }
  98. ////////////////////////////////////////////////////////////////////////////
  99. ////////////////////////////////// SLOTS ///////////////////////////////////
  100. ////////////////////////////////////////////////////////////////////////////
  101. void DownloadWidget::downloadAttachment()
  102. {
  103. if (m_downloading)
  104. {
  105. qDebug() << "Already downloading!!";
  106. return;
  107. }
  108. QString filename;
  109. filename = QFileDialog::getSaveFileName(this,
  110. tr("Save File As..."),
  111. QDir::homePath() + "/"
  112. + m_suggestedFilename,
  113. tr("All files") + " (*)");
  114. if (!filename.isEmpty())
  115. {
  116. m_downloading = true;
  117. m_infoLabel->setText(QStringLiteral("..."));
  118. m_infoLabel->setToolTip(QString());
  119. m_infoLabel->show();
  120. m_downloadButton->hide();
  121. m_openButton->hide();
  122. m_progressBar->show();
  123. m_progressBar->setValue(0);
  124. m_progressBar->setToolTip(QString());
  125. m_cancelButton->show();
  126. m_downloadedFile.setFileName(filename);
  127. m_downloadedFile.open(QIODevice::WriteOnly);
  128. m_networkReply = this->m_pumpController->getMedia(m_fileUrl);
  129. connect(m_networkReply, &QIODevice::readyRead,
  130. this, &DownloadWidget::storeFileData);
  131. connect(m_networkReply, &QNetworkReply::downloadProgress,
  132. this, &DownloadWidget::updateProgressBar);
  133. connect(m_pumpController, &PumpController::downloadCompleted,
  134. this, &DownloadWidget::completeDownload);
  135. connect(m_pumpController, &PumpController::downloadFailed,
  136. this, &DownloadWidget::onDownloadFailed);
  137. }
  138. }
  139. void DownloadWidget::openAttachment()
  140. {
  141. /*
  142. * TODO: Open button could be visible from the start, and actually
  143. * download the file to temporary storage before opening it.
  144. * This would hide the Download button.
  145. * When download completes, a new "Save" button would appear, to
  146. * let the user save the temporary file to regular storage.
  147. */
  148. if (m_downloadedFile.exists())
  149. {
  150. QDesktopServices::openUrl(QUrl::fromLocalFile(m_downloadedFile.fileName()));
  151. }
  152. else
  153. {
  154. m_infoLabel->setText(tr("File not found!"));
  155. m_infoLabel->setToolTip(m_downloadedFile.fileName());
  156. m_openButton->hide();
  157. m_downloadButton->show(); // Chance to download again.
  158. }
  159. }
  160. void DownloadWidget::cancelDownload()
  161. {
  162. int confirmation = QMessageBox::question(this, tr("Abort download?"),
  163. tr("Do you want to stop "
  164. "downloading the attached "
  165. "file?"),
  166. tr("&Yes, stop"),
  167. tr("&No, continue"),
  168. QString(), 1, 1);
  169. if (confirmation == 0)
  170. {
  171. m_aborted = true;
  172. m_networkReply->abort();
  173. const QString abortMessage = tr("Download aborted");
  174. m_infoLabel->setText(abortMessage);
  175. m_pumpController->showStatusMessageAndLogIt(abortMessage
  176. + QStringLiteral("."));
  177. resetWidget();
  178. }
  179. else
  180. {
  181. qDebug() << "Confirmation cancelled, NOT stopping download";
  182. }
  183. }
  184. void DownloadWidget::completeDownload(QString url)
  185. {
  186. if (url == m_fileUrl // Ensure completed download is this download
  187. && !m_aborted) // And wasn't aborted
  188. {
  189. m_infoLabel->setText(tr("Download completed"));
  190. resetWidget(); // This also closes the file
  191. // FIXME: pass this through GlobalObject
  192. m_pumpController->showStatusMessageAndLogIt(tr("Attachment downloaded "
  193. "successfully to %1",
  194. "%1 = filename")
  195. .arg(m_downloadedFile.fileName()));
  196. m_openButton->setToolTip("<b></b>"
  197. + tr("Open the downloaded attachment with "
  198. "your system's default program for "
  199. "this type of file.")
  200. + "<br /><br />"
  201. + m_downloadedFile.fileName());
  202. m_openButton->show();
  203. m_downloadButton->hide();
  204. }
  205. }
  206. void DownloadWidget::onDownloadFailed(QString url)
  207. {
  208. if (url == m_fileUrl) // Ensure failed download is this download
  209. {
  210. m_infoLabel->setText(tr("Download failed"));
  211. m_infoLabel->setToolTip(url);
  212. qDebug() << "Download FAILED!" << url;
  213. resetWidget();
  214. // FIXME: pass this through GlobalObject
  215. m_pumpController->showStatusMessageAndLogIt(tr("Downloading attachment "
  216. "failed: %1",
  217. "%1 = filename")
  218. .arg(this->m_downloadedFile.fileName()),
  219. url);
  220. }
  221. }
  222. void DownloadWidget::storeFileData()
  223. {
  224. QByteArray data = m_networkReply->readAll();
  225. int httpStatus = m_networkReply->attribute(QNetworkRequest::HttpStatusCodeAttribute)
  226. .toInt();
  227. if (httpStatus == 200)
  228. {
  229. m_downloadedFile.write(data);
  230. qDebug() << "Storing data into:" << m_downloadedFile.fileName();
  231. qDebug() << data.length() << "bytes";
  232. }
  233. else
  234. {
  235. qDebug() << "Not storing data into:" << m_downloadedFile.fileName();
  236. qDebug() << "Because HTTP status code is:" << httpStatus;
  237. }
  238. }
  239. void DownloadWidget::updateProgressBar(qint64 received, qint64 total)
  240. {
  241. m_progressBar->setRange(0, total);
  242. m_progressBar->setValue(received);
  243. m_infoLabel->setText(tr("Downloading %1 KiB...")
  244. .arg(QLocale::system().toString(total / 1024)));
  245. QString downloadedTooltip = tr("%1 KiB downloaded")
  246. .arg(QLocale::system().toString(received / 1024));
  247. m_infoLabel->setToolTip(downloadedTooltip);
  248. m_progressBar->setToolTip(downloadedTooltip);
  249. }