diff --git a/CMakeLists.txt b/CMakeLists.txt index 22b8328066..3272b7365c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -356,7 +356,6 @@ if (Qt5WebEngineWidgets_FOUND AND ENABLE_QTWEBENGINE) ${otter_src} src/modules/backends/web/qtwebengine/QtWebEnginePage.cpp src/modules/backends/web/qtwebengine/QtWebEngineUrlRequestInterceptor.cpp - src/modules/backends/web/qtwebengine/QtWebEngineTransfer.cpp src/modules/backends/web/qtwebengine/QtWebEngineWebBackend.cpp src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp ) diff --git a/src/core/TransfersManager.cpp b/src/core/TransfersManager.cpp index 3b83bac996..2c074abda8 100644 --- a/src/core/TransfersManager.cpp +++ b/src/core/TransfersManager.cpp @@ -226,9 +226,6 @@ void Transfer::start(QNetworkReply *reply, const QString &target) } m_device->reset(); - - m_mimeType = mimeDatabase.mimeTypeForData(m_device); - m_device->seek(m_device->size()); handleDataAvailable(); @@ -243,11 +240,6 @@ void Transfer::start(QNetworkReply *reply, const QString &target) if (target.isEmpty()) { - if (!SettingsManager::getOption(SettingsManager::Browser_AlwaysAskWhereToSaveDownloadOption).toBool()) - { - m_options |= IsQuickTransferOption; - } - const QString directory(m_options.testFlag(IsQuickTransferOption) ? Utils::normalizePath(SettingsManager::getOption(SettingsManager::Paths_DownloadsOption).toString()) : QString()); const QString fileName(getSuggestedFileName()); @@ -896,6 +888,20 @@ bool Transfer::setTarget(const QString &target, bool canOverwriteExisting) return false; } + else if (result == QMessageBox::Yes) + { + const QFileInfo information(target); + const QString path(Utils::getSavePath(information.fileName(), information.path(), {}, false).path); + + if (path.isEmpty()) + { + cancel(); + + return false; + } + + mutableTarget = path; + } } if (!m_device) @@ -1175,7 +1181,8 @@ TransfersManager* TransfersManager::getInstance() return m_instance; } -Transfer* TransfersManager::startTransfer(const QUrl &source, const QString &target, Transfer::TransferOptions options) +Transfer* TransfersManager::startTransfer(const QUrl &source, const QString target, Transfer::TransferOptions options, + std::function startCallback) { QNetworkRequest request; request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork); @@ -1184,16 +1191,31 @@ Transfer* TransfersManager::startTransfer(const QUrl &source, const QString &tar request.setUrl(QUrl(source)); Transfer *transfer(new Transfer(options, m_instance)); - transfer->start(NetworkManagerFactory::getNetworkManager(options.testFlag(Transfer::IsPrivateOption))->get(request), target); - if (transfer->getState() == Transfer::CancelledState) - { - transfer->deleteLater(); + QNetworkReply *reply = NetworkManagerFactory::getNetworkManager(options.testFlag(Transfer::IsPrivateOption))->get(request); + QObject *ctx = new QObject(); - return nullptr; - } + connect(reply, &QNetworkReply::metaDataChanged, + ctx, [ctx, transfer, reply, request, target, startCallback]() { + delete ctx; - addTransfer(transfer); + transfer->start(reply, target); + + if (transfer->getState() == Transfer::CancelledState || + transfer->getState() == Transfer::ErrorState) + { + transfer->deleteLater(); + + return nullptr; + } + + addTransfer(transfer); + + if (startCallback) + { + startCallback(transfer); + } + }); return transfer; } diff --git a/src/core/TransfersManager.h b/src/core/TransfersManager.h index f48d110758..cd31d646e1 100644 --- a/src/core/TransfersManager.h +++ b/src/core/TransfersManager.h @@ -148,7 +148,7 @@ class TransfersManager final : public QObject static void addTransfer(Transfer *transfer); static void clearTransfers(int period = 0); static TransfersManager* getInstance(); - static Transfer* startTransfer(const QUrl &source, const QString &target = {}, Transfer::TransferOptions options = Transfer::CanAskForPathOption); + static Transfer* startTransfer(const QUrl &source, const QString target = {}, Transfer::TransferOptions options = Transfer::CanAskForPathOption, std::function startCallback = nullptr); static Transfer* startTransfer(const QNetworkRequest &request, const QString &target = {}, Transfer::TransferOptions options = Transfer::CanAskForPathOption); static Transfer* startTransfer(QNetworkReply *reply, const QString &target = {}, Transfer::TransferOptions options = Transfer::CanAskForPathOption); static QVector getTransfers(); diff --git a/src/core/Utils.cpp b/src/core/Utils.cpp index 437f8f2211..6a89914969 100644 --- a/src/core/Utils.cpp +++ b/src/core/Utils.cpp @@ -651,6 +651,8 @@ SaveInformation getSavePath(const QString &fileName, const QString &directory, Q if (dialog.exec() == QDialog::Rejected || dialog.selectedFiles().isEmpty()) { + path.clear(); + break; } diff --git a/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.cpp b/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.cpp deleted file mode 100644 index 21aa8706f3..0000000000 --- a/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/************************************************************************** -* Otter Browser: Web browser controlled by the user, not vice-versa. -* Copyright (C) 2016 - 2019 Michal Dutkiewicz aka Emdek -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -* -**************************************************************************/ - -#include "QtWebEngineTransfer.h" - -#include -#include - -namespace Otter -{ - -QtWebEngineTransfer::QtWebEngineTransfer(QWebEngineDownloadItem *item, TransferOptions options, QObject *parent) : Transfer(options, parent), - m_item(item), - m_suggestedFileName(QFileInfo(item->path()).fileName()) -{ - m_item->accept(); - m_item->setParent(this); - - markAsStarted(); - - connect(m_item, &QWebEngineDownloadItem::finished, this, &QtWebEngineTransfer::markAsFinished); - connect(m_item, &QWebEngineDownloadItem::downloadProgress, this, &QtWebEngineTransfer::handleDownloadProgress); - connect(m_item, &QWebEngineDownloadItem::stateChanged, this, [&](QWebEngineDownloadItem::DownloadState state) - { - switch (state) - { - case QWebEngineDownloadItem::DownloadCancelled: - case QWebEngineDownloadItem::DownloadCompleted: - case QWebEngineDownloadItem::DownloadInterrupted: - emit stopped(); - - break; - default: - break; - } - - emit changed(); - }); -} - -void QtWebEngineTransfer::cancel() -{ - if (m_item) - { - m_item->cancel(); - m_item->deleteLater(); - } - else - { - Transfer::cancel(); - } -} - -QUrl QtWebEngineTransfer::getSource() const -{ - if (!m_item) - { - return Transfer::getSource(); - } - - return m_item->url(); -} - -QString QtWebEngineTransfer::getSuggestedFileName() -{ - return m_suggestedFileName; -} - -QString QtWebEngineTransfer::getTarget() const -{ - if (!m_item) - { - return Transfer::getTarget(); - } - - return m_item->path(); -} - -QMimeType QtWebEngineTransfer::getMimeType() const -{ - if (!m_item) - { - return Transfer::getMimeType(); - } - - return QMimeDatabase().mimeTypeForName(m_item->mimeType()); -} - -qint64 QtWebEngineTransfer::getBytesReceived() const -{ - if (!m_item) - { - return Transfer::getBytesReceived(); - } - - return m_item->receivedBytes(); -} - -qint64 QtWebEngineTransfer::getBytesTotal() const -{ - if (!m_item) - { - return Transfer::getBytesTotal(); - } - - return m_item->totalBytes(); -} - -Transfer::TransferState QtWebEngineTransfer::getState() const -{ - if (!m_item) - { - return Transfer::getState(); - } - - switch (m_item->state()) - { - case QWebEngineDownloadItem::DownloadRequested: - case QWebEngineDownloadItem::DownloadInProgress: - return RunningState; - case QWebEngineDownloadItem::DownloadCompleted: - return FinishedState; - case QWebEngineDownloadItem::DownloadCancelled: - return CancelledState; - case QWebEngineDownloadItem::DownloadInterrupted: - return ErrorState; - default: - return UnknownState; - } - - return UnknownState; -} - -bool QtWebEngineTransfer::setTarget(const QString &target, bool canOverwriteExisting) -{ - if (!m_item) - { - return Transfer::setTarget(target, canOverwriteExisting); - } - - m_item->setPath(target); - - return true; -} - -} diff --git a/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.h b/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.h deleted file mode 100644 index 52981d8bc7..0000000000 --- a/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.h +++ /dev/null @@ -1,56 +0,0 @@ -/************************************************************************** -* Otter Browser: Web browser controlled by the user, not vice-versa. -* Copyright (C) 2016 - 2019 Michal Dutkiewicz aka Emdek -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -* -**************************************************************************/ - -#ifndef OTTER_QTWEBENGINETRANSFER_H -#define OTTER_QTWEBENGINETRANSFER_H - -#include "../../../../core/TransfersManager.h" - -#include - -namespace Otter -{ - -class QtWebEngineTransfer final : public Transfer -{ - Q_OBJECT - -public: - explicit QtWebEngineTransfer(QWebEngineDownloadItem *item, TransferOptions options = CanAskForPathOption, QObject *parent = nullptr); - - QUrl getSource() const override; - QString getSuggestedFileName() override; - QString getTarget() const override; - QMimeType getMimeType() const override; - qint64 getBytesReceived() const override; - qint64 getBytesTotal() const override; - TransferState getState() const override; - -public slots: - void cancel() override; - bool setTarget(const QString &target, bool canOverwriteExisting = false) override; - -private: - QPointer m_item; - QString m_suggestedFileName; -}; - -} - -#endif diff --git a/src/modules/backends/web/qtwebengine/QtWebEngineWebBackend.cpp b/src/modules/backends/web/qtwebengine/QtWebEngineWebBackend.cpp index 3df3502a52..1a41fb2a66 100644 --- a/src/modules/backends/web/qtwebengine/QtWebEngineWebBackend.cpp +++ b/src/modules/backends/web/qtwebengine/QtWebEngineWebBackend.cpp @@ -20,7 +20,6 @@ #include "QtWebEngineWebBackend.h" #include "QtWebEnginePage.h" -#include "QtWebEngineTransfer.h" #include "QtWebEngineUrlRequestInterceptor.h" #include "QtWebEngineWebWidget.h" #include "../../../../core/ContentFiltersManager.h" @@ -36,6 +35,7 @@ #include #include +#include #include #include #include @@ -67,77 +67,11 @@ void QtWebEngineWebBackend::handleDownloadRequested(QWebEngineDownloadItem *item return; } - const QWebEngineProfile *profile(qobject_cast(sender())); - QtWebEngineTransfer *transfer(new QtWebEngineTransfer(item, (Transfer::CanNotifyOption | ((profile && profile->isOffTheRecord()) ? Transfer::IsPrivateOption : Transfer::NoOption)))); - - if (transfer->getState() == Transfer::CancelledState) - { - transfer->deleteLater(); - - return; - } - QtWebEnginePage *page(qobject_cast(item->page())); if (page && page->getWebWidget()) { - page->getWebWidget()->startTransfer(transfer); - - return; - } - - const HandlersManager::HandlerDefinition handler(HandlersManager::getHandler(transfer->getMimeType())); - - switch (handler.transferMode) - { - case HandlersManager::HandlerDefinition::IgnoreTransfer: - transfer->cancel(); - transfer->deleteLater(); - - break; - case HandlersManager::HandlerDefinition::AskTransfer: - TransferDialog(transfer).exec(); - - break; - case HandlersManager::HandlerDefinition::OpenTransfer: - transfer->setOpenCommand(handler.openCommand); - - TransfersManager::addTransfer(transfer); - - break; - case HandlersManager::HandlerDefinition::SaveTransfer: - transfer->setTarget(handler.downloadsPath + QDir::separator() + transfer->getSuggestedFileName()); - - if (transfer->getState() == Transfer::CancelledState) - { - TransfersManager::addTransfer(transfer); - } - else - { - transfer->deleteLater(); - } - - break; - case HandlersManager::HandlerDefinition::SaveAsTransfer: - { - const QString path(Utils::getSavePath(transfer->getSuggestedFileName(), handler.downloadsPath, {}, true).path); - - if (path.isEmpty()) - { - transfer->cancel(); - transfer->deleteLater(); - - return; - } - - transfer->setTarget(path); - - TransfersManager::addTransfer(transfer); - } - - break; - default: - break; + page->getWebWidget()->startTransfer(item->url(), QMimeDatabase().mimeTypeForName(item->mimeType()), QFileInfo(item->path()).fileName()); } } diff --git a/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp b/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp index ebd39f7f49..ea1802199a 100644 --- a/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp +++ b/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp @@ -341,11 +341,11 @@ void QtWebEngineWebWidget::triggerAction(int identifier, const QVariantMap ¶ break; case ActionsManager::SaveLinkToDiskAction: - startTransfer(TransfersManager::startTransfer(m_hitResult.linkUrl.toString(), {}, (Transfer::CanNotifyOption | (isPrivate() ? Transfer::IsPrivateOption : Transfer::NoOption)))); + startSaveAsTransfer(m_hitResult.linkUrl.toString()); break; case ActionsManager::SaveLinkToDownloadsAction: - TransfersManager::startTransfer(m_hitResult.linkUrl.toString(), {}, (Transfer::CanNotifyOption | Transfer::CanAskForPathOption | Transfer::IsQuickTransferOption | (isPrivate() ? Transfer::IsPrivateOption : Transfer::NoOption))); + startDownloadsTransfer(m_hitResult.linkUrl.toString()); break; case ActionsManager::OpenFrameAction: diff --git a/src/ui/TransferDialog.cpp b/src/ui/TransferDialog.cpp index 09f4310289..aa9c4fc9aa 100644 --- a/src/ui/TransferDialog.cpp +++ b/src/ui/TransferDialog.cpp @@ -55,7 +55,8 @@ TransferDialog::TransferDialog(Transfer *transfer, QWidget *parent) : Dialog(par } m_ui->nameTextLabelWidget->setText(fileName); - m_ui->typeTextLabelWidget->setText(transfer->getMimeType().comment()); + const QMimeType mimeType(transfer->getMimeType()); + m_ui->typeTextLabelWidget->setText(mimeType.comment() == "unknown" ? mimeType.name() : mimeType.comment()); m_ui->fromTextLabelWidget->setText(Utils::extractHost(transfer->getSource())); m_ui->openWithComboBoxWidget->setMimeType(transfer->getMimeType()); @@ -157,8 +158,6 @@ void TransferDialog::handleButtonClicked(QAbstractButton *button) } } - TransfersManager::addTransfer(m_transfer); - accept(); } diff --git a/src/ui/WebWidget.cpp b/src/ui/WebWidget.cpp index e729566590..494ed19602 100644 --- a/src/ui/WebWidget.cpp +++ b/src/ui/WebWidget.cpp @@ -151,75 +151,82 @@ void WebWidget::startReloadTimer() } } -void WebWidget::startTransfer(Transfer *transfer) +void WebWidget::startSaveAsTransfer(const QUrl url) { - if (transfer->getState() == Transfer::CancelledState) - { - transfer->deleteLater(); + QString suggestedFilename = QFileInfo(url.toString()).fileName(); + const QString directory(Utils::normalizePath(SettingsManager::getOption(SettingsManager::Paths_DownloadsOption).toString())); + const SaveInformation saveInfo = Utils::getSavePath(suggestedFilename, directory, {}, true); + if (!saveInfo.canSave) + { return; } + QString target = saveInfo.path; + TransfersManager::startTransfer(url, target, Transfer::CanNotifyOption | Transfer::CanOverwriteOption | (isPrivate() ? Transfer::IsPrivateOption : Transfer::NoOption)); +} - const HandlersManager::HandlerDefinition handler(HandlersManager::getHandler(transfer->getMimeType())); - - switch (handler.transferMode) - { - case HandlersManager::HandlerDefinition::IgnoreTransfer: - transfer->cancel(); - transfer->deleteLater(); +void WebWidget::startDownloadsTransfer(const QUrl url) +{ + QString suggestedFilename = QFileInfo(url.toString()).fileName(); + const QString directory(Utils::normalizePath(SettingsManager::getOption(SettingsManager::Paths_DownloadsOption).toString())); - break; - case HandlersManager::HandlerDefinition::AskTransfer: - { - TransferDialog *transferDialog(new TransferDialog(transfer, this)); - ContentsDialog *dialog(new ContentsDialog(ThemesManager::createIcon(QLatin1String("download")), transferDialog->windowTitle(), QString(), QString(), QDialogButtonBox::NoButton, transferDialog, this)); + QString target = directory + QDir::separator() + suggestedFilename; + TransfersManager::startTransfer(url, target, Transfer::CanNotifyOption | Transfer::CanAskForPathOption | Transfer::IsQuickTransferOption | (isPrivate() ? Transfer::IsPrivateOption : Transfer::NoOption)); +} - connect(transferDialog, &TransferDialog::finished, dialog, &ContentsDialog::close); +void WebWidget::startTransfer(const QUrl url, QMimeType mimeType, QString suggestedFilename) +{ + const HandlersManager::HandlerDefinition handler(HandlersManager::getHandler(mimeType)); - showDialog(dialog, false); - } + if (handler.transferMode == HandlersManager::HandlerDefinition::IgnoreTransfer) + { + return; + } - break; - case HandlersManager::HandlerDefinition::OpenTransfer: - transfer->setOpenCommand(handler.openCommand); + QString target; + Transfer::TransferOptions transferOptions = Transfer::CanNotifyOption; - TransfersManager::addTransfer(transfer); + switch (handler.transferMode) + { + case HandlersManager::HandlerDefinition::OpenTransfer: + transferOptions |= Transfer::HasToOpenAfterFinishOption; - break; - case HandlersManager::HandlerDefinition::SaveTransfer: - transfer->setTarget(handler.downloadsPath + QDir::separator() + transfer->getSuggestedFileName()); + break; + case HandlersManager::HandlerDefinition::SaveTransfer: + target = handler.downloadsPath + QDir::separator() + suggestedFilename; - if (transfer->getState() == Transfer::CancelledState) - { - TransfersManager::addTransfer(transfer); - } - else - { - transfer->deleteLater(); - } - - break; - case HandlersManager::HandlerDefinition::SaveAsTransfer: - { - const QString path(Utils::getSavePath(transfer->getSuggestedFileName(), handler.downloadsPath, {}, true).path); + break; + case HandlersManager::HandlerDefinition::SaveAsTransfer: + { + const SaveInformation saveInfo = Utils::getSavePath(suggestedFilename, handler.downloadsPath, {}, true); + if (!saveInfo.canSave) + { + return; + } + target = saveInfo.path; - if (path.isEmpty()) - { - transfer->cancel(); - transfer->deleteLater(); + break; + } + default: + break; + } - return; - } + TransfersManager::startTransfer(url, target, transferOptions, [this, handler](Transfer *transfer){ - transfer->setTarget(path, true); + if (handler.transferMode == HandlersManager::HandlerDefinition::OpenTransfer) + { + transfer->setOpenCommand(handler.openCommand); + } + else if (handler.transferMode == HandlersManager::HandlerDefinition::AskTransfer) + { + TransferDialog *transferDialog(new TransferDialog(transfer, this)); + ContentsDialog *dialog(new ContentsDialog(ThemesManager::createIcon(QLatin1String("download")), transferDialog->windowTitle(), QString(), QString(), QDialogButtonBox::NoButton, transferDialog, this)); - TransfersManager::addTransfer(transfer); - } + connect(transferDialog, &TransferDialog::finished, dialog, &ContentsDialog::close); - break; - default: - break; - } + showDialog(dialog, false); + } + }); } void WebWidget::clearOptions() diff --git a/src/ui/WebWidget.h b/src/ui/WebWidget.h index 974787cf78..1d4a2e244a 100644 --- a/src/ui/WebWidget.h +++ b/src/ui/WebWidget.h @@ -28,6 +28,7 @@ #include "../core/PasswordsManager.h" #include "../core/SessionsManager.h" #include "../core/SpellCheckManager.h" +#include "../core/TransfersManager.h" #include #include @@ -273,8 +274,10 @@ public slots: void timerEvent(QTimerEvent *event) override; void openUrl(const QUrl &url, SessionsManager::OpenHints hints); - void startReloadTimer(); - void startTransfer(Transfer *transfer); + void startReloadTimer(); + void startTransfer(const QUrl url, QMimeType mimeType, QString suggestedFilename); + void startSaveAsTransfer(const QUrl url); + void startDownloadsTransfer(const QUrl url); void handleToolTipEvent(QHelpEvent *event, QWidget *widget); void updateHitTestResult(const QPoint &position); virtual void updateWatchedData(ChangeWatcher watcher);