19#include "ui_downloadmanager.h"
41#include <QStandardPaths>
42#include <QWebEngineHistory>
43#include <QWebEngineDownloadRequest>
44#include <QtWebEngineWidgetsVersion>
49#include <QWinTaskbarButton>
50#include <QWinTaskbarProgress>
58 , m_lastDownloadOption(NoOption)
60 setWindowFlags(windowFlags() ^ Qt::WindowMaximizeButtonHint);
63 if (QtWin::isCompositionEnabled()) {
64 QtWin::extendFrameIntoClientArea(
this, -1, -1, -1, -1);
67 ui->clearButton->setIcon(QIcon::fromTheme(
QSL(
"edit-clear")));
70 connect(ui->clearButton, &QAbstractButton::clicked,
this, &DownloadManager::clearList);
72 auto* clearShortcut =
new QShortcut(QKeySequence(
QSL(
"CTRL+L")),
this);
73 connect(clearShortcut, &QShortcut::activated,
this, &DownloadManager::clearList);
86 m_downloadPath = settings.
value(
QSL(
"defaultDownloadPath"), QString()).toString();
87 m_lastDownloadPath = settings.
value(
QSL(
"lastDownloadPath"), QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)).toString();
88 m_closeOnFinish = settings.
value(
QSL(
"CloseManagerOnFinish"),
false).toBool();
91 m_useExternalManager = settings.
value(
QSL(
"UseExternalManager"),
false).toBool();
92 m_externalExecutable = settings.
value(
QSL(
"ExternalManagerExecutable"), QString()).toString();
93 m_externalArguments = settings.
value(
QSL(
"ExternalManagerArguments"), QString()).toString();
96 if (!m_externalArguments.contains(QLatin1String(
"%d"))) {
97 m_externalArguments.append(QLatin1String(
" %d"));
103 m_timer.start(500,
this);
110void DownloadManager::resizeEvent(QResizeEvent* e)
112 QWidget::resizeEvent(e);
116void DownloadManager::keyPressEvent(QKeyEvent* e)
118 if (e->key() == Qt::Key_Escape
119 || (e->key() == Qt::Key_W && e->modifiers() == Qt::ControlModifier)) {
123 QWidget::keyPressEvent(e);
126void DownloadManager::closeDownloadTab(QWebEngineDownloadRequest *item)
const
129 auto testWebView = [](
TabbedWebView *view,
const QUrl &url) {
137 if (page->history()->count() != 0) {
147 auto *page = qobject_cast<WebPage*>(item->page());
151 auto *view = qobject_cast<TabbedWebView*>(page->
view());
155 if (testWebView(view, QUrl())) {
160QWinTaskbarButton *DownloadManager::taskbarButton()
163 if (!m_taskbarButton) {
165 m_taskbarButton =
new QWinTaskbarButton(window ? window->windowHandle() : windowHandle());
166 m_taskbarButton->progress()->setRange(0, 100);
168 return m_taskbarButton;
176 QString arguments = m_externalArguments;
177 arguments.replace(QLatin1String(
"%d"), QString::fromUtf8(url.toEncoded()));
183void DownloadManager::timerEvent(QTimerEvent* e)
185 QVector<QTime> remTimes;
186 QVector<int> progresses;
187 QVector<double> speeds;
189 if (e->timerId() == m_timer.timerId()) {
190 if (!ui->list->count()) {
191 ui->speedLabel->clear();
192 setWindowTitle(tr(
"Download Manager"));
194 taskbarButton()->progress()->hide();
198 for (
int i = 0;
i < ui->list->count();
i++) {
199 auto* downItem = qobject_cast<DownloadItem*>(ui->list->itemWidget(ui->list->item(
i)));
200 if (!downItem || downItem->isCancelled() || !downItem->isDownloading()) {
203 progresses.append(downItem->progress());
204 remTimes.append(downItem->remainingTime());
205 speeds.append(downItem->currentSpeed());
207 if (remTimes.isEmpty()) {
212 for (
const QTime &time : std::as_const(remTimes)) {
213 if (time > remaining) {
219 for (
int prog : std::as_const(progresses)) {
222 progress = progress / progresses.count();
225 for (
double spee : std::as_const(speeds)) {
230 ui->speedLabel->setText(tr(
"%1% of %2 files (%3) %4 remaining").arg(QString::number(progress), QString::number(progresses.count()),
234 setWindowTitle(tr(
"%1% - Download Manager").arg(progress));
236 taskbarButton()->progress()->show();
237 taskbarButton()->progress()->setValue(progress);
241 QWidget::timerEvent(e);
244void DownloadManager::clearList()
246 QList<DownloadItem*> items;
247 for (
int i = 0;
i < ui->list->count();
i++) {
248 auto* downItem = qobject_cast<DownloadItem*>(ui->list->itemWidget(ui->list->item(
i)));
252 if (downItem->isDownloading()) {
255 items.append(downItem);
263 QElapsedTimer downloadTimer;
264 downloadTimer.start();
266 closeDownloadTab(downloadItem);
268 QString downloadPath;
269 bool openFile =
false;
271 const QString fileName = downloadItem->downloadFileName();
273 const bool forceAsk = downloadItem->savePageFormat() != QWebEngineDownloadRequest::UnknownSaveFormat
274 || downloadItem->isSavePageDownload();
276 if (m_useExternalManager) {
278 }
else if (forceAsk || m_downloadPath.isEmpty()) {
279 enum Result { Open = 1, Save = 2,
ExternalManager = 3, SavePage = 4, Unknown = 0 };
280 Result result = Unknown;
282 if (downloadItem->savePageFormat() != QWebEngineDownloadRequest::UnknownSaveFormat) {
285 }
else if (downloadItem->isSavePageDownload()) {
293 result = Result(optionsDialog.
exec());
304 downloadPath = QFileDialog::getSaveFileName(
mApp->activeWindow(), tr(
"Save file as..."), m_lastDownloadPath + QLatin1Char(
'/') + fileName);
306 if (!downloadPath.isEmpty()) {
307 m_lastDownloadPath = QFileInfo(downloadPath).absolutePath();
314 const QString mhtml = tr(
"MIME HTML Archive (*.mhtml)");
315 const QString htmlSingle = tr(
"HTML Page, single (*.html)");
316 const QString htmlComplete = tr(
"HTML Page, complete (*.html)");
317 const QString filter = QStringLiteral(
"%1;;%2;;%3").arg(mhtml, htmlSingle, htmlComplete);
319 QString selectedFilter;
320 downloadPath = QFileDialog::getSaveFileName(
mApp->activeWindow(), tr(
"Save page as..."),
321 m_lastDownloadPath + QLatin1Char(
'/') + fileName,
322 filter, &selectedFilter);
324 if (!downloadPath.isEmpty()) {
325 m_lastDownloadPath = QFileInfo(downloadPath).absolutePath();
329 QWebEngineDownloadRequest::SavePageFormat format = QWebEngineDownloadRequest::UnknownSaveFormat;
331 if (selectedFilter == mhtml) {
332 format = QWebEngineDownloadRequest::MimeHtmlSaveFormat;
333 }
else if (selectedFilter == htmlSingle) {
334 format = QWebEngineDownloadRequest::SingleHtmlSaveFormat;
335 }
else if (selectedFilter == htmlComplete) {
336 format = QWebEngineDownloadRequest::CompleteHtmlSaveFormat;
339 if (format != QWebEngineDownloadRequest::UnknownSaveFormat) {
340 downloadItem->setSavePageFormat(format);
351 downloadItem->cancel();
358 if (downloadPath.isEmpty()) {
359 downloadItem->cancel();
364 downloadItem->setDownloadDirectory(QFileInfo(downloadPath).absoluteDir().absolutePath());
365 downloadItem->setDownloadFileName(QFileInfo(downloadPath).fileName());
366 downloadItem->accept();
369 auto* listItem =
new QListWidgetItem(ui->list);
370 auto* downItem =
new DownloadItem(listItem, downloadItem, QFileInfo(downloadPath).absolutePath(), QFileInfo(downloadPath).fileName(), openFile,
this);
371 downItem->setDownTimer(downloadTimer);
372 downItem->startDownloading();
377 ui->list->setItemWidget(listItem, downItem);
378 listItem->setSizeHint(downItem->sizeHint());
381 m_activeDownloadsCount++;
387 return m_model->
count();
392 return m_activeDownloadsCount;
397 m_activeDownloadsCount = 0;
398 bool downloadingAllFilesFinished =
true;
399 for (
int i = 0;
i < ui->list->count();
i++) {
400 auto* downItem = qobject_cast<DownloadItem*>(ui->list->itemWidget(ui->list->item(
i)));
404 if (downItem->isDownloading()) {
405 m_activeDownloadsCount++;
407 if (downItem->isCancelled() || !downItem->isDownloading()) {
410 downloadingAllFilesFinished =
false;
415 if (downloadingAllFilesFinished) {
416 if (success && qApp->activeWindow() !=
this) {
417 mApp->desktopNotifications()->showNotification(QIcon::fromTheme(
QSL(
"download"), QIcon(
QSL(
":icons/other/download.svg"))).pixmap(48), tr(
"Falkon: Download Finished"), tr(
"All files have been successfully downloaded."));
418 if (!m_closeOnFinish) {
423 ui->speedLabel->clear();
424 setWindowTitle(tr(
"Download Manager"));
426 taskbarButton()->progress()->hide();
428 if (m_closeOnFinish) {
440 bool isDownloading =
false;
441 for (
int i = 0;
i < ui->list->count();
i++) {
442 auto* downItem = qobject_cast<DownloadItem*>(ui->list->itemWidget(ui->list->item(
i)));
446 if (downItem->isDownloading()) {
447 isDownloading =
true;
452 return !isDownloading;
457 return m_useExternalManager;
460void DownloadManager::closeEvent(QCloseEvent* e)
462 if (
mApp->windowCount() == 0) {
464 QMessageBox::StandardButton button = QMessageBox::warning(
this, tr(
"Warning"),
465 tr(
"Are you sure you want to quit? All uncompleted downloads will be cancelled!"), QMessageBox::Yes | QMessageBox::No);
466 if (button != QMessageBox::Yes) {
472 mApp->quitApplication();
TabWidget * tabWidget() const
int normalTabsCount() const
static QString path(Path type)
static QString remaingTimeToString(QTime time)
static QString currentSpeedToString(double speed)
void downloadFinished(bool success)
void deleteItem(DownloadItem *)
void download(QWebEngineDownloadRequest *downloadItem)
void startExternalManager(const QUrl &url)
int activeDownloadsCount() const
bool useExternalManager() const
int downloadsCount() const
DownloadManager(QWidget *parent=nullptr)
void downloadAdded(DownloadItem *item)
void downloadsCountChanged()
~DownloadManager() override
void removeDownload(DownloadItem *item)
void downloadAdded(DownloadItem *item)
void addDownload(DownloadItem *item)
void showExternalManagerOption(bool show)
void setLastDownloadOption(const DownloadManager::DownloadOption &option)
void beginGroup(const QString &prefix)
QVariant value(const QString &key, const QVariant &defaultValue=QVariant())
void setValue(const QString &key, const QVariant &defaultValue=QVariant())
void closeView() override
BrowserWindow * browserWindow() const
#define DEFAULT_DOWNLOAD_USE_NATIVE_DIALOG