From a3c73ca564ea8af34a62f9501121916775f4bc2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Thu, 7 Nov 2019 20:12:31 +0100 Subject: [PATCH 01/71] Rename --- src/core/AdblockContentFiltersProfile.cpp | 8 ++++---- src/core/AdblockContentFiltersProfile.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/AdblockContentFiltersProfile.cpp b/src/core/AdblockContentFiltersProfile.cpp index 24dd02fa10..ffa60a7efb 100644 --- a/src/core/AdblockContentFiltersProfile.cpp +++ b/src/core/AdblockContentFiltersProfile.cpp @@ -354,7 +354,7 @@ ContentFiltersManager::CheckResult AdblockContentFiltersProfile::checkUrlSubstri const QChar treeChar(subString.at(i)); bool childrenExists(false); - currentResult = evaluateRulesInNode(node, currentRule, request); + currentResult = evaluateNodeRules(node, currentRule, request); if (currentResult.isBlocked) { @@ -420,7 +420,7 @@ ContentFiltersManager::CheckResult AdblockContentFiltersProfile::checkUrlSubstri currentRule += treeChar; } - currentResult = evaluateRulesInNode(node, currentRule, request); + currentResult = evaluateNodeRules(node, currentRule, request); if (currentResult.isBlocked) { @@ -435,7 +435,7 @@ ContentFiltersManager::CheckResult AdblockContentFiltersProfile::checkUrlSubstri { if (node->children.at(i)->value == QLatin1Char('^')) { - currentResult = evaluateRulesInNode(node, currentRule, request); + currentResult = evaluateNodeRules(node, currentRule, request); if (currentResult.isBlocked) { @@ -736,7 +736,7 @@ QUrl AdblockContentFiltersProfile::getUpdateUrl() const return m_updateUrl; } -ContentFiltersManager::CheckResult AdblockContentFiltersProfile::evaluateRulesInNode(const Node *node, const QString ¤tRule, const Request &request) const +ContentFiltersManager::CheckResult AdblockContentFiltersProfile::evaluateNodeRules(const Node *node, const QString ¤tRule, const Request &request) const { ContentFiltersManager::CheckResult result; diff --git a/src/core/AdblockContentFiltersProfile.h b/src/core/AdblockContentFiltersProfile.h index 3a38c9044a..12c64867ce 100644 --- a/src/core/AdblockContentFiltersProfile.h +++ b/src/core/AdblockContentFiltersProfile.h @@ -141,7 +141,7 @@ class AdblockContentFiltersProfile final : public ContentFiltersProfile void deleteNode(Node *node) const; ContentFiltersManager::CheckResult checkUrlSubstring(const Node *node, const QString &subString, QString currentRule, const Request &request) const; ContentFiltersManager::CheckResult checkRuleMatch(const ContentBlockingRule *rule, const QString ¤tRule, const Request &request) const; - ContentFiltersManager::CheckResult evaluateRulesInNode(const Node *node, const QString ¤tRule, const Request &request) const; + ContentFiltersManager::CheckResult evaluateNodeRules(const Node *node, const QString ¤tRule, const Request &request) const; bool loadRules(); bool resolveDomainExceptions(const QString &url, const QStringList &ruleList) const; From 72bc6cb7e7900642c525ec83652121dc434c4914 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Fri, 8 Nov 2019 20:48:21 +0100 Subject: [PATCH 02/71] Move Rule declaration to Node --- src/core/AdblockContentFiltersProfile.cpp | 6 ++-- src/core/AdblockContentFiltersProfile.h | 34 +++++++++++------------ 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/core/AdblockContentFiltersProfile.cpp b/src/core/AdblockContentFiltersProfile.cpp index ffa60a7efb..bf62f7f6e5 100644 --- a/src/core/AdblockContentFiltersProfile.cpp +++ b/src/core/AdblockContentFiltersProfile.cpp @@ -272,7 +272,7 @@ void AdblockContentFiltersProfile::parseRuleLine(const QString &rule) } } - addRule(new ContentBlockingRule(rule, blockedDomains, allowedDomains, ruleOptions, ruleMatch, isException, needsDomainCheck), line); + addRule(new Node::Rule(rule, blockedDomains, allowedDomains, ruleOptions, ruleMatch, isException, needsDomainCheck), line); } void AdblockContentFiltersProfile::parseStyleSheetRule(const QStringList &line, QMultiHash &list) const @@ -285,7 +285,7 @@ void AdblockContentFiltersProfile::parseStyleSheetRule(const QStringList &line, } } -void AdblockContentFiltersProfile::addRule(ContentBlockingRule *rule, const QString &ruleString) const +void AdblockContentFiltersProfile::addRule(Node::Rule *rule, const QString &ruleString) const { Node *node(m_root); @@ -451,7 +451,7 @@ ContentFiltersManager::CheckResult AdblockContentFiltersProfile::checkUrlSubstri return result; } -ContentFiltersManager::CheckResult AdblockContentFiltersProfile::checkRuleMatch(const ContentBlockingRule *rule, const QString ¤tRule, const Request &request) const +ContentFiltersManager::CheckResult AdblockContentFiltersProfile::checkRuleMatch(const Node::Rule *rule, const QString ¤tRule, const Request &request) const { switch (rule->ruleMatch) { diff --git a/src/core/AdblockContentFiltersProfile.h b/src/core/AdblockContentFiltersProfile.h index 12c64867ce..a5b0f3d2e0 100644 --- a/src/core/AdblockContentFiltersProfile.h +++ b/src/core/AdblockContentFiltersProfile.h @@ -95,26 +95,26 @@ class AdblockContentFiltersProfile final : public ContentFiltersProfile ExactMatch }; - struct ContentBlockingRule final + struct Node final { - QString rule; - QStringList blockedDomains; - QStringList allowedDomains; - RuleOptions ruleOptions = NoOption; - RuleMatch ruleMatch = ContainsMatch; - bool isException = false; - bool needsDomainCheck = false; - - explicit ContentBlockingRule(const QString &ruleValue, const QStringList &blockedDomainsValue, const QStringList &allowedDomainsValue, RuleOptions ruleOptionsValue, RuleMatch ruleMatchValue, bool isExceptionValue, bool needsDomainCheckValue) : rule(ruleValue), blockedDomains(blockedDomainsValue), allowedDomains(allowedDomainsValue), ruleOptions(ruleOptionsValue), ruleMatch(ruleMatchValue), isException(isExceptionValue), needsDomainCheck(needsDomainCheckValue) + struct Rule final { - } - }; + QString rule; + QStringList blockedDomains; + QStringList allowedDomains; + RuleOptions ruleOptions = NoOption; + RuleMatch ruleMatch = ContainsMatch; + bool isException = false; + bool needsDomainCheck = false; + + explicit Rule(const QString &ruleValue, const QStringList &blockedDomainsValue, const QStringList &allowedDomainsValue, RuleOptions ruleOptionsValue, RuleMatch ruleMatchValue, bool isExceptionValue, bool needsDomainCheckValue) : rule(ruleValue), blockedDomains(blockedDomainsValue), allowedDomains(allowedDomainsValue), ruleOptions(ruleOptionsValue), ruleMatch(ruleMatchValue), isException(isExceptionValue), needsDomainCheck(needsDomainCheckValue) + { + } + }; - struct Node final - { QChar value = 0; QVarLengthArray children; - QVarLengthArray rules; + QVarLengthArray rules; }; struct Request final @@ -137,10 +137,10 @@ class AdblockContentFiltersProfile final : public ContentFiltersProfile void loadHeader(); void parseRuleLine(const QString &rule); void parseStyleSheetRule(const QStringList &line, QMultiHash &list) const; - void addRule(ContentBlockingRule *rule, const QString &ruleString) const; + void addRule(Node::Rule *rule, const QString &ruleString) const; void deleteNode(Node *node) const; ContentFiltersManager::CheckResult checkUrlSubstring(const Node *node, const QString &subString, QString currentRule, const Request &request) const; - ContentFiltersManager::CheckResult checkRuleMatch(const ContentBlockingRule *rule, const QString ¤tRule, const Request &request) const; + ContentFiltersManager::CheckResult checkRuleMatch(const Node::Rule *rule, const QString ¤tRule, const Request &request) const; ContentFiltersManager::CheckResult evaluateNodeRules(const Node *node, const QString ¤tRule, const Request &request) const; bool loadRules(); bool resolveDomainExceptions(const QString &url, const QStringList &ruleList) const; From 4a57d4080673334e30cced05c729625f909e39c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Sat, 9 Nov 2019 21:12:08 +0100 Subject: [PATCH 03/71] Drop addRule() --- src/core/AdblockContentFiltersProfile.cpp | 31 ++++++++++------------- src/core/AdblockContentFiltersProfile.h | 1 - 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/core/AdblockContentFiltersProfile.cpp b/src/core/AdblockContentFiltersProfile.cpp index bf62f7f6e5..10972e60d5 100644 --- a/src/core/AdblockContentFiltersProfile.cpp +++ b/src/core/AdblockContentFiltersProfile.cpp @@ -272,26 +272,11 @@ void AdblockContentFiltersProfile::parseRuleLine(const QString &rule) } } - addRule(new Node::Rule(rule, blockedDomains, allowedDomains, ruleOptions, ruleMatch, isException, needsDomainCheck), line); -} - -void AdblockContentFiltersProfile::parseStyleSheetRule(const QStringList &line, QMultiHash &list) const -{ - const QStringList domains(line.at(0).split(QLatin1Char(','))); - - for (int i = 0; i < domains.count(); ++i) - { - list.insert(domains.at(i), line.at(1)); - } -} - -void AdblockContentFiltersProfile::addRule(Node::Rule *rule, const QString &ruleString) const -{ Node *node(m_root); - for (int i = 0; i < ruleString.length(); ++i) + for (int i = 0; i < line.length(); ++i) { - const QChar value(ruleString.at(i)); + const QChar value(line.at(i)); bool childrenExists(false); for (int j = 0; j < node->children.count(); ++j) @@ -326,7 +311,17 @@ void AdblockContentFiltersProfile::addRule(Node::Rule *rule, const QString &rule } } - node->rules.append(rule); + node->rules.append(new Node::Rule(rule, blockedDomains, allowedDomains, ruleOptions, ruleMatch, isException, needsDomainCheck)); +} + +void AdblockContentFiltersProfile::parseStyleSheetRule(const QStringList &line, QMultiHash &list) const +{ + const QStringList domains(line.at(0).split(QLatin1Char(','))); + + for (int i = 0; i < domains.count(); ++i) + { + list.insert(domains.at(i), line.at(1)); + } } void AdblockContentFiltersProfile::deleteNode(Node *node) const diff --git a/src/core/AdblockContentFiltersProfile.h b/src/core/AdblockContentFiltersProfile.h index a5b0f3d2e0..92624e4935 100644 --- a/src/core/AdblockContentFiltersProfile.h +++ b/src/core/AdblockContentFiltersProfile.h @@ -137,7 +137,6 @@ class AdblockContentFiltersProfile final : public ContentFiltersProfile void loadHeader(); void parseRuleLine(const QString &rule); void parseStyleSheetRule(const QStringList &line, QMultiHash &list) const; - void addRule(Node::Rule *rule, const QString &ruleString) const; void deleteNode(Node *node) const; ContentFiltersManager::CheckResult checkUrlSubstring(const Node *node, const QString &subString, QString currentRule, const Request &request) const; ContentFiltersManager::CheckResult checkRuleMatch(const Node::Rule *rule, const QString ¤tRule, const Request &request) const; From cd37e687d90766566c0aa3237e128f9c19291e58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Sun, 10 Nov 2019 20:57:19 +0100 Subject: [PATCH 04/71] Use two sets of flags instead of one with big enum --- src/core/AdblockContentFiltersProfile.cpp | 15 +++++----- src/core/AdblockContentFiltersProfile.h | 35 +++++++++-------------- 2 files changed, 22 insertions(+), 28 deletions(-) diff --git a/src/core/AdblockContentFiltersProfile.cpp b/src/core/AdblockContentFiltersProfile.cpp index 10972e60d5..fda1758967 100644 --- a/src/core/AdblockContentFiltersProfile.cpp +++ b/src/core/AdblockContentFiltersProfile.cpp @@ -197,7 +197,8 @@ void AdblockContentFiltersProfile::parseRuleLine(const QString &rule) QStringList allowedDomains; QStringList blockedDomains; - RuleOptions ruleOptions; + RuleOptions ruleOptions(NoOption); + RuleOptions ruleExceptions(NoOption); RuleMatch ruleMatch(ContainsMatch); const bool isException(line.startsWith(QLatin1String("@@"))); @@ -247,7 +248,7 @@ void AdblockContentFiltersProfile::parseRuleLine(const QString &rule) } else if (option != WebSocketOption && option != PopupOption) { - ruleOptions |= static_cast(option * 2); + ruleExceptions |= option; } } else if (optionName.startsWith(QLatin1String("domain"))) @@ -311,7 +312,7 @@ void AdblockContentFiltersProfile::parseRuleLine(const QString &rule) } } - node->rules.append(new Node::Rule(rule, blockedDomains, allowedDomains, ruleOptions, ruleMatch, isException, needsDomainCheck)); + node->rules.append(new Node::Rule(rule, blockedDomains, allowedDomains, ruleOptions, ruleExceptions, ruleMatch, isException, needsDomainCheck)); } void AdblockContentFiltersProfile::parseStyleSheetRule(const QStringList &line, QMultiHash &list) const @@ -503,11 +504,11 @@ ContentFiltersManager::CheckResult AdblockContentFiltersProfile::checkRuleMatch( isBlocked = (hasAllowedDomains ? !resolveDomainExceptions(request.baseHost, rule->allowedDomains) : isBlocked); - if (rule->ruleOptions.testFlag(ThirdPartyExceptionOption) || rule->ruleOptions.testFlag(ThirdPartyOption)) + if (rule->ruleOptions.testFlag(ThirdPartyOption) || rule->ruleExceptions.testFlag(ThirdPartyOption)) { if (request.baseHost.isEmpty() || requestSubdomainList.contains(request.baseHost)) { - isBlocked = rule->ruleOptions.testFlag(ThirdPartyExceptionOption); + isBlocked = rule->ruleExceptions.testFlag(ThirdPartyOption); } else if (!hasBlockedDomains && !hasAllowedDomains) { @@ -523,7 +524,7 @@ ContentFiltersManager::CheckResult AdblockContentFiltersProfile::checkRuleMatch( { const bool supportsException(iterator.value() != WebSocketOption && iterator.value() != PopupOption); - if (rule->ruleOptions.testFlag(iterator.value()) || (supportsException && rule->ruleOptions.testFlag(static_cast(iterator.value() * 2)))) + if (rule->ruleOptions.testFlag(iterator.value()) || (supportsException && rule->ruleExceptions.testFlag(iterator.value()))) { if (request.resourceType == iterator.key()) { @@ -531,7 +532,7 @@ ContentFiltersManager::CheckResult AdblockContentFiltersProfile::checkRuleMatch( } else if (supportsException) { - isBlocked = (isBlocked ? rule->ruleOptions.testFlag(static_cast(iterator.value() * 2)) : isBlocked); + isBlocked = (isBlocked ? rule->ruleExceptions.testFlag(iterator.value()) : isBlocked); } else { diff --git a/src/core/AdblockContentFiltersProfile.h b/src/core/AdblockContentFiltersProfile.h index 92624e4935..a4db386e99 100644 --- a/src/core/AdblockContentFiltersProfile.h +++ b/src/core/AdblockContentFiltersProfile.h @@ -60,29 +60,21 @@ class AdblockContentFiltersProfile final : public ContentFiltersProfile bool isUpdating() const override; protected: - enum RuleOption : quint32 + enum RuleOption : quint16 { NoOption = 0, ThirdPartyOption = 1, - ThirdPartyExceptionOption = 2, - StyleSheetOption = 4, - StyleSheetExceptionOption = 8, - ScriptOption = 16, - ScriptExceptionOption = 32, - ImageOption = 64, - ImageExceptionOption = 128, - ObjectOption = 256, - ObjectExceptionOption = 512, - ObjectSubRequestOption = 1024, - ObjectSubRequestExceptionOption = 2048, - SubDocumentOption = 4096, - SubDocumentExceptionOption = 8192, - XmlHttpRequestOption = 16384, - XmlHttpRequestExceptionOption = 32768, - WebSocketOption = 65536, - PopupOption = 131072, - ElementHideOption = 262144, - GenericHideOption = 524288 + StyleSheetOption = 2, + ScriptOption = 4, + ImageOption = 8, + ObjectOption = 16, + ObjectSubRequestOption = 32, + SubDocumentOption = 64, + XmlHttpRequestOption = 128, + WebSocketOption = 256, + PopupOption = 512, + ElementHideOption = 1024, + GenericHideOption = 2048 }; Q_DECLARE_FLAGS(RuleOptions, RuleOption) @@ -103,11 +95,12 @@ class AdblockContentFiltersProfile final : public ContentFiltersProfile QStringList blockedDomains; QStringList allowedDomains; RuleOptions ruleOptions = NoOption; + RuleOptions ruleExceptions = NoOption; RuleMatch ruleMatch = ContainsMatch; bool isException = false; bool needsDomainCheck = false; - explicit Rule(const QString &ruleValue, const QStringList &blockedDomainsValue, const QStringList &allowedDomainsValue, RuleOptions ruleOptionsValue, RuleMatch ruleMatchValue, bool isExceptionValue, bool needsDomainCheckValue) : rule(ruleValue), blockedDomains(blockedDomainsValue), allowedDomains(allowedDomainsValue), ruleOptions(ruleOptionsValue), ruleMatch(ruleMatchValue), isException(isExceptionValue), needsDomainCheck(needsDomainCheckValue) + explicit Rule(const QString &ruleValue, const QStringList &blockedDomainsValue, const QStringList &allowedDomainsValue, RuleOptions ruleOptionsValue, RuleOptions ruleExceptionsValue, RuleMatch ruleMatchValue, bool isExceptionValue, bool needsDomainCheckValue) : rule(ruleValue), blockedDomains(blockedDomainsValue), allowedDomains(allowedDomainsValue), ruleOptions(ruleOptionsValue), ruleExceptions(ruleExceptionsValue), ruleMatch(ruleMatchValue), isException(isExceptionValue), needsDomainCheck(needsDomainCheckValue) { } }; From bfbf960fed20235ba4dc189534f2a4047c1d36e3 Mon Sep 17 00:00:00 2001 From: fnkkio <57486061+fnkkio@users.noreply.github.com> Date: Mon, 11 Nov 2019 21:56:25 +0200 Subject: [PATCH 05/71] Fix crashes after clearing the entire browsing history --- src/core/HistoryModel.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/HistoryModel.cpp b/src/core/HistoryModel.cpp index 1814ad6d8b..7d6157ac33 100644 --- a/src/core/HistoryModel.cpp +++ b/src/core/HistoryModel.cpp @@ -124,6 +124,9 @@ void HistoryModel::clearRecentEntries(uint period) { clear(); + m_urls.clear(); + m_identifiers.clear(); + emit cleared(); return; From 17d0df64fedb2313dff0c667c70fe6b261c4a277 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Mon, 11 Nov 2019 21:30:59 +0100 Subject: [PATCH 06/71] Set values directly on Rule instance --- src/core/AdblockContentFiltersProfile.cpp | 31 ++++++++++------------- src/core/AdblockContentFiltersProfile.h | 4 --- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/src/core/AdblockContentFiltersProfile.cpp b/src/core/AdblockContentFiltersProfile.cpp index fda1758967..44468322ca 100644 --- a/src/core/AdblockContentFiltersProfile.cpp +++ b/src/core/AdblockContentFiltersProfile.cpp @@ -195,35 +195,32 @@ void AdblockContentFiltersProfile::parseRuleLine(const QString &rule) return; } - QStringList allowedDomains; - QStringList blockedDomains; - RuleOptions ruleOptions(NoOption); - RuleOptions ruleExceptions(NoOption); - RuleMatch ruleMatch(ContainsMatch); - const bool isException(line.startsWith(QLatin1String("@@"))); + Node::Rule *definition(new Node::Rule()); + definition->rule = rule; + definition->isException = line.startsWith(QLatin1String("@@")); - if (isException) + if (definition->isException) { line = line.mid(2); } - const bool needsDomainCheck(line.startsWith(QLatin1String("||"))); + definition->needsDomainCheck = line.startsWith(QLatin1String("||")); - if (needsDomainCheck) + if (definition->needsDomainCheck) { line = line.mid(2); } if (line.startsWith(QLatin1Char('|'))) { - ruleMatch = StartMatch; + definition->ruleMatch = StartMatch; line = line.mid(1); } if (line.endsWith(QLatin1Char('|'))) { - ruleMatch = ((ruleMatch == StartMatch) ? ExactMatch : EndMatch); + definition->ruleMatch = ((definition->ruleMatch == StartMatch) ? ExactMatch : EndMatch); line = line.left(line.length() - 1); } @@ -237,18 +234,18 @@ void AdblockContentFiltersProfile::parseRuleLine(const QString &rule) { const RuleOption option(m_options.value(optionName)); - if ((!isException || optionException) && (option == ElementHideOption || option == GenericHideOption)) + if ((!definition->isException || optionException) && (option == ElementHideOption || option == GenericHideOption)) { continue; } if (!optionException) { - ruleOptions |= option; + definition->ruleOptions |= option; } else if (option != WebSocketOption && option != PopupOption) { - ruleExceptions |= option; + definition->ruleExceptions |= option; } } else if (optionName.startsWith(QLatin1String("domain"))) @@ -259,12 +256,12 @@ void AdblockContentFiltersProfile::parseRuleLine(const QString &rule) { if (parsedDomains.at(j).startsWith(QLatin1Char('~'))) { - allowedDomains.append(parsedDomains.at(j).mid(1)); + definition->allowedDomains.append(parsedDomains.at(j).mid(1)); continue; } - blockedDomains.append(parsedDomains.at(j)); + definition->blockedDomains.append(parsedDomains.at(j)); } } else @@ -312,7 +309,7 @@ void AdblockContentFiltersProfile::parseRuleLine(const QString &rule) } } - node->rules.append(new Node::Rule(rule, blockedDomains, allowedDomains, ruleOptions, ruleExceptions, ruleMatch, isException, needsDomainCheck)); + node->rules.append(definition); } void AdblockContentFiltersProfile::parseStyleSheetRule(const QStringList &line, QMultiHash &list) const diff --git a/src/core/AdblockContentFiltersProfile.h b/src/core/AdblockContentFiltersProfile.h index a4db386e99..59b7c1b740 100644 --- a/src/core/AdblockContentFiltersProfile.h +++ b/src/core/AdblockContentFiltersProfile.h @@ -99,10 +99,6 @@ class AdblockContentFiltersProfile final : public ContentFiltersProfile RuleMatch ruleMatch = ContainsMatch; bool isException = false; bool needsDomainCheck = false; - - explicit Rule(const QString &ruleValue, const QStringList &blockedDomainsValue, const QStringList &allowedDomainsValue, RuleOptions ruleOptionsValue, RuleOptions ruleExceptionsValue, RuleMatch ruleMatchValue, bool isExceptionValue, bool needsDomainCheckValue) : rule(ruleValue), blockedDomains(blockedDomainsValue), allowedDomains(allowedDomainsValue), ruleOptions(ruleOptionsValue), ruleExceptions(ruleExceptionsValue), ruleMatch(ruleMatchValue), isException(isExceptionValue), needsDomainCheck(needsDomainCheckValue) - { - } }; QChar value = 0; From a9c4a53b7a943afa2f58957ff9dd6f40b1fc5f71 Mon Sep 17 00:00:00 2001 From: fnkkio <57486061+fnkkio@users.noreply.github.com> Date: Tue, 12 Nov 2019 18:22:41 +0200 Subject: [PATCH 07/71] Ignore all types of empty URLs for BookmarkPageAction --- src/ui/ContentsWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/ContentsWidget.cpp b/src/ui/ContentsWidget.cpp index 95617f816d..18b37e7549 100644 --- a/src/ui/ContentsWidget.cpp +++ b/src/ui/ContentsWidget.cpp @@ -178,7 +178,7 @@ void ContentsWidget::triggerAction(int identifier, const QVariantMap ¶meters { const QUrl url(parameters.value(QLatin1String("url"), getUrl()).toUrl().adjusted(QUrl::RemovePassword)); - if (url.isEmpty()) + if (Utils::isUrlEmpty(url)) { break; } From 11e69f3fb402e1ca876c755884b9d986d64b929f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Tue, 12 Nov 2019 21:11:10 +0100 Subject: [PATCH 08/71] Disable BookmarkPageAction if URL is considered empty --- src/ui/WebWidget.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ui/WebWidget.cpp b/src/ui/WebWidget.cpp index 2f335cce5c..54309b3b2b 100644 --- a/src/ui/WebWidget.cpp +++ b/src/ui/WebWidget.cpp @@ -1338,7 +1338,12 @@ ActionsManager::ActionDefinition::State WebWidget::getActionState(int identifier break; case ActionsManager::BookmarkPageAction: - state.text = (BookmarksManager::hasBookmark(getUrl()) ? QCoreApplication::translate("actions", "Edit Bookmark…") : QCoreApplication::translate("actions", "Add Bookmark…")); + { + const QUrl url(getUrl()); + + state.text = (BookmarksManager::hasBookmark(url) ? QCoreApplication::translate("actions", "Edit Bookmark…") : QCoreApplication::translate("actions", "Add Bookmark…")); + state.isEnabled = !Utils::isUrlEmpty(url); + } break; case ActionsManager::LoadPluginsAction: From d0ce9e6b7309f5307720a2d49fbb40c88855e3a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Wed, 13 Nov 2019 20:02:42 +0100 Subject: [PATCH 09/71] Drop redundant this-> --- src/ui/WebWidget.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ui/WebWidget.cpp b/src/ui/WebWidget.cpp index 54309b3b2b..e729566590 100644 --- a/src/ui/WebWidget.cpp +++ b/src/ui/WebWidget.cpp @@ -1240,14 +1240,14 @@ ActionsManager::ActionDefinition::State WebWidget::getActionState(int identifier break; case ActionsManager::CutAction: - state.isEnabled = (this->hasSelection() && !getSelectedText().trimmed().isEmpty() && m_hitResult.flags.testFlag(HitTestResult::IsContentEditableTest)); + state.isEnabled = (hasSelection() && !getSelectedText().trimmed().isEmpty() && m_hitResult.flags.testFlag(HitTestResult::IsContentEditableTest)); break; case ActionsManager::CopyAction: case ActionsManager::CopyPlainTextAction: case ActionsManager::CopyToNoteAction: case ActionsManager::UnselectAction: - state.isEnabled = (this->hasSelection() && !getSelectedText().trimmed().isEmpty()); + state.isEnabled = (hasSelection() && !getSelectedText().trimmed().isEmpty()); break; case ActionsManager::PasteAction: @@ -1278,7 +1278,7 @@ ActionsManager::ActionDefinition::State WebWidget::getActionState(int identifier break; case ActionsManager::DeleteAction: - state.isEnabled = (m_hitResult.flags.testFlag(HitTestResult::IsContentEditableTest) && !m_hitResult.flags.testFlag(HitTestResult::IsEmptyTest) && this->hasSelection() && !getSelectedText().trimmed().isEmpty()); + state.isEnabled = (m_hitResult.flags.testFlag(HitTestResult::IsContentEditableTest) && !m_hitResult.flags.testFlag(HitTestResult::IsEmptyTest) && hasSelection() && !getSelectedText().trimmed().isEmpty()); break; case ActionsManager::SelectAllAction: From abf883ac9738d5b5f7e91e502fa11924ae953644 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Thu, 14 Nov 2019 20:46:12 +0100 Subject: [PATCH 10/71] Rename --- src/modules/widgets/address/AddressWidget.cpp | 24 +++++++++---------- src/modules/widgets/address/AddressWidget.h | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/modules/widgets/address/AddressWidget.cpp b/src/modules/widgets/address/AddressWidget.cpp index 5bb3e0063e..f5d0e46c34 100644 --- a/src/modules/widgets/address/AddressWidget.cpp +++ b/src/modules/widgets/address/AddressWidget.cpp @@ -318,14 +318,14 @@ AddressWidget::AddressWidget(Window *window, QWidget *parent) : LineEditWidget(p m_hints(SessionsManager::DefaultOpen), m_hasFeeds(false), m_isNavigatingCompletion(false), - m_isUsingSimpleMode(false), + m_isSimplified(false), m_wasEdited(false) { const ToolBarWidget *toolBar(qobject_cast(parent)); if (!toolBar) { - m_isUsingSimpleMode = true; + m_isSimplified = true; } setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); @@ -368,7 +368,7 @@ void AddressWidget::changeEvent(QEvent *event) switch (event->type()) { case QEvent::LanguageChange: - if (!m_isUsingSimpleMode) + if (!m_isSimplified) { setPlaceholderText(tr("Enter address or search…")); } @@ -403,7 +403,7 @@ void AddressWidget::paintEvent(QPaintEvent *event) style()->drawPrimitive(QStyle::PE_IndicatorArrowDown, &dropdownArrowOption, &painter, this); } - if (m_isUsingSimpleMode) + if (m_isSimplified) { return; } @@ -458,7 +458,7 @@ void AddressWidget::keyPressEvent(QKeyEvent *event) break; case Qt::Key_Enter: case Qt::Key_Return: - if (!m_isUsingSimpleMode) + if (!m_isSimplified) { handleUserInput(text().trimmed(), SessionsManager::calculateOpenHints(SessionsManager::CurrentTabOpen, Qt::LeftButton, event->modifiers())); } @@ -513,7 +513,7 @@ void AddressWidget::contextMenuEvent(QContextMenuEvent *event) menu.addAction(new Action(ActionsManager::CopyAction, {}, executor, &menu)); menu.addAction(new Action(ActionsManager::PasteAction, {}, executor, &menu)); - if (!m_isUsingSimpleMode) + if (!m_isSimplified) { menu.addAction(new Action(ActionsManager::PasteAndGoAction, {}, ActionExecutor::Object(m_window, m_window), this)); } @@ -864,7 +864,7 @@ void AddressWidget::handleOptionChanged(int identifier, const QVariant &value) break; case SettingsManager::AddressField_LayoutOption: - if (m_isUsingSimpleMode) + if (m_isSimplified) { m_layout = {AddressEntry, HistoryDropdownEntry}; } @@ -935,7 +935,7 @@ void AddressWidget::handleLoadingStateChanged() void AddressWidget::handleUserInput(const QString &text, SessionsManager::OpenHints hints) { - if (m_isUsingSimpleMode) + if (m_isSimplified) { return; } @@ -1244,7 +1244,7 @@ void AddressWidget::updateCompletion(bool isTypedHistory) types |= AddressCompletionModel::HistoryCompletionType; } - if (!m_isUsingSimpleMode && SettingsManager::getOption(SettingsManager::AddressField_SuggestSearchOption).toBool()) + if (!m_isSimplified && SettingsManager::getOption(SettingsManager::AddressField_SuggestSearchOption).toBool()) { types |= AddressCompletionModel::SearchSuggestionsCompletionType; } @@ -1366,7 +1366,7 @@ void AddressWidget::setWindow(Window *window) }); } } - else if (mainWindow && !mainWindow->isAboutToClose() && !m_isUsingSimpleMode) + else if (mainWindow && !mainWindow->isAboutToClose() && !m_isSimplified) { connect(this, &AddressWidget::requestedSearch, mainWindow, &MainWindow::search); } @@ -1380,12 +1380,12 @@ void AddressWidget::setUrl(const QUrl &url, bool force) { const QString text(Utils::isUrlEmpty(url) ? QString() : url.toString()); - if (!m_isUsingSimpleMode) + if (!m_isSimplified) { updateGeometries(); } - if (m_isUsingSimpleMode || ((force || !m_wasEdited || !hasFocus()) && url.scheme() != QLatin1String("javascript"))) + if (m_isSimplified || ((force || !m_wasEdited || !hasFocus()) && url.scheme() != QLatin1String("javascript"))) { const QString host(url.host(QUrl::FullyEncoded)); QString toolTip(text); diff --git a/src/modules/widgets/address/AddressWidget.h b/src/modules/widgets/address/AddressWidget.h index 409f96a63e..927dc53c13 100644 --- a/src/modules/widgets/address/AddressWidget.h +++ b/src/modules/widgets/address/AddressWidget.h @@ -157,7 +157,7 @@ protected slots: SessionsManager::OpenHints m_hints; bool m_hasFeeds; bool m_isNavigatingCompletion; - bool m_isUsingSimpleMode; + bool m_isSimplified; bool m_wasEdited; static int m_entryIdentifierEnumerator; From 500ce94f0442c5dd98cc4525d9ed89178c931167 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Fri, 15 Nov 2019 22:32:29 +0100 Subject: [PATCH 11/71] Replace boolean by enum --- src/ui/FilePathWidget.cpp | 10 +++++----- src/ui/FilePathWidget.h | 10 ++++++++-- src/ui/OptionWidget.cpp | 2 +- src/ui/preferences/PreferencesAdvancedPageWidget.cpp | 2 +- src/ui/preferences/PreferencesGeneralPageWidget.cpp | 2 +- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/ui/FilePathWidget.cpp b/src/ui/FilePathWidget.cpp index 471eb07cae..bbc7734202 100644 --- a/src/ui/FilePathWidget.cpp +++ b/src/ui/FilePathWidget.cpp @@ -49,7 +49,7 @@ FilePathWidget::FilePathWidget(QWidget *parent) : QWidget(parent), m_browseButton(new QPushButton(tr("Browse…"), this)), m_lineEditWidget(new LineEditWidget(this)), m_completer(nullptr), - m_selectFile(true) + m_openMode(FileMode) { QHBoxLayout *layout(new QHBoxLayout(this)); layout->addWidget(m_lineEditWidget); @@ -85,7 +85,7 @@ void FilePathWidget::focusInEvent(QFocusEvent *event) void FilePathWidget::selectPath() { QString path(m_lineEditWidget->text().isEmpty() ? QStandardPaths::standardLocations(QStandardPaths::HomeLocation).value(0) : m_lineEditWidget->text()); - path = (m_selectFile ? QFileDialog::getOpenFileName(this, tr("Select File"), path, m_filter) : QFileDialog::getExistingDirectory(this, tr("Select Directory"), path)); + path = ((m_openMode == FileMode) ? QFileDialog::getOpenFileName(this, tr("Select File"), path, m_filter) : QFileDialog::getExistingDirectory(this, tr("Select Directory"), path)); if (!path.isEmpty()) { @@ -100,7 +100,7 @@ void FilePathWidget::updateCompleter() m_completer = new QCompleter(this); FileSystemCompleterModel *model(new FileSystemCompleterModel(m_completer)); - model->setFilter(m_selectFile ? (QDir::AllDirs | QDir::Files) : QDir::AllDirs); + model->setFilter((m_openMode == FileMode) ? (QDir::AllDirs | QDir::Files) : QDir::AllDirs); m_completer->setModel(model); @@ -117,9 +117,9 @@ void FilePathWidget::setFilters(const QStringList &filters) m_filter = Utils::formatFileTypes(filters); } -void FilePathWidget::setSelectFile(bool mode) +void FilePathWidget::setOpenMode(OpenMode mode) { - m_selectFile = mode; + m_openMode = mode; } void FilePathWidget::setPath(const QString &path) diff --git a/src/ui/FilePathWidget.h b/src/ui/FilePathWidget.h index 6da79e8cbc..6fc2991200 100644 --- a/src/ui/FilePathWidget.h +++ b/src/ui/FilePathWidget.h @@ -45,10 +45,16 @@ class FilePathWidget final : public QWidget Q_OBJECT public: + enum OpenMode + { + DirectoryMode = 0, + FileMode + }; + explicit FilePathWidget(QWidget *parent = nullptr); void setFilters(const QStringList &filters); - void setSelectFile(bool mode); + void setOpenMode(OpenMode mode); void setPath(const QString &path); QString getPath() const; @@ -65,7 +71,7 @@ protected slots: LineEditWidget *m_lineEditWidget; QCompleter *m_completer; QString m_filter; - bool m_selectFile; + OpenMode m_openMode; signals: void pathChanged(const QString &path); diff --git a/src/ui/OptionWidget.cpp b/src/ui/OptionWidget.cpp index de07e50be4..5202fb59dd 100644 --- a/src/ui/OptionWidget.cpp +++ b/src/ui/OptionWidget.cpp @@ -110,7 +110,7 @@ OptionWidget::OptionWidget(const QVariant &value, SettingsManager::OptionType ty m_widget = m_filePathWidget = new FilePathWidget(this); m_filePathWidget->setPath(value.toString()); - m_filePathWidget->setSelectFile(false); + m_filePathWidget->setOpenMode(FilePathWidget::DirectoryMode); connect(m_filePathWidget, &FilePathWidget::pathChanged, this, &OptionWidget::markAsModified); diff --git a/src/ui/preferences/PreferencesAdvancedPageWidget.cpp b/src/ui/preferences/PreferencesAdvancedPageWidget.cpp index 0d3accb149..00dfa31791 100644 --- a/src/ui/preferences/PreferencesAdvancedPageWidget.cpp +++ b/src/ui/preferences/PreferencesAdvancedPageWidget.cpp @@ -199,7 +199,7 @@ PreferencesAdvancedPageWidget::PreferencesAdvancedPageWidget(QWidget *parent) : m_ui->downloadsItemView->setModel(downloadsModel); m_ui->downloadsItemView->sortByColumn(0, Qt::AscendingOrder); - m_ui->downloadsFilePathWidget->setSelectFile(false); + m_ui->downloadsFilePathWidget->setOpenMode(FilePathWidget::DirectoryMode); m_ui->downloadsApplicationComboBoxWidget->setAlwaysShowDefaultApplication(true); m_ui->sendReferrerCheckBox->setChecked(SettingsManager::getOption(SettingsManager::Network_EnableReferrerOption).toBool()); diff --git a/src/ui/preferences/PreferencesGeneralPageWidget.cpp b/src/ui/preferences/PreferencesGeneralPageWidget.cpp index 083a72ca60..1d73b3e4bf 100644 --- a/src/ui/preferences/PreferencesGeneralPageWidget.cpp +++ b/src/ui/preferences/PreferencesGeneralPageWidget.cpp @@ -57,7 +57,7 @@ PreferencesGeneralPageWidget::PreferencesGeneralPageWidget(QWidget *parent) : QW m_ui->useBookmarkAsHomePageButton->setMenu(bookmarksMenu); m_ui->useBookmarkAsHomePageButton->setEnabled(BookmarksManager::getModel()->getRootItem()->rowCount() > 0); - m_ui->downloadsFilePathWidget->setSelectFile(false); + m_ui->downloadsFilePathWidget->setOpenMode(FilePathWidget::DirectoryMode); m_ui->downloadsFilePathWidget->setPath(SettingsManager::getOption(SettingsManager::Paths_DownloadsOption).toString()); m_ui->alwaysAskCheckBox->setChecked(SettingsManager::getOption(SettingsManager::Browser_AlwaysAskWhereToSaveDownloadOption).toBool()); m_ui->tabsInsteadOfWindowsCheckBox->setChecked(SettingsManager::getOption(SettingsManager::Browser_OpenLinksInNewTabOption).toBool()); From 29e840e4228504987a7ae21293a5203210dfa2fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Sat, 16 Nov 2019 22:07:19 +0100 Subject: [PATCH 12/71] Add getter for OpenMode --- src/ui/FilePathWidget.cpp | 5 +++++ src/ui/FilePathWidget.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/ui/FilePathWidget.cpp b/src/ui/FilePathWidget.cpp index bbc7734202..82d8c938ac 100644 --- a/src/ui/FilePathWidget.cpp +++ b/src/ui/FilePathWidget.cpp @@ -139,4 +139,9 @@ QString FilePathWidget::getPath() const return m_lineEditWidget->text(); } +FilePathWidget::OpenMode FilePathWidget::getOpenMode() const +{ + return m_openMode; +} + } diff --git a/src/ui/FilePathWidget.h b/src/ui/FilePathWidget.h index 6fc2991200..b5e523de92 100644 --- a/src/ui/FilePathWidget.h +++ b/src/ui/FilePathWidget.h @@ -57,6 +57,7 @@ class FilePathWidget final : public QWidget void setOpenMode(OpenMode mode); void setPath(const QString &path); QString getPath() const; + OpenMode getOpenMode() const; protected: void changeEvent(QEvent *event) override; From d6c63441b535f699a2b753316e48dc2c022fde9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Sun, 17 Nov 2019 21:10:55 +0100 Subject: [PATCH 13/71] Fix warning --- src/core/AdblockContentFiltersProfile.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/AdblockContentFiltersProfile.h b/src/core/AdblockContentFiltersProfile.h index 59b7c1b740..2d15e77932 100644 --- a/src/core/AdblockContentFiltersProfile.h +++ b/src/core/AdblockContentFiltersProfile.h @@ -113,7 +113,7 @@ class AdblockContentFiltersProfile final : public ContentFiltersProfile QString requestUrl; NetworkManager::ResourceType resourceType = NetworkManager::OtherType; - explicit Request(const QUrl &baseUrlValue, const QUrl &requestUrlValue, NetworkManager::ResourceType resourceTypeValue) : baseHost(baseUrlValue.host()), requestUrl(requestUrlValue.toString()), requestHost(requestUrlValue.host()), resourceType(resourceTypeValue) + explicit Request(const QUrl &baseUrlValue, const QUrl &requestUrlValue, NetworkManager::ResourceType resourceTypeValue) : baseHost(baseUrlValue.host()), requestHost(requestUrlValue.host()), requestUrl(requestUrlValue.toString()), resourceType(resourceTypeValue) { if (requestUrl.startsWith(QLatin1String("//"))) { From 81cc8a3a69394f866d8149933b6663048c87e4ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Mon, 18 Nov 2019 21:55:29 +0100 Subject: [PATCH 14/71] Check for exceptions too --- src/core/AdblockContentFiltersProfile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/AdblockContentFiltersProfile.cpp b/src/core/AdblockContentFiltersProfile.cpp index 44468322ca..8f02faead4 100644 --- a/src/core/AdblockContentFiltersProfile.cpp +++ b/src/core/AdblockContentFiltersProfile.cpp @@ -513,7 +513,7 @@ ContentFiltersManager::CheckResult AdblockContentFiltersProfile::checkRuleMatch( } } - if (rule->ruleOptions != NoOption) + if (rule->ruleOptions != NoOption || rule->ruleExceptions != NoOption) { QHash::const_iterator iterator; From c226e985fcb93fe90af54ac376396d407d396fd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Tue, 19 Nov 2019 20:28:15 +0100 Subject: [PATCH 15/71] [QtWebEngine] Emit signals on state change --- .../web/qtwebengine/QtWebEngineTransfer.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.cpp b/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.cpp index 94337dec56..21aa8706f3 100644 --- a/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.cpp +++ b/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.cpp @@ -36,6 +36,22 @@ QtWebEngineTransfer::QtWebEngineTransfer(QWebEngineDownloadItem *item, TransferO 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() From 080831235ae9fa342488efd05a158e4b67e0de37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Wed, 20 Nov 2019 21:45:20 +0100 Subject: [PATCH 16/71] [QtWebKit] Drop not needed specifiers --- src/modules/backends/web/qtwebkit/QtWebKitPage.cpp | 2 +- src/modules/backends/web/qtwebkit/QtWebKitPage.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/backends/web/qtwebkit/QtWebKitPage.cpp b/src/modules/backends/web/qtwebkit/QtWebKitPage.cpp index 4b47d115cd..8517705cd4 100644 --- a/src/modules/backends/web/qtwebkit/QtWebKitPage.cpp +++ b/src/modules/backends/web/qtwebkit/QtWebKitPage.cpp @@ -952,7 +952,7 @@ bool QtWebKitPage::shouldInterruptJavaScript() return QWebPage::shouldInterruptJavaScript(); } -bool QtWebKitPage::supportsExtension(QWebPage::Extension extension) const +bool QtWebKitPage::supportsExtension(Extension extension) const { return (extension == ChooseMultipleFilesExtension || extension == ErrorPageExtension); } diff --git a/src/modules/backends/web/qtwebkit/QtWebKitPage.h b/src/modules/backends/web/qtwebkit/QtWebKitPage.h index 548d250c6a..332164427d 100644 --- a/src/modules/backends/web/qtwebkit/QtWebKitPage.h +++ b/src/modules/backends/web/qtwebkit/QtWebKitPage.h @@ -94,7 +94,7 @@ public slots: QString userAgentForUrl(const QUrl &url) const override; QString getDefaultUserAgent() const; QVariant getOption(int identifier) const; - bool acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type) override; + bool acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, NavigationType type) override; bool javaScriptConfirm(QWebFrame *frame, const QString &message) override; bool javaScriptPrompt(QWebFrame *frame, const QString &message, const QString &defaultValue, QString *result) override; @@ -116,7 +116,7 @@ protected slots: signals: void requestedNewWindow(WebWidget *widget, SessionsManager::OpenHints hints, const QVariantMap ¶meters); void requestedPopupWindow(const QUrl &parentUrl, const QUrl &popupUrl); - void aboutToNavigate(const QUrl &url, QWebFrame *frame, QWebPage::NavigationType navigationType); + void aboutToNavigate(const QUrl &url, QWebFrame *frame, NavigationType navigationType); void isDisplayingErrorPageChanged(QWebFrame *frame, bool isVisible); void viewingMediaChanged(bool isViewingMedia); From 554b50217967280718850c25f0e3ad8f5c9facb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Thu, 21 Nov 2019 21:58:25 +0100 Subject: [PATCH 17/71] [QtWebKit] Drop not needed specifiers --- .../backends/web/qtwebkit/QtWebKitNetworkManager.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/modules/backends/web/qtwebkit/QtWebKitNetworkManager.cpp b/src/modules/backends/web/qtwebkit/QtWebKitNetworkManager.cpp index 2f08a50cc3..4af0b8e49b 100644 --- a/src/modules/backends/web/qtwebkit/QtWebKitNetworkManager.cpp +++ b/src/modules/backends/web/qtwebkit/QtWebKitNetworkManager.cpp @@ -402,7 +402,7 @@ void QtWebKitNetworkManager::handleOnlineStateChanged(bool isOnline) { if (isOnline) { - setNetworkAccessible(QNetworkAccessManager::Accessible); + setNetworkAccessible(Accessible); } } @@ -567,7 +567,7 @@ QtWebKitNetworkManager* QtWebKitNetworkManager::clone() const return new QtWebKitNetworkManager((cache() == nullptr), m_cookieJarProxy->clone(nullptr), nullptr); } -QNetworkReply* QtWebKitNetworkManager::createRequest(QNetworkAccessManager::Operation operation, const QNetworkRequest &request, QIODevice *outgoingData) +QNetworkReply* QtWebKitNetworkManager::createRequest(Operation operation, const QNetworkRequest &request, QIODevice *outgoingData) { if (m_widget && request.url() == m_formRequestUrl) { @@ -575,7 +575,7 @@ QNetworkReply* QtWebKitNetworkManager::createRequest(QNetworkAccessManager::Oper m_widget->openFormRequest(request, operation, outgoingData); - return QNetworkAccessManager::createRequest(QNetworkAccessManager::GetOperation, QNetworkRequest()); + return QNetworkAccessManager::createRequest(GetOperation, QNetworkRequest()); } if (m_widget && request.url().path() == QLatin1String("/otter-message") && request.hasRawHeader(QByteArrayLiteral("X-Otter-Token")) && request.hasRawHeader(QByteArrayLiteral("X-Otter-Data"))) @@ -645,7 +645,7 @@ QNetworkReply* QtWebKitNetworkManager::createRequest(QNetworkAccessManager::Oper } } - return QNetworkAccessManager::createRequest(QNetworkAccessManager::GetOperation, QNetworkRequest(QUrl())); + return QNetworkAccessManager::createRequest(GetOperation, QNetworkRequest(QUrl())); } if (m_widget && (m_contentBlockingExceptions.isEmpty() || !m_contentBlockingExceptions.contains(request.url()))) @@ -656,7 +656,7 @@ QNetworkReply* QtWebKitNetworkManager::createRequest(QNetworkAccessManager::Oper if (!m_areImagesEnabled && request.url() != m_mainRequestUrl && resourceType == NetworkManager::ImageType) { - return QNetworkAccessManager::createRequest(QNetworkAccessManager::GetOperation, QNetworkRequest(QUrl())); + return QNetworkAccessManager::createRequest(GetOperation, QNetworkRequest(QUrl())); } if (needsContentBlockingCheck) @@ -684,7 +684,7 @@ QNetworkReply* QtWebKitNetworkManager::createRequest(QNetworkAccessManager::Oper emit requestBlocked(resource); - return QNetworkAccessManager::createRequest(QNetworkAccessManager::GetOperation, QNetworkRequest()); + return QNetworkAccessManager::createRequest(GetOperation, QNetworkRequest()); } } } From f140b4f7174f6619d809117084d52641962f146f Mon Sep 17 00:00:00 2001 From: fnkkio <57486061+fnkkio@users.noreply.github.com> Date: Fri, 22 Nov 2019 13:41:09 +0200 Subject: [PATCH 18/71] Do not call TransfersManager::addTransfer() twice --- src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp b/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp index d9e3cce38b..ebd39f7f49 100644 --- a/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp +++ b/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp @@ -345,7 +345,7 @@ void QtWebEngineWebWidget::triggerAction(int identifier, const QVariantMap ¶ break; case ActionsManager::SaveLinkToDownloadsAction: - TransfersManager::addTransfer(TransfersManager::startTransfer(m_hitResult.linkUrl.toString(), {}, (Transfer::CanNotifyOption | Transfer::CanAskForPathOption | Transfer::IsQuickTransferOption | (isPrivate() ? Transfer::IsPrivateOption : Transfer::NoOption)))); + TransfersManager::startTransfer(m_hitResult.linkUrl.toString(), {}, (Transfer::CanNotifyOption | Transfer::CanAskForPathOption | Transfer::IsQuickTransferOption | (isPrivate() ? Transfer::IsPrivateOption : Transfer::NoOption))); break; case ActionsManager::OpenFrameAction: From 5f4c50a1ace6f874ced0de73f18fecd313d66280 Mon Sep 17 00:00:00 2001 From: fnkkio <57486061+fnkkio@users.noreply.github.com> Date: Fri, 22 Nov 2019 14:11:41 +0200 Subject: [PATCH 19/71] Fix BookmarksComboBoxWidget not expanding, fixes #1615 --- src/ui/BookmarksComboBoxWidget.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ui/BookmarksComboBoxWidget.cpp b/src/ui/BookmarksComboBoxWidget.cpp index b6de19fbc1..0660384ac0 100644 --- a/src/ui/BookmarksComboBoxWidget.cpp +++ b/src/ui/BookmarksComboBoxWidget.cpp @@ -97,6 +97,8 @@ void BookmarksComboBoxWidget::setCurrentFolder(BookmarksModel::Bookmark *folder) if (folder) { setCurrentIndex(folder->index()); + + getView()->expand(folder->index()); } } From 80ae55e7a5a973c22e518592652db19774bb4ccf Mon Sep 17 00:00:00 2001 From: Stefan Comanescu Date: Thu, 21 Nov 2019 14:12:26 +0200 Subject: [PATCH 20/71] Fix potential segfault in TransfersManager::addTransfer --- src/core/TransfersManager.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/TransfersManager.cpp b/src/core/TransfersManager.cpp index bc08a0d529..3b83bac996 100644 --- a/src/core/TransfersManager.cpp +++ b/src/core/TransfersManager.cpp @@ -1016,6 +1016,11 @@ void TransfersManager::updateRunningTransfersState() void TransfersManager::addTransfer(Transfer *transfer) { + if (!transfer) + { + return; + } + m_transfers.append(transfer); transfer->setUpdateInterval(500); From 21a3c7b99de1580d705716a4a1cb8cfc5dfe069b Mon Sep 17 00:00:00 2001 From: Stefan Comanescu Date: Fri, 22 Nov 2019 14:13:28 +0200 Subject: [PATCH 21/71] Updater fix for cases when TransferManager::startTransfer could return nullptr --- src/core/Updater.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/core/Updater.cpp b/src/core/Updater.cpp index 5672edda67..83eca7ac25 100644 --- a/src/core/Updater.cpp +++ b/src/core/Updater.cpp @@ -59,9 +59,13 @@ Updater::Updater(const UpdateChecker::UpdateInformation &information, QObject *p downloadFile(information.scriptUrl, path); m_transfer = downloadFile(information.fileUrl, path); - m_transfer->setUpdateInterval(500); - connect(m_transfer, &Transfer::progressChanged, this, &Updater::updateProgress); + if (m_transfer) + { + m_transfer->setUpdateInterval(500); + + connect(m_transfer, &Transfer::progressChanged, this, &Updater::updateProgress); + } } void Updater::handleTransferFinished() @@ -130,9 +134,13 @@ Transfer* Updater::downloadFile(const QUrl &url, const QString &path) { const QString urlString(url.path()); Transfer *transfer(TransfersManager::startTransfer(url, path + urlString.mid(urlString.lastIndexOf(QLatin1Char('/')) + 1), (Transfer::CanOverwriteOption))); - transfer->setParent(this); - connect(transfer, &Transfer::finished, this, &Updater::handleTransferFinished); + if (transfer) + { + transfer->setParent(this); + + connect(transfer, &Transfer::finished, this, &Updater::handleTransferFinished); + } return transfer; } From b89a1033563fb31199bd8a7ff1be321fecc9f283 Mon Sep 17 00:00:00 2001 From: fnkkio <57486061+fnkkio@users.noreply.github.com> Date: Fri, 22 Nov 2019 16:26:48 +0200 Subject: [PATCH 22/71] Update state of download options widgets, fixes #1620 --- src/ui/preferences/PreferencesAdvancedPageWidget.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ui/preferences/PreferencesAdvancedPageWidget.cpp b/src/ui/preferences/PreferencesAdvancedPageWidget.cpp index 00dfa31791..5ff284b6a7 100644 --- a/src/ui/preferences/PreferencesAdvancedPageWidget.cpp +++ b/src/ui/preferences/PreferencesAdvancedPageWidget.cpp @@ -661,6 +661,8 @@ void PreferencesAdvancedPageWidget::updateDownloadsActions() m_ui->downloadsApplicationComboBoxWidget->setMimeType(QMimeDatabase().mimeTypeForName(index.data(Qt::DisplayRole).toString())); m_ui->downloadsApplicationComboBoxWidget->setCurrentCommand(index.data(OpenCommandRole).toString()); + updateDownloadsMode(); + m_ui->downloadsButtonGroup->blockSignals(false); m_ui->downloadsAskButton->blockSignals(false); m_ui->downloadsSaveButton->blockSignals(false); From 2e9f3861cd1deaa8a7fdddd0e6ae7b6e20cbffe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Fri, 22 Nov 2019 22:14:57 +0100 Subject: [PATCH 23/71] Define base class for creating backend specific HTML bookmark importers --- src/core/WebBackend.cpp | 12 ++++++++++++ src/core/WebBackend.h | 14 ++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/core/WebBackend.cpp b/src/core/WebBackend.cpp index 8a57207001..31526d7a65 100644 --- a/src/core/WebBackend.cpp +++ b/src/core/WebBackend.cpp @@ -22,6 +22,11 @@ namespace Otter { +HtmlBookmarksImportJob::HtmlBookmarksImportJob(const QString &path, QObject *parent) : Job(parent) +{ + Q_UNUSED(path) +} + WebPageThumbnailJob::WebPageThumbnailJob(const QUrl &url, const QSize &size, QObject *parent) : Job(parent) { Q_UNUSED(url) @@ -32,6 +37,13 @@ WebBackend::WebBackend(QObject *parent) : QObject(parent) { } +HtmlBookmarksImportJob* WebBackend::createBookmarksImportJob(const QString &path) +{ + Q_UNUSED(path) + + return nullptr; +} + WebPageThumbnailJob* WebBackend::createPageThumbnailJob(const QUrl &url, const QSize &size) { Q_UNUSED(url) diff --git a/src/core/WebBackend.h b/src/core/WebBackend.h index 398abef5e9..5874a09892 100644 --- a/src/core/WebBackend.h +++ b/src/core/WebBackend.h @@ -30,6 +30,19 @@ namespace Otter class ContentsWidget; class WebWidget; +class HtmlBookmarksImportJob : public Job +{ + Q_OBJECT + +public: + explicit HtmlBookmarksImportJob(const QString &path, QObject *parent = nullptr); + +signals: + void importStarted(int total); + void importProgress(int total, int amount); + void importFinished(bool isSuccess, int total); +}; + class WebPageThumbnailJob : public Job { Q_OBJECT @@ -76,6 +89,7 @@ class WebBackend : public QObject, public Addon explicit WebBackend(QObject *parent = nullptr); virtual WebWidget* createWidget(const QVariantMap ¶meters, ContentsWidget *parent = nullptr) = 0; + virtual HtmlBookmarksImportJob* createBookmarksImportJob(const QString &path); virtual WebPageThumbnailJob* createPageThumbnailJob(const QUrl &url, const QSize &size); virtual QString getEngineVersion() const = 0; virtual QString getSslVersion() const = 0; From eb9fdbb230e64a4da3ea512f856ff62c919777f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Sat, 23 Nov 2019 22:14:57 +0100 Subject: [PATCH 24/71] Use Bookmark::getChild() --- src/modules/windows/web/StartPageModel.cpp | 4 ++-- src/ui/ToolBarWidget.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/windows/web/StartPageModel.cpp b/src/modules/windows/web/StartPageModel.cpp index 990e369006..07075eeaee 100644 --- a/src/modules/windows/web/StartPageModel.cpp +++ b/src/modules/windows/web/StartPageModel.cpp @@ -57,7 +57,7 @@ void StartPageModel::reloadModel() { for (int i = 0; i < m_bookmark->rowCount(); ++i) { - const BookmarksModel::Bookmark *bookmark(static_cast(m_bookmark->child(i))); + const BookmarksModel::Bookmark *bookmark(m_bookmark->getChild(i)); if (bookmark) { @@ -127,7 +127,7 @@ void StartPageModel::addTile(const QUrl &url) for (int j = 0; j < m_bookmark->rowCount(); ++j) { - BookmarksModel::Bookmark *childBookmark(static_cast(m_bookmark->child(j))); + BookmarksModel::Bookmark *childBookmark(m_bookmark->getChild(j)); if (childBookmark && childBookmark->getRawData(Qt::DisplayRole).toString() == directories.at(i)) { diff --git a/src/ui/ToolBarWidget.cpp b/src/ui/ToolBarWidget.cpp index e4adfa8995..eb65647206 100644 --- a/src/ui/ToolBarWidget.cpp +++ b/src/ui/ToolBarWidget.cpp @@ -676,7 +676,7 @@ void ToolBarWidget::loadBookmarks() for (int i = 0; i < m_bookmark->rowCount(); ++i) { - BookmarksModel::Bookmark *bookmark(static_cast(m_bookmark->child(i))); + BookmarksModel::Bookmark *bookmark(m_bookmark->getChild(i)); if (bookmark) { From fedb7ddf4f02ba5b4dfa9d40315981546cbd663d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Sat, 23 Nov 2019 22:30:55 +0100 Subject: [PATCH 25/71] Add helper method to access parent Bookmark --- src/core/BookmarksImporter.cpp | 4 ++-- src/core/BookmarksImporter.h | 2 +- src/core/BookmarksModel.cpp | 12 ++++++++++++ src/core/BookmarksModel.h | 1 + src/modules/importers/opera/OperaNotesImporter.cpp | 2 +- .../windows/bookmarks/BookmarksContentsWidget.cpp | 2 +- src/modules/windows/notes/NotesContentsWidget.cpp | 2 +- src/ui/BookmarkPropertiesDialog.cpp | 4 ++-- src/ui/BookmarkPropertiesDialog.h | 2 +- 9 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/core/BookmarksImporter.cpp b/src/core/BookmarksImporter.cpp index 3f4b98db37..d911d0ba1a 100644 --- a/src/core/BookmarksImporter.cpp +++ b/src/core/BookmarksImporter.cpp @@ -1,7 +1,7 @@ /************************************************************************** * Otter Browser: Web browser controlled by the user, not vice-versa. * Copyright (C) 2014 Piotr Wójcik -* Copyright (C) 2014 - 2018 Michal Dutkiewicz aka Emdek +* Copyright (C) 2014 - 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 @@ -41,7 +41,7 @@ void BookmarksImporter::goToParent() if (m_currentFolder) { - m_currentFolder = static_cast(m_currentFolder->parent()); + m_currentFolder = m_currentFolder->getParent(); } if (!m_currentFolder) diff --git a/src/core/BookmarksImporter.h b/src/core/BookmarksImporter.h index 646960104a..95a704b7ad 100644 --- a/src/core/BookmarksImporter.h +++ b/src/core/BookmarksImporter.h @@ -1,7 +1,7 @@ /************************************************************************** * Otter Browser: Web browser controlled by the user, not vice-versa. * Copyright (C) 2014 Piotr Wójcik -* Copyright (C) 2014 - 2018 Michal Dutkiewicz aka Emdek +* Copyright (C) 2014 - 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 diff --git a/src/core/BookmarksModel.cpp b/src/core/BookmarksModel.cpp index 63877a26f6..e26d143355 100644 --- a/src/core/BookmarksModel.cpp +++ b/src/core/BookmarksModel.cpp @@ -83,6 +83,18 @@ QStandardItem* BookmarksModel::Bookmark::clone() const return bookmark; } +BookmarksModel::Bookmark* BookmarksModel::Bookmark::getParent() const +{ + BookmarksModel *model(qobject_cast(this->model())); + + if (model) + { + return model->getBookmark(index().parent()); + } + + return nullptr; +} + BookmarksModel::Bookmark* BookmarksModel::Bookmark::getChild(int index) const { BookmarksModel *model(qobject_cast(this->model())); diff --git a/src/core/BookmarksModel.h b/src/core/BookmarksModel.h index 4682551a2d..bda1ddd676 100644 --- a/src/core/BookmarksModel.h +++ b/src/core/BookmarksModel.h @@ -76,6 +76,7 @@ class BookmarksModel final : public QStandardItemModel void setData(const QVariant &value, int role) override; void setItemData(const QVariant &value, int role); QStandardItem* clone() const override; + Bookmark* getParent() const; Bookmark* getChild(int index) const; QString getTitle() const; QString getDescription() const; diff --git a/src/modules/importers/opera/OperaNotesImporter.cpp b/src/modules/importers/opera/OperaNotesImporter.cpp index 65ae5a1e2b..e640d4a22d 100644 --- a/src/modules/importers/opera/OperaNotesImporter.cpp +++ b/src/modules/importers/opera/OperaNotesImporter.cpp @@ -188,7 +188,7 @@ bool OperaNotesImporter::import(const QString &path) { if (m_currentFolder) { - m_currentFolder = static_cast(m_currentFolder->parent()); + m_currentFolder = m_currentFolder->getParent(); } if (!m_currentFolder) diff --git a/src/modules/windows/bookmarks/BookmarksContentsWidget.cpp b/src/modules/windows/bookmarks/BookmarksContentsWidget.cpp index ae0b0d0931..3396b99cbd 100644 --- a/src/modules/windows/bookmarks/BookmarksContentsWidget.cpp +++ b/src/modules/windows/bookmarks/BookmarksContentsWidget.cpp @@ -311,7 +311,7 @@ BookmarksContentsWidget::BookmarkLocation BookmarksContentsWidget::getBookmarkCr const BookmarksModel::BookmarkType type(item->getType()); - location.folder = ((type == BookmarksModel::RootBookmark || type == BookmarksModel::FolderBookmark) ? item : static_cast(item->parent())); + location.folder = ((type == BookmarksModel::RootBookmark || type == BookmarksModel::FolderBookmark) ? item : item->getParent()); location.row = ((location.folder && location.folder->index() == index) ? -1 : (index.row() + 1)); return location; diff --git a/src/modules/windows/notes/NotesContentsWidget.cpp b/src/modules/windows/notes/NotesContentsWidget.cpp index 375e11dbdf..19e710a0ef 100644 --- a/src/modules/windows/notes/NotesContentsWidget.cpp +++ b/src/modules/windows/notes/NotesContentsWidget.cpp @@ -322,7 +322,7 @@ BookmarksModel::Bookmark* NotesContentsWidget::findFolder(const QModelIndex &ind const BookmarksModel::BookmarkType type(item->getType()); - return ((type == BookmarksModel::RootBookmark || type == BookmarksModel::FolderBookmark) ? item : static_cast(item->parent())); + return ((type == BookmarksModel::RootBookmark || type == BookmarksModel::FolderBookmark) ? item : item->getParent()); } QString NotesContentsWidget::getTitle() const diff --git a/src/ui/BookmarkPropertiesDialog.cpp b/src/ui/BookmarkPropertiesDialog.cpp index dc3083498b..ca04c98419 100644 --- a/src/ui/BookmarkPropertiesDialog.cpp +++ b/src/ui/BookmarkPropertiesDialog.cpp @@ -1,6 +1,6 @@ /************************************************************************** * Otter Browser: Web browser controlled by the user, not vice-versa. -* Copyright (C) 2013 - 2018 Michal Dutkiewicz aka Emdek +* Copyright (C) 2013 - 2019 Michal Dutkiewicz aka Emdek * Copyright (C) 2014 Piotr Wójcik * * This program is free software: you can redistribute it and/or modify @@ -40,7 +40,7 @@ BookmarkPropertiesDialog::BookmarkPropertiesDialog(BookmarksModel::Bookmark *boo const bool isUrl(type == BookmarksModel::FeedBookmark || type == BookmarksModel::UrlBookmark); m_ui->setupUi(this); - m_ui->folderComboBox->setCurrentFolder(static_cast(bookmark->parent())); + m_ui->folderComboBox->setCurrentFolder(bookmark->getParent()); m_ui->titleLineEditWidget->setText(m_bookmark->getTitle()); m_ui->addressLineEditWidget->setText(m_bookmark->getUrl().toDisplayString()); m_ui->addressLineEditWidget->setVisible(isUrl); diff --git a/src/ui/BookmarkPropertiesDialog.h b/src/ui/BookmarkPropertiesDialog.h index 17f5cc358a..ed7a81a486 100644 --- a/src/ui/BookmarkPropertiesDialog.h +++ b/src/ui/BookmarkPropertiesDialog.h @@ -1,6 +1,6 @@ /************************************************************************** * Otter Browser: Web browser controlled by the user, not vice-versa. -* Copyright (C) 2013 - 2018 Michal Dutkiewicz aka Emdek +* Copyright (C) 2013 - 2019 Michal Dutkiewicz aka Emdek * Copyright (C) 2014 Piotr Wójcik * * This program is free software: you can redistribute it and/or modify From 0727a6c3fe63ecc0f0ddc940478bae1598423eab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Sat, 23 Nov 2019 22:33:05 +0100 Subject: [PATCH 26/71] Add helper methods --- src/core/WebBackend.cpp | 42 ++++++++++++++++++++++++++++++++++++++++- src/core/WebBackend.h | 15 ++++++++++++++- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/core/WebBackend.cpp b/src/core/WebBackend.cpp index 31526d7a65..01bde9baf1 100644 --- a/src/core/WebBackend.cpp +++ b/src/core/WebBackend.cpp @@ -18,15 +18,55 @@ **************************************************************************/ #include "WebBackend.h" +#include "BookmarksManager.h" namespace Otter { -HtmlBookmarksImportJob::HtmlBookmarksImportJob(const QString &path, QObject *parent) : Job(parent) +HtmlBookmarksImportJob::HtmlBookmarksImportJob(BookmarksModel::Bookmark *folder, const QString &path, bool areDuplicatesAllowed, QObject *parent) : Job(parent), + m_currentFolder(folder), + m_importFolder(folder), + m_areDuplicatesAllowed(areDuplicatesAllowed) { Q_UNUSED(path) } +void HtmlBookmarksImportJob::goToParent() +{ + if (m_currentFolder != m_importFolder) + { + if (m_currentFolder) + { + m_currentFolder = m_currentFolder->getParent(); + } + + if (!m_currentFolder) + { + m_currentFolder = (m_importFolder ? m_importFolder : BookmarksManager::getModel()->getRootItem()); + } + } +} + +void HtmlBookmarksImportJob::setCurrentFolder(BookmarksModel::Bookmark *folder) +{ + m_currentFolder = folder; +} + +BookmarksModel::Bookmark* HtmlBookmarksImportJob::getCurrentFolder() const +{ + return m_currentFolder; +} + +BookmarksModel::Bookmark* HtmlBookmarksImportJob::getImportFolder() const +{ + return m_importFolder; +} + +bool HtmlBookmarksImportJob::areDuplicatesAllowed() const +{ + return m_areDuplicatesAllowed; +} + WebPageThumbnailJob::WebPageThumbnailJob(const QUrl &url, const QSize &size, QObject *parent) : Job(parent) { Q_UNUSED(url) diff --git a/src/core/WebBackend.h b/src/core/WebBackend.h index 5874a09892..63422fbe43 100644 --- a/src/core/WebBackend.h +++ b/src/core/WebBackend.h @@ -21,6 +21,7 @@ #define OTTER_WEBBACKEND_H #include "AddonsManager.h" +#include "BookmarksModel.h" #include "Job.h" #include "SpellCheckManager.h" @@ -35,7 +36,19 @@ class HtmlBookmarksImportJob : public Job Q_OBJECT public: - explicit HtmlBookmarksImportJob(const QString &path, QObject *parent = nullptr); + explicit HtmlBookmarksImportJob(BookmarksModel::Bookmark *folder, const QString &path, bool areDuplicatesAllowed, QObject *parent = nullptr); + +protected: + void goToParent(); + void setCurrentFolder(BookmarksModel::Bookmark *folder); + BookmarksModel::Bookmark* getCurrentFolder() const; + BookmarksModel::Bookmark* getImportFolder() const; + bool areDuplicatesAllowed() const; + +private: + BookmarksModel::Bookmark *m_currentFolder; + BookmarksModel::Bookmark *m_importFolder; + bool m_areDuplicatesAllowed; signals: void importStarted(int total); From a1f0bd81d71695bd45025afdac1baa04ba84a8dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Sun, 24 Nov 2019 21:56:58 +0100 Subject: [PATCH 27/71] Create base class for all import jobs --- src/core/Importer.cpp | 49 +++++++++++++++++++++++++++++++++++++++++ src/core/Importer.h | 36 ++++++++++++++++++++++++++++++ src/core/WebBackend.cpp | 49 +++-------------------------------------- src/core/WebBackend.h | 29 ++---------------------- 4 files changed, 90 insertions(+), 73 deletions(-) diff --git a/src/core/Importer.cpp b/src/core/Importer.cpp index ec864a0a96..fbf5189c09 100644 --- a/src/core/Importer.cpp +++ b/src/core/Importer.cpp @@ -1,6 +1,7 @@ /************************************************************************** * Otter Browser: Web browser controlled by the user, not vice-versa. * Copyright (C) 2013 - 2019 Michal Dutkiewicz aka Emdek +* Copyright (C) 2014 Piotr Wójcik * * 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 @@ -18,6 +19,7 @@ **************************************************************************/ #include "Importer.h" +#include "BookmarksManager.h" namespace Otter { @@ -55,4 +57,51 @@ bool Importer::canCancel() return false; } +ImportJob::ImportJob(QObject *parent) : Job(parent) +{ +} + +BookmarksImportJob::BookmarksImportJob(BookmarksModel::Bookmark *folder, bool areDuplicatesAllowed, QObject *parent) : ImportJob(parent), + m_currentFolder(folder), + m_importFolder(folder), + m_areDuplicatesAllowed(areDuplicatesAllowed) +{ +} + +void BookmarksImportJob::goToParent() +{ + if (m_currentFolder != m_importFolder) + { + if (m_currentFolder) + { + m_currentFolder = m_currentFolder->getParent(); + } + + if (!m_currentFolder) + { + m_currentFolder = (m_importFolder ? m_importFolder : BookmarksManager::getModel()->getRootItem()); + } + } +} + +void BookmarksImportJob::setCurrentFolder(BookmarksModel::Bookmark *folder) +{ + m_currentFolder = folder; +} + +BookmarksModel::Bookmark* BookmarksImportJob::getCurrentFolder() const +{ + return m_currentFolder; +} + +BookmarksModel::Bookmark* BookmarksImportJob::getImportFolder() const +{ + return m_importFolder; +} + +bool BookmarksImportJob::areDuplicatesAllowed() const +{ + return m_areDuplicatesAllowed; +} + } diff --git a/src/core/Importer.h b/src/core/Importer.h index 23422930bc..2a947dc63a 100644 --- a/src/core/Importer.h +++ b/src/core/Importer.h @@ -1,6 +1,7 @@ /************************************************************************** * Otter Browser: Web browser controlled by the user, not vice-versa. * Copyright (C) 2013 - 2019 Michal Dutkiewicz aka Emdek +* Copyright (C) 2014 Piotr Wójcik * * 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 @@ -21,6 +22,8 @@ #define OTTER_IMPORTER_H #include "AddonsManager.h" +#include "BookmarksModel.h" +#include "Job.h" namespace Otter { @@ -83,6 +86,39 @@ protected slots: void importFinished(ImportType type, ImportResult result, int total); }; +class ImportJob : public Job +{ + Q_OBJECT + +public: + explicit ImportJob(QObject *parent = nullptr); + +signals: + void importStarted(Importer::ImportType type, int total); + void importProgress(Importer::ImportType type, int total, int amount); + void importFinished(Importer::ImportType type, bool isSuccess, int total); +}; + +class BookmarksImportJob : public ImportJob +{ + Q_OBJECT + +public: + explicit BookmarksImportJob(BookmarksModel::Bookmark *folder, bool areDuplicatesAllowed, QObject *parent = nullptr); + +protected: + void goToParent(); + void setCurrentFolder(BookmarksModel::Bookmark *folder); + BookmarksModel::Bookmark* getCurrentFolder() const; + BookmarksModel::Bookmark* getImportFolder() const; + bool areDuplicatesAllowed() const; + +private: + BookmarksModel::Bookmark *m_currentFolder; + BookmarksModel::Bookmark *m_importFolder; + bool m_areDuplicatesAllowed; +}; + } #endif diff --git a/src/core/WebBackend.cpp b/src/core/WebBackend.cpp index 01bde9baf1..2b4d3a30cf 100644 --- a/src/core/WebBackend.cpp +++ b/src/core/WebBackend.cpp @@ -18,55 +18,10 @@ **************************************************************************/ #include "WebBackend.h" -#include "BookmarksManager.h" namespace Otter { -HtmlBookmarksImportJob::HtmlBookmarksImportJob(BookmarksModel::Bookmark *folder, const QString &path, bool areDuplicatesAllowed, QObject *parent) : Job(parent), - m_currentFolder(folder), - m_importFolder(folder), - m_areDuplicatesAllowed(areDuplicatesAllowed) -{ - Q_UNUSED(path) -} - -void HtmlBookmarksImportJob::goToParent() -{ - if (m_currentFolder != m_importFolder) - { - if (m_currentFolder) - { - m_currentFolder = m_currentFolder->getParent(); - } - - if (!m_currentFolder) - { - m_currentFolder = (m_importFolder ? m_importFolder : BookmarksManager::getModel()->getRootItem()); - } - } -} - -void HtmlBookmarksImportJob::setCurrentFolder(BookmarksModel::Bookmark *folder) -{ - m_currentFolder = folder; -} - -BookmarksModel::Bookmark* HtmlBookmarksImportJob::getCurrentFolder() const -{ - return m_currentFolder; -} - -BookmarksModel::Bookmark* HtmlBookmarksImportJob::getImportFolder() const -{ - return m_importFolder; -} - -bool HtmlBookmarksImportJob::areDuplicatesAllowed() const -{ - return m_areDuplicatesAllowed; -} - WebPageThumbnailJob::WebPageThumbnailJob(const QUrl &url, const QSize &size, QObject *parent) : Job(parent) { Q_UNUSED(url) @@ -77,9 +32,11 @@ WebBackend::WebBackend(QObject *parent) : QObject(parent) { } -HtmlBookmarksImportJob* WebBackend::createBookmarksImportJob(const QString &path) +BookmarksImportJob* WebBackend::createBookmarksImportJob(BookmarksModel::Bookmark *folder, const QString &path, bool areDuplicatesAllowed) { + Q_UNUSED(folder) Q_UNUSED(path) + Q_UNUSED(areDuplicatesAllowed) return nullptr; } diff --git a/src/core/WebBackend.h b/src/core/WebBackend.h index 63422fbe43..e8cb85910e 100644 --- a/src/core/WebBackend.h +++ b/src/core/WebBackend.h @@ -22,7 +22,7 @@ #include "AddonsManager.h" #include "BookmarksModel.h" -#include "Job.h" +#include "Importer.h" #include "SpellCheckManager.h" namespace Otter @@ -31,31 +31,6 @@ namespace Otter class ContentsWidget; class WebWidget; -class HtmlBookmarksImportJob : public Job -{ - Q_OBJECT - -public: - explicit HtmlBookmarksImportJob(BookmarksModel::Bookmark *folder, const QString &path, bool areDuplicatesAllowed, QObject *parent = nullptr); - -protected: - void goToParent(); - void setCurrentFolder(BookmarksModel::Bookmark *folder); - BookmarksModel::Bookmark* getCurrentFolder() const; - BookmarksModel::Bookmark* getImportFolder() const; - bool areDuplicatesAllowed() const; - -private: - BookmarksModel::Bookmark *m_currentFolder; - BookmarksModel::Bookmark *m_importFolder; - bool m_areDuplicatesAllowed; - -signals: - void importStarted(int total); - void importProgress(int total, int amount); - void importFinished(bool isSuccess, int total); -}; - class WebPageThumbnailJob : public Job { Q_OBJECT @@ -102,7 +77,7 @@ class WebBackend : public QObject, public Addon explicit WebBackend(QObject *parent = nullptr); virtual WebWidget* createWidget(const QVariantMap ¶meters, ContentsWidget *parent = nullptr) = 0; - virtual HtmlBookmarksImportJob* createBookmarksImportJob(const QString &path); + virtual BookmarksImportJob* createBookmarksImportJob(BookmarksModel::Bookmark *folder, const QString &path, bool areDuplicatesAllowed); virtual WebPageThumbnailJob* createPageThumbnailJob(const QUrl &url, const QSize &size); virtual QString getEngineVersion() const = 0; virtual QString getSslVersion() const = 0; From 023a95a90c3c2bedbf38c23bfc0b3cd9a9efb4e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Mon, 25 Nov 2019 19:50:46 +0100 Subject: [PATCH 28/71] Adjust the signature --- src/core/Importer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/Importer.h b/src/core/Importer.h index 2a947dc63a..1aa73b1dd9 100644 --- a/src/core/Importer.h +++ b/src/core/Importer.h @@ -96,7 +96,7 @@ class ImportJob : public Job signals: void importStarted(Importer::ImportType type, int total); void importProgress(Importer::ImportType type, int total, int amount); - void importFinished(Importer::ImportType type, bool isSuccess, int total); + void importFinished(Importer::ImportType type, Importer::ImportResult result, int total); }; class BookmarksImportJob : public ImportJob From ad8a748fe8d4fffead04328721d54d4db9e5bf43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Mon, 25 Nov 2019 20:12:03 +0100 Subject: [PATCH 29/71] Move QtWebKit based HTML bookmarks import to QtWebKitBookmarksImportJob class --- .../web/qtwebkit/QtWebKitWebBackend.cpp | 196 +++++++++++++++++ .../web/qtwebkit/QtWebKitWebBackend.h | 26 +++ .../importers/html/HtmlBookmarksImporter.cpp | 198 +++--------------- .../importers/html/HtmlBookmarksImporter.h | 17 +- 4 files changed, 251 insertions(+), 186 deletions(-) diff --git a/src/modules/backends/web/qtwebkit/QtWebKitWebBackend.cpp b/src/modules/backends/web/qtwebkit/QtWebKitWebBackend.cpp index b19f89b3cb..c1ebc8ad3f 100644 --- a/src/modules/backends/web/qtwebkit/QtWebKitWebBackend.cpp +++ b/src/modules/backends/web/qtwebkit/QtWebKitWebBackend.cpp @@ -22,6 +22,7 @@ #include "QtWebKitHistoryInterface.h" #include "QtWebKitPage.h" #include "QtWebKitWebWidget.h" +#include "../../../../core/BookmarksManager.h" #include "../../../../core/NetworkManagerFactory.h" #include "../../../../core/SettingsManager.h" @@ -177,6 +178,11 @@ WebWidget* QtWebKitWebBackend::createWidget(const QVariantMap ¶meters, Conte return widget; } +BookmarksImportJob* QtWebKitWebBackend::createBookmarksImportJob(BookmarksModel::Bookmark *folder, const QString &path, bool areDuplicatesAllowed) +{ + return new QtWebKitBookmarksImportJob(folder, path, areDuplicatesAllowed, this); +} + WebPageThumbnailJob* QtWebKitWebBackend::createPageThumbnailJob(const QUrl &url, const QSize &size) { return new QtWebKitWebPageThumbnailJob(url, size, this); @@ -277,6 +283,196 @@ int QtWebKitWebBackend::getOptionIdentifier(QtWebKitWebBackend::OptionIdentifier return -1; } +QtWebKitBookmarksImportJob::QtWebKitBookmarksImportJob(BookmarksModel::Bookmark *folder, const QString &path, bool areDuplicatesAllowed, QObject *parent) : BookmarksImportJob(folder, areDuplicatesAllowed, parent), + m_path(path), + m_currentAmount(0), + m_totalAmount(-1), + m_isRunning(false) +{ +} + +void QtWebKitBookmarksImportJob::processElement(const QWebElement &element) +{ + QWebElement entryElement(element.findFirst(QLatin1String("dt, hr"))); + + while (!entryElement.isNull()) + { + if (entryElement.tagName().toLower() == QLatin1String("hr")) + { + BookmarksManager::addBookmark(BookmarksModel::SeparatorBookmark, {}, getCurrentFolder()); + + ++m_currentAmount; + + emit importProgress(Importer::BookmarksImport, m_totalAmount, m_currentAmount); + } + else + { + BookmarksModel::BookmarkType type(BookmarksModel::UnknownBookmark); + QWebElement matchedElement(entryElement.findFirst(QLatin1String("dt > h3"))); + + if (matchedElement.isNull()) + { + matchedElement = entryElement.findFirst(QLatin1String("dt > a")); + + if (!matchedElement.isNull()) + { + type = (matchedElement.hasAttribute(QLatin1String("FEEDURL")) ? BookmarksModel::FeedBookmark : BookmarksModel::UrlBookmark); + } + } + else + { + type = BookmarksModel::FolderBookmark; + } + + if (type != BookmarksModel::UnknownBookmark && !matchedElement.isNull()) + { + QMap metaData({{BookmarksModel::TitleRole, matchedElement.toPlainText()}}); + const bool isUrlBookmark(type == BookmarksModel::UrlBookmark || type == BookmarksModel::FeedBookmark); + + if (isUrlBookmark) + { + const QUrl url(matchedElement.attribute(QLatin1String("HREF"))); + + if (!areDuplicatesAllowed() && BookmarksManager::hasBookmark(url)) + { + entryElement = entryElement.nextSibling(); + + continue; + } + + metaData[BookmarksModel::UrlRole] = url; + } + + if (matchedElement.hasAttribute(QLatin1String("SHORTCUTURL"))) + { + const QString keyword(matchedElement.attribute(QLatin1String("SHORTCUTURL"))); + + if (!keyword.isEmpty() && !BookmarksManager::hasKeyword(keyword)) + { + metaData[BookmarksModel::KeywordRole] = keyword; + } + } + + if (matchedElement.hasAttribute(QLatin1String("ADD_DATE"))) + { + const QDateTime dateTime(getDateTime(matchedElement, QLatin1String("ADD_DATE"))); + + if (dateTime.isValid()) + { + metaData[BookmarksModel::TimeAddedRole] = dateTime; + metaData[BookmarksModel::TimeModifiedRole] = dateTime; + } + } + + if (matchedElement.hasAttribute(QLatin1String("LAST_MODIFIED"))) + { + const QDateTime dateTime(getDateTime(matchedElement, QLatin1String("LAST_MODIFIED"))); + + if (dateTime.isValid()) + { + metaData[BookmarksModel::TimeModifiedRole] = dateTime; + } + } + + if (isUrlBookmark && matchedElement.hasAttribute(QLatin1String("LAST_VISITED"))) + { + const QDateTime dateTime(getDateTime(matchedElement, QLatin1String("LAST_VISITED"))); + + if (dateTime.isValid()) + { + metaData[BookmarksModel::TimeVisitedRole] = dateTime; + } + } + + BookmarksModel::Bookmark *bookmark(BookmarksManager::addBookmark(type, metaData, getCurrentFolder())); + + ++m_currentAmount; + + emit importProgress(Importer::BookmarksImport, m_totalAmount, m_currentAmount); + + if (type == BookmarksModel::FolderBookmark) + { + setCurrentFolder(bookmark); + processElement(entryElement); + } + + if (entryElement.nextSibling().tagName().toLower() == QLatin1String("dd")) + { + bookmark->setItemData(entryElement.nextSibling().toPlainText(), BookmarksModel::DescriptionRole); + + entryElement = entryElement.nextSibling(); + } + } + } + + entryElement = entryElement.nextSibling(); + } + + goToParent(); +} + +void QtWebKitBookmarksImportJob::start() +{ + QFile file(m_path); + + if (!file.open(QIODevice::ReadOnly)) + { + emit importFinished(Importer::BookmarksImport, Importer::FailedImport, 0); + emit jobFinished(false); + + deleteLater(); + + return; + } + + m_isRunning = true; + + QWebPage page; + page.settings()->setAttribute(QWebSettings::JavascriptEnabled, false); + page.mainFrame()->setHtml(QString::fromLatin1(file.readAll())); + + m_totalAmount = page.mainFrame()->findAllElements(QLatin1String("dt, hr")).count(); + + emit importStarted(Importer::BookmarksImport, m_totalAmount); + + BookmarksManager::getModel()->beginImport(getImportFolder(), page.mainFrame()->findAllElements(QLatin1String("a[href]")).count(), page.mainFrame()->findAllElements(QLatin1String("a[shortcuturl]")).count()); + + processElement(page.mainFrame()->documentElement().findFirst(QLatin1String("dl"))); + + BookmarksManager::getModel()->endImport(); + + emit importFinished(Importer::BookmarksImport, Importer::SuccessfullImport, m_totalAmount); + emit jobFinished(true); + + file.close(); + + m_isRunning = false; + + deleteLater(); +} + +void QtWebKitBookmarksImportJob::cancel() +{ +} + +QDateTime QtWebKitBookmarksImportJob::getDateTime(const QWebElement &element, const QString &attribute) +{ +#if QT_VERSION < 0x050800 + const uint seconds(element.attribute(attribute).toUInt()); + + return ((seconds > 0) ? QDateTime::fromTime_t(seconds) : QDateTime()); +#else + const qint64 seconds(element.attribute(attribute).toLongLong()); + + return ((seconds != 0) ? QDateTime::fromSecsSinceEpoch(seconds) : QDateTime()); +#endif +} + +bool QtWebKitBookmarksImportJob::isRunning() const +{ + return m_isRunning; +} + QtWebKitWebPageThumbnailJob::QtWebKitWebPageThumbnailJob(const QUrl &url, const QSize &size, QObject *parent) : WebPageThumbnailJob(url, size, parent), m_page(nullptr), m_url(url), diff --git a/src/modules/backends/web/qtwebkit/QtWebKitWebBackend.h b/src/modules/backends/web/qtwebkit/QtWebKitWebBackend.h index d748ed321b..235ffa396d 100644 --- a/src/modules/backends/web/qtwebkit/QtWebKitWebBackend.h +++ b/src/modules/backends/web/qtwebkit/QtWebKitWebBackend.h @@ -22,6 +22,8 @@ #include "../../../../core/WebBackend.h" +#include + namespace Otter { @@ -43,6 +45,7 @@ class QtWebKitWebBackend final : public WebBackend explicit QtWebKitWebBackend(QObject *parent = nullptr); WebWidget* createWidget(const QVariantMap ¶meters, ContentsWidget *parent = nullptr) override; + BookmarksImportJob* createBookmarksImportJob(BookmarksModel::Bookmark *folder, const QString &path, bool areDuplicatesAllowed) override; WebPageThumbnailJob* createPageThumbnailJob(const QUrl &url, const QSize &size) override; QString getName() const override; QString getTitle() const override; @@ -80,6 +83,29 @@ protected slots: friend class QtWebKitSpellChecker; }; +class QtWebKitBookmarksImportJob final : public BookmarksImportJob +{ + Q_OBJECT + +public: + explicit QtWebKitBookmarksImportJob(BookmarksModel::Bookmark *folder, const QString &path, bool areDuplicatesAllowed, QObject *parent = nullptr); + bool isRunning() const override; + +public slots: + void start() override; + void cancel() override; + +protected: + void processElement(const QWebElement &element); + static QDateTime getDateTime(const QWebElement &element, const QString &attribute); + +private: + QString m_path; + int m_currentAmount; + int m_totalAmount; + bool m_isRunning; +}; + class QtWebKitWebPageThumbnailJob final : public WebPageThumbnailJob { Q_OBJECT diff --git a/src/modules/importers/html/HtmlBookmarksImporter.cpp b/src/modules/importers/html/HtmlBookmarksImporter.cpp index 70f22e1fee..c3aba152b9 100644 --- a/src/modules/importers/html/HtmlBookmarksImporter.cpp +++ b/src/modules/importers/html/HtmlBookmarksImporter.cpp @@ -19,150 +19,20 @@ **************************************************************************/ #include "HtmlBookmarksImporter.h" -#include "../../../core/BookmarksManager.h" +#include "../../../core/WebBackend.h" #include "../../../ui/BookmarksImporterWidget.h" #include #include -#ifdef OTTER_ENABLE_QTWEBKIT -//TODO QtWebKit should not be used directly -#include -#include -#include -#endif namespace Otter { -HtmlBookmarksImporter::HtmlBookmarksImporter(QObject *parent) : BookmarksImporter(parent), - m_optionsWidget(nullptr), - m_currentAmount(0), - m_totalAmount(-1) +HtmlBookmarksImporter::HtmlBookmarksImporter(QObject *parent) : Importer(parent), + m_optionsWidget(nullptr) { } -#ifdef OTTER_ENABLE_QTWEBKIT -void HtmlBookmarksImporter::processElement(const QWebElement &element) -{ - QWebElement entryElement(element.findFirst(QLatin1String("dt, hr"))); - - while (!entryElement.isNull()) - { - if (entryElement.tagName().toLower() == QLatin1String("hr")) - { - BookmarksManager::addBookmark(BookmarksModel::SeparatorBookmark, {}, getCurrentFolder()); - - ++m_currentAmount; - - emit importProgress(BookmarksImport, m_totalAmount, m_currentAmount); - } - else - { - BookmarksModel::BookmarkType type(BookmarksModel::UnknownBookmark); - QWebElement matchedElement(entryElement.findFirst(QLatin1String("dt > h3"))); - - if (matchedElement.isNull()) - { - matchedElement = entryElement.findFirst(QLatin1String("dt > a")); - - if (!matchedElement.isNull()) - { - type = (matchedElement.hasAttribute(QLatin1String("FEEDURL")) ? BookmarksModel::FeedBookmark : BookmarksModel::UrlBookmark); - } - } - else - { - type = BookmarksModel::FolderBookmark; - } - - if (type != BookmarksModel::UnknownBookmark && !matchedElement.isNull()) - { - QMap metaData({{BookmarksModel::TitleRole, matchedElement.toPlainText()}}); - const bool isUrlBookmark(type == BookmarksModel::UrlBookmark || type == BookmarksModel::FeedBookmark); - - if (isUrlBookmark) - { - const QUrl url(matchedElement.attribute(QLatin1String("HREF"))); - - if (!areDuplicatesAllowed() && BookmarksManager::hasBookmark(url)) - { - entryElement = entryElement.nextSibling(); - - continue; - } - - metaData[BookmarksModel::UrlRole] = url; - } - - if (matchedElement.hasAttribute(QLatin1String("SHORTCUTURL"))) - { - const QString keyword(matchedElement.attribute(QLatin1String("SHORTCUTURL"))); - - if (!keyword.isEmpty() && !BookmarksManager::hasKeyword(keyword)) - { - metaData[BookmarksModel::KeywordRole] = keyword; - } - } - - if (matchedElement.hasAttribute(QLatin1String("ADD_DATE"))) - { - const QDateTime dateTime(getDateTime(matchedElement, QLatin1String("ADD_DATE"))); - - if (dateTime.isValid()) - { - metaData[BookmarksModel::TimeAddedRole] = dateTime; - metaData[BookmarksModel::TimeModifiedRole] = dateTime; - } - } - - if (matchedElement.hasAttribute(QLatin1String("LAST_MODIFIED"))) - { - const QDateTime dateTime(getDateTime(matchedElement, QLatin1String("LAST_MODIFIED"))); - - if (dateTime.isValid()) - { - metaData[BookmarksModel::TimeModifiedRole] = dateTime; - } - } - - if (isUrlBookmark && matchedElement.hasAttribute(QLatin1String("LAST_VISITED"))) - { - const QDateTime dateTime(getDateTime(matchedElement, QLatin1String("LAST_VISITED"))); - - if (dateTime.isValid()) - { - metaData[BookmarksModel::TimeVisitedRole] = dateTime; - } - } - - BookmarksModel::Bookmark *bookmark(BookmarksManager::addBookmark(type, metaData, getCurrentFolder())); - - ++m_currentAmount; - - emit importProgress(BookmarksImport, m_totalAmount, m_currentAmount); - - if (type == BookmarksModel::FolderBookmark) - { - setCurrentFolder(bookmark); - processElement(entryElement); - } - - if (entryElement.nextSibling().tagName().toLower() == QLatin1String("dd")) - { - bookmark->setItemData(entryElement.nextSibling().toPlainText(), BookmarksModel::DescriptionRole); - - entryElement = entryElement.nextSibling(); - } - } - } - - entryElement = entryElement.nextSibling(); - } - - goToParent(); -} -#endif - QWidget* HtmlBookmarksImporter::createOptionsWidget(QWidget *parent) { if (!m_optionsWidget) @@ -213,80 +83,64 @@ QUrl HtmlBookmarksImporter::getHomePage() const return QUrl(QLatin1String("https://otter-browser.org/")); } -#ifdef OTTER_ENABLE_QTWEBKIT -QDateTime HtmlBookmarksImporter::getDateTime(const QWebElement &element, const QString &attribute) +QStringList HtmlBookmarksImporter::getFileFilters() const { -#if QT_VERSION < 0x050800 - const uint seconds(element.attribute(attribute).toUInt()); - - return ((seconds > 0) ? QDateTime::fromTime_t(seconds) : QDateTime()); -#else - const qint64 seconds(element.attribute(attribute).toLongLong()); - - return ((seconds != 0) ? QDateTime::fromSecsSinceEpoch(seconds) : QDateTime()); -#endif + return {tr("HTML files (*.htm *.html)")}; } -#endif -QStringList HtmlBookmarksImporter::getFileFilters() const +Importer::ImportType HtmlBookmarksImporter::getImportType() const { - return {tr("HTML files (*.htm *.html)")}; + return BookmarksImport; } bool HtmlBookmarksImporter::import(const QString &path) { -#ifdef OTTER_ENABLE_QTWEBKIT - QFile file(getSuggestedPath(path)); + WebBackend *webBackend(AddonsManager::getWebBackend()); - if (!file.open(QIODevice::ReadOnly)) + if (!webBackend) { emit importFinished(BookmarksImport, FailedImport, 0); return false; } + BookmarksModel::Bookmark *folder(nullptr); + bool areDuplicatesAllowed(false); + if (m_optionsWidget) { if (m_optionsWidget->hasToRemoveExisting()) { - removeAllBookmarks(); + BookmarksManager::getModel()->getRootItem()->removeRows(0, BookmarksManager::getModel()->getRootItem()->rowCount()); if (m_optionsWidget->isImportingIntoSubfolder()) { - setImportFolder(BookmarksManager::addBookmark(BookmarksModel::FolderBookmark, {{BookmarksModel::TitleRole, m_optionsWidget->getSubfolderName()}})); + folder = BookmarksManager::addBookmark(BookmarksModel::FolderBookmark, {{BookmarksModel::TitleRole, m_optionsWidget->getSubfolderName()}}); } } else { - setAllowDuplicates(m_optionsWidget->areDuplicatesAllowed()); - setImportFolder(m_optionsWidget->getTargetFolder()); + folder = m_optionsWidget->getTargetFolder(); + areDuplicatesAllowed = m_optionsWidget->areDuplicatesAllowed(); } } - QWebPage page; - page.settings()->setAttribute(QWebSettings::JavascriptEnabled, false); - page.mainFrame()->setHtml(QString::fromLatin1(file.readAll())); - - m_totalAmount = page.mainFrame()->findAllElements(QLatin1String("dt, hr")).count(); + BookmarksImportJob *job(webBackend->createBookmarksImportJob(folder, getSuggestedPath(path), areDuplicatesAllowed)); - emit importStarted(BookmarksImport, m_totalAmount); - - BookmarksManager::getModel()->beginImport(getImportFolder(), page.mainFrame()->findAllElements(QLatin1String("a[href]")).count(), page.mainFrame()->findAllElements(QLatin1String("a[shortcuturl]")).count()); - - processElement(page.mainFrame()->documentElement().findFirst(QLatin1String("dl"))); + if (!job) + { + emit importFinished(BookmarksImport, FailedImport, 0); - BookmarksManager::getModel()->endImport(); + return false; + } - emit importFinished(BookmarksImport, SuccessfullImport, m_totalAmount); + connect(job, &BookmarksImportJob::importStarted, this, &HtmlBookmarksImporter::importStarted); + connect(job, &BookmarksImportJob::importProgress, this, &HtmlBookmarksImporter::importProgress); + connect(job, &BookmarksImportJob::importFinished, this, &HtmlBookmarksImporter::importFinished); - file.close(); + job->start(); return true; -#else - Q_UNUSED(path) - - return false; -#endif } } diff --git a/src/modules/importers/html/HtmlBookmarksImporter.h b/src/modules/importers/html/HtmlBookmarksImporter.h index ccdf4588cb..db38eb1068 100644 --- a/src/modules/importers/html/HtmlBookmarksImporter.h +++ b/src/modules/importers/html/HtmlBookmarksImporter.h @@ -21,18 +21,14 @@ #ifndef OTTER_HTMLBOOKMARKSIMPORTER_H #define OTTER_HTMLBOOKMARKSIMPORTER_H -#include "../../../core/BookmarksImporter.h" - -#ifdef OTTER_ENABLE_QTWEBKIT -#include -#endif +#include "../../../core/Importer.h" namespace Otter { class BookmarksImporterWidget; -class HtmlBookmarksImporter final : public BookmarksImporter +class HtmlBookmarksImporter final : public Importer { Q_OBJECT @@ -48,20 +44,13 @@ class HtmlBookmarksImporter final : public BookmarksImporter QString getGroup() const override; QUrl getHomePage() const override; QStringList getFileFilters() const override; + ImportType getImportType() const override; public slots: bool import(const QString &path) override; -#ifdef OTTER_ENABLE_QTWEBKIT -protected: - void processElement(const QWebElement &element); - static QDateTime getDateTime(const QWebElement &element, const QString &attribute); -#endif - private: BookmarksImporterWidget *m_optionsWidget; - int m_currentAmount; - int m_totalAmount; }; } From 8990c26ca8d6f97e938250389af40fad9c0ea7a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Mon, 25 Nov 2019 20:13:52 +0100 Subject: [PATCH 30/71] Move logic to OperaBookmarksImportJob --- CMakeLists.txt | 1 - src/core/BookmarksImporter.cpp | 94 ---------------- src/core/BookmarksImporter.h | 57 ---------- .../opera/OperaBookmarksImporter.cpp | 105 ++++++++++++------ .../importers/opera/OperaBookmarksImporter.h | 24 +++- 5 files changed, 95 insertions(+), 186 deletions(-) delete mode 100644 src/core/BookmarksImporter.cpp delete mode 100644 src/core/BookmarksImporter.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 02e569083b..22b8328066 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,7 +91,6 @@ set(otter_src src/core/AddonsManager.cpp src/core/AddressCompletionModel.cpp src/core/Application.cpp - src/core/BookmarksImporter.cpp src/core/BookmarksManager.cpp src/core/BookmarksModel.cpp src/core/ContentFiltersManager.cpp diff --git a/src/core/BookmarksImporter.cpp b/src/core/BookmarksImporter.cpp deleted file mode 100644 index d911d0ba1a..0000000000 --- a/src/core/BookmarksImporter.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/************************************************************************** -* Otter Browser: Web browser controlled by the user, not vice-versa. -* Copyright (C) 2014 Piotr Wójcik -* Copyright (C) 2014 - 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 "BookmarksImporter.h" -#include "BookmarksManager.h" - -namespace Otter -{ - -BookmarksImporter::BookmarksImporter(QObject *parent) : Importer(parent), - m_currentFolder(nullptr), - m_importFolder(nullptr), - m_areDuplicatesAllowed(true) -{ - setImportFolder(BookmarksManager::getModel()->getRootItem()); -} - -void BookmarksImporter::goToParent() -{ - if (m_currentFolder == m_importFolder) - { - return; - } - - if (m_currentFolder) - { - m_currentFolder = m_currentFolder->getParent(); - } - - if (!m_currentFolder) - { - m_currentFolder = (m_importFolder ? m_importFolder : BookmarksManager::getModel()->getRootItem()); - } -} - -void BookmarksImporter::removeAllBookmarks() -{ - BookmarksManager::getModel()->getRootItem()->removeRows(0, BookmarksManager::getModel()->getRootItem()->rowCount()); -} - -void BookmarksImporter::setAllowDuplicates(bool allow) -{ - m_areDuplicatesAllowed = allow; -} - -void BookmarksImporter::setCurrentFolder(BookmarksModel::Bookmark *folder) -{ - m_currentFolder = folder; -} - -void BookmarksImporter::setImportFolder(BookmarksModel::Bookmark *folder) -{ - m_importFolder = folder; - m_currentFolder = folder; -} - -BookmarksModel::Bookmark* BookmarksImporter::getCurrentFolder() const -{ - return m_currentFolder; -} - -BookmarksModel::Bookmark* BookmarksImporter::getImportFolder() const -{ - return m_importFolder; -} - -Importer::ImportType BookmarksImporter::getImportType() const -{ - return BookmarksImport; -} - -bool BookmarksImporter::areDuplicatesAllowed() const -{ - return m_areDuplicatesAllowed; -} - -} diff --git a/src/core/BookmarksImporter.h b/src/core/BookmarksImporter.h deleted file mode 100644 index 95a704b7ad..0000000000 --- a/src/core/BookmarksImporter.h +++ /dev/null @@ -1,57 +0,0 @@ -/************************************************************************** -* Otter Browser: Web browser controlled by the user, not vice-versa. -* Copyright (C) 2014 Piotr Wójcik -* Copyright (C) 2014 - 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_BOOKMARKSIMPORTER_H -#define OTTER_BOOKMARKSIMPORTER_H - -#include "BookmarksModel.h" -#include "Importer.h" - -namespace Otter -{ - -class BookmarksImporter : public Importer -{ - Q_OBJECT - -public: - explicit BookmarksImporter(QObject *parent = nullptr); - - ImportType getImportType() const override; - -protected: - void goToParent(); - void removeAllBookmarks(); - void setAllowDuplicates(bool allow); - void setCurrentFolder(BookmarksModel::Bookmark *folder); - void setImportFolder(BookmarksModel::Bookmark *folder); - BookmarksModel::Bookmark* getCurrentFolder() const; - BookmarksModel::Bookmark* getImportFolder() const; - bool areDuplicatesAllowed() const; - -private: - BookmarksModel::Bookmark *m_currentFolder; - BookmarksModel::Bookmark *m_importFolder; - bool m_areDuplicatesAllowed; -}; - -} - -#endif diff --git a/src/modules/importers/opera/OperaBookmarksImporter.cpp b/src/modules/importers/opera/OperaBookmarksImporter.cpp index 6f92061421..a1f08e72a6 100644 --- a/src/modules/importers/opera/OperaBookmarksImporter.cpp +++ b/src/modules/importers/opera/OperaBookmarksImporter.cpp @@ -31,7 +31,7 @@ namespace Otter { -OperaBookmarksImporter::OperaBookmarksImporter(QObject *parent) : BookmarksImporter(parent), +OperaBookmarksImporter::OperaBookmarksImporter(QObject *parent) : Importer(parent), m_optionsWidget(nullptr) { } @@ -104,17 +104,67 @@ QStringList OperaBookmarksImporter::getFileFilters() const return {tr("Opera bookmarks files (bookmarks.adr)")}; } +Importer::ImportType OperaBookmarksImporter::getImportType() const +{ + return BookmarksImport; +} + bool OperaBookmarksImporter::import(const QString &path) { - QFile file(getSuggestedPath(path)); + BookmarksModel::Bookmark *folder(nullptr); + bool areDuplicatesAllowed(false); + + if (m_optionsWidget) + { + if (m_optionsWidget->hasToRemoveExisting()) + { + BookmarksManager::getModel()->getRootItem()->removeRows(0, BookmarksManager::getModel()->getRootItem()->rowCount()); + + if (m_optionsWidget->isImportingIntoSubfolder()) + { + folder = BookmarksManager::addBookmark(BookmarksModel::FolderBookmark, {{BookmarksModel::TitleRole, m_optionsWidget->getSubfolderName()}}); + } + } + else + { + folder = m_optionsWidget->getTargetFolder(); + areDuplicatesAllowed = m_optionsWidget->areDuplicatesAllowed(); + } + } + + BookmarksImportJob *job(new OperaBookmarksImportJob(folder, getSuggestedPath(path), areDuplicatesAllowed, this)); + + connect(job, &BookmarksImportJob::importStarted, this, &OperaBookmarksImporter::importStarted); + connect(job, &BookmarksImportJob::importProgress, this, &OperaBookmarksImporter::importProgress); + connect(job, &BookmarksImportJob::importFinished, this, &OperaBookmarksImporter::importFinished); + + job->start(); + + return true; +} + +OperaBookmarksImportJob::OperaBookmarksImportJob(BookmarksModel::Bookmark *folder, const QString &path, bool areDuplicatesAllowed, QObject *parent) : BookmarksImportJob(folder, areDuplicatesAllowed, parent), + m_path(path), + m_isRunning(false) +{ +} + +void OperaBookmarksImportJob::start() +{ + QFile file(m_path); if (!file.open(QIODevice::ReadOnly)) { - emit importFinished(BookmarksImport, FailedImport, 0); + emit importFinished(Importer::BookmarksImport, Importer::FailedImport, 0); + emit jobFinished(false); - return false; + deleteLater(); + + return; } + m_isRunning = true; + QTextStream stream(&file); stream.setCodec("UTF-8"); @@ -122,35 +172,16 @@ bool OperaBookmarksImporter::import(const QString &path) if (line != QLatin1String("Opera Hotlist version 2.0")) { - emit importFinished(BookmarksImport, FailedImport, 0); - - return false; - } + emit importFinished(Importer::BookmarksImport, Importer::FailedImport, 0); + emit jobFinished(false); - emit importStarted(BookmarksImport, -1); - - if (m_optionsWidget) - { - if (m_optionsWidget->hasToRemoveExisting()) - { - removeAllBookmarks(); + deleteLater(); - if (m_optionsWidget->isImportingIntoSubfolder()) - { - setImportFolder(BookmarksManager::addBookmark(BookmarksModel::FolderBookmark, {{BookmarksModel::TitleRole, m_optionsWidget->getSubfolderName()}}, BookmarksManager::getModel()->getRootItem())); - } - else - { - setImportFolder(BookmarksManager::getModel()->getRootItem()); - } - } - else - { - setAllowDuplicates(m_optionsWidget->areDuplicatesAllowed()); - setImportFolder(m_optionsWidget->getTargetFolder()); - } + return; } + emit importStarted(Importer::BookmarksImport, -1); + const int estimatedAmount((file.size() > 0) ? static_cast(file.size() / 250) : 0); int totalAmount(0); @@ -260,11 +291,23 @@ bool OperaBookmarksImporter::import(const QString &path) BookmarksManager::getModel()->endImport(); - emit importFinished(BookmarksImport, SuccessfullImport, totalAmount); + emit importFinished(Importer::BookmarksImport, Importer::SuccessfullImport, totalAmount); + emit jobFinished(true); file.close(); - return true; + m_isRunning = false; + + deleteLater(); +} + +void OperaBookmarksImportJob::cancel() +{ +} + +bool OperaBookmarksImportJob::isRunning() const +{ + return m_isRunning; } } diff --git a/src/modules/importers/opera/OperaBookmarksImporter.h b/src/modules/importers/opera/OperaBookmarksImporter.h index 4655938c59..7beb1a3b9f 100644 --- a/src/modules/importers/opera/OperaBookmarksImporter.h +++ b/src/modules/importers/opera/OperaBookmarksImporter.h @@ -21,14 +21,14 @@ #ifndef OTTER_OPERABOOKMARKSIMPORTER_H #define OTTER_OPERABOOKMARKSIMPORTER_H -#include "../../../core/BookmarksImporter.h" +#include "../../../core/Importer.h" namespace Otter { class BookmarksImporterWidget; -class OperaBookmarksImporter final : public BookmarksImporter +class OperaBookmarksImporter final : public Importer { Q_OBJECT @@ -44,10 +44,27 @@ class OperaBookmarksImporter final : public BookmarksImporter QString getGroup() const override; QUrl getHomePage() const override; QStringList getFileFilters() const override; + ImportType getImportType() const override; public slots: bool import(const QString &path) override; +private: + BookmarksImporterWidget *m_optionsWidget; +}; + +class OperaBookmarksImportJob final : public BookmarksImportJob +{ + Q_OBJECT + +public: + explicit OperaBookmarksImportJob(BookmarksModel::Bookmark *folder, const QString &path, bool areDuplicatesAllowed, QObject *parent = nullptr); + bool isRunning() const override; + +public slots: + void start() override; + void cancel() override; + protected: enum OperaBookmarkEntry { @@ -59,7 +76,8 @@ public slots: }; private: - BookmarksImporterWidget *m_optionsWidget; + QString m_path; + bool m_isRunning; }; } From 3ca1336ec3655958e210fb9abb4ac222038c1652 Mon Sep 17 00:00:00 2001 From: fnkkio <57486061+fnkkio@users.noreply.github.com> Date: Mon, 25 Nov 2019 21:27:42 +0200 Subject: [PATCH 31/71] Hide suggestion popups when changing tab, fixes #1606 --- src/modules/widgets/address/AddressWidget.cpp | 2 ++ src/modules/widgets/search/SearchWidget.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/modules/widgets/address/AddressWidget.cpp b/src/modules/widgets/address/AddressWidget.cpp index f5d0e46c34..63a5b36c69 100644 --- a/src/modules/widgets/address/AddressWidget.cpp +++ b/src/modules/widgets/address/AddressWidget.cpp @@ -1307,6 +1307,7 @@ void AddressWidget::setWindow(Window *window) disconnect(m_window.data(), &Window::arbitraryActionsStateChanged, this, &AddressWidget::handleActionsStateChanged); disconnect(m_window.data(), &Window::contentStateChanged, this, &AddressWidget::updateGeometries); disconnect(m_window.data(), &Window::loadingStateChanged, this, &AddressWidget::handleLoadingStateChanged); + disconnect(m_window->getMainWindow(), &MainWindow::currentWindowChanged, this, &AddressWidget::hidePopup); if (m_window->getWebWidget()) { @@ -1341,6 +1342,7 @@ void AddressWidget::setWindow(Window *window) connect(window, &Window::arbitraryActionsStateChanged, this, &AddressWidget::handleActionsStateChanged); connect(window, &Window::contentStateChanged, this, &AddressWidget::updateGeometries); connect(window, &Window::loadingStateChanged, this, &AddressWidget::handleLoadingStateChanged); + connect(window->getMainWindow(), &MainWindow::currentWindowChanged, this, &AddressWidget::hidePopup); connect(window, &Window::destroyed, this, [&](QObject *object) { if (qobject_cast(object) == m_window) diff --git a/src/modules/widgets/search/SearchWidget.cpp b/src/modules/widgets/search/SearchWidget.cpp index c01dc1ffa4..51b576113a 100644 --- a/src/modules/widgets/search/SearchWidget.cpp +++ b/src/modules/widgets/search/SearchWidget.cpp @@ -753,6 +753,7 @@ void SearchWidget::setWindow(Window *window) disconnect(this, &SearchWidget::requestedSearch, m_window.data(), &Window::requestedSearch); disconnect(m_window.data(), &Window::loadingStateChanged, this, &SearchWidget::handleLoadingStateChanged); disconnect(m_window.data(), &Window::optionChanged, this, &SearchWidget::handleWindowOptionChanged); + disconnect(m_window->getMainWindow(), &MainWindow::currentWindowChanged, this, &SearchWidget::hidePopup); if (m_window->getWebWidget()) { @@ -776,6 +777,7 @@ void SearchWidget::setWindow(Window *window) connect(this, &SearchWidget::requestedSearch, window, &Window::requestedSearch); connect(window, &Window::loadingStateChanged, this, &SearchWidget::handleLoadingStateChanged); connect(window, &Window::optionChanged, this, &SearchWidget::handleWindowOptionChanged); + connect(window->getMainWindow(), &MainWindow::currentWindowChanged, this, &SearchWidget::hidePopup); connect(window, &Window::destroyed, this, [&](QObject *object) { if (qobject_cast(object) == m_window) From a3137be4e8eb4963ad6ec4831aa09b3975c51eb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Tue, 26 Nov 2019 21:46:05 +0100 Subject: [PATCH 32/71] Use helper method --- src/modules/importers/opml/OpmlImporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/importers/opml/OpmlImporter.cpp b/src/modules/importers/opml/OpmlImporter.cpp index fdc1795831..5df3e8d450 100644 --- a/src/modules/importers/opml/OpmlImporter.cpp +++ b/src/modules/importers/opml/OpmlImporter.cpp @@ -36,7 +36,7 @@ void OpmlImporter::importFolder(FeedsModel::Entry *source, FeedsModel::Entry *ta { for (int i = 0; i < source->rowCount(); ++i) { - FeedsModel::Entry *sourceEntry(static_cast(source->child(i))); + FeedsModel::Entry *sourceEntry(source->getChild(i)); if (!sourceEntry) { From fd0ac56a212f6e8be6d435645c241da3be1fe7bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Wed, 27 Nov 2019 21:32:39 +0100 Subject: [PATCH 33/71] [QtWebEngine] Simplify --- src/modules/backends/web/qtwebengine/QtWebEnginePage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/backends/web/qtwebengine/QtWebEnginePage.cpp b/src/modules/backends/web/qtwebengine/QtWebEnginePage.cpp index 94cf09881f..27c3844902 100644 --- a/src/modules/backends/web/qtwebengine/QtWebEnginePage.cpp +++ b/src/modules/backends/web/qtwebengine/QtWebEnginePage.cpp @@ -346,7 +346,7 @@ QString QtWebEnginePage::createJavaScriptList(QStringList rules) const for (int i = 0; i < rules.count(); ++i) { - rules[i] = rules[i].replace(QLatin1Char('\''), QLatin1String("\\'")); + rules[i].replace(QLatin1Char('\''), QLatin1String("\\'")); } return QLatin1Char('\'') + rules.join(QLatin1String("','")) + QLatin1Char('\''); From 912c0ab73564a77ca2b162440980e2bc32de6e19 Mon Sep 17 00:00:00 2001 From: fnkkio <57486061+fnkkio@users.noreply.github.com> Date: Thu, 28 Nov 2019 21:28:39 +0200 Subject: [PATCH 34/71] Fix minor typo --- src/ui/preferences/PreferencesAdvancedPageWidget.cpp | 6 +++--- src/ui/preferences/PreferencesAdvancedPageWidget.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ui/preferences/PreferencesAdvancedPageWidget.cpp b/src/ui/preferences/PreferencesAdvancedPageWidget.cpp index 5ff284b6a7..8b2824fdcc 100644 --- a/src/ui/preferences/PreferencesAdvancedPageWidget.cpp +++ b/src/ui/preferences/PreferencesAdvancedPageWidget.cpp @@ -841,7 +841,7 @@ void PreferencesAdvancedPageWidget::updateUserAgentsActions() m_ui->userAgentsRemoveButton->setEnabled(index.isValid() && index.data(UserAgentsModel::IdentifierRole).toString() != QLatin1String("default")); } -void PreferencesAdvancedPageWidget::saveUsuerAgents(QJsonArray *userAgents, const QStandardItem *parent) +void PreferencesAdvancedPageWidget::saveUserAgents(QJsonArray *userAgents, const QStandardItem *parent) { for (int i = 0; i < parent->rowCount(); ++i) { @@ -859,7 +859,7 @@ void PreferencesAdvancedPageWidget::saveUsuerAgents(QJsonArray *userAgents, cons { QJsonArray userAgentsArray; - saveUsuerAgents(&userAgentsArray, item); + saveUserAgents(&userAgentsArray, item); userAgentObject.insert(QLatin1String("children"), userAgentsArray); } @@ -1702,7 +1702,7 @@ void PreferencesAdvancedPageWidget::save() { QJsonArray userAgentsArray; - saveUsuerAgents(&userAgentsArray, m_ui->userAgentsViewWidget->getSourceModel()->invisibleRootItem()); + saveUserAgents(&userAgentsArray, m_ui->userAgentsViewWidget->getSourceModel()->invisibleRootItem()); JsonSettings settings; settings.setArray(userAgentsArray); diff --git a/src/ui/preferences/PreferencesAdvancedPageWidget.h b/src/ui/preferences/PreferencesAdvancedPageWidget.h index b07522d750..16f2eebb98 100644 --- a/src/ui/preferences/PreferencesAdvancedPageWidget.h +++ b/src/ui/preferences/PreferencesAdvancedPageWidget.h @@ -84,7 +84,7 @@ protected slots: void addUserAgent(QAction *action); void editUserAgent(); void updateUserAgentsActions(); - void saveUsuerAgents(QJsonArray *userAgents, const QStandardItem *parent); + void saveUserAgents(QJsonArray *userAgents, const QStandardItem *parent); void addProxy(QAction *action); void editProxy(); void updateProxiesActions(); From 0597fb72546b3c5f5034008db9430c0468667768 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Thu, 28 Nov 2019 21:17:18 +0100 Subject: [PATCH 35/71] [QtWebEngine] Silence cppcheck warning --- src/modules/backends/web/qtwebengine/QtWebEnginePage.cpp | 8 +++++--- src/modules/backends/web/qtwebengine/QtWebEnginePage.h | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/modules/backends/web/qtwebengine/QtWebEnginePage.cpp b/src/modules/backends/web/qtwebengine/QtWebEnginePage.cpp index 27c3844902..623b69d00d 100644 --- a/src/modules/backends/web/qtwebengine/QtWebEnginePage.cpp +++ b/src/modules/backends/web/qtwebengine/QtWebEnginePage.cpp @@ -337,19 +337,21 @@ QtWebEngineWebWidget* QtWebEnginePage::createWidget(SessionsManager::OpenHints h return widget; } -QString QtWebEnginePage::createJavaScriptList(QStringList rules) const +QString QtWebEnginePage::createJavaScriptList(const QStringList &rules) const { if (rules.isEmpty()) { return {}; } + QStringList parsedRules(rules); + for (int i = 0; i < rules.count(); ++i) { - rules[i].replace(QLatin1Char('\''), QLatin1String("\\'")); + parsedRules[i].replace(QLatin1Char('\''), QLatin1String("\\'")); } - return QLatin1Char('\'') + rules.join(QLatin1String("','")) + QLatin1Char('\''); + return QLatin1Char('\'') + parsedRules.join(QLatin1String("','")) + QLatin1Char('\''); } QString QtWebEnginePage::createScriptSource(const QString &path, const QStringList ¶meters) const diff --git a/src/modules/backends/web/qtwebengine/QtWebEnginePage.h b/src/modules/backends/web/qtwebengine/QtWebEnginePage.h index eebdb8126f..c817f3eeb4 100644 --- a/src/modules/backends/web/qtwebengine/QtWebEnginePage.h +++ b/src/modules/backends/web/qtwebengine/QtWebEnginePage.h @@ -63,7 +63,7 @@ class QtWebEnginePage final : public QWebEnginePage void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString ¬e, int line, const QString &source) override; QWebEnginePage* createWindow(WebWindowType type) override; QtWebEngineWebWidget* createWidget(SessionsManager::OpenHints hints); - QString createJavaScriptList(QStringList rules) const; + QString createJavaScriptList(const QStringList &rules) const; QStringList chooseFiles(FileSelectionMode mode, const QStringList &oldFiles, const QStringList &acceptedMimeTypes) override; bool acceptNavigationRequest(const QUrl &url, QWebEnginePage::NavigationType type, bool isMainFrame) override; bool javaScriptConfirm(const QUrl &url, const QString &message) override; From 62fc372843dca778669d81556d78459169d767c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Fri, 29 Nov 2019 20:48:15 +0100 Subject: [PATCH 36/71] [QtWebEngine] Drop not needed specifiers --- src/modules/backends/web/qtwebengine/QtWebEnginePage.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/backends/web/qtwebengine/QtWebEnginePage.h b/src/modules/backends/web/qtwebengine/QtWebEnginePage.h index c817f3eeb4..603be4c57f 100644 --- a/src/modules/backends/web/qtwebengine/QtWebEnginePage.h +++ b/src/modules/backends/web/qtwebengine/QtWebEnginePage.h @@ -65,7 +65,7 @@ class QtWebEnginePage final : public QWebEnginePage QtWebEngineWebWidget* createWidget(SessionsManager::OpenHints hints); QString createJavaScriptList(const QStringList &rules) const; QStringList chooseFiles(FileSelectionMode mode, const QStringList &oldFiles, const QStringList &acceptedMimeTypes) override; - bool acceptNavigationRequest(const QUrl &url, QWebEnginePage::NavigationType type, bool isMainFrame) override; + bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame) override; bool javaScriptConfirm(const QUrl &url, const QString &message) override; bool javaScriptPrompt(const QUrl &url, const QString &message, const QString &defaultValue, QString *result) override; @@ -77,7 +77,7 @@ protected slots: QtWebEngineWebWidget *m_widget; QVector m_popups; QVector m_history; - QWebEnginePage::NavigationType m_previousNavigationType; + NavigationType m_previousNavigationType; bool m_isIgnoringJavaScriptPopups; bool m_isViewingMedia; bool m_isPopup; @@ -85,7 +85,7 @@ protected slots: signals: void requestedNewWindow(WebWidget *widget, SessionsManager::OpenHints hints, const QVariantMap ¶meters); void requestedPopupWindow(const QUrl &parentUrl, const QUrl &popupUrl); - void aboutToNavigate(const QUrl &url, QWebEnginePage::NavigationType navigationType); + void aboutToNavigate(const QUrl &url, NavigationType navigationType); void viewingMediaChanged(bool isViewingMedia); }; From 3c54273f1c1b3661d31c174748770f16842b9c95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Sat, 30 Nov 2019 19:23:23 +0100 Subject: [PATCH 37/71] [QtWebKit] Move QWebInspector wrapper together with QtWebKitWebWidget --- CMakeLists.txt | 1 - .../web/qtwebkit/QtWebKitInspector.cpp | 48 ------------------- .../backends/web/qtwebkit/QtWebKitInspector.h | 41 ---------------- .../web/qtwebkit/QtWebKitWebWidget.cpp | 35 ++++++++++---- .../backends/web/qtwebkit/QtWebKitWebWidget.h | 14 +++++- 5 files changed, 39 insertions(+), 100 deletions(-) delete mode 100644 src/modules/backends/web/qtwebkit/QtWebKitInspector.cpp delete mode 100644 src/modules/backends/web/qtwebkit/QtWebKitInspector.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 22b8328066..bfcedaa269 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -377,7 +377,6 @@ if (Qt5WebKitWidgets_FOUND AND ENABLE_QTWEBKIT) src/modules/backends/web/qtwebkit/QtWebKitCookieJar.cpp src/modules/backends/web/qtwebkit/QtWebKitFtpListingNetworkReply.cpp src/modules/backends/web/qtwebkit/QtWebKitHistoryInterface.cpp - src/modules/backends/web/qtwebkit/QtWebKitInspector.cpp src/modules/backends/web/qtwebkit/QtWebKitNetworkManager.cpp src/modules/backends/web/qtwebkit/QtWebKitNotificationPresenter.cpp src/modules/backends/web/qtwebkit/QtWebKitPage.cpp diff --git a/src/modules/backends/web/qtwebkit/QtWebKitInspector.cpp b/src/modules/backends/web/qtwebkit/QtWebKitInspector.cpp deleted file mode 100644 index 11b9b27a1f..0000000000 --- a/src/modules/backends/web/qtwebkit/QtWebKitInspector.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/************************************************************************** -* Otter Browser: Web browser controlled by the user, not vice-versa. -* Copyright (C) 2015 - 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 "QtWebKitInspector.h" - -#include -#include - -namespace Otter -{ - -QtWebKitInspector::QtWebKitInspector(QWidget *parent) : QWebInspector(parent) -{ - setMinimumHeight(200); -} - -void QtWebKitInspector::childEvent(QChildEvent *event) -{ - QWebInspector::childEvent(event); - - if (event->type() == QEvent::ChildAdded && event->child()->inherits("QWebView")) - { - QWebView *webView(qobject_cast(event->child())); - - if (webView) - { - webView->settings()->setAttribute(QWebSettings::JavascriptEnabled, true); - } - } -} - -} diff --git a/src/modules/backends/web/qtwebkit/QtWebKitInspector.h b/src/modules/backends/web/qtwebkit/QtWebKitInspector.h deleted file mode 100644 index 4e3e8a6b67..0000000000 --- a/src/modules/backends/web/qtwebkit/QtWebKitInspector.h +++ /dev/null @@ -1,41 +0,0 @@ -/************************************************************************** -* Otter Browser: Web browser controlled by the user, not vice-versa. -* Copyright (C) 2015 - 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_QTWEBKITINSPECTOR_H -#define OTTER_QTWEBKITINSPECTOR_H - -#include - -namespace Otter -{ - -class QtWebKitInspector final : public QWebInspector -{ - Q_OBJECT - -public: - explicit QtWebKitInspector(QWidget *parent); - -protected: - void childEvent(QChildEvent *event) override; -}; - -} - -#endif diff --git a/src/modules/backends/web/qtwebkit/QtWebKitWebWidget.cpp b/src/modules/backends/web/qtwebkit/QtWebKitWebWidget.cpp index ad7cb2524d..75b659c16f 100644 --- a/src/modules/backends/web/qtwebkit/QtWebKitWebWidget.cpp +++ b/src/modules/backends/web/qtwebkit/QtWebKitWebWidget.cpp @@ -19,7 +19,6 @@ **************************************************************************/ #include "QtWebKitWebWidget.h" -#include "QtWebKitInspector.h" #include "QtWebKitNetworkManager.h" #include "QtWebKitPage.h" #include "QtWebKitPluginWidget.h" @@ -74,10 +73,30 @@ namespace Otter { +QtWebKitInspectorWidget::QtWebKitInspectorWidget(QWidget *parent) : QWebInspector(parent) +{ + setMinimumHeight(200); +} + +void QtWebKitInspectorWidget::childEvent(QChildEvent *event) +{ + QWebInspector::childEvent(event); + + if (event->type() == QEvent::ChildAdded && event->child()->inherits("QWebView")) + { + QWebView *webView(qobject_cast(event->child())); + + if (webView) + { + webView->settings()->setAttribute(QWebSettings::JavascriptEnabled, true); + } + } +} + QtWebKitWebWidget::QtWebKitWebWidget(const QVariantMap ¶meters, WebBackend *backend, QtWebKitNetworkManager *networkManager, ContentsWidget *parent) : WebWidget(parameters, backend, parent), m_webView(new QWebView(this)), m_page(nullptr), - m_inspector(nullptr), + m_inspectorWidget(nullptr), m_networkManager(networkManager), m_formRequestOperation(QNetworkAccessManager::GetOperation), m_loadingState(FinishedLoadingState), @@ -1675,7 +1694,7 @@ void QtWebKitWebWidget::triggerAction(int identifier, const QVariantMap ¶met { const bool showInspector(parameters.value(QLatin1String("isChecked"), !getActionState(identifier, parameters).isChecked).toBool()); - if (showInspector && !m_inspector) + if (showInspector && !m_inspectorWidget) { getInspector(); } @@ -1951,15 +1970,15 @@ WebWidget* QtWebKitWebWidget::clone(bool cloneHistory, bool isPrivate, const QSt QWidget* QtWebKitWebWidget::getInspector() { - if (!m_inspector) + if (!m_inspectorWidget) { m_page->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true); - m_inspector = new QtWebKitInspector(this); - m_inspector->setPage(m_page); + m_inspectorWidget = new QtWebKitInspectorWidget(this); + m_inspectorWidget->setPage(m_page); } - return m_inspector; + return m_inspectorWidget; } QWidget* QtWebKitWebWidget::getViewport() @@ -2658,7 +2677,7 @@ bool QtWebKitWebWidget::isFullScreen() const bool QtWebKitWebWidget::isInspecting() const { - return (m_inspector && m_inspector->isVisible()); + return (m_inspectorWidget && m_inspectorWidget->isVisible()); } bool QtWebKitWebWidget::isNavigating() const diff --git a/src/modules/backends/web/qtwebkit/QtWebKitWebWidget.h b/src/modules/backends/web/qtwebkit/QtWebKitWebWidget.h index db9ee1b6b1..aa33575987 100644 --- a/src/modules/backends/web/qtwebkit/QtWebKitWebWidget.h +++ b/src/modules/backends/web/qtwebkit/QtWebKitWebWidget.h @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -32,12 +33,21 @@ namespace Otter { class ContentsDialog; -class QtWebKitInspector; +class QtWebKitInspectorWidget; class QtWebKitNetworkManager; class QtWebKitWebBackend; class QtWebKitPage; class SourceViewerWebWidget; +class QtWebKitInspectorWidget final : public QWebInspector +{ +public: + explicit QtWebKitInspectorWidget(QWidget *parent); + +protected: + void childEvent(QChildEvent *event) override; +}; + class QtWebKitWebWidget final : public WebWidget { Q_OBJECT @@ -170,7 +180,7 @@ protected slots: private: QWebView *m_webView; QtWebKitPage *m_page; - QtWebKitInspector *m_inspector; + QtWebKitInspectorWidget *m_inspectorWidget; QtWebKitNetworkManager *m_networkManager; QString m_messageToken; QString m_pluginToken; From 9c431be2b206a7c8e929dc15ab7229a3873ba92e Mon Sep 17 00:00:00 2001 From: fnkkio <57486061+fnkkio@users.noreply.github.com> Date: Sun, 1 Dec 2019 21:28:18 +0200 Subject: [PATCH 38/71] Update downloadsItemView data before saving, fixes #1624 --- src/ui/preferences/PreferencesAdvancedPageWidget.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ui/preferences/PreferencesAdvancedPageWidget.cpp b/src/ui/preferences/PreferencesAdvancedPageWidget.cpp index 8b2824fdcc..3dbf4ecec7 100644 --- a/src/ui/preferences/PreferencesAdvancedPageWidget.cpp +++ b/src/ui/preferences/PreferencesAdvancedPageWidget.cpp @@ -1672,6 +1672,8 @@ void PreferencesAdvancedPageWidget::save() QFile::remove(SessionsManager::getReadableDataPath(QLatin1String("handlers.ini"))); + updateDownloadsOptions(); + for (int i = 0; i < m_ui->downloadsItemView->getRowCount(); ++i) { const QModelIndex index(m_ui->downloadsItemView->getIndex(i, 0)); From 867055ad0d7ca45830cec886acfc396ccca46025 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Sun, 1 Dec 2019 21:50:43 +0100 Subject: [PATCH 39/71] [QtWebKit] Mark as explicit --- src/modules/backends/web/qtwebkit/QtWebKitPage.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/backends/web/qtwebkit/QtWebKitPage.h b/src/modules/backends/web/qtwebkit/QtWebKitPage.h index 332164427d..b6d3dc5260 100644 --- a/src/modules/backends/web/qtwebkit/QtWebKitPage.h +++ b/src/modules/backends/web/qtwebkit/QtWebKitPage.h @@ -83,7 +83,7 @@ public slots: void updateStyleSheets(const QUrl &url = {}); protected: - QtWebKitPage(); + explicit QtWebKitPage(); explicit QtWebKitPage(const QUrl &url); void markAsPopup(); From ca7b9e80983357fc466141e5c6402e3c208eb75d Mon Sep 17 00:00:00 2001 From: fnkkio <57486061+fnkkio@users.noreply.github.com> Date: Mon, 2 Dec 2019 22:59:40 +0200 Subject: [PATCH 40/71] Add x-url-title as part of MIME data, fixes #1629 --- src/core/BookmarksModel.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/BookmarksModel.cpp b/src/core/BookmarksModel.cpp index e26d143355..5954048a99 100644 --- a/src/core/BookmarksModel.cpp +++ b/src/core/BookmarksModel.cpp @@ -1215,6 +1215,7 @@ QMimeData* BookmarksModel::mimeData(const QModelIndexList &indexes) const if (indexes.count() == 1) { mimeData->setProperty("x-item-index", indexes.at(0)); + mimeData->setProperty("x-url-title", indexes.at(0).data(TitleRole).toString()); } for (int i = 0; i < indexes.count(); ++i) From 3b8fd7753a65beeb87323e4403d49c1aabc4cf86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Mon, 2 Dec 2019 22:09:07 +0100 Subject: [PATCH 41/71] Make getDateTime() more generic and move it to base class --- src/core/Importer.cpp | 13 +++++++++++++ src/core/Importer.h | 1 + .../web/qtwebkit/QtWebKitWebBackend.cpp | 19 +++---------------- .../web/qtwebkit/QtWebKitWebBackend.h | 1 - 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/core/Importer.cpp b/src/core/Importer.cpp index fbf5189c09..45dcf20a8d 100644 --- a/src/core/Importer.cpp +++ b/src/core/Importer.cpp @@ -99,6 +99,19 @@ BookmarksModel::Bookmark* BookmarksImportJob::getImportFolder() const return m_importFolder; } +QDateTime BookmarksImportJob::getDateTime(const QString ×tamp) const +{ +#if QT_VERSION < 0x050800 + const uint seconds(timestamp.toUInt()); + + return ((seconds > 0) ? QDateTime::fromTime_t(seconds) : QDateTime()); +#else + const qint64 seconds(timestamp.toLongLong()); + + return ((seconds != 0) ? QDateTime::fromSecsSinceEpoch(seconds) : QDateTime()); +#endif +} + bool BookmarksImportJob::areDuplicatesAllowed() const { return m_areDuplicatesAllowed; diff --git a/src/core/Importer.h b/src/core/Importer.h index 1aa73b1dd9..1805818aa0 100644 --- a/src/core/Importer.h +++ b/src/core/Importer.h @@ -111,6 +111,7 @@ class BookmarksImportJob : public ImportJob void setCurrentFolder(BookmarksModel::Bookmark *folder); BookmarksModel::Bookmark* getCurrentFolder() const; BookmarksModel::Bookmark* getImportFolder() const; + QDateTime getDateTime(const QString ×tamp) const; bool areDuplicatesAllowed() const; private: diff --git a/src/modules/backends/web/qtwebkit/QtWebKitWebBackend.cpp b/src/modules/backends/web/qtwebkit/QtWebKitWebBackend.cpp index c1ebc8ad3f..c8d8e43677 100644 --- a/src/modules/backends/web/qtwebkit/QtWebKitWebBackend.cpp +++ b/src/modules/backends/web/qtwebkit/QtWebKitWebBackend.cpp @@ -355,7 +355,7 @@ void QtWebKitBookmarksImportJob::processElement(const QWebElement &element) if (matchedElement.hasAttribute(QLatin1String("ADD_DATE"))) { - const QDateTime dateTime(getDateTime(matchedElement, QLatin1String("ADD_DATE"))); + const QDateTime dateTime(getDateTime(matchedElement.attribute(QLatin1String("ADD_DATE")))); if (dateTime.isValid()) { @@ -366,7 +366,7 @@ void QtWebKitBookmarksImportJob::processElement(const QWebElement &element) if (matchedElement.hasAttribute(QLatin1String("LAST_MODIFIED"))) { - const QDateTime dateTime(getDateTime(matchedElement, QLatin1String("LAST_MODIFIED"))); + const QDateTime dateTime(getDateTime(matchedElement.attribute(QLatin1String("LAST_MODIFIED")))); if (dateTime.isValid()) { @@ -376,7 +376,7 @@ void QtWebKitBookmarksImportJob::processElement(const QWebElement &element) if (isUrlBookmark && matchedElement.hasAttribute(QLatin1String("LAST_VISITED"))) { - const QDateTime dateTime(getDateTime(matchedElement, QLatin1String("LAST_VISITED"))); + const QDateTime dateTime(getDateTime(matchedElement.attribute(QLatin1String("LAST_VISITED")))); if (dateTime.isValid()) { @@ -455,19 +455,6 @@ void QtWebKitBookmarksImportJob::cancel() { } -QDateTime QtWebKitBookmarksImportJob::getDateTime(const QWebElement &element, const QString &attribute) -{ -#if QT_VERSION < 0x050800 - const uint seconds(element.attribute(attribute).toUInt()); - - return ((seconds > 0) ? QDateTime::fromTime_t(seconds) : QDateTime()); -#else - const qint64 seconds(element.attribute(attribute).toLongLong()); - - return ((seconds != 0) ? QDateTime::fromSecsSinceEpoch(seconds) : QDateTime()); -#endif -} - bool QtWebKitBookmarksImportJob::isRunning() const { return m_isRunning; diff --git a/src/modules/backends/web/qtwebkit/QtWebKitWebBackend.h b/src/modules/backends/web/qtwebkit/QtWebKitWebBackend.h index 235ffa396d..1c29b3073c 100644 --- a/src/modules/backends/web/qtwebkit/QtWebKitWebBackend.h +++ b/src/modules/backends/web/qtwebkit/QtWebKitWebBackend.h @@ -97,7 +97,6 @@ public slots: protected: void processElement(const QWebElement &element); - static QDateTime getDateTime(const QWebElement &element, const QString &attribute); private: QString m_path; From 734e6c50d86d7f68758902e9346292c9f7b23302 Mon Sep 17 00:00:00 2001 From: fnkkio <57486061+fnkkio@users.noreply.github.com> Date: Tue, 3 Dec 2019 22:33:54 +0200 Subject: [PATCH 42/71] Update downloadsItemView data on every change, references #1624 --- src/ui/ApplicationComboBoxWidget.cpp | 4 ++++ src/ui/ApplicationComboBoxWidget.h | 3 +++ src/ui/FilePathWidget.cpp | 11 +++++++++++ src/ui/FilePathWidget.h | 2 ++ src/ui/preferences/PreferencesAdvancedPageWidget.cpp | 3 +++ 5 files changed, 23 insertions(+) diff --git a/src/ui/ApplicationComboBoxWidget.cpp b/src/ui/ApplicationComboBoxWidget.cpp index 11fcd0885a..116290528a 100644 --- a/src/ui/ApplicationComboBoxWidget.cpp +++ b/src/ui/ApplicationComboBoxWidget.cpp @@ -70,6 +70,8 @@ void ApplicationComboBoxWidget::handleIndexChanged(int index) insertItem(m_previousIndex, QFileInfo(path).baseName(), path); setCurrentIndex(m_previousIndex); + + emit currentCommandChanged(); } connect(this, static_cast(&ApplicationComboBoxWidget::currentIndexChanged), this, &ApplicationComboBoxWidget::handleIndexChanged); @@ -77,6 +79,8 @@ void ApplicationComboBoxWidget::handleIndexChanged(int index) else { m_previousIndex = index; + + emit currentCommandChanged(); } } diff --git a/src/ui/ApplicationComboBoxWidget.h b/src/ui/ApplicationComboBoxWidget.h index e9522c2688..5bb945c466 100644 --- a/src/ui/ApplicationComboBoxWidget.h +++ b/src/ui/ApplicationComboBoxWidget.h @@ -47,6 +47,9 @@ protected slots: private: int m_previousIndex; bool m_alwaysShowDefaultApplication; + +signals: + void currentCommandChanged(); }; } diff --git a/src/ui/FilePathWidget.cpp b/src/ui/FilePathWidget.cpp index 82d8c938ac..282802f0c7 100644 --- a/src/ui/FilePathWidget.cpp +++ b/src/ui/FilePathWidget.cpp @@ -79,9 +79,20 @@ void FilePathWidget::focusInEvent(QFocusEvent *event) { QWidget::focusInEvent(event); + m_initialPath = getPath(); m_lineEditWidget->setFocus(); } +void FilePathWidget::focusOutEvent(QFocusEvent *event) +{ + QWidget::focusOutEvent(event); + + if (m_initialPath != getPath()) + { + emit pathChanged(getPath()); + } +} + void FilePathWidget::selectPath() { QString path(m_lineEditWidget->text().isEmpty() ? QStandardPaths::standardLocations(QStandardPaths::HomeLocation).value(0) : m_lineEditWidget->text()); diff --git a/src/ui/FilePathWidget.h b/src/ui/FilePathWidget.h index b5e523de92..097370a4f9 100644 --- a/src/ui/FilePathWidget.h +++ b/src/ui/FilePathWidget.h @@ -62,6 +62,7 @@ class FilePathWidget final : public QWidget protected: void changeEvent(QEvent *event) override; void focusInEvent(QFocusEvent *event) override; + void focusOutEvent(QFocusEvent *event) override; protected slots: void selectPath(); @@ -72,6 +73,7 @@ protected slots: LineEditWidget *m_lineEditWidget; QCompleter *m_completer; QString m_filter; + QString m_initialPath; OpenMode m_openMode; signals: diff --git a/src/ui/preferences/PreferencesAdvancedPageWidget.cpp b/src/ui/preferences/PreferencesAdvancedPageWidget.cpp index 3dbf4ecec7..f1f5d6925c 100644 --- a/src/ui/preferences/PreferencesAdvancedPageWidget.cpp +++ b/src/ui/preferences/PreferencesAdvancedPageWidget.cpp @@ -398,6 +398,9 @@ PreferencesAdvancedPageWidget::PreferencesAdvancedPageWidget(QWidget *parent) : connect(m_ui->downloadsRemoveMimeTypeButton, &QPushButton::clicked, this, &PreferencesAdvancedPageWidget::removeDownloadsMimeType); connect(m_ui->downloadsButtonGroup, static_cast(&QButtonGroup::buttonToggled), this, &PreferencesAdvancedPageWidget::updateDownloadsOptions); connect(m_ui->downloadsButtonGroup, static_cast(&QButtonGroup::buttonToggled), this, &PreferencesAdvancedPageWidget::updateDownloadsMode); + connect(m_ui->downloadsSaveDirectlyCheckBox, &QCheckBox::toggled, this, &PreferencesAdvancedPageWidget::updateDownloadsOptions); + connect(m_ui->downloadsFilePathWidget, &Otter::FilePathWidget::pathChanged, this, &PreferencesAdvancedPageWidget::updateDownloadsOptions); + connect(m_ui->downloadsApplicationComboBoxWidget, &Otter::ApplicationComboBoxWidget::currentCommandChanged, this, &PreferencesAdvancedPageWidget::updateDownloadsOptions); connect(m_ui->userAgentsViewWidget, &ItemViewWidget::needsActionsUpdate, this, &PreferencesAdvancedPageWidget::updateUserAgentsActions); connect(m_ui->userAgentsAddButton->menu(), &QMenu::triggered, this, &PreferencesAdvancedPageWidget::addUserAgent); connect(m_ui->userAgentsEditButton, &QPushButton::clicked, this, &PreferencesAdvancedPageWidget::editUserAgent); From f2c7f66b4637d4b3f9e58a461faf173265f11a58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Tue, 3 Dec 2019 21:55:25 +0100 Subject: [PATCH 43/71] Profile path is not supposed to be empty --- src/core/Application.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/core/Application.cpp b/src/core/Application.cpp index 9471bfb601..0222cf0836 100644 --- a/src/core/Application.cpp +++ b/src/core/Application.cpp @@ -277,8 +277,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv), QCryptographicHash hash(QCryptographicHash::Md5); hash.addData(profilePath.toUtf8()); - const QString identifier(QString::fromLatin1(hash.result().toHex())); - const QString server(applicationName() + (identifier.isEmpty() ? QString() : (QLatin1Char('-') + identifier))); + const QString server(applicationName() + QLatin1Char('-') + QString::fromLatin1(hash.result().toHex())); QLocalSocket socket; socket.connectToServer(server); From 726397de9c60ae2d74aa10bb71f84dc0f3e7c3f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Wed, 4 Dec 2019 20:27:48 +0100 Subject: [PATCH 44/71] Rename --- src/core/Application.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/Application.cpp b/src/core/Application.cpp index 0222cf0836..1c9eb14193 100644 --- a/src/core/Application.cpp +++ b/src/core/Application.cpp @@ -277,9 +277,9 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv), QCryptographicHash hash(QCryptographicHash::Md5); hash.addData(profilePath.toUtf8()); - const QString server(applicationName() + QLatin1Char('-') + QString::fromLatin1(hash.result().toHex())); + const QString serverName(applicationName() + QLatin1Char('-') + QString::fromLatin1(hash.result().toHex())); QLocalSocket socket; - socket.connectToServer(server); + socket.connectToServer(serverName); if (socket.waitForConnected(500)) { @@ -310,9 +310,9 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv), m_localServer->setSocketOptions(QLocalServer::UserAccessOption); - if (!m_localServer->listen(server) && m_localServer->serverError() == QAbstractSocket::AddressInUseError && QLocalServer::removeServer(server)) + if (!m_localServer->listen(serverName) && m_localServer->serverError() == QAbstractSocket::AddressInUseError && QLocalServer::removeServer(serverName)) { - m_localServer->listen(server); + m_localServer->listen(serverName); } m_isFirstRun = !QFile::exists(profilePath); From af71022e96acdc77cf1ea8589387c7d9c8239967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Thu, 5 Dec 2019 21:01:45 +0100 Subject: [PATCH 45/71] Add explicit method to check if SSL is supported by the backend --- src/core/Application.cpp | 2 +- src/core/WebBackend.h | 1 + .../backends/web/qtwebengine/QtWebEngineWebBackend.cpp | 5 +++++ src/modules/backends/web/qtwebengine/QtWebEngineWebBackend.h | 1 + src/modules/backends/web/qtwebkit/QtWebKitWebBackend.cpp | 5 +++++ src/modules/backends/web/qtwebkit/QtWebKitWebBackend.h | 1 + 6 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/core/Application.cpp b/src/core/Application.cpp index 1c9eb14193..3117dc3ee7 100644 --- a/src/core/Application.cpp +++ b/src/core/Application.cpp @@ -444,7 +444,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv), const WebBackend *webBackend(AddonsManager::getWebBackend()); - if (!QSslSocket::supportsSsl() || (webBackend && webBackend->getSslVersion().isEmpty())) + if (!QSslSocket::supportsSsl() || (webBackend && !webBackend->hasSslSupport())) { QMessageBox::warning(nullptr, tr("Warning"), tr("SSL support is not available or incomplete.\nSome websites may work incorrectly or do not work at all."), QMessageBox::Close); } diff --git a/src/core/WebBackend.h b/src/core/WebBackend.h index e8cb85910e..cf2ad17abf 100644 --- a/src/core/WebBackend.h +++ b/src/core/WebBackend.h @@ -85,6 +85,7 @@ class WebBackend : public QObject, public Addon virtual QVector getDictionaries() const; AddonType getType() const override; virtual BackendCapabilities getCapabilities() const; + virtual bool hasSslSupport() const = 0; }; } diff --git a/src/modules/backends/web/qtwebengine/QtWebEngineWebBackend.cpp b/src/modules/backends/web/qtwebengine/QtWebEngineWebBackend.cpp index 3df3502a52..b1eb2857aa 100644 --- a/src/modules/backends/web/qtwebengine/QtWebEngineWebBackend.cpp +++ b/src/modules/backends/web/qtwebengine/QtWebEngineWebBackend.cpp @@ -344,4 +344,9 @@ WebBackend::BackendCapabilities QtWebEngineWebBackend::getCapabilities() const return (UserScriptsCapability | GlobalCookiesPolicyCapability | GlobalContentFilteringCapability | GlobalDoNotTrackCapability | GlobalProxyCapability | GlobalReferrerCapability | GlobalUserAgentCapability); } +bool QtWebEngineWebBackend::hasSslSupport() const +{ + return true; +} + } diff --git a/src/modules/backends/web/qtwebengine/QtWebEngineWebBackend.h b/src/modules/backends/web/qtwebengine/QtWebEngineWebBackend.h index 303842ceda..5e8386552b 100644 --- a/src/modules/backends/web/qtwebengine/QtWebEngineWebBackend.h +++ b/src/modules/backends/web/qtwebengine/QtWebEngineWebBackend.h @@ -57,6 +57,7 @@ class QtWebEngineWebBackend final : public WebBackend #endif QUrl getHomePage() const override; WebBackend::BackendCapabilities getCapabilities() const override; + bool hasSslSupport() const override; #if QTWEBENGINECORE_VERSION >= 0x050D00 protected: diff --git a/src/modules/backends/web/qtwebkit/QtWebKitWebBackend.cpp b/src/modules/backends/web/qtwebkit/QtWebKitWebBackend.cpp index c8d8e43677..226923cc8c 100644 --- a/src/modules/backends/web/qtwebkit/QtWebKitWebBackend.cpp +++ b/src/modules/backends/web/qtwebkit/QtWebKitWebBackend.cpp @@ -283,6 +283,11 @@ int QtWebKitWebBackend::getOptionIdentifier(QtWebKitWebBackend::OptionIdentifier return -1; } +bool QtWebKitWebBackend::hasSslSupport() const +{ + return QSslSocket::supportsSsl(); +} + QtWebKitBookmarksImportJob::QtWebKitBookmarksImportJob(BookmarksModel::Bookmark *folder, const QString &path, bool areDuplicatesAllowed, QObject *parent) : BookmarksImportJob(folder, areDuplicatesAllowed, parent), m_path(path), m_currentAmount(0), diff --git a/src/modules/backends/web/qtwebkit/QtWebKitWebBackend.h b/src/modules/backends/web/qtwebkit/QtWebKitWebBackend.h index 1c29b3073c..4593d7bbe5 100644 --- a/src/modules/backends/web/qtwebkit/QtWebKitWebBackend.h +++ b/src/modules/backends/web/qtwebkit/QtWebKitWebBackend.h @@ -57,6 +57,7 @@ class QtWebKitWebBackend final : public WebBackend QUrl getHomePage() const override; BackendCapabilities getCapabilities() const override; static int getOptionIdentifier(OptionIdentifier identifier); + bool hasSslSupport() const override; protected: static QtWebKitWebBackend* getInstance(); From 245cb10033ac5a9166e7f1d41403788e5c77c269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Fri, 6 Dec 2019 22:27:01 +0100 Subject: [PATCH 46/71] Simplify --- src/core/Application.cpp | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/core/Application.cpp b/src/core/Application.cpp index 3117dc3ee7..621fdc7cf2 100644 --- a/src/core/Application.cpp +++ b/src/core/Application.cpp @@ -1016,14 +1016,7 @@ void Application::handleNewConnection() if (!mainWindow || !SettingsManager::getOption(SettingsManager::Browser_OpenLinksInNewTabOption).toBool() || (isPrivate && !mainWindow->isPrivate())) { - QVariantMap parameters; - - if (isPrivate) - { - parameters[QLatin1String("hints")] = SessionsManager::PrivateOpen; - } - - createWindow(parameters); + createWindow({{QLatin1String("hints"), (isPrivate ? SessionsManager::PrivateOpen : SessionsManager::DefaultOpen)}}); } } else @@ -1032,12 +1025,7 @@ void Application::handleNewConnection() if (sessionData.isClean || QMessageBox::warning(nullptr, tr("Warning"), tr("This session was not saved correctly.\nAre you sure that you want to restore this session anyway?"), (QMessageBox::Yes | QMessageBox::No), QMessageBox::No) == QMessageBox::Yes) { - QVariantMap parameters; - - if (isPrivate) - { - parameters[QLatin1String("hints")] = SessionsManager::PrivateOpen; - } + const QVariantMap parameters({{QLatin1String("hints"), (isPrivate ? SessionsManager::PrivateOpen : SessionsManager::DefaultOpen)}}); for (int i = 0; i < sessionData.windows.count(); ++i) { From 09098025e52596cdc093706b638a33f6457e8daa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Sat, 7 Dec 2019 21:29:51 +0100 Subject: [PATCH 47/71] Simplify --- src/core/Application.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/core/Application.cpp b/src/core/Application.cpp index 621fdc7cf2..283d9b0bde 100644 --- a/src/core/Application.cpp +++ b/src/core/Application.cpp @@ -1071,12 +1071,7 @@ void Application::handlePositionalArguments(QCommandLineParser *parser, bool for if (openHints.testFlag(SessionsManager::NewWindowOpen)) { - QVariantMap parameters; - - if (openHints.testFlag(SessionsManager::PrivateOpen)) - { - parameters[QLatin1String("hints")] = SessionsManager::PrivateOpen; - } + const QVariantMap parameters({{QLatin1String("hints"), (openHints.testFlag(SessionsManager::PrivateOpen) ? SessionsManager::PrivateOpen : SessionsManager::DefaultOpen)}}); if (urls.isEmpty()) { From 879d560824efcaab9fed30e0c4c16e303e1f8fcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Sun, 8 Dec 2019 21:35:11 +0100 Subject: [PATCH 48/71] Simplify --- src/core/SessionsManager.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/core/SessionsManager.cpp b/src/core/SessionsManager.cpp index 974c79310f..c7c1d63719 100644 --- a/src/core/SessionsManager.cpp +++ b/src/core/SessionsManager.cpp @@ -558,12 +558,7 @@ bool SessionsManager::restoreSession(const SessionInformation &session, MainWind m_sessionTitle = session.title; } - QVariantMap parameters; - - if (isPrivate) - { - parameters[QLatin1String("hints")] = PrivateOpen; - } + const QVariantMap parameters({{QLatin1String("hints"), (isPrivate ? SessionsManager::PrivateOpen : SessionsManager::DefaultOpen)}}); for (int i = 0; i < session.windows.count(); ++i) { From 5e4d26936932c6445aacddcc86d327e01de9ceb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Mon, 9 Dec 2019 21:59:35 +0100 Subject: [PATCH 49/71] Simplify --- src/modules/windows/web/WebContentsWidget.cpp | 25 +++---------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/src/modules/windows/web/WebContentsWidget.cpp b/src/modules/windows/web/WebContentsWidget.cpp index b2a3afe5ba..7c9675c9f8 100644 --- a/src/modules/windows/web/WebContentsWidget.cpp +++ b/src/modules/windows/web/WebContentsWidget.cpp @@ -311,14 +311,7 @@ void WebContentsWidget::search(const QString &search, const QString &query) { if (m_webWidget->getUrl().scheme() == QLatin1String("view-source")) { - QVariantMap parameters; - - if (isPrivate()) - { - parameters[QLatin1String("hints")] = SessionsManager::PrivateOpen; - } - - setWidget(nullptr, parameters, (m_webWidget ? m_webWidget->getOptions() : QHash())); + setWidget(nullptr, {{QLatin1String("hints"), (isPrivate() ? SessionsManager::PrivateOpen : SessionsManager::DefaultOpen)}}, (m_webWidget ? m_webWidget->getOptions() : QHash())); } m_webWidget->search(search, query); @@ -1277,12 +1270,7 @@ void WebContentsWidget::setZoom(int zoom) void WebContentsWidget::setUrl(const QUrl &url, bool isTyped) { const QHash options(m_webWidget ? m_webWidget->getOptions() : QHash()); - QVariantMap parameters; - - if (isPrivate()) - { - parameters[QLatin1String("hints")] = SessionsManager::PrivateOpen; - } + const QVariantMap parameters({{QLatin1String("hints"), (isPrivate() ? SessionsManager::PrivateOpen : SessionsManager::DefaultOpen)}}); if (url.scheme() == QLatin1String("view-source") && m_webWidget->getUrl().scheme() != QLatin1String("view-source")) { @@ -1328,14 +1316,7 @@ void WebContentsWidget::setParent(Window *window) WebContentsWidget* WebContentsWidget::clone(bool cloneHistory) const { - QVariantMap parameters; - - if (m_webWidget->isPrivate()) - { - parameters[QLatin1String("hints")] = SessionsManager::PrivateOpen; - } - - WebContentsWidget *webWidget(new WebContentsWidget(parameters, m_webWidget->getOptions(), m_webWidget->clone(cloneHistory), nullptr, nullptr)); + WebContentsWidget *webWidget(new WebContentsWidget({{QLatin1String("hints"), (isPrivate() ? SessionsManager::PrivateOpen : SessionsManager::DefaultOpen)}}, m_webWidget->getOptions(), m_webWidget->clone(cloneHistory), nullptr, nullptr)); webWidget->m_webWidget->setRequestedUrl(m_webWidget->getUrl(), false, true); return webWidget; From 085cba7d8bb5db86c31768170452768bf179a88d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Tue, 10 Dec 2019 21:42:52 +0100 Subject: [PATCH 50/71] Simplify --- src/ui/Window.cpp | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/src/ui/Window.cpp b/src/ui/Window.cpp index 2e14075a52..c3dae17dd7 100644 --- a/src/ui/Window.cpp +++ b/src/ui/Window.cpp @@ -224,14 +224,7 @@ void Window::search(const QString &query, const QString &searchEngine) return; } - QVariantMap parameters; - - if (isPrivate()) - { - parameters[QLatin1String("hints")] = SessionsManager::PrivateOpen; - } - - widget = new WebContentsWidget(parameters, {}, nullptr, this, this); + widget = new WebContentsWidget({{QLatin1String("hints"), (isPrivate() ? SessionsManager::PrivateOpen : SessionsManager::DefaultOpen)}}, {}, nullptr, this, this); setContentsWidget(widget); } @@ -531,14 +524,7 @@ Window* Window::clone(bool cloneHistory, MainWindow *mainWindow) const return nullptr; } - QVariantMap parameters({{QLatin1String("size"), size()}}); - - if (isPrivate()) - { - parameters[QLatin1String("hints")] = SessionsManager::PrivateOpen; - } - - return new Window(parameters, m_contentsWidget->clone(cloneHistory), mainWindow); + return new Window({{QLatin1String("size"), size()}, {QLatin1String("hints"), (isPrivate() ? SessionsManager::PrivateOpen : SessionsManager::DefaultOpen)}}, m_contentsWidget->clone(cloneHistory), mainWindow); } MainWindow* Window::getMainWindow() const From 1bd9e82594afc63a8aba73e19233d67338666a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Wed, 11 Dec 2019 21:49:03 +0100 Subject: [PATCH 51/71] Simplify --- src/main.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 68d946f96f..888e6cfa4a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -207,14 +207,7 @@ int main(int argc, char *argv[]) if (Application::getWindows().isEmpty()) { - QVariantMap parameters; - - if (isPrivate) - { - parameters[QLatin1String("hints")] = SessionsManager::PrivateOpen; - } - - Application::createWindow(parameters); + Application::createWindow({{QLatin1String("hints"), (isPrivate ? SessionsManager::PrivateOpen : SessionsManager::DefaultOpen)}}); } return Application::exec(); From 729d8d4c0c56cb02a75f34e5f3de6636f2805813 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Thu, 12 Dec 2019 18:44:41 +0100 Subject: [PATCH 52/71] Compare as lists --- src/ui/SidebarWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/SidebarWidget.cpp b/src/ui/SidebarWidget.cpp index 2abd386969..9d640cb02f 100644 --- a/src/ui/SidebarWidget.cpp +++ b/src/ui/SidebarWidget.cpp @@ -347,7 +347,7 @@ void SidebarWidget::updatePanels() { const ToolBarsManager::ToolBarDefinition definition(m_toolBarWidget->getDefinition()); - if (m_buttons.keys().toSet() == definition.panels.toSet()) + if (m_buttons.keys() == definition.panels) { selectPanel(definition.currentPanel); From 8ca63e08c6b81d7aa398fd290e1ab07570d9f1ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Thu, 12 Dec 2019 19:09:38 +0100 Subject: [PATCH 53/71] Fix deprecation warning --- src/modules/windows/transfers/TransfersContentsWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/windows/transfers/TransfersContentsWidget.cpp b/src/modules/windows/transfers/TransfersContentsWidget.cpp index acf187bbeb..faef906d4a 100644 --- a/src/modules/windows/transfers/TransfersContentsWidget.cpp +++ b/src/modules/windows/transfers/TransfersContentsWidget.cpp @@ -227,7 +227,7 @@ void TransfersContentsWidget::clearFinishedTransfers() void TransfersContentsWidget::handleTransferAdded(Transfer *transfer) { QList items({new QStandardItem(), new QStandardItem(QFileInfo(transfer->getTarget()).fileName())}); - items[0]->setData(qVariantFromValue(static_cast(transfer)), InstanceRole); + items[0]->setData(QVariant::fromValue(static_cast(transfer)), InstanceRole); items[0]->setFlags(items[0]->flags() | Qt::ItemNeverHasChildren); items[1]->setFlags(items[1]->flags() | Qt::ItemNeverHasChildren); items.reserve(m_model->columnCount()); From 05da2cac5dbc5295f261213d6da777f7d219a379 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Fri, 13 Dec 2019 17:54:12 +0100 Subject: [PATCH 54/71] Redo find in page mechanism to support async results --- .../web/qtwebengine/QtWebEngineWebWidget.cpp | 151 +- .../web/qtwebengine/QtWebEngineWebWidget.h | 4 +- .../web/qtwebkit/QtWebKitWebWidget.cpp | 2336 ++++++++--------- .../backends/web/qtwebkit/QtWebKitWebWidget.h | 2 +- src/modules/windows/web/WebContentsWidget.cpp | 7 +- src/ui/SourceViewerWebWidget.cpp | 10 +- src/ui/SourceViewerWebWidget.h | 2 +- src/ui/WebWidget.h | 3 +- 8 files changed, 1248 insertions(+), 1267 deletions(-) diff --git a/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp b/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp index ebd39f7f49..7d99ffbfb9 100644 --- a/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp +++ b/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp @@ -198,50 +198,6 @@ void QtWebEngineWebWidget::ensureInitialized() } } -void QtWebEngineWebWidget::search(const QString &query, const QString &searchEngine) -{ - QNetworkRequest request; - QNetworkAccessManager::Operation method; - QByteArray body; - - if (SearchEnginesManager::setupSearchQuery(query, searchEngine, &request, &method, &body)) - { - setRequestedUrl(request.url(), false, true); - updateOptions(request.url()); - - if (method == QNetworkAccessManager::PostOperation) - { - QWebEngineHttpRequest httpRequest(request.url(), QWebEngineHttpRequest::Post); - httpRequest.setPostData(body); - - m_page->load(httpRequest); - } - else - { - setUrl(request.url(), false); - } - } -} - -void QtWebEngineWebWidget::print(QPrinter *printer) -{ - QEventLoop eventLoop; - - m_page->print(printer, [&](bool) - { - eventLoop.quit(); - }); - - eventLoop.exec(); -} - -void QtWebEngineWebWidget::clearOptions() -{ - WebWidget::clearOptions(); - - updateOptions(getUrl()); -} - void QtWebEngineWebWidget::triggerAction(int identifier, const QVariantMap ¶meters, ActionsManager::TriggerType trigger) { switch (identifier) @@ -879,6 +835,74 @@ void QtWebEngineWebWidget::triggerAction(int identifier, const QVariantMap ¶ } } +void QtWebEngineWebWidget::clearOptions() +{ + WebWidget::clearOptions(); + + updateOptions(getUrl()); +} + +void QtWebEngineWebWidget::findInPage(const QString &text, FindFlags flags) +{ + if (text.isEmpty()) + { + m_page->findText(text); + + return; + } + + QWebEnginePage::FindFlags nativeFlags; + + if (flags.testFlag(BackwardFind)) + { + nativeFlags |= QWebEnginePage::FindBackward; + } + + if (flags.testFlag(CaseSensitiveFind)) + { + nativeFlags |= QWebEnginePage::FindCaseSensitively; + } + + m_page->findText(text, nativeFlags); +} + +void QtWebEngineWebWidget::search(const QString &query, const QString &searchEngine) +{ + QNetworkRequest request; + QNetworkAccessManager::Operation method; + QByteArray body; + + if (SearchEnginesManager::setupSearchQuery(query, searchEngine, &request, &method, &body)) + { + setRequestedUrl(request.url(), false, true); + updateOptions(request.url()); + + if (method == QNetworkAccessManager::PostOperation) + { + QWebEngineHttpRequest httpRequest(request.url(), QWebEngineHttpRequest::Post); + httpRequest.setPostData(body); + + m_page->load(httpRequest); + } + else + { + setUrl(request.url(), false); + } + } +} + +void QtWebEngineWebWidget::print(QPrinter *printer) +{ + QEventLoop eventLoop; + + m_page->print(printer, [&](bool) + { + eventLoop.quit(); + }); + + eventLoop.exec(); +} + void QtWebEngineWebWidget::handleLoadStarted() { m_lastUrlClickTime = {}; @@ -1730,45 +1754,6 @@ int QtWebEngineWebWidget::getZoom() const return static_cast(m_page->zoomFactor() * 100); } -int QtWebEngineWebWidget::findInPage(const QString &text, FindFlags flags) -{ - if (text.isEmpty()) - { - m_page->findText(text); - - return 0; - } - - QWebEnginePage::FindFlags nativeFlags; - - if (flags.testFlag(BackwardFind)) - { - nativeFlags |= QWebEnginePage::FindBackward; - } - - if (flags.testFlag(CaseSensitiveFind)) - { - nativeFlags |= QWebEnginePage::FindCaseSensitively; - } - - QEventLoop eventLoop; - bool hasMatch(false); - - m_page->findText(text, nativeFlags, [&](const QVariant &result) - { - hasMatch = result.toBool(); - - eventLoop.quit(); - }); - - connect(this, &QtWebEngineWebWidget::aboutToReload, &eventLoop, &QEventLoop::quit); - connect(this, &QtWebEngineWebWidget::destroyed, &eventLoop, &QEventLoop::quit); - - eventLoop.exec(); - - return (hasMatch ? -1 : 0); -} - bool QtWebEngineWebWidget::canGoBack() const { return m_page->history()->canGoBack(); diff --git a/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.h b/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.h index 085dea5f87..5e37ab7750 100644 --- a/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.h +++ b/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.h @@ -92,7 +92,6 @@ class QtWebEngineWebWidget final : public WebWidget QMultiMap getMetaData() const override; LoadingState getLoadingState() const override; int getZoom() const override; - int findInPage(const QString &text, FindFlags flags = NoFlagsFind) override; bool hasSelection() const override; bool hasWatchedChanges(ChangeWatcher watcher) const override; bool isAudible() const override; @@ -102,8 +101,9 @@ class QtWebEngineWebWidget final : public WebWidget bool eventFilter(QObject *object, QEvent *event) override; public slots: - void clearOptions() override; void triggerAction(int identifier, const QVariantMap ¶meters = {}, ActionsManager::TriggerType trigger = ActionsManager::UnknownTrigger) override; + void clearOptions() override; + void findInPage(const QString &text, FindFlags flags = NoFlagsFind) override; void setActiveStyleSheet(const QString &styleSheet) override; void setPermission(FeaturePermission feature, const QUrl &url, PermissionPolicies policies) override; void setOption(int identifier, const QVariant &value) override; diff --git a/src/modules/backends/web/qtwebkit/QtWebKitWebWidget.cpp b/src/modules/backends/web/qtwebkit/QtWebKitWebWidget.cpp index 75b659c16f..e153dfaed9 100644 --- a/src/modules/backends/web/qtwebkit/QtWebKitWebWidget.cpp +++ b/src/modules/backends/web/qtwebkit/QtWebKitWebWidget.cpp @@ -248,1507 +248,1530 @@ void QtWebKitWebWidget::focusInEvent(QFocusEvent *event) emit widgetActivated(this); } -void QtWebKitWebWidget::search(const QString &query, const QString &searchEngine) -{ - QNetworkRequest request; - QNetworkAccessManager::Operation method; - QByteArray body; - - if (SearchEnginesManager::setupSearchQuery(query, searchEngine, &request, &method, &body)) - { - setRequestedUrl(request.url(), false, true); - updateOptions(request.url()); - - m_page->mainFrame()->load(request, method, body); - } -} - -void QtWebKitWebWidget::print(QPrinter *printer) +void QtWebKitWebWidget::triggerAction(int identifier, const QVariantMap ¶meters, ActionsManager::TriggerType trigger) { - m_page->mainFrame()->print(printer); -} + const HitTestResult hitResult(getCurrentHitTestResult()); -void QtWebKitWebWidget::saveState(QWebFrame *frame, QWebHistoryItem *item) -{ - if (frame == m_page->mainFrame()) + switch (identifier) { - QVariantList state(m_page->history()->currentItem().userData().toList()); - - if (state.isEmpty() || state.count() < 4) - { - state = {0, getZoom(), m_page->mainFrame()->scrollPosition(), QDateTime::currentDateTimeUtc()}; - } - else - { - state[ZoomEntryData] = getZoom(); - state[PositionEntryData] = m_page->mainFrame()->scrollPosition(); - } + case ActionsManager::SaveAction: + if (m_page->isViewingMedia()) + { + const SaveInformation information(Utils::getSavePath(suggestSaveFileName(SingleFileSaveFormat))); - item->setUserData(state); - } -} + if (information.canSave) + { + QNetworkRequest request(getUrl()); + request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); -void QtWebKitWebWidget::restoreState(QWebFrame *frame) -{ - if (frame == m_page->mainFrame()) - { - const QVariantList state(m_page->history()->currentItem().userData().toList()); + TransfersManager::startTransfer(m_networkManager->get(request), information.path, (Transfer::CanAskForPathOption | Transfer::CanAutoDeleteOption | Transfer::CanOverwriteOption | Transfer::IsPrivateOption)); + } + } + else + { + SaveFormat format(UnknownSaveFormat); + const QString path(getSavePath({SingleFileSaveFormat, PdfSaveFormat}, &format)); - setZoom(state.value(ZoomEntryData, getZoom()).toInt()); + if (!path.isEmpty()) + { + switch (format) + { + case PdfSaveFormat: + { + QPrinter printer; + printer.setOutputFormat(QPrinter::PdfFormat); + printer.setOutputFileName(path); + printer.setCreator(QStringLiteral("Otter Browser %1").arg(Application::getFullVersion())); + printer.setDocName(getTitle()); - if (m_page->mainFrame()->scrollPosition().isNull()) - { - m_page->mainFrame()->setScrollPosition(state.value(PositionEntryData).toPoint()); - } - } -} + m_page->mainFrame()->print(&printer); + } -void QtWebKitWebWidget::clearPluginToken() -{ - QList frames({m_page->mainFrame()}); + break; + default: + { + QNetworkRequest request(getUrl()); + request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); - while (!frames.isEmpty()) - { - const QWebFrame *frame(frames.takeFirst()); - QWebElement element(frame->documentElement().findFirst(QStringLiteral("object[data-otter-browser='%1'], embed[data-otter-browser='%1']").arg(m_pluginToken))); + TransfersManager::startTransfer(m_networkManager->get(request), path, (Transfer::CanAskForPathOption | Transfer::CanAutoDeleteOption | Transfer::CanOverwriteOption | Transfer::IsPrivateOption)); + } - if (!element.isNull()) - { - element.removeAttribute(QLatin1String("data-otter-browser")); + break; + } + } + } break; - } - - frames.append(frame->childFrames()); - } - - emit arbitraryActionsStateChanged({ActionsManager::LoadPluginsAction}); - - m_pluginToken.clear(); -} - -void QtWebKitWebWidget::resetSpellCheck(QWebElement element) -{ - if (element.isNull()) - { - element = m_page->mainFrame()->findFirstElement(QLatin1String("*:focus")); - } - - if (!element.isNull()) - { - m_page->runScript(QLatin1String("resetSpellCheck"), element); - } -} - -void QtWebKitWebWidget::muteAudio(QWebFrame *frame, bool isMuted) -{ - if (!frame) - { - return; - } - - const QString script(QLatin1String("this.muted = ") + (isMuted ? QLatin1String("true") : QLatin1String("false"))); - const QWebElementCollection elements(frame->findAllElements(QLatin1String("audio, video"))); - - for (int i = 0; i < elements.count(); ++i) - { - elements.at(i).evaluateJavaScript(script); - } - - const QList frames(frame->childFrames()); - - for (int i = 0; i < frames.count(); ++i) - { - muteAudio(frames.at(i), isMuted); - } -} - -void QtWebKitWebWidget::openRequest(const QNetworkRequest &request, QNetworkAccessManager::Operation operation, QIODevice *outgoingData) -{ - m_formRequest = request; - m_formRequestOperation = operation; - m_formRequestBody = (outgoingData ? outgoingData->readAll() : QByteArray()); - - if (outgoingData) - { - outgoingData->close(); - outgoingData->deleteLater(); - } - - setRequestedUrl(m_formRequest.url(), false, true); - updateOptions(m_formRequest.url()); - - QTimer::singleShot(50, this, [&]() - { - m_page->mainFrame()->load(m_formRequest, m_formRequestOperation, m_formRequestBody); - - m_formRequest = QNetworkRequest(); - m_formRequestBody.clear(); - }); -} + case ActionsManager::ClearTabHistoryAction: + if (parameters.value(QLatin1String("clearGlobalHistory")).toBool()) + { + for (int i = 0; i < m_page->history()->count(); ++i) + { + const quint64 historyIdentifier(m_page->history()->itemAt(i).userData().toList().value(IdentifierEntryData).toULongLong()); -void QtWebKitWebWidget::openFormRequest(const QNetworkRequest &request, QNetworkAccessManager::Operation operation, QIODevice *outgoingData) -{ - m_page->triggerAction(QWebPage::Stop); + if (historyIdentifier > 0) + { + HistoryManager::removeEntry(historyIdentifier); + } + } + } - QtWebKitWebWidget *widget(qobject_cast(clone(false))); - widget->openRequest(request, operation, outgoingData); + setUrl(QUrl(QLatin1String("about:blank"))); - emit requestedNewWindow(widget, SessionsManager::calculateOpenHints(SessionsManager::NewTabOpen), {}); -} + m_page->history()->clear(); -void QtWebKitWebWidget::startDelayedTransfer(Transfer *transfer) -{ - m_transfers.enqueue(transfer); + emit categorizedActionsStateChanged({ActionsManager::ActionDefinition::NavigationCategory}); - if (m_transfersTimer == 0) - { - m_transfersTimer = startTimer(250); - } -} + break; + case ActionsManager::PurgeTabHistoryAction: + triggerAction(ActionsManager::ClearTabHistoryAction, {{QLatin1String("clearGlobalHistory"), true}}, trigger); -void QtWebKitWebWidget::handleDownloadRequested(const QNetworkRequest &request) -{ - const HitTestResult hitResult(getCurrentHitTestResult()); + break; + case ActionsManager::MuteTabMediaAction: + m_isAudioMuted = !m_isAudioMuted; - if ((!hitResult.imageUrl.isEmpty() && request.url() == hitResult.imageUrl) || (!hitResult.mediaUrl.isEmpty() && request.url() == hitResult.mediaUrl)) - { - NetworkCache *cache(NetworkManagerFactory::getCache()); + muteAudio(m_page->mainFrame(), m_isAudioMuted); - if (cache && cache->metaData(request.url()).isValid()) - { - QIODevice *device(cache->data(request.url())); + emit arbitraryActionsStateChanged({ActionsManager::MuteTabMediaAction}); - if (device && device->size() > 0) + break; + case ActionsManager::OpenLinkAction: + case ActionsManager::OpenLinkInCurrentTabAction: + case ActionsManager::OpenLinkInNewTabAction: + case ActionsManager::OpenLinkInNewTabBackgroundAction: + case ActionsManager::OpenLinkInNewWindowAction: + case ActionsManager::OpenLinkInNewWindowBackgroundAction: + case ActionsManager::OpenLinkInNewPrivateTabAction: + case ActionsManager::OpenLinkInNewPrivateTabBackgroundAction: + case ActionsManager::OpenLinkInNewPrivateWindowAction: + case ActionsManager::OpenLinkInNewPrivateWindowBackgroundAction: { - const QString path(Utils::getSavePath(request.url().fileName()).path); + const SessionsManager::OpenHints hints((identifier == ActionsManager::OpenLinkAction) ? SessionsManager::calculateOpenHints(parameters) : mapOpenActionToOpenHints(identifier)); - if (path.isEmpty()) + if (hints == SessionsManager::DefaultOpen && !hitResult.flags.testFlag(HitTestResult::IsLinkFromSelectionTest)) { - device->deleteLater(); + m_page->triggerAction(QWebPage::OpenLink); - return; + setClickPosition({}); } - - QFile file(path); - - if (!file.open(QIODevice::WriteOnly)) + else if (hitResult.linkUrl.isValid()) { - QMessageBox::critical(this, tr("Error"), tr("Failed to open file for writing."), QMessageBox::Close); + openUrl(hitResult.linkUrl, hints); } + } - file.write(device->readAll()); - file.close(); + break; + case ActionsManager::CopyLinkToClipboardAction: + if (!hitResult.linkUrl.isEmpty()) + { + Application::clipboard()->setText(hitResult.linkUrl.toString(QUrl::EncodeReserved | QUrl::EncodeSpaces)); + } - device->deleteLater(); + break; + case ActionsManager::BookmarkLinkAction: + if (hitResult.linkUrl.isValid()) + { + const QString title(hitResult.title); - return; + Application::triggerAction(ActionsManager::BookmarkPageAction, {{QLatin1String("url"), hitResult.linkUrl}, {QLatin1String("title"), (title.isEmpty() ? m_page->mainFrame()->hitTestContent(hitResult.hitPosition).element().toPlainText() : title)}}, parentWidget(), trigger); + } + + break; + case ActionsManager::SaveLinkToDiskAction: + if (hitResult.linkUrl.isValid()) + { + handleDownloadRequested(QNetworkRequest(hitResult.linkUrl)); + } + else + { + m_page->triggerAction(QWebPage::DownloadLinkToDisk); + } + + break; + case ActionsManager::SaveLinkToDownloadsAction: + TransfersManager::addTransfer(TransfersManager::startTransfer(hitResult.linkUrl.toString(), {}, (Transfer::CanNotifyOption | Transfer::CanAskForPathOption | Transfer::IsQuickTransferOption | (isPrivate() ? Transfer::IsPrivateOption : Transfer::NoOption)))); + + break; + case ActionsManager::OpenFrameAction: + case ActionsManager::OpenFrameInCurrentTabAction: + case ActionsManager::OpenFrameInNewTabAction: + case ActionsManager::OpenFrameInNewTabBackgroundAction: + if (hitResult.frameUrl.isValid()) + { + openUrl(hitResult.frameUrl, ((identifier == ActionsManager::OpenFrameAction) ? SessionsManager::calculateOpenHints(parameters) : mapOpenActionToOpenHints(identifier))); } - if (device) + break; + case ActionsManager::CopyFrameLinkToClipboardAction: + if (hitResult.frameUrl.isValid()) { - device->deleteLater(); + Application::clipboard()->setText(hitResult.frameUrl.toString(QUrl::EncodeReserved | QUrl::EncodeSpaces)); } - } - else if (!hitResult.imageUrl.isEmpty() && hitResult.imageUrl.scheme() == QLatin1String("data") && hitResult.imageUrl.url().contains(QLatin1String(";base64,"))) - { - const QString imageUrl(hitResult.imageUrl.url()); - const QString imageType(imageUrl.mid(11, (imageUrl.indexOf(QLatin1Char(';')) - 11))); - const QString path(Utils::getSavePath(tr("file") + QLatin1Char('.') + imageType).path); - if (!path.isEmpty()) + break; + case ActionsManager::ReloadFrameAction: + if (hitResult.frameUrl.isValid()) { - QImageWriter writer(path); + const QUrl url(hitResult.frameUrl); + QWebFrame *frame(m_page->mainFrame()->hitTestContent(hitResult.hitPosition).frame()); - if (!writer.write(QImage::fromData(QByteArray::fromBase64(imageUrl.mid(imageUrl.indexOf(QLatin1String(";base64,")) + 7).toUtf8()), imageType.toStdString().c_str()))) + if (frame) { - Console::addMessage(tr("Failed to save image: %1").arg(writer.errorString()), Console::OtherCategory, Console::ErrorLevel, path, -1, getWindowIdentifier()); + m_networkManager->addContentBlockingException(url, NetworkManager::SubFrameType); + + frame->setUrl({}); + frame->setUrl(url); } } - return; - } - - QNetworkRequest mutableRequest(request); - mutableRequest.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); + break; + case ActionsManager::ViewFrameSourceAction: + if (hitResult.frameUrl.isValid()) + { + const QString defaultEncoding(m_page->settings()->defaultTextEncoding()); + QNetworkRequest request(hitResult.frameUrl); + request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); - TransfersManager::startTransfer(m_networkManager->get(mutableRequest), {}, (Transfer::CanAskForPathOption | Transfer::CanAutoDeleteOption | Transfer::IsPrivateOption)); - } - else - { - startDelayedTransfer(TransfersManager::startTransfer(request, {}, (Transfer::CanNotifyOption | (isPrivate() ? Transfer::IsPrivateOption : Transfer::NoOption)))); - } -} + QNetworkReply *reply(m_networkManager->get(request)); + SourceViewerWebWidget *sourceViewer(new SourceViewerWebWidget(isPrivate())); + sourceViewer->setRequestedUrl(QUrl(QLatin1String("view-source:") + hitResult.frameUrl.toString()), false); -void QtWebKitWebWidget::handleUnsupportedContent(QNetworkReply *reply) -{ - m_networkManager->registerTransfer(reply); + if (!defaultEncoding.isEmpty()) + { + sourceViewer->setOption(SettingsManager::Content_DefaultCharacterEncodingOption, defaultEncoding); + } - startDelayedTransfer(TransfersManager::startTransfer(reply, {}, (Transfer::CanNotifyOption | (isPrivate() ? Transfer::IsPrivateOption : Transfer::NoOption)))); -} + m_viewSourceReplies[reply] = sourceViewer; -void QtWebKitWebWidget::handleOptionChanged(int identifier, const QVariant &value) -{ - switch (identifier) - { - case SettingsManager::Content_BackgroundColorOption: - { - QPalette palette(m_page->palette()); - palette.setColor(QPalette::Base, QColor(value.toString())); + connect(reply, &QNetworkReply::finished, this, &QtWebKitWebWidget::handleViewSourceReplyFinished); - m_page->setPalette(palette); + emit requestedNewWindow(sourceViewer, SessionsManager::DefaultOpen, {}); } break; - case SettingsManager::History_BrowsingLimitAmountWindowOption: - m_page->history()->setMaximumItemCount(value.toInt()); - - break; - case SettingsManager::Permissions_ScriptsCanShowStatusMessagesOption: - disconnect(m_page, &QtWebKitPage::statusBarMessage, this, &QtWebKitWebWidget::setStatusMessage); - - if (value.toBool() || SettingsManager::getOption(identifier, Utils::extractHost(getUrl())).toBool()) + case ActionsManager::OpenImageAction: + case ActionsManager::OpenImageInNewTabAction: + case ActionsManager::OpenImageInNewTabBackgroundAction: + if (hitResult.imageUrl.isValid()) { - connect(m_page, &QtWebKitPage::statusBarMessage, this, &QtWebKitWebWidget::setStatusMessage); + openUrl(hitResult.imageUrl, ((identifier == ActionsManager::OpenImageAction) ? SessionsManager::calculateOpenHints(parameters) : mapOpenActionToOpenHints(identifier))); } - else + + break; + case ActionsManager::SaveImageToDiskAction: + if (hitResult.imageUrl.isValid()) { - setStatusMessage({}); + handleDownloadRequested(QNetworkRequest(hitResult.imageUrl)); } break; - default: - break; - } -} - -void QtWebKitWebWidget::handleLoadStarted() -{ - if (m_loadingState == OngoingLoadingState) - { - return; - } - - m_thumbnail = {}; - m_messageToken = QUuid::createUuid().toString(); - m_canLoadPlugins = (getOption(SettingsManager::Permissions_EnablePluginsOption, getUrl()).toString() == QLatin1String("enabled")); - m_loadingState = OngoingLoadingState; - - setStatusMessage({}); - setStatusMessageOverride({}); - - emit geometryChanged(); - emit categorizedActionsStateChanged({ActionsManager::ActionDefinition::NavigationCategory}); - emit loadingStateChanged(OngoingLoadingState); -} - -void QtWebKitWebWidget::handleLoadProgress(int progress) -{ - m_networkManager->setPageInformation(TotalLoadingProgressInformation, progress); -} - -void QtWebKitWebWidget::handleLoadFinished(bool result) -{ - if (m_isAudioMuted) - { - muteAudio(m_page->mainFrame(), true); - } - - if (m_loadingState != OngoingLoadingState) - { - return; - } + case ActionsManager::CopyImageToClipboardAction: + { + const QPixmap pixmap(m_page->mainFrame()->hitTestContent(hitResult.hitPosition).pixmap()); - m_networkManager->handleLoadFinished(result); + if (!pixmap.isNull()) + { + Application::clipboard()->setPixmap(pixmap); + } + else + { + m_page->triggerAction(QWebPage::CopyImageToClipboard); + } + } - m_thumbnail = {}; - m_loadingState = FinishedLoadingState; + break; + case ActionsManager::CopyImageUrlToClipboardAction: + if (!hitResult.imageUrl.isEmpty()) + { + Application::clipboard()->setText(hitResult.imageUrl.toString(QUrl::EncodeReserved | QUrl::EncodeSpaces)); + } - updateAmountOfDeferredPlugins(); - handleHistory(); - startReloadTimer(); + break; + case ActionsManager::ReloadImageAction: + if (!hitResult.imageUrl.isEmpty()) + { + m_networkManager->addContentBlockingException(hitResult.imageUrl, NetworkManager::ImageType); - emit categorizedActionsStateChanged({ActionsManager::ActionDefinition::NavigationCategory}); - emit contentStateChanged(getContentState()); - emit loadingStateChanged(FinishedLoadingState); - emit watchedDataChanged(FeedsWatcher); - emit watchedDataChanged(LinksWatcher); - emit watchedDataChanged(MetaDataWatcher); - emit watchedDataChanged(SearchEnginesWatcher); - emit watchedDataChanged(StylesheetsWatcher); -} + m_page->settings()->setAttribute(QWebSettings::AutoLoadImages, true); -void QtWebKitWebWidget::handleViewSourceReplyFinished() -{ - QNetworkReply *reply(qobject_cast(sender())); + if (getUrl().matches(hitResult.imageUrl, (QUrl::NormalizePathSegments | QUrl::RemoveFragment | QUrl::StripTrailingSlash))) + { + triggerAction(ActionsManager::ReloadAndBypassCacheAction, {}, trigger); + } + else + { + QWebElement element(m_page->mainFrame()->hitTestContent(hitResult.hitPosition).element()); + const QUrl url(hitResult.imageUrl); + const QString src(element.attribute(QLatin1String("src"))); + NetworkCache *cache(NetworkManagerFactory::getCache()); - if (reply) - { - if (reply->error() == QNetworkReply::NoError && m_viewSourceReplies.contains(reply) && m_viewSourceReplies[reply]) - { - m_viewSourceReplies[reply]->setContents(reply->readAll(), reply->header(QNetworkRequest::ContentTypeHeader).toString()); - } + element.setAttribute(QLatin1String("src"), {}); - m_viewSourceReplies.remove(reply); + if (cache) + { + cache->remove(url); + } - reply->deleteLater(); - } -} + element.setAttribute(QLatin1String("src"), src); -void QtWebKitWebWidget::handlePrintRequest(QWebFrame *frame) -{ - QPrintPreviewDialog printPreviewDialog(this); - printPreviewDialog.setWindowFlags(printPreviewDialog.windowFlags() | Qt::WindowMaximizeButtonHint | Qt::WindowMinimizeButtonHint); - printPreviewDialog.setWindowTitle(tr("Print Preview")); + m_page->mainFrame()->documentElement().evaluateJavaScript(QStringLiteral("var images = document.querySelectorAll('img[src=\"%1\"]'); for (var i = 0; i < images.length; ++i) { images[i].src = ''; images[i].src = '%1'; }").arg(src)); + } + } - if (Application::getActiveWindow()) - { - printPreviewDialog.resize(Application::getActiveWindow()->size()); - } + break; + case ActionsManager::ImagePropertiesAction: + { + QVariantMap properties({{QLatin1String("alternativeText"), hitResult.alternateText}, {QLatin1String("longDescription"), hitResult.longDescription}}); + const QPixmap pixmap(m_page->mainFrame()->hitTestContent(hitResult.hitPosition).pixmap()); - connect(&printPreviewDialog, &QPrintPreviewDialog::paintRequested, frame, &QWebFrame::print); + if (!pixmap.isNull()) + { + properties[QLatin1String("width")] = pixmap.width(); + properties[QLatin1String("height")] = pixmap.height(); + properties[QLatin1String("depth")] = pixmap.depth(); + } - printPreviewDialog.exec(); -} + ImagePropertiesDialog *imagePropertiesDialog(new ImagePropertiesDialog(hitResult.imageUrl, properties, (m_networkManager->cache() ? m_networkManager->cache()->data(hitResult.imageUrl) : nullptr), this)); + imagePropertiesDialog->setButtonsVisible(false); -void QtWebKitWebWidget::handleHistory() -{ - if (isPrivate() || m_page->history()->count() == 0) - { - return; - } + ContentsDialog *dialog(new ContentsDialog(ThemesManager::createIcon(QLatin1String("dialog-information")), imagePropertiesDialog->windowTitle(), {}, {}, QDialogButtonBox::Close, imagePropertiesDialog, this)); - const QUrl url(m_page->history()->currentItem().url()); - const QVariant state(m_page->history()->currentItem().userData()); + connect(this, &QtWebKitWebWidget::aboutToReload, dialog, &ContentsDialog::close); + connect(imagePropertiesDialog, &ImagePropertiesDialog::finished, dialog, &ContentsDialog::close); - if (state.isValid()) - { - const quint64 identifier(state.toList().value(IdentifierEntryData).toULongLong()); + showDialog(dialog, false); + } - if (identifier > 0) - { - HistoryManager::updateEntry(identifier, url, getTitle(), m_page->mainFrame()->icon()); - } - } - else - { - m_page->history()->currentItem().setUserData(QVariantList({(Utils::isUrlEmpty(url) ? 0 : HistoryManager::addEntry(url, getTitle(), m_page->mainFrame()->icon(), m_isTypedIn)), getZoom(), QPoint(0, 0), QDateTime::currentDateTimeUtc()})); + break; + case ActionsManager::SaveMediaToDiskAction: + if (hitResult.mediaUrl.isValid()) + { + handleDownloadRequested(QNetworkRequest(hitResult.mediaUrl)); + } - if (m_isTypedIn) - { - m_isTypedIn = false; - } + break; + case ActionsManager::CopyMediaUrlToClipboardAction: + if (!hitResult.mediaUrl.isEmpty()) + { + Application::clipboard()->setText(hitResult.mediaUrl.toString(QUrl::EncodeReserved | QUrl::EncodeSpaces)); + } - SessionsManager::markSessionAsModified(); - BookmarksManager::updateVisits(url.toString()); - } -} + break; + case ActionsManager::MediaControlsAction: + m_page->triggerAction(QWebPage::ToggleMediaControls, parameters.value(QLatin1String("isChecked"), !getActionState(identifier, parameters).isChecked).toBool()); -void QtWebKitWebWidget::handleNavigationRequest(const QUrl &url, QWebPage::NavigationType type) -{ - if (type != QWebPage::NavigationTypeBackOrForward && (type != QWebPage::NavigationTypeLinkClicked || !getUrl().matches(url, QUrl::RemoveFragment))) - { - handleLoadStarted(); - handleHistory(); + break; + case ActionsManager::MediaLoopAction: + m_page->triggerAction(QWebPage::ToggleMediaLoop, parameters.value(QLatin1String("isChecked"), !getActionState(identifier, parameters).isChecked).toBool()); - m_networkManager->resetStatistics(); - } + break; + case ActionsManager::MediaPlayPauseAction: + m_page->triggerAction(QWebPage::ToggleMediaPlayPause); - updateOptions(url); + break; + case ActionsManager::MediaMuteAction: + m_page->triggerAction(QWebPage::ToggleMediaMute); - m_isNavigating = true; + break; + case ActionsManager::MediaPlaybackRateAction: + m_page->mainFrame()->hitTestContent(hitResult.hitPosition).element().evaluateJavaScript(QStringLiteral("this.playbackRate = %1").arg(parameters.value(QLatin1String("rate"), 1).toReal())); - emit aboutToNavigate(); -} + break; + case ActionsManager::GoBackAction: + m_page->triggerAction(QWebPage::Back); -void QtWebKitWebWidget::handleFullScreenRequest(QWebFullScreenRequest request) -{ - request.accept(); + break; + case ActionsManager::GoForwardAction: + m_page->triggerAction(QWebPage::Forward); - if (request.toggleOn()) - { - const QString value(SettingsManager::getOption(SettingsManager::Permissions_EnableFullScreenOption, Utils::extractHost(request.origin())).toString()); + break; + case ActionsManager::GoToHistoryIndexAction: + if (parameters.contains(QLatin1String("index"))) + { + const int index(parameters[QLatin1String("index")].toInt()); - if (value == QLatin1String("allow")) - { - MainWindow *mainWindow(MainWindow::findMainWindow(this)); + if (index >= 0 && index < m_page->history()->count()) + { + m_page->history()->goToItem(m_page->history()->itemAt(index)); + } + } - if (mainWindow && !mainWindow->isFullScreen()) + break; + case ActionsManager::RewindAction: + m_page->history()->goToItem(m_page->history()->itemAt(0)); + + break; + case ActionsManager::FastForwardAction: { - mainWindow->triggerAction(ActionsManager::FullScreenAction); + const QUrl url(m_page->mainFrame()->evaluateJavaScript(getFastForwardScript(true)).toUrl()); + + if (url.isValid()) + { + setUrl(url); + } + else if (canGoForward()) + { + m_page->triggerAction(QWebPage::Forward); + } } - } - else if (value == QLatin1String("ask")) - { - emit requestedPermission(FullScreenFeature, request.origin(), false); - } - } - else - { - MainWindow *mainWindow(MainWindow::findMainWindow(this)); - if (mainWindow && mainWindow->isFullScreen()) - { - mainWindow->triggerAction(ActionsManager::FullScreenAction); - } + break; + case ActionsManager::RemoveHistoryIndexAction: + if (parameters.contains(QLatin1String("index"))) + { + const int index(parameters[QLatin1String("index")].toInt()); - emit requestedPermission(FullScreenFeature, request.origin(), true); - } + if (index >= 0 && index < m_page->history()->count()) + { + if (parameters.value(QLatin1String("clearGlobalHistory"), false).toBool()) + { + const quint64 entryIdentifier(m_page->history()->itemAt(index).userData().toList().value(IdentifierEntryData).toULongLong()); - m_isFullScreen = request.toggleOn(); + if (entryIdentifier > 0) + { + HistoryManager::removeEntry(entryIdentifier); + } + } - emit isFullScreenChanged(m_isFullScreen); -} + Session::Window::History history(getHistory()); + history.entries.removeAt(index); -void QtWebKitWebWidget::handlePermissionRequest(QWebFrame *frame, QWebPage::Feature feature) -{ - notifyPermissionRequested(frame, feature, false); -} + if (history.index >= index) + { + history.index = (history.index - 1); + } -void QtWebKitWebWidget::handlePermissionCancel(QWebFrame *frame, QWebPage::Feature feature) -{ - notifyPermissionRequested(frame, feature, true); -} + setHistory(history); + } + } -void QtWebKitWebWidget::notifyTitleChanged() -{ - emit titleChanged(getTitle()); + break; + case ActionsManager::StopAction: + m_page->triggerAction(QWebPage::Stop); - handleHistory(); -} + break; + case ActionsManager::StopScheduledReloadAction: + m_page->triggerAction(QWebPage::StopScheduledPageRefresh); -void QtWebKitWebWidget::notifyUrlChanged(const QUrl &url) -{ - m_isNavigating = false; + break; + case ActionsManager::ReloadAction: + emit aboutToReload(); - updateOptions(url); + m_page->triggerAction(QWebPage::Stop); + m_page->triggerAction(QWebPage::Reload); - emit urlChanged(url); - emit arbitraryActionsStateChanged({ActionsManager::InspectPageAction, ActionsManager::InspectElementAction}); - emit categorizedActionsStateChanged({ActionsManager::ActionDefinition::NavigationCategory, ActionsManager::ActionDefinition::PageCategory}); + break; + case ActionsManager::ReloadOrStopAction: + if (m_loadingState == OngoingLoadingState) + { + triggerAction(ActionsManager::StopAction, {}, trigger); + } + else + { + triggerAction(ActionsManager::ReloadAction, {}, trigger); + } - SessionsManager::markSessionAsModified(); -} + break; + case ActionsManager::ReloadAndBypassCacheAction: + m_page->triggerAction(QWebPage::ReloadAndBypassCache); -void QtWebKitWebWidget::notifyIconChanged() -{ - emit iconChanged(getIcon()); -} + break; + case ActionsManager::ContextMenuAction: + if (parameters.contains(QLatin1String("context")) && parameters[QLatin1String("context")].toInt() == QContextMenuEvent::Keyboard) + { + const QWebElement element(m_page->mainFrame()->findFirstElement(QLatin1String(":focus"))); -void QtWebKitWebWidget::notifyPermissionRequested(QWebFrame *frame, QWebPage::Feature nativeFeature, bool cancel) -{ - FeaturePermission feature(UnknownFeature); + if (element.isNull()) + { + setClickPosition(m_webView->mapFromGlobal(QCursor::pos())); + } + else + { + QPoint clickPosition(element.geometry().center()); + QWebFrame *frame(element.webFrame()); - switch (nativeFeature) - { - case QWebPage::Geolocation: - feature = GeolocationFeature; + while (frame) + { + clickPosition -= frame->scrollPosition(); - break; - case QWebPage::Notifications: - feature = NotificationsFeature; + frame = frame->parentFrame(); + } - break; - default: - return; - } + setClickPosition(clickPosition); + } + } + else + { + setClickPosition(m_webView->mapFromGlobal(QCursor::pos())); + } - const QUrl url(frame->url().isValid() ? frame->url() : frame->requestedUrl()); + showContextMenu(getClickPosition()); - if (cancel) - { - emit requestedPermission(feature, url, true); - } - else - { - switch (getPermission(feature, url)) - { - case GrantedPermission: - m_page->setFeaturePermission(frame, nativeFeature, QWebPage::PermissionGrantedByUser); + break; + case ActionsManager::UndoAction: + m_page->triggerAction(QWebPage::Undo); - break; - case DeniedPermission: - m_page->setFeaturePermission(frame, nativeFeature, QWebPage::PermissionDeniedByUser); + break; + case ActionsManager::RedoAction: + m_page->triggerAction(QWebPage::Redo); - break; - default: - emit requestedPermission(feature, url, false); + break; + case ActionsManager::CutAction: + m_page->triggerAction(QWebPage::Cut); - break; - } - } -} + break; + case ActionsManager::CopyAction: + if (parameters.value(QLatin1String("mode")) == QLatin1String("plainText")) + { + const QString text(getSelectedText()); + + if (!text.isEmpty()) + { + Application::clipboard()->setText(text); + } + } + else + { + m_page->triggerAction(QWebPage::Copy); + } -void QtWebKitWebWidget::notifySavePasswordRequested(const PasswordsManager::PasswordInformation &password, bool isUpdate) -{ - emit requestedSavePassword(password, isUpdate); -} + break; + case ActionsManager::CopyPlainTextAction: + triggerAction(ActionsManager::CopyAction, {{QLatin1String("mode"), QLatin1String("plainText")}}, trigger); -void QtWebKitWebWidget::updateAmountOfDeferredPlugins() -{ - const int amountOfDeferredPlugins(m_canLoadPlugins ? 0 : findChildren().count()); + break; + case ActionsManager::CopyAddressAction: + Application::clipboard()->setText(getUrl().toString()); - if (amountOfDeferredPlugins != m_amountOfDeferredPlugins) - { - const bool needsActionUpdate(amountOfDeferredPlugins == 0 || m_amountOfDeferredPlugins == 0); + break; + case ActionsManager::CopyToNoteAction: + NotesManager::addNote(BookmarksModel::UrlBookmark, {{BookmarksModel::UrlRole, getUrl()}, {BookmarksModel::DescriptionRole, getSelectedText()}}); - m_amountOfDeferredPlugins = amountOfDeferredPlugins; + break; + case ActionsManager::PasteAction: + if (parameters.contains(QLatin1String("note"))) + { + const BookmarksModel::Bookmark *bookmark(NotesManager::getModel()->getBookmark(parameters[QLatin1String("note")].toULongLong())); - if (needsActionUpdate) - { - emit arbitraryActionsStateChanged({ActionsManager::LoadPluginsAction}); - } - } -} + if (bookmark) + { + triggerAction(ActionsManager::PasteAction, {{QLatin1String("text"), bookmark->getDescription()}}, trigger); + } + } + else if (parameters.contains(QLatin1String("text"))) + { + QMimeData *mimeData(new QMimeData()); + const QStringList mimeTypes(Application::clipboard()->mimeData()->formats()); -void QtWebKitWebWidget::updateOptions(const QUrl &url) -{ - const QString encoding(getOption(SettingsManager::Content_DefaultCharacterEncodingOption, url).toString()); - const bool arePluginsEnabled(getOption(SettingsManager::Permissions_EnablePluginsOption, url).toString() != QLatin1String("disabled")); - QWebSettings *settings(m_page->settings()); - settings->setAttribute(QWebSettings::AutoLoadImages, (getOption(SettingsManager::Permissions_EnableImagesOption, url).toString() != QLatin1String("onlyCached"))); - settings->setAttribute(QWebSettings::DnsPrefetchEnabled, getOption(SettingsManager::Network_EnableDnsPrefetchOption, url).toBool()); - settings->setAttribute(QWebSettings::PluginsEnabled, arePluginsEnabled); - settings->setAttribute(QWebSettings::JavaEnabled, arePluginsEnabled); - settings->setAttribute(QWebSettings::JavascriptEnabled, (m_page->isDisplayingErrorPage() || m_page->isViewingMedia() || getOption(SettingsManager::Permissions_EnableJavaScriptOption, url).toBool())); - settings->setAttribute(QWebSettings::JavascriptCanAccessClipboard, getOption(SettingsManager::Permissions_ScriptsCanAccessClipboardOption, url).toBool()); - settings->setAttribute(QWebSettings::JavascriptCanOpenWindows, (getOption(SettingsManager::Permissions_ScriptsCanOpenWindowsOption, url).toString() != QLatin1String("blockAll"))); - settings->setAttribute(QWebSettings::WebGLEnabled, getOption(SettingsManager::Permissions_EnableWebglOption, url).toBool()); - settings->setAttribute(QWebSettings::LocalStorageEnabled, getOption(SettingsManager::Permissions_EnableLocalStorageOption, url).toBool()); - settings->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, getOption(SettingsManager::Permissions_EnableOfflineStorageDatabaseOption, url).toBool()); - settings->setAttribute(QWebSettings::OfflineWebApplicationCacheEnabled, getOption(SettingsManager::Permissions_EnableOfflineWebApplicationCacheOption, url).toBool()); - settings->setAttribute(QWebSettings::AllowRunningInsecureContent, getOption(SettingsManager::Security_AllowMixedContentOption, url).toBool()); - settings->setAttribute(QWebSettings::MediaEnabled, getOption(QtWebKitWebBackend::getOptionIdentifier(QtWebKitWebBackend::QtWebKitBackend_EnableMediaOption), url).toBool()); - settings->setAttribute(QWebSettings::MediaSourceEnabled, getOption(QtWebKitWebBackend::getOptionIdentifier(QtWebKitWebBackend::QtWebKitBackend_EnableMediaSourceOption), url).toBool()); - settings->setAttribute(QWebSettings::WebSecurityEnabled, getOption(QtWebKitWebBackend::getOptionIdentifier(QtWebKitWebBackend::QtWebKitBackend_EnableWebSecurityOption), url).toBool()); - settings->setDefaultTextEncoding((encoding == QLatin1String("auto")) ? QString() : encoding); + for (int i = 0; i < mimeTypes.count(); ++i) + { + mimeData->setData(mimeTypes.at(i), Application::clipboard()->mimeData()->data(mimeTypes.at(i))); + } - disconnect(m_page, &QtWebKitPage::geometryChangeRequested, this, &QtWebKitWebWidget::requestedGeometryChange); - disconnect(m_page, &QtWebKitPage::statusBarMessage, this, &QtWebKitWebWidget::setStatusMessage); + Application::clipboard()->setText(parameters[QLatin1String("text")].toString()); - if (getOption(SettingsManager::Permissions_ScriptsCanChangeWindowGeometryOption, url).toBool()) - { - connect(m_page, &QtWebKitPage::geometryChangeRequested, this, &QtWebKitWebWidget::requestedGeometryChange); - } + m_page->triggerAction(QWebPage::Paste); - if (getOption(SettingsManager::Permissions_ScriptsCanShowStatusMessagesOption, url).toBool()) - { - connect(m_page, &QtWebKitPage::statusBarMessage, this, &QtWebKitWebWidget::setStatusMessage); - } - else - { - setStatusMessage({}); - } + Application::clipboard()->setMimeData(mimeData); + } + else + { + m_page->triggerAction(QWebPage::Paste); + } - m_page->updateStyleSheets(url); + break; + case ActionsManager::DeleteAction: + m_page->triggerAction(QWebPage::DeleteEndOfWord); - m_networkManager->updateOptions(url); + break; + case ActionsManager::SelectAllAction: + m_page->triggerAction(QWebPage::SelectAll); - m_canLoadPlugins = (getOption(SettingsManager::Permissions_EnablePluginsOption, url).toString() == QLatin1String("enabled")); -} + break; + case ActionsManager::UnselectAction: + m_page->triggerAction(QWebPage::Unselect); -void QtWebKitWebWidget::clearOptions() -{ - WebWidget::clearOptions(); + break; + case ActionsManager::ClearAllAction: + m_page->triggerAction(QWebPage::SelectAll); + m_page->triggerAction(QWebPage::DeleteEndOfWord); - updateOptions(getUrl()); -} + break; + case ActionsManager::CheckSpellingAction: + { + QWebElement element(m_page->mainFrame()->hitTestContent(hitResult.hitPosition).element()); + element.evaluateJavaScript(QStringLiteral("this.spellcheck = %1").arg(parameters.value(QLatin1String("isChecked"), !getActionState(identifier, parameters).isChecked).toBool() ? QLatin1String("true") : QLatin1String("false"))); -void QtWebKitWebWidget::fillPassword(const PasswordsManager::PasswordInformation &password) -{ - QFile file(QLatin1String(":/modules/backends/web/qtwebkit/resources/formFiller.js")); + if (parameters.contains(QLatin1String("dictionary"))) + { + setOption(SettingsManager::Browser_SpellCheckDictionaryOption, parameters.value(QLatin1String("dictionary"))); + } + else + { + resetSpellCheck(element); + } - if (!file.open(QIODevice::ReadOnly)) - { - return; - } + emit arbitraryActionsStateChanged({ActionsManager::CheckSpellingAction}); + } - QJsonArray fieldsArray; + break; + case ActionsManager::CreateSearchAction: + { + const QWebElement element(m_page->mainFrame()->hitTestContent(hitResult.hitPosition).element()); + QWebElement parentElement(element.parent()); - for (int i = 0; i < password.fields.count(); ++i) - { - fieldsArray.append(QJsonObject({{QLatin1String("name"), password.fields.at(i).name}, {QLatin1String("value"), password.fields.at(i).value}, {QLatin1String("type"), ((password.fields.at(i).type == PasswordsManager::PasswordField) ? QLatin1String("password") : QLatin1String("text"))}})); - } + while (!parentElement.isNull() && parentElement.tagName().toLower() != QLatin1String("form")) + { + parentElement = parentElement.parent(); + } - const QString script(QString::fromLatin1(file.readAll()).arg(QString::fromLatin1(QJsonDocument(fieldsArray).toJson(QJsonDocument::Indented)))); + if (!parentElement.hasAttribute(QLatin1String("action"))) + { + break; + } - file.close(); + QList inputElements(parentElement.findAll(QLatin1String("button:not([disabled])[name][type='submit'], input:not([disabled])[name], select:not([disabled])[name], textarea:not([disabled])[name]")).toList()); - QList frames({m_page->mainFrame()}); + if (inputElements.isEmpty()) + { + break; + } - while (!frames.isEmpty()) - { - const QWebFrame *frame(frames.takeFirst()); - frame->documentElement().evaluateJavaScript(script); + QWebElement searchTermsElement; + const QString tagName(element.tagName().toLower()); + const QUrl url(parentElement.attribute(QLatin1String("action"))); + const QIcon icon(m_page->mainFrame()->icon()); + SearchEnginesManager::SearchEngineDefinition searchEngine; + searchEngine.title = getTitle(); + searchEngine.formUrl = getUrl(); + searchEngine.icon = (icon.isNull() ? ThemesManager::createIcon(QLatin1String("edit-find")) : icon); + searchEngine.resultsUrl.url = (url.isEmpty() ? getUrl() : resolveUrl(parentElement.webFrame(), url)).toString(); + searchEngine.resultsUrl.enctype = parentElement.attribute(QLatin1String("enctype")); + searchEngine.resultsUrl.method = ((parentElement.attribute(QLatin1String("method"), QLatin1String("get")).toLower() == QLatin1String("post")) ? QLatin1String("post") : QLatin1String("get")); - frames.append(frame->childFrames()); - } -} + if (tagName != QLatin1String("select")) + { + const QString type(element.attribute(QLatin1String("type"))); -void QtWebKitWebWidget::triggerAction(int identifier, const QVariantMap ¶meters, ActionsManager::TriggerType trigger) -{ - const HitTestResult hitResult(getCurrentHitTestResult()); + if (!inputElements.contains(element) && (type == QLatin1String("image") || type == QLatin1String("submit"))) + { + inputElements.append(element); + } - switch (identifier) - { - case ActionsManager::SaveAction: - if (m_page->isViewingMedia()) - { - const SaveInformation information(Utils::getSavePath(suggestSaveFileName(SingleFileSaveFormat))); + if (tagName == QLatin1String("textarea") || type == QLatin1String("email") || type == QLatin1String("password") || type == QLatin1String("search") || type == QLatin1String("tel") || type == QLatin1String("text") || type == QLatin1String("url")) + { + searchTermsElement = element; + } + } - if (information.canSave) + if (searchTermsElement.isNull()) { - QNetworkRequest request(getUrl()); - request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); - - TransfersManager::startTransfer(m_networkManager->get(request), information.path, (Transfer::CanAskForPathOption | Transfer::CanAutoDeleteOption | Transfer::CanOverwriteOption | Transfer::IsPrivateOption)); + searchTermsElement = parentElement.findFirst(QLatin1String("input:not([disabled])[name][type='search']")); } - } - else - { - SaveFormat format(UnknownSaveFormat); - const QString path(getSavePath({SingleFileSaveFormat, PdfSaveFormat}, &format)); - if (!path.isEmpty()) + for (int i = 0; i < inputElements.count(); ++i) { - switch (format) + const QString name(inputElements.at(i).attribute(QLatin1String("name"))); + + if (inputElements.at(i).tagName().toLower() != QLatin1String("select")) { - case PdfSaveFormat: + const QString type(inputElements.at(i).attribute(QLatin1String("type"))); + const bool isSubmit(type == QLatin1String("image") || type == QLatin1String("submit")); + + if ((isSubmit && inputElements.at(i) != element) || ((type == QLatin1String("checkbox") || type == QLatin1String("radio")) && !inputElements[i].evaluateJavaScript(QLatin1String("this.checked")).toBool())) + { + continue; + } + + if (isSubmit && inputElements.at(i) == element) + { + if (inputElements.at(i).hasAttribute(QLatin1String("formaction"))) { - QPrinter printer; - printer.setOutputFormat(QPrinter::PdfFormat); - printer.setOutputFileName(path); - printer.setCreator(QStringLiteral("Otter Browser %1").arg(Application::getFullVersion())); - printer.setDocName(getTitle()); + searchEngine.resultsUrl.url = resolveUrl(parentElement.webFrame(), inputElements.at(i).attribute(QLatin1String("formaction"))).toString(); + } - m_page->mainFrame()->print(&printer); + if (inputElements.at(i).hasAttribute(QLatin1String("formenctype"))) + { + searchEngine.resultsUrl.enctype = inputElements.at(i).attribute(QLatin1String("formenctype")); } - break; - default: + if (inputElements.at(i).hasAttribute(QLatin1String("formmethod"))) { - QNetworkRequest request(getUrl()); - request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); + searchEngine.resultsUrl.method = inputElements.at(i).attribute(QLatin1String("formmethod")); + } + } + + if (!isSubmit && searchTermsElement.isNull() && type != QLatin1String("hidden")) + { + searchTermsElement = inputElements.at(i); + } - TransfersManager::startTransfer(m_networkManager->get(request), path, (Transfer::CanAskForPathOption | Transfer::CanAutoDeleteOption | Transfer::CanOverwriteOption | Transfer::IsPrivateOption)); - } + if (!name.isEmpty()) + { + searchEngine.resultsUrl.parameters.addQueryItem(name, ((inputElements.at(i) == searchTermsElement) ? QLatin1String("{searchTerms}") : inputElements[i].evaluateJavaScript((inputElements.at(i).tagName().toLower() == QLatin1String("button")) ? QLatin1String("this.innerHTML") : QLatin1String("this.value")).toString())); + } + } + else if (!name.isEmpty()) + { + const QWebElementCollection optionElements(inputElements.at(i).findAll(QLatin1String("option:checked"))); - break; + for (int j = 0; j < optionElements.count(); ++j) + { + searchEngine.resultsUrl.parameters.addQueryItem(name, optionElements.at(j).evaluateJavaScript(QLatin1String("this.value")).toString()); + } } } - } - break; - case ActionsManager::ClearTabHistoryAction: - if (parameters.value(QLatin1String("clearGlobalHistory")).toBool()) - { - for (int i = 0; i < m_page->history()->count(); ++i) - { - const quint64 historyIdentifier(m_page->history()->itemAt(i).userData().toList().value(IdentifierEntryData).toULongLong()); + SearchEnginePropertiesDialog dialog(searchEngine, SearchEnginesManager::getSearchKeywords(), this); - if (historyIdentifier > 0) - { - HistoryManager::removeEntry(historyIdentifier); - } + if (dialog.exec() == QDialog::Accepted) + { + SearchEnginesManager::addSearchEngine(dialog.getSearchEngine()); } } - setUrl(QUrl(QLatin1String("about:blank"))); - - m_page->history()->clear(); + break; + case ActionsManager::ScrollToStartAction: + m_page->mainFrame()->setScrollPosition(QPoint(m_page->mainFrame()->scrollPosition().x(), 0)); - emit categorizedActionsStateChanged({ActionsManager::ActionDefinition::NavigationCategory}); + break; + case ActionsManager::ScrollToEndAction: + m_page->mainFrame()->setScrollPosition(QPoint(m_page->mainFrame()->scrollPosition().x(), m_page->mainFrame()->scrollBarMaximum(Qt::Vertical))); break; - case ActionsManager::PurgeTabHistoryAction: - triggerAction(ActionsManager::ClearTabHistoryAction, {{QLatin1String("clearGlobalHistory"), true}}, trigger); + case ActionsManager::ScrollPageUpAction: + m_page->mainFrame()->setScrollPosition(QPoint(m_page->mainFrame()->scrollPosition().x(), qMax(0, (m_page->mainFrame()->scrollPosition().y() - m_webView->height())))); break; - case ActionsManager::MuteTabMediaAction: - m_isAudioMuted = !m_isAudioMuted; + case ActionsManager::ScrollPageDownAction: + m_page->mainFrame()->setScrollPosition(QPoint(m_page->mainFrame()->scrollPosition().x(), qMin(m_page->mainFrame()->scrollBarMaximum(Qt::Vertical), (m_page->mainFrame()->scrollPosition().y() + m_webView->height())))); - muteAudio(m_page->mainFrame(), m_isAudioMuted); + break; + case ActionsManager::ScrollPageLeftAction: + m_page->mainFrame()->setScrollPosition(QPoint(qMax(0, (m_page->mainFrame()->scrollPosition().x() - m_webView->width())), m_page->mainFrame()->scrollPosition().y())); - emit arbitraryActionsStateChanged({ActionsManager::MuteTabMediaAction}); + break; + case ActionsManager::ScrollPageRightAction: + m_page->mainFrame()->setScrollPosition(QPoint(qMin(m_page->mainFrame()->scrollBarMaximum(Qt::Horizontal), (m_page->mainFrame()->scrollPosition().x() + m_webView->width())), m_page->mainFrame()->scrollPosition().y())); break; - case ActionsManager::OpenLinkAction: - case ActionsManager::OpenLinkInCurrentTabAction: - case ActionsManager::OpenLinkInNewTabAction: - case ActionsManager::OpenLinkInNewTabBackgroundAction: - case ActionsManager::OpenLinkInNewWindowAction: - case ActionsManager::OpenLinkInNewWindowBackgroundAction: - case ActionsManager::OpenLinkInNewPrivateTabAction: - case ActionsManager::OpenLinkInNewPrivateTabBackgroundAction: - case ActionsManager::OpenLinkInNewPrivateWindowAction: - case ActionsManager::OpenLinkInNewPrivateWindowBackgroundAction: + case ActionsManager::TakeScreenshotAction: { - const SessionsManager::OpenHints hints((identifier == ActionsManager::OpenLinkAction) ? SessionsManager::calculateOpenHints(parameters) : mapOpenActionToOpenHints(identifier)); + const QString mode(parameters.value(QLatin1String("mode"), QLatin1String("viewport")).toString()); + const QSize viewportSize(m_page->viewportSize()); + const QSize contentsSize((mode == QLatin1String("viewport")) ? viewportSize : m_page->mainFrame()->contentsSize()); + const QRect rectangle((mode == QLatin1String("area")) ? JsonSettings::readRectangle(parameters.value(QLatin1String("geometry"))) : QRect()); + QPixmap pixmap(rectangle.isValid() ? rectangle.size() : contentsSize); + QPainter painter(&pixmap); - if (hints == SessionsManager::DefaultOpen && !hitResult.flags.testFlag(HitTestResult::IsLinkFromSelectionTest)) + m_page->setViewportSize(contentsSize); + + if (rectangle.isValid()) { - m_page->triggerAction(QWebPage::OpenLink); + painter.translate(-rectangle.topLeft()); - setClickPosition({}); + m_page->mainFrame()->render(&painter, {rectangle}); } - else if (hitResult.linkUrl.isValid()) + else { - openUrl(hitResult.linkUrl, hints); + m_page->mainFrame()->render(&painter); + } + + m_page->setViewportSize(viewportSize); + + const QStringList filters({tr("PNG image (*.png)"), tr("JPEG image (*.jpg *.jpeg)")}); + const SaveInformation result(Utils::getSavePath(suggestSaveFileName(QLatin1String(".png")), {}, filters)); + + if (result.canSave) + { + pixmap.save(result.path, ((filters.indexOf(result.filter) == 0) ? "PNG" : "JPEG")); } } break; - case ActionsManager::CopyLinkToClipboardAction: - if (!hitResult.linkUrl.isEmpty()) + case ActionsManager::ActivateContentAction: { - Application::clipboard()->setText(hitResult.linkUrl.toString(QUrl::EncodeReserved | QUrl::EncodeSpaces)); + m_webView->setFocus(); + + m_page->mainFrame()->setFocus(); + + const QString tagName(m_page->mainFrame()->findFirstElement(QLatin1String(":focus")).tagName().toLower()); + + if (tagName == QLatin1String("textarea") || tagName == QLatin1String("input")) + { + m_page->mainFrame()->documentElement().evaluateJavaScript(QLatin1String("document.activeElement.blur()")); + } } break; - case ActionsManager::BookmarkLinkAction: - if (hitResult.linkUrl.isValid()) + case ActionsManager::LoadPluginsAction: { - const QString title(hitResult.title); + m_canLoadPlugins = true; - Application::triggerAction(ActionsManager::BookmarkPageAction, {{QLatin1String("url"), hitResult.linkUrl}, {QLatin1String("title"), (title.isEmpty() ? m_page->mainFrame()->hitTestContent(hitResult.hitPosition).element().toPlainText() : title)}}, parentWidget(), trigger); + QList frames({m_page->mainFrame()}); + + while (!frames.isEmpty()) + { + const QWebFrame *frame(frames.takeFirst()); + const QWebElementCollection elements(frame->documentElement().findAll(QLatin1String("object, embed"))); + + for (int i = 0; i < elements.count(); ++i) + { + elements.at(i).replace(elements.at(i).clone()); + } + + frames.append(frame->childFrames()); + } + + m_amountOfDeferredPlugins = 0; + + emit arbitraryActionsStateChanged({ActionsManager::LoadPluginsAction}); } break; - case ActionsManager::SaveLinkToDiskAction: - if (hitResult.linkUrl.isValid()) + case ActionsManager::ViewSourceAction: + if (canViewSource()) { - handleDownloadRequested(QNetworkRequest(hitResult.linkUrl)); + const QString defaultEncoding(m_page->settings()->defaultTextEncoding()); + QNetworkRequest request(getUrl()); + request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); + + QNetworkReply *reply(m_networkManager->get(request)); + SourceViewerWebWidget *sourceViewer(new SourceViewerWebWidget(isPrivate())); + sourceViewer->setRequestedUrl(QUrl(QLatin1String("view-source:") + getUrl().toString()), false); + + if (!defaultEncoding.isEmpty()) + { + sourceViewer->setOption(SettingsManager::Content_DefaultCharacterEncodingOption, defaultEncoding); + } + + m_viewSourceReplies[reply] = sourceViewer; + + connect(reply, &QNetworkReply::finished, this, &QtWebKitWebWidget::handleViewSourceReplyFinished); + + emit requestedNewWindow(sourceViewer, SessionsManager::DefaultOpen, {}); } - else + + break; + case ActionsManager::InspectPageAction: { - m_page->triggerAction(QWebPage::DownloadLinkToDisk); + const bool showInspector(parameters.value(QLatin1String("isChecked"), !getActionState(identifier, parameters).isChecked).toBool()); + + if (showInspector && !m_inspectorWidget) + { + getInspector(); + } + + emit requestedInspectorVisibilityChange(showInspector); + emit arbitraryActionsStateChanged({ActionsManager::InspectPageAction}); } break; - case ActionsManager::SaveLinkToDownloadsAction: - TransfersManager::addTransfer(TransfersManager::startTransfer(hitResult.linkUrl.toString(), {}, (Transfer::CanNotifyOption | Transfer::CanAskForPathOption | Transfer::IsQuickTransferOption | (isPrivate() ? Transfer::IsPrivateOption : Transfer::NoOption)))); + case ActionsManager::InspectElementAction: + triggerAction(ActionsManager::InspectPageAction, {{QLatin1String("isChecked"), true}}, trigger); - break; - case ActionsManager::OpenFrameAction: - case ActionsManager::OpenFrameInCurrentTabAction: - case ActionsManager::OpenFrameInNewTabAction: - case ActionsManager::OpenFrameInNewTabBackgroundAction: - if (hitResult.frameUrl.isValid()) - { - openUrl(hitResult.frameUrl, ((identifier == ActionsManager::OpenFrameAction) ? SessionsManager::calculateOpenHints(parameters) : mapOpenActionToOpenHints(identifier))); - } + m_page->triggerAction(QWebPage::InspectElement); break; - case ActionsManager::CopyFrameLinkToClipboardAction: - if (hitResult.frameUrl.isValid()) + case ActionsManager::FullScreenAction: { - Application::clipboard()->setText(hitResult.frameUrl.toString(QUrl::EncodeReserved | QUrl::EncodeSpaces)); + const MainWindow *mainWindow(MainWindow::findMainWindow(this)); + + if (mainWindow && !mainWindow->isFullScreen()) + { + m_page->mainFrame()->evaluateJavaScript(QLatin1String("document.webkitExitFullscreen()")); + } } break; - case ActionsManager::ReloadFrameAction: - if (hitResult.frameUrl.isValid()) + case ActionsManager::WebsitePreferencesAction: { - const QUrl url(hitResult.frameUrl); - QWebFrame *frame(m_page->mainFrame()->hitTestContent(hitResult.hitPosition).frame()); + const QUrl url(getUrl()); + CookieJar *cookieJar(m_networkManager->getCookieJar()); + WebsitePreferencesDialog dialog(Utils::extractHost(url), (url.host().isEmpty() ? QVector() : cookieJar->getCookies(url.host())), this); - if (frame) + if (dialog.exec() == QDialog::Accepted) { - m_networkManager->addContentBlockingException(url, NetworkManager::SubFrameType); + updateOptions(url); - frame->setUrl({}); - frame->setUrl(url); + const QVector cookiesToDelete(dialog.getCookiesToDelete()); + const QVector cookiesToInsert(dialog.getCookiesToInsert()); + + for (int i = 0; i < cookiesToDelete.count(); ++i) + { + cookieJar->forceDeleteCookie(cookiesToDelete.at(i)); + } + + for (int i = 0; i < cookiesToInsert.count(); ++i) + { + cookieJar->forceInsertCookie(cookiesToInsert.at(i)); + } } } break; - case ActionsManager::ViewFrameSourceAction: - if (hitResult.frameUrl.isValid()) - { - const QString defaultEncoding(m_page->settings()->defaultTextEncoding()); - QNetworkRequest request(hitResult.frameUrl); - request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); + default: + break; + } +} - QNetworkReply *reply(m_networkManager->get(request)); - SourceViewerWebWidget *sourceViewer(new SourceViewerWebWidget(isPrivate())); - sourceViewer->setRequestedUrl(QUrl(QLatin1String("view-source:") + hitResult.frameUrl.toString()), false); +void QtWebKitWebWidget::findInPage(const QString &text, FindFlags flags) +{ + QWebPage::FindFlags nativeFlags(QWebPage::FindWrapsAroundDocument | QWebPage::FindBeginsInSelection); - if (!defaultEncoding.isEmpty()) - { - sourceViewer->setOption(SettingsManager::Content_DefaultCharacterEncodingOption, defaultEncoding); - } + if (flags.testFlag(BackwardFind)) + { + nativeFlags |= QWebPage::FindBackward; + } - m_viewSourceReplies[reply] = sourceViewer; + if (flags.testFlag(CaseSensitiveFind)) + { + nativeFlags |= QWebPage::FindCaseSensitively; + } + + if (flags.testFlag(HighlightAllFind) || text.isEmpty()) + { + m_page->findText({}, QWebPage::HighlightAllOccurrences); + m_page->findText(text, (nativeFlags | QWebPage::HighlightAllOccurrences)); + } - connect(reply, &QNetworkReply::finished, this, &QtWebKitWebWidget::handleViewSourceReplyFinished); + m_page->findText(text, nativeFlags); +} - emit requestedNewWindow(sourceViewer, SessionsManager::DefaultOpen, {}); - } +void QtWebKitWebWidget::search(const QString &query, const QString &searchEngine) +{ + QNetworkRequest request; + QNetworkAccessManager::Operation method; + QByteArray body; - break; - case ActionsManager::OpenImageAction: - case ActionsManager::OpenImageInNewTabAction: - case ActionsManager::OpenImageInNewTabBackgroundAction: - if (hitResult.imageUrl.isValid()) - { - openUrl(hitResult.imageUrl, ((identifier == ActionsManager::OpenImageAction) ? SessionsManager::calculateOpenHints(parameters) : mapOpenActionToOpenHints(identifier))); - } + if (SearchEnginesManager::setupSearchQuery(query, searchEngine, &request, &method, &body)) + { + setRequestedUrl(request.url(), false, true); + updateOptions(request.url()); - break; - case ActionsManager::SaveImageToDiskAction: - if (hitResult.imageUrl.isValid()) - { - handleDownloadRequested(QNetworkRequest(hitResult.imageUrl)); - } + m_page->mainFrame()->load(request, method, body); + } +} - break; - case ActionsManager::CopyImageToClipboardAction: - { - const QPixmap pixmap(m_page->mainFrame()->hitTestContent(hitResult.hitPosition).pixmap()); +void QtWebKitWebWidget::print(QPrinter *printer) +{ + m_page->mainFrame()->print(printer); +} - if (!pixmap.isNull()) - { - Application::clipboard()->setPixmap(pixmap); - } - else - { - m_page->triggerAction(QWebPage::CopyImageToClipboard); - } - } +void QtWebKitWebWidget::saveState(QWebFrame *frame, QWebHistoryItem *item) +{ + if (frame == m_page->mainFrame()) + { + QVariantList state(m_page->history()->currentItem().userData().toList()); - break; - case ActionsManager::CopyImageUrlToClipboardAction: - if (!hitResult.imageUrl.isEmpty()) - { - Application::clipboard()->setText(hitResult.imageUrl.toString(QUrl::EncodeReserved | QUrl::EncodeSpaces)); - } + if (state.isEmpty() || state.count() < 4) + { + state = {0, getZoom(), m_page->mainFrame()->scrollPosition(), QDateTime::currentDateTimeUtc()}; + } + else + { + state[ZoomEntryData] = getZoom(); + state[PositionEntryData] = m_page->mainFrame()->scrollPosition(); + } - break; - case ActionsManager::ReloadImageAction: - if (!hitResult.imageUrl.isEmpty()) - { - m_networkManager->addContentBlockingException(hitResult.imageUrl, NetworkManager::ImageType); + item->setUserData(state); + } +} - m_page->settings()->setAttribute(QWebSettings::AutoLoadImages, true); +void QtWebKitWebWidget::restoreState(QWebFrame *frame) +{ + if (frame == m_page->mainFrame()) + { + const QVariantList state(m_page->history()->currentItem().userData().toList()); - if (getUrl().matches(hitResult.imageUrl, (QUrl::NormalizePathSegments | QUrl::RemoveFragment | QUrl::StripTrailingSlash))) - { - triggerAction(ActionsManager::ReloadAndBypassCacheAction, {}, trigger); - } - else - { - QWebElement element(m_page->mainFrame()->hitTestContent(hitResult.hitPosition).element()); - const QUrl url(hitResult.imageUrl); - const QString src(element.attribute(QLatin1String("src"))); - NetworkCache *cache(NetworkManagerFactory::getCache()); + setZoom(state.value(ZoomEntryData, getZoom()).toInt()); - element.setAttribute(QLatin1String("src"), {}); + if (m_page->mainFrame()->scrollPosition().isNull()) + { + m_page->mainFrame()->setScrollPosition(state.value(PositionEntryData).toPoint()); + } + } +} - if (cache) - { - cache->remove(url); - } +void QtWebKitWebWidget::clearPluginToken() +{ + QList frames({m_page->mainFrame()}); - element.setAttribute(QLatin1String("src"), src); + while (!frames.isEmpty()) + { + const QWebFrame *frame(frames.takeFirst()); + QWebElement element(frame->documentElement().findFirst(QStringLiteral("object[data-otter-browser='%1'], embed[data-otter-browser='%1']").arg(m_pluginToken))); - m_page->mainFrame()->documentElement().evaluateJavaScript(QStringLiteral("var images = document.querySelectorAll('img[src=\"%1\"]'); for (var i = 0; i < images.length; ++i) { images[i].src = ''; images[i].src = '%1'; }").arg(src)); - } - } + if (!element.isNull()) + { + element.removeAttribute(QLatin1String("data-otter-browser")); break; - case ActionsManager::ImagePropertiesAction: - { - QVariantMap properties({{QLatin1String("alternativeText"), hitResult.alternateText}, {QLatin1String("longDescription"), hitResult.longDescription}}); - const QPixmap pixmap(m_page->mainFrame()->hitTestContent(hitResult.hitPosition).pixmap()); + } - if (!pixmap.isNull()) - { - properties[QLatin1String("width")] = pixmap.width(); - properties[QLatin1String("height")] = pixmap.height(); - properties[QLatin1String("depth")] = pixmap.depth(); - } + frames.append(frame->childFrames()); + } - ImagePropertiesDialog *imagePropertiesDialog(new ImagePropertiesDialog(hitResult.imageUrl, properties, (m_networkManager->cache() ? m_networkManager->cache()->data(hitResult.imageUrl) : nullptr), this)); - imagePropertiesDialog->setButtonsVisible(false); + emit arbitraryActionsStateChanged({ActionsManager::LoadPluginsAction}); - ContentsDialog *dialog(new ContentsDialog(ThemesManager::createIcon(QLatin1String("dialog-information")), imagePropertiesDialog->windowTitle(), {}, {}, QDialogButtonBox::Close, imagePropertiesDialog, this)); + m_pluginToken.clear(); +} - connect(this, &QtWebKitWebWidget::aboutToReload, dialog, &ContentsDialog::close); - connect(imagePropertiesDialog, &ImagePropertiesDialog::finished, dialog, &ContentsDialog::close); +void QtWebKitWebWidget::resetSpellCheck(QWebElement element) +{ + if (element.isNull()) + { + element = m_page->mainFrame()->findFirstElement(QLatin1String("*:focus")); + } - showDialog(dialog, false); - } + if (!element.isNull()) + { + m_page->runScript(QLatin1String("resetSpellCheck"), element); + } +} - break; - case ActionsManager::SaveMediaToDiskAction: - if (hitResult.mediaUrl.isValid()) - { - handleDownloadRequested(QNetworkRequest(hitResult.mediaUrl)); - } +void QtWebKitWebWidget::muteAudio(QWebFrame *frame, bool isMuted) +{ + if (!frame) + { + return; + } - break; - case ActionsManager::CopyMediaUrlToClipboardAction: - if (!hitResult.mediaUrl.isEmpty()) - { - Application::clipboard()->setText(hitResult.mediaUrl.toString(QUrl::EncodeReserved | QUrl::EncodeSpaces)); - } + const QString script(QLatin1String("this.muted = ") + (isMuted ? QLatin1String("true") : QLatin1String("false"))); + const QWebElementCollection elements(frame->findAllElements(QLatin1String("audio, video"))); - break; - case ActionsManager::MediaControlsAction: - m_page->triggerAction(QWebPage::ToggleMediaControls, parameters.value(QLatin1String("isChecked"), !getActionState(identifier, parameters).isChecked).toBool()); + for (int i = 0; i < elements.count(); ++i) + { + elements.at(i).evaluateJavaScript(script); + } - break; - case ActionsManager::MediaLoopAction: - m_page->triggerAction(QWebPage::ToggleMediaLoop, parameters.value(QLatin1String("isChecked"), !getActionState(identifier, parameters).isChecked).toBool()); + const QList frames(frame->childFrames()); - break; - case ActionsManager::MediaPlayPauseAction: - m_page->triggerAction(QWebPage::ToggleMediaPlayPause); + for (int i = 0; i < frames.count(); ++i) + { + muteAudio(frames.at(i), isMuted); + } +} - break; - case ActionsManager::MediaMuteAction: - m_page->triggerAction(QWebPage::ToggleMediaMute); +void QtWebKitWebWidget::openRequest(const QNetworkRequest &request, QNetworkAccessManager::Operation operation, QIODevice *outgoingData) +{ + m_formRequest = request; + m_formRequestOperation = operation; + m_formRequestBody = (outgoingData ? outgoingData->readAll() : QByteArray()); - break; - case ActionsManager::MediaPlaybackRateAction: - m_page->mainFrame()->hitTestContent(hitResult.hitPosition).element().evaluateJavaScript(QStringLiteral("this.playbackRate = %1").arg(parameters.value(QLatin1String("rate"), 1).toReal())); + if (outgoingData) + { + outgoingData->close(); + outgoingData->deleteLater(); + } - break; - case ActionsManager::GoBackAction: - m_page->triggerAction(QWebPage::Back); + setRequestedUrl(m_formRequest.url(), false, true); + updateOptions(m_formRequest.url()); - break; - case ActionsManager::GoForwardAction: - m_page->triggerAction(QWebPage::Forward); + QTimer::singleShot(50, this, [&]() + { + m_page->mainFrame()->load(m_formRequest, m_formRequestOperation, m_formRequestBody); - break; - case ActionsManager::GoToHistoryIndexAction: - if (parameters.contains(QLatin1String("index"))) - { - const int index(parameters[QLatin1String("index")].toInt()); + m_formRequest = QNetworkRequest(); + m_formRequestBody.clear(); + }); +} - if (index >= 0 && index < m_page->history()->count()) - { - m_page->history()->goToItem(m_page->history()->itemAt(index)); - } - } +void QtWebKitWebWidget::openFormRequest(const QNetworkRequest &request, QNetworkAccessManager::Operation operation, QIODevice *outgoingData) +{ + m_page->triggerAction(QWebPage::Stop); - break; - case ActionsManager::RewindAction: - m_page->history()->goToItem(m_page->history()->itemAt(0)); + QtWebKitWebWidget *widget(qobject_cast(clone(false))); + widget->openRequest(request, operation, outgoingData); - break; - case ActionsManager::FastForwardAction: - { - const QUrl url(m_page->mainFrame()->evaluateJavaScript(getFastForwardScript(true)).toUrl()); + emit requestedNewWindow(widget, SessionsManager::calculateOpenHints(SessionsManager::NewTabOpen), {}); +} - if (url.isValid()) - { - setUrl(url); - } - else if (canGoForward()) - { - m_page->triggerAction(QWebPage::Forward); - } - } +void QtWebKitWebWidget::startDelayedTransfer(Transfer *transfer) +{ + m_transfers.enqueue(transfer); - break; - case ActionsManager::RemoveHistoryIndexAction: - if (parameters.contains(QLatin1String("index"))) - { - const int index(parameters[QLatin1String("index")].toInt()); + if (m_transfersTimer == 0) + { + m_transfersTimer = startTimer(250); + } +} - if (index >= 0 && index < m_page->history()->count()) - { - if (parameters.value(QLatin1String("clearGlobalHistory"), false).toBool()) - { - const quint64 entryIdentifier(m_page->history()->itemAt(index).userData().toList().value(IdentifierEntryData).toULongLong()); +void QtWebKitWebWidget::handleDownloadRequested(const QNetworkRequest &request) +{ + const HitTestResult hitResult(getCurrentHitTestResult()); - if (entryIdentifier > 0) - { - HistoryManager::removeEntry(entryIdentifier); - } - } + if ((!hitResult.imageUrl.isEmpty() && request.url() == hitResult.imageUrl) || (!hitResult.mediaUrl.isEmpty() && request.url() == hitResult.mediaUrl)) + { + NetworkCache *cache(NetworkManagerFactory::getCache()); - Session::Window::History history(getHistory()); - history.entries.removeAt(index); + if (cache && cache->metaData(request.url()).isValid()) + { + QIODevice *device(cache->data(request.url())); - if (history.index >= index) - { - history.index = (history.index - 1); - } + if (device && device->size() > 0) + { + const QString path(Utils::getSavePath(request.url().fileName()).path); - setHistory(history); + if (path.isEmpty()) + { + device->deleteLater(); + + return; } - } - break; - case ActionsManager::StopAction: - m_page->triggerAction(QWebPage::Stop); + QFile file(path); - break; - case ActionsManager::StopScheduledReloadAction: - m_page->triggerAction(QWebPage::StopScheduledPageRefresh); + if (!file.open(QIODevice::WriteOnly)) + { + QMessageBox::critical(this, tr("Error"), tr("Failed to open file for writing."), QMessageBox::Close); + } - break; - case ActionsManager::ReloadAction: - emit aboutToReload(); + file.write(device->readAll()); + file.close(); - m_page->triggerAction(QWebPage::Stop); - m_page->triggerAction(QWebPage::Reload); + device->deleteLater(); - break; - case ActionsManager::ReloadOrStopAction: - if (m_loadingState == OngoingLoadingState) - { - triggerAction(ActionsManager::StopAction, {}, trigger); + return; } - else + + if (device) { - triggerAction(ActionsManager::ReloadAction, {}, trigger); + device->deleteLater(); } + } + else if (!hitResult.imageUrl.isEmpty() && hitResult.imageUrl.scheme() == QLatin1String("data") && hitResult.imageUrl.url().contains(QLatin1String(";base64,"))) + { + const QString imageUrl(hitResult.imageUrl.url()); + const QString imageType(imageUrl.mid(11, (imageUrl.indexOf(QLatin1Char(';')) - 11))); + const QString path(Utils::getSavePath(tr("file") + QLatin1Char('.') + imageType).path); - break; - case ActionsManager::ReloadAndBypassCacheAction: - m_page->triggerAction(QWebPage::ReloadAndBypassCache); - - break; - case ActionsManager::ContextMenuAction: - if (parameters.contains(QLatin1String("context")) && parameters[QLatin1String("context")].toInt() == QContextMenuEvent::Keyboard) + if (!path.isEmpty()) { - const QWebElement element(m_page->mainFrame()->findFirstElement(QLatin1String(":focus"))); + QImageWriter writer(path); - if (element.isNull()) + if (!writer.write(QImage::fromData(QByteArray::fromBase64(imageUrl.mid(imageUrl.indexOf(QLatin1String(";base64,")) + 7).toUtf8()), imageType.toStdString().c_str()))) { - setClickPosition(m_webView->mapFromGlobal(QCursor::pos())); + Console::addMessage(tr("Failed to save image: %1").arg(writer.errorString()), Console::OtherCategory, Console::ErrorLevel, path, -1, getWindowIdentifier()); } - else - { - QPoint clickPosition(element.geometry().center()); - QWebFrame *frame(element.webFrame()); + } - while (frame) - { - clickPosition -= frame->scrollPosition(); + return; + } - frame = frame->parentFrame(); - } + QNetworkRequest mutableRequest(request); + mutableRequest.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); - setClickPosition(clickPosition); - } - } - else - { - setClickPosition(m_webView->mapFromGlobal(QCursor::pos())); - } + TransfersManager::startTransfer(m_networkManager->get(mutableRequest), {}, (Transfer::CanAskForPathOption | Transfer::CanAutoDeleteOption | Transfer::IsPrivateOption)); + } + else + { + startDelayedTransfer(TransfersManager::startTransfer(request, {}, (Transfer::CanNotifyOption | (isPrivate() ? Transfer::IsPrivateOption : Transfer::NoOption)))); + } +} - showContextMenu(getClickPosition()); +void QtWebKitWebWidget::handleUnsupportedContent(QNetworkReply *reply) +{ + m_networkManager->registerTransfer(reply); - break; - case ActionsManager::UndoAction: - m_page->triggerAction(QWebPage::Undo); + startDelayedTransfer(TransfersManager::startTransfer(reply, {}, (Transfer::CanNotifyOption | (isPrivate() ? Transfer::IsPrivateOption : Transfer::NoOption)))); +} - break; - case ActionsManager::RedoAction: - m_page->triggerAction(QWebPage::Redo); +void QtWebKitWebWidget::handleOptionChanged(int identifier, const QVariant &value) +{ + switch (identifier) + { + case SettingsManager::Content_BackgroundColorOption: + { + QPalette palette(m_page->palette()); + palette.setColor(QPalette::Base, QColor(value.toString())); + + m_page->setPalette(palette); + } break; - case ActionsManager::CutAction: - m_page->triggerAction(QWebPage::Cut); + case SettingsManager::History_BrowsingLimitAmountWindowOption: + m_page->history()->setMaximumItemCount(value.toInt()); break; - case ActionsManager::CopyAction: - if (parameters.value(QLatin1String("mode")) == QLatin1String("plainText")) - { - const QString text(getSelectedText()); + case SettingsManager::Permissions_ScriptsCanShowStatusMessagesOption: + disconnect(m_page, &QtWebKitPage::statusBarMessage, this, &QtWebKitWebWidget::setStatusMessage); - if (!text.isEmpty()) - { - Application::clipboard()->setText(text); - } + if (value.toBool() || SettingsManager::getOption(identifier, Utils::extractHost(getUrl())).toBool()) + { + connect(m_page, &QtWebKitPage::statusBarMessage, this, &QtWebKitWebWidget::setStatusMessage); } else { - m_page->triggerAction(QWebPage::Copy); + setStatusMessage({}); } break; - case ActionsManager::CopyPlainTextAction: - triggerAction(ActionsManager::CopyAction, {{QLatin1String("mode"), QLatin1String("plainText")}}, trigger); - + default: break; - case ActionsManager::CopyAddressAction: - Application::clipboard()->setText(getUrl().toString()); + } +} - break; - case ActionsManager::CopyToNoteAction: - NotesManager::addNote(BookmarksModel::UrlBookmark, {{BookmarksModel::UrlRole, getUrl()}, {BookmarksModel::DescriptionRole, getSelectedText()}}); +void QtWebKitWebWidget::handleLoadStarted() +{ + if (m_loadingState == OngoingLoadingState) + { + return; + } - break; - case ActionsManager::PasteAction: - if (parameters.contains(QLatin1String("note"))) - { - const BookmarksModel::Bookmark *bookmark(NotesManager::getModel()->getBookmark(parameters[QLatin1String("note")].toULongLong())); + m_thumbnail = {}; + m_messageToken = QUuid::createUuid().toString(); + m_canLoadPlugins = (getOption(SettingsManager::Permissions_EnablePluginsOption, getUrl()).toString() == QLatin1String("enabled")); + m_loadingState = OngoingLoadingState; - if (bookmark) - { - triggerAction(ActionsManager::PasteAction, {{QLatin1String("text"), bookmark->getDescription()}}, trigger); - } - } - else if (parameters.contains(QLatin1String("text"))) - { - QMimeData *mimeData(new QMimeData()); - const QStringList mimeTypes(Application::clipboard()->mimeData()->formats()); + setStatusMessage({}); + setStatusMessageOverride({}); - for (int i = 0; i < mimeTypes.count(); ++i) - { - mimeData->setData(mimeTypes.at(i), Application::clipboard()->mimeData()->data(mimeTypes.at(i))); - } + emit geometryChanged(); + emit categorizedActionsStateChanged({ActionsManager::ActionDefinition::NavigationCategory}); + emit loadingStateChanged(OngoingLoadingState); +} - Application::clipboard()->setText(parameters[QLatin1String("text")].toString()); +void QtWebKitWebWidget::handleLoadProgress(int progress) +{ + m_networkManager->setPageInformation(TotalLoadingProgressInformation, progress); +} - m_page->triggerAction(QWebPage::Paste); +void QtWebKitWebWidget::handleLoadFinished(bool result) +{ + if (m_isAudioMuted) + { + muteAudio(m_page->mainFrame(), true); + } - Application::clipboard()->setMimeData(mimeData); - } - else - { - m_page->triggerAction(QWebPage::Paste); - } + if (m_loadingState != OngoingLoadingState) + { + return; + } - break; - case ActionsManager::DeleteAction: - m_page->triggerAction(QWebPage::DeleteEndOfWord); + m_networkManager->handleLoadFinished(result); - break; - case ActionsManager::SelectAllAction: - m_page->triggerAction(QWebPage::SelectAll); + m_thumbnail = {}; + m_loadingState = FinishedLoadingState; - break; - case ActionsManager::UnselectAction: - m_page->triggerAction(QWebPage::Unselect); + updateAmountOfDeferredPlugins(); + handleHistory(); + startReloadTimer(); + + emit categorizedActionsStateChanged({ActionsManager::ActionDefinition::NavigationCategory}); + emit contentStateChanged(getContentState()); + emit loadingStateChanged(FinishedLoadingState); + emit watchedDataChanged(FeedsWatcher); + emit watchedDataChanged(LinksWatcher); + emit watchedDataChanged(MetaDataWatcher); + emit watchedDataChanged(SearchEnginesWatcher); + emit watchedDataChanged(StylesheetsWatcher); +} - break; - case ActionsManager::ClearAllAction: - m_page->triggerAction(QWebPage::SelectAll); - m_page->triggerAction(QWebPage::DeleteEndOfWord); +void QtWebKitWebWidget::handleViewSourceReplyFinished() +{ + QNetworkReply *reply(qobject_cast(sender())); - break; - case ActionsManager::CheckSpellingAction: - { - QWebElement element(m_page->mainFrame()->hitTestContent(hitResult.hitPosition).element()); - element.evaluateJavaScript(QStringLiteral("this.spellcheck = %1").arg(parameters.value(QLatin1String("isChecked"), !getActionState(identifier, parameters).isChecked).toBool() ? QLatin1String("true") : QLatin1String("false"))); + if (reply) + { + if (reply->error() == QNetworkReply::NoError && m_viewSourceReplies.contains(reply) && m_viewSourceReplies[reply]) + { + m_viewSourceReplies[reply]->setContents(reply->readAll(), reply->header(QNetworkRequest::ContentTypeHeader).toString()); + } - if (parameters.contains(QLatin1String("dictionary"))) - { - setOption(SettingsManager::Browser_SpellCheckDictionaryOption, parameters.value(QLatin1String("dictionary"))); - } - else - { - resetSpellCheck(element); - } + m_viewSourceReplies.remove(reply); - emit arbitraryActionsStateChanged({ActionsManager::CheckSpellingAction}); - } + reply->deleteLater(); + } +} - break; - case ActionsManager::CreateSearchAction: - { - const QWebElement element(m_page->mainFrame()->hitTestContent(hitResult.hitPosition).element()); - QWebElement parentElement(element.parent()); +void QtWebKitWebWidget::handlePrintRequest(QWebFrame *frame) +{ + QPrintPreviewDialog printPreviewDialog(this); + printPreviewDialog.setWindowFlags(printPreviewDialog.windowFlags() | Qt::WindowMaximizeButtonHint | Qt::WindowMinimizeButtonHint); + printPreviewDialog.setWindowTitle(tr("Print Preview")); - while (!parentElement.isNull() && parentElement.tagName().toLower() != QLatin1String("form")) - { - parentElement = parentElement.parent(); - } + if (Application::getActiveWindow()) + { + printPreviewDialog.resize(Application::getActiveWindow()->size()); + } - if (!parentElement.hasAttribute(QLatin1String("action"))) - { - break; - } + connect(&printPreviewDialog, &QPrintPreviewDialog::paintRequested, frame, &QWebFrame::print); - QList inputElements(parentElement.findAll(QLatin1String("button:not([disabled])[name][type='submit'], input:not([disabled])[name], select:not([disabled])[name], textarea:not([disabled])[name]")).toList()); + printPreviewDialog.exec(); +} - if (inputElements.isEmpty()) - { - break; - } +void QtWebKitWebWidget::handleHistory() +{ + if (isPrivate() || m_page->history()->count() == 0) + { + return; + } - QWebElement searchTermsElement; - const QString tagName(element.tagName().toLower()); - const QUrl url(parentElement.attribute(QLatin1String("action"))); - const QIcon icon(m_page->mainFrame()->icon()); - SearchEnginesManager::SearchEngineDefinition searchEngine; - searchEngine.title = getTitle(); - searchEngine.formUrl = getUrl(); - searchEngine.icon = (icon.isNull() ? ThemesManager::createIcon(QLatin1String("edit-find")) : icon); - searchEngine.resultsUrl.url = (url.isEmpty() ? getUrl() : resolveUrl(parentElement.webFrame(), url)).toString(); - searchEngine.resultsUrl.enctype = parentElement.attribute(QLatin1String("enctype")); - searchEngine.resultsUrl.method = ((parentElement.attribute(QLatin1String("method"), QLatin1String("get")).toLower() == QLatin1String("post")) ? QLatin1String("post") : QLatin1String("get")); + const QUrl url(m_page->history()->currentItem().url()); + const QVariant state(m_page->history()->currentItem().userData()); - if (tagName != QLatin1String("select")) - { - const QString type(element.attribute(QLatin1String("type"))); + if (state.isValid()) + { + const quint64 identifier(state.toList().value(IdentifierEntryData).toULongLong()); - if (!inputElements.contains(element) && (type == QLatin1String("image") || type == QLatin1String("submit"))) - { - inputElements.append(element); - } + if (identifier > 0) + { + HistoryManager::updateEntry(identifier, url, getTitle(), m_page->mainFrame()->icon()); + } + } + else + { + m_page->history()->currentItem().setUserData(QVariantList({(Utils::isUrlEmpty(url) ? 0 : HistoryManager::addEntry(url, getTitle(), m_page->mainFrame()->icon(), m_isTypedIn)), getZoom(), QPoint(0, 0), QDateTime::currentDateTimeUtc()})); - if (tagName == QLatin1String("textarea") || type == QLatin1String("email") || type == QLatin1String("password") || type == QLatin1String("search") || type == QLatin1String("tel") || type == QLatin1String("text") || type == QLatin1String("url")) - { - searchTermsElement = element; - } - } + if (m_isTypedIn) + { + m_isTypedIn = false; + } - if (searchTermsElement.isNull()) - { - searchTermsElement = parentElement.findFirst(QLatin1String("input:not([disabled])[name][type='search']")); - } + SessionsManager::markSessionAsModified(); + BookmarksManager::updateVisits(url.toString()); + } +} - for (int i = 0; i < inputElements.count(); ++i) - { - const QString name(inputElements.at(i).attribute(QLatin1String("name"))); +void QtWebKitWebWidget::handleNavigationRequest(const QUrl &url, QWebPage::NavigationType type) +{ + if (type != QWebPage::NavigationTypeBackOrForward && (type != QWebPage::NavigationTypeLinkClicked || !getUrl().matches(url, QUrl::RemoveFragment))) + { + handleLoadStarted(); + handleHistory(); - if (inputElements.at(i).tagName().toLower() != QLatin1String("select")) - { - const QString type(inputElements.at(i).attribute(QLatin1String("type"))); - const bool isSubmit(type == QLatin1String("image") || type == QLatin1String("submit")); + m_networkManager->resetStatistics(); + } - if ((isSubmit && inputElements.at(i) != element) || ((type == QLatin1String("checkbox") || type == QLatin1String("radio")) && !inputElements[i].evaluateJavaScript(QLatin1String("this.checked")).toBool())) - { - continue; - } + updateOptions(url); - if (isSubmit && inputElements.at(i) == element) - { - if (inputElements.at(i).hasAttribute(QLatin1String("formaction"))) - { - searchEngine.resultsUrl.url = resolveUrl(parentElement.webFrame(), inputElements.at(i).attribute(QLatin1String("formaction"))).toString(); - } + m_isNavigating = true; - if (inputElements.at(i).hasAttribute(QLatin1String("formenctype"))) - { - searchEngine.resultsUrl.enctype = inputElements.at(i).attribute(QLatin1String("formenctype")); - } + emit aboutToNavigate(); +} - if (inputElements.at(i).hasAttribute(QLatin1String("formmethod"))) - { - searchEngine.resultsUrl.method = inputElements.at(i).attribute(QLatin1String("formmethod")); - } - } +void QtWebKitWebWidget::handleFullScreenRequest(QWebFullScreenRequest request) +{ + request.accept(); - if (!isSubmit && searchTermsElement.isNull() && type != QLatin1String("hidden")) - { - searchTermsElement = inputElements.at(i); - } + if (request.toggleOn()) + { + const QString value(SettingsManager::getOption(SettingsManager::Permissions_EnableFullScreenOption, Utils::extractHost(request.origin())).toString()); - if (!name.isEmpty()) - { - searchEngine.resultsUrl.parameters.addQueryItem(name, ((inputElements.at(i) == searchTermsElement) ? QLatin1String("{searchTerms}") : inputElements[i].evaluateJavaScript((inputElements.at(i).tagName().toLower() == QLatin1String("button")) ? QLatin1String("this.innerHTML") : QLatin1String("this.value")).toString())); - } - } - else if (!name.isEmpty()) - { - const QWebElementCollection optionElements(inputElements.at(i).findAll(QLatin1String("option:checked"))); + if (value == QLatin1String("allow")) + { + MainWindow *mainWindow(MainWindow::findMainWindow(this)); - for (int j = 0; j < optionElements.count(); ++j) - { - searchEngine.resultsUrl.parameters.addQueryItem(name, optionElements.at(j).evaluateJavaScript(QLatin1String("this.value")).toString()); - } - } - } + if (mainWindow && !mainWindow->isFullScreen()) + { + mainWindow->triggerAction(ActionsManager::FullScreenAction); + } + } + else if (value == QLatin1String("ask")) + { + emit requestedPermission(FullScreenFeature, request.origin(), false); + } + } + else + { + MainWindow *mainWindow(MainWindow::findMainWindow(this)); - SearchEnginePropertiesDialog dialog(searchEngine, SearchEnginesManager::getSearchKeywords(), this); + if (mainWindow && mainWindow->isFullScreen()) + { + mainWindow->triggerAction(ActionsManager::FullScreenAction); + } - if (dialog.exec() == QDialog::Accepted) - { - SearchEnginesManager::addSearchEngine(dialog.getSearchEngine()); - } - } + emit requestedPermission(FullScreenFeature, request.origin(), true); + } - break; - case ActionsManager::ScrollToStartAction: - m_page->mainFrame()->setScrollPosition(QPoint(m_page->mainFrame()->scrollPosition().x(), 0)); + m_isFullScreen = request.toggleOn(); - break; - case ActionsManager::ScrollToEndAction: - m_page->mainFrame()->setScrollPosition(QPoint(m_page->mainFrame()->scrollPosition().x(), m_page->mainFrame()->scrollBarMaximum(Qt::Vertical))); + emit isFullScreenChanged(m_isFullScreen); +} - break; - case ActionsManager::ScrollPageUpAction: - m_page->mainFrame()->setScrollPosition(QPoint(m_page->mainFrame()->scrollPosition().x(), qMax(0, (m_page->mainFrame()->scrollPosition().y() - m_webView->height())))); +void QtWebKitWebWidget::handlePermissionRequest(QWebFrame *frame, QWebPage::Feature feature) +{ + notifyPermissionRequested(frame, feature, false); +} - break; - case ActionsManager::ScrollPageDownAction: - m_page->mainFrame()->setScrollPosition(QPoint(m_page->mainFrame()->scrollPosition().x(), qMin(m_page->mainFrame()->scrollBarMaximum(Qt::Vertical), (m_page->mainFrame()->scrollPosition().y() + m_webView->height())))); +void QtWebKitWebWidget::handlePermissionCancel(QWebFrame *frame, QWebPage::Feature feature) +{ + notifyPermissionRequested(frame, feature, true); +} - break; - case ActionsManager::ScrollPageLeftAction: - m_page->mainFrame()->setScrollPosition(QPoint(qMax(0, (m_page->mainFrame()->scrollPosition().x() - m_webView->width())), m_page->mainFrame()->scrollPosition().y())); +void QtWebKitWebWidget::notifyTitleChanged() +{ + emit titleChanged(getTitle()); - break; - case ActionsManager::ScrollPageRightAction: - m_page->mainFrame()->setScrollPosition(QPoint(qMin(m_page->mainFrame()->scrollBarMaximum(Qt::Horizontal), (m_page->mainFrame()->scrollPosition().x() + m_webView->width())), m_page->mainFrame()->scrollPosition().y())); + handleHistory(); +} - break; - case ActionsManager::TakeScreenshotAction: - { - const QString mode(parameters.value(QLatin1String("mode"), QLatin1String("viewport")).toString()); - const QSize viewportSize(m_page->viewportSize()); - const QSize contentsSize((mode == QLatin1String("viewport")) ? viewportSize : m_page->mainFrame()->contentsSize()); - const QRect rectangle((mode == QLatin1String("area")) ? JsonSettings::readRectangle(parameters.value(QLatin1String("geometry"))) : QRect()); - QPixmap pixmap(rectangle.isValid() ? rectangle.size() : contentsSize); - QPainter painter(&pixmap); +void QtWebKitWebWidget::notifyUrlChanged(const QUrl &url) +{ + m_isNavigating = false; - m_page->setViewportSize(contentsSize); + updateOptions(url); - if (rectangle.isValid()) - { - painter.translate(-rectangle.topLeft()); + emit urlChanged(url); + emit arbitraryActionsStateChanged({ActionsManager::InspectPageAction, ActionsManager::InspectElementAction}); + emit categorizedActionsStateChanged({ActionsManager::ActionDefinition::NavigationCategory, ActionsManager::ActionDefinition::PageCategory}); - m_page->mainFrame()->render(&painter, {rectangle}); - } - else - { - m_page->mainFrame()->render(&painter); - } + SessionsManager::markSessionAsModified(); +} - m_page->setViewportSize(viewportSize); +void QtWebKitWebWidget::notifyIconChanged() +{ + emit iconChanged(getIcon()); +} - const QStringList filters({tr("PNG image (*.png)"), tr("JPEG image (*.jpg *.jpeg)")}); - const SaveInformation result(Utils::getSavePath(suggestSaveFileName(QLatin1String(".png")), {}, filters)); +void QtWebKitWebWidget::notifyPermissionRequested(QWebFrame *frame, QWebPage::Feature nativeFeature, bool cancel) +{ + FeaturePermission feature(UnknownFeature); - if (result.canSave) - { - pixmap.save(result.path, ((filters.indexOf(result.filter) == 0) ? "PNG" : "JPEG")); - } - } + switch (nativeFeature) + { + case QWebPage::Geolocation: + feature = GeolocationFeature; break; - case ActionsManager::ActivateContentAction: - { - m_webView->setFocus(); + case QWebPage::Notifications: + feature = NotificationsFeature; - m_page->mainFrame()->setFocus(); + break; + default: + return; + } - const QString tagName(m_page->mainFrame()->findFirstElement(QLatin1String(":focus")).tagName().toLower()); + const QUrl url(frame->url().isValid() ? frame->url() : frame->requestedUrl()); - if (tagName == QLatin1String("textarea") || tagName == QLatin1String("input")) - { - m_page->mainFrame()->documentElement().evaluateJavaScript(QLatin1String("document.activeElement.blur()")); - } - } + if (cancel) + { + emit requestedPermission(feature, url, true); + } + else + { + switch (getPermission(feature, url)) + { + case GrantedPermission: + m_page->setFeaturePermission(frame, nativeFeature, QWebPage::PermissionGrantedByUser); - break; - case ActionsManager::LoadPluginsAction: - { - m_canLoadPlugins = true; + break; + case DeniedPermission: + m_page->setFeaturePermission(frame, nativeFeature, QWebPage::PermissionDeniedByUser); - QList frames({m_page->mainFrame()}); + break; + default: + emit requestedPermission(feature, url, false); - while (!frames.isEmpty()) - { - const QWebFrame *frame(frames.takeFirst()); - const QWebElementCollection elements(frame->documentElement().findAll(QLatin1String("object, embed"))); + break; + } + } +} - for (int i = 0; i < elements.count(); ++i) - { - elements.at(i).replace(elements.at(i).clone()); - } +void QtWebKitWebWidget::notifySavePasswordRequested(const PasswordsManager::PasswordInformation &password, bool isUpdate) +{ + emit requestedSavePassword(password, isUpdate); +} - frames.append(frame->childFrames()); - } +void QtWebKitWebWidget::updateAmountOfDeferredPlugins() +{ + const int amountOfDeferredPlugins(m_canLoadPlugins ? 0 : findChildren().count()); - m_amountOfDeferredPlugins = 0; + if (amountOfDeferredPlugins != m_amountOfDeferredPlugins) + { + const bool needsActionUpdate(amountOfDeferredPlugins == 0 || m_amountOfDeferredPlugins == 0); - emit arbitraryActionsStateChanged({ActionsManager::LoadPluginsAction}); - } + m_amountOfDeferredPlugins = amountOfDeferredPlugins; - break; - case ActionsManager::ViewSourceAction: - if (canViewSource()) - { - const QString defaultEncoding(m_page->settings()->defaultTextEncoding()); - QNetworkRequest request(getUrl()); - request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); + if (needsActionUpdate) + { + emit arbitraryActionsStateChanged({ActionsManager::LoadPluginsAction}); + } + } +} - QNetworkReply *reply(m_networkManager->get(request)); - SourceViewerWebWidget *sourceViewer(new SourceViewerWebWidget(isPrivate())); - sourceViewer->setRequestedUrl(QUrl(QLatin1String("view-source:") + getUrl().toString()), false); +void QtWebKitWebWidget::updateOptions(const QUrl &url) +{ + const QString encoding(getOption(SettingsManager::Content_DefaultCharacterEncodingOption, url).toString()); + const bool arePluginsEnabled(getOption(SettingsManager::Permissions_EnablePluginsOption, url).toString() != QLatin1String("disabled")); + QWebSettings *settings(m_page->settings()); + settings->setAttribute(QWebSettings::AutoLoadImages, (getOption(SettingsManager::Permissions_EnableImagesOption, url).toString() != QLatin1String("onlyCached"))); + settings->setAttribute(QWebSettings::DnsPrefetchEnabled, getOption(SettingsManager::Network_EnableDnsPrefetchOption, url).toBool()); + settings->setAttribute(QWebSettings::PluginsEnabled, arePluginsEnabled); + settings->setAttribute(QWebSettings::JavaEnabled, arePluginsEnabled); + settings->setAttribute(QWebSettings::JavascriptEnabled, (m_page->isDisplayingErrorPage() || m_page->isViewingMedia() || getOption(SettingsManager::Permissions_EnableJavaScriptOption, url).toBool())); + settings->setAttribute(QWebSettings::JavascriptCanAccessClipboard, getOption(SettingsManager::Permissions_ScriptsCanAccessClipboardOption, url).toBool()); + settings->setAttribute(QWebSettings::JavascriptCanOpenWindows, (getOption(SettingsManager::Permissions_ScriptsCanOpenWindowsOption, url).toString() != QLatin1String("blockAll"))); + settings->setAttribute(QWebSettings::WebGLEnabled, getOption(SettingsManager::Permissions_EnableWebglOption, url).toBool()); + settings->setAttribute(QWebSettings::LocalStorageEnabled, getOption(SettingsManager::Permissions_EnableLocalStorageOption, url).toBool()); + settings->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, getOption(SettingsManager::Permissions_EnableOfflineStorageDatabaseOption, url).toBool()); + settings->setAttribute(QWebSettings::OfflineWebApplicationCacheEnabled, getOption(SettingsManager::Permissions_EnableOfflineWebApplicationCacheOption, url).toBool()); + settings->setAttribute(QWebSettings::AllowRunningInsecureContent, getOption(SettingsManager::Security_AllowMixedContentOption, url).toBool()); + settings->setAttribute(QWebSettings::MediaEnabled, getOption(QtWebKitWebBackend::getOptionIdentifier(QtWebKitWebBackend::QtWebKitBackend_EnableMediaOption), url).toBool()); + settings->setAttribute(QWebSettings::MediaSourceEnabled, getOption(QtWebKitWebBackend::getOptionIdentifier(QtWebKitWebBackend::QtWebKitBackend_EnableMediaSourceOption), url).toBool()); + settings->setAttribute(QWebSettings::WebSecurityEnabled, getOption(QtWebKitWebBackend::getOptionIdentifier(QtWebKitWebBackend::QtWebKitBackend_EnableWebSecurityOption), url).toBool()); + settings->setDefaultTextEncoding((encoding == QLatin1String("auto")) ? QString() : encoding); - if (!defaultEncoding.isEmpty()) - { - sourceViewer->setOption(SettingsManager::Content_DefaultCharacterEncodingOption, defaultEncoding); - } + disconnect(m_page, &QtWebKitPage::geometryChangeRequested, this, &QtWebKitWebWidget::requestedGeometryChange); + disconnect(m_page, &QtWebKitPage::statusBarMessage, this, &QtWebKitWebWidget::setStatusMessage); - m_viewSourceReplies[reply] = sourceViewer; + if (getOption(SettingsManager::Permissions_ScriptsCanChangeWindowGeometryOption, url).toBool()) + { + connect(m_page, &QtWebKitPage::geometryChangeRequested, this, &QtWebKitWebWidget::requestedGeometryChange); + } - connect(reply, &QNetworkReply::finished, this, &QtWebKitWebWidget::handleViewSourceReplyFinished); + if (getOption(SettingsManager::Permissions_ScriptsCanShowStatusMessagesOption, url).toBool()) + { + connect(m_page, &QtWebKitPage::statusBarMessage, this, &QtWebKitWebWidget::setStatusMessage); + } + else + { + setStatusMessage({}); + } - emit requestedNewWindow(sourceViewer, SessionsManager::DefaultOpen, {}); - } + m_page->updateStyleSheets(url); - break; - case ActionsManager::InspectPageAction: - { - const bool showInspector(parameters.value(QLatin1String("isChecked"), !getActionState(identifier, parameters).isChecked).toBool()); + m_networkManager->updateOptions(url); - if (showInspector && !m_inspectorWidget) - { - getInspector(); - } + m_canLoadPlugins = (getOption(SettingsManager::Permissions_EnablePluginsOption, url).toString() == QLatin1String("enabled")); +} - emit requestedInspectorVisibilityChange(showInspector); - emit arbitraryActionsStateChanged({ActionsManager::InspectPageAction}); - } +void QtWebKitWebWidget::clearOptions() +{ + WebWidget::clearOptions(); - break; - case ActionsManager::InspectElementAction: - triggerAction(ActionsManager::InspectPageAction, {{QLatin1String("isChecked"), true}}, trigger); + updateOptions(getUrl()); +} - m_page->triggerAction(QWebPage::InspectElement); +void QtWebKitWebWidget::fillPassword(const PasswordsManager::PasswordInformation &password) +{ + QFile file(QLatin1String(":/modules/backends/web/qtwebkit/resources/formFiller.js")); - break; - case ActionsManager::FullScreenAction: - { - const MainWindow *mainWindow(MainWindow::findMainWindow(this)); + if (!file.open(QIODevice::ReadOnly)) + { + return; + } - if (mainWindow && !mainWindow->isFullScreen()) - { - m_page->mainFrame()->evaluateJavaScript(QLatin1String("document.webkitExitFullscreen()")); - } - } + QJsonArray fieldsArray; - break; - case ActionsManager::WebsitePreferencesAction: - { - const QUrl url(getUrl()); - CookieJar *cookieJar(m_networkManager->getCookieJar()); - WebsitePreferencesDialog dialog(Utils::extractHost(url), (url.host().isEmpty() ? QVector() : cookieJar->getCookies(url.host())), this); + for (int i = 0; i < password.fields.count(); ++i) + { + fieldsArray.append(QJsonObject({{QLatin1String("name"), password.fields.at(i).name}, {QLatin1String("value"), password.fields.at(i).value}, {QLatin1String("type"), ((password.fields.at(i).type == PasswordsManager::PasswordField) ? QLatin1String("password") : QLatin1String("text"))}})); + } - if (dialog.exec() == QDialog::Accepted) - { - updateOptions(url); + const QString script(QString::fromLatin1(file.readAll()).arg(QString::fromLatin1(QJsonDocument(fieldsArray).toJson(QJsonDocument::Indented)))); - const QVector cookiesToDelete(dialog.getCookiesToDelete()); - const QVector cookiesToInsert(dialog.getCookiesToInsert()); + file.close(); - for (int i = 0; i < cookiesToDelete.count(); ++i) - { - cookieJar->forceDeleteCookie(cookiesToDelete.at(i)); - } + QList frames({m_page->mainFrame()}); - for (int i = 0; i < cookiesToInsert.count(); ++i) - { - cookieJar->forceInsertCookie(cookiesToInsert.at(i)); - } - } - } + while (!frames.isEmpty()) + { + const QWebFrame *frame(frames.takeFirst()); + frame->documentElement().evaluateJavaScript(script); - break; - default: - break; + frames.append(frame->childFrames()); } } @@ -2558,29 +2581,6 @@ int QtWebKitWebWidget::getAmountOfDeferredPlugins() const return m_amountOfDeferredPlugins; } -int QtWebKitWebWidget::findInPage(const QString &text, FindFlags flags) -{ - QWebPage::FindFlags nativeFlags(QWebPage::FindWrapsAroundDocument | QWebPage::FindBeginsInSelection); - - if (flags.testFlag(BackwardFind)) - { - nativeFlags |= QWebPage::FindBackward; - } - - if (flags.testFlag(CaseSensitiveFind)) - { - nativeFlags |= QWebPage::FindCaseSensitively; - } - - if (flags.testFlag(HighlightAllFind) || text.isEmpty()) - { - m_page->findText({}, QWebPage::HighlightAllOccurrences); - m_page->findText(text, (nativeFlags | QWebPage::HighlightAllOccurrences)); - } - - return (m_page->findText(text, nativeFlags) ? -1 : 0); -} - bool QtWebKitWebWidget::canLoadPlugins() const { return m_canLoadPlugins; diff --git a/src/modules/backends/web/qtwebkit/QtWebKitWebWidget.h b/src/modules/backends/web/qtwebkit/QtWebKitWebWidget.h index aa33575987..54e27bbd0e 100644 --- a/src/modules/backends/web/qtwebkit/QtWebKitWebWidget.h +++ b/src/modules/backends/web/qtwebkit/QtWebKitWebWidget.h @@ -88,7 +88,6 @@ class QtWebKitWebWidget final : public WebWidget ContentStates getContentState() const override; LoadingState getLoadingState() const override; int getZoom() const override; - int findInPage(const QString &text, FindFlags flags = NoFlagsFind) override; bool hasSelection() const override; bool hasWatchedChanges(ChangeWatcher watcher) const override; bool isAudible() const override; @@ -99,6 +98,7 @@ class QtWebKitWebWidget final : public WebWidget public slots: void clearOptions() override; + void findInPage(const QString &text, FindFlags flags = NoFlagsFind) override; void fillPassword(const PasswordsManager::PasswordInformation &password) override; void triggerAction(int identifier, const QVariantMap ¶meters = {}, ActionsManager::TriggerType trigger = ActionsManager::UnknownTrigger) override; void setActiveStyleSheet(const QString &styleSheet) override; diff --git a/src/modules/windows/web/WebContentsWidget.cpp b/src/modules/windows/web/WebContentsWidget.cpp index 7c9675c9f8..a4c37a59f2 100644 --- a/src/modules/windows/web/WebContentsWidget.cpp +++ b/src/modules/windows/web/WebContentsWidget.cpp @@ -686,17 +686,12 @@ void WebContentsWidget::findInPage(WebWidget::FindFlags flags) m_quickFindQuery = (m_searchBarWidget ? m_searchBarWidget->getQuery() : m_sharedQuickFindQuery); - const int matchesAmount(m_webWidget->findInPage(m_quickFindQuery, flags)); + m_webWidget->findInPage(m_quickFindQuery, flags); if (!m_quickFindQuery.isEmpty() && !isPrivate() && SettingsManager::getOption(SettingsManager::Search_ReuseLastQuickFindQueryOption).toBool()) { m_sharedQuickFindQuery = m_quickFindQuery; } - - if (m_searchBarWidget) - { - m_searchBarWidget->setMatchesAmount(matchesAmount); - } } void WebContentsWidget::addInformationBar(QWidget *widget) diff --git a/src/ui/SourceViewerWebWidget.cpp b/src/ui/SourceViewerWebWidget.cpp index 7a933177b1..6b5e8eb4f0 100644 --- a/src/ui/SourceViewerWebWidget.cpp +++ b/src/ui/SourceViewerWebWidget.cpp @@ -257,6 +257,11 @@ void SourceViewerWebWidget::triggerAction(int identifier, const QVariantMap &par } } +void SourceViewerWebWidget::findInPage(const QString &text, WebWidget::FindFlags flags) +{ + m_sourceViewer->findText(text, flags); +} + void SourceViewerWebWidget::print(QPrinter *printer) { m_sourceViewer->print(printer); @@ -522,11 +527,6 @@ int SourceViewerWebWidget::getZoom() const return m_sourceViewer->getZoom(); } -int SourceViewerWebWidget::findInPage(const QString &text, WebWidget::FindFlags flags) -{ - return m_sourceViewer->findText(text, flags); -} - bool SourceViewerWebWidget::canRedo() const { return m_sourceViewer->document()->isRedoAvailable(); diff --git a/src/ui/SourceViewerWebWidget.h b/src/ui/SourceViewerWebWidget.h index 51039b5e9c..8ee3417543 100644 --- a/src/ui/SourceViewerWebWidget.h +++ b/src/ui/SourceViewerWebWidget.h @@ -49,7 +49,6 @@ class SourceViewerWebWidget final : public WebWidget HitTestResult getHitTestResult(const QPoint &position) override; WebWidget::LoadingState getLoadingState() const override; int getZoom() const override; - int findInPage(const QString &text, FindFlags flags = NoFlagsFind) override; bool canRedo() const override; bool canUndo() const override; bool hasSelection() const override; @@ -57,6 +56,7 @@ class SourceViewerWebWidget final : public WebWidget public slots: void triggerAction(int identifier, const QVariantMap ¶meters = {}, ActionsManager::TriggerType trigger = ActionsManager::UnknownTrigger) override; + void findInPage(const QString &text, FindFlags flags = NoFlagsFind) override; void setOption(int identifier, const QVariant &value) override; void setScrollPosition(const QPoint &position) override; void setHistory(const Session::Window::History &history) override; diff --git a/src/ui/WebWidget.h b/src/ui/WebWidget.h index 974787cf78..83c940a451 100644 --- a/src/ui/WebWidget.h +++ b/src/ui/WebWidget.h @@ -244,7 +244,6 @@ class WebWidget : public QWidget, public ActionExecutor virtual WebWidget::LoadingState getLoadingState() const = 0; quint64 getWindowIdentifier() const; virtual int getZoom() const = 0; - virtual int findInPage(const QString &text, FindFlags flags = NoFlagsFind) = 0; bool hasOption(int identifier) const; virtual bool hasSelection() const; virtual bool hasWatchedChanges(ChangeWatcher watcher) const; @@ -258,6 +257,7 @@ public slots: void triggerAction(int identifier, const QVariantMap ¶meters = {}, ActionsManager::TriggerType trigger = ActionsManager::UnknownTrigger) override; virtual void clearOptions(); virtual void fillPassword(const PasswordsManager::PasswordInformation &password); + virtual void findInPage(const QString &text, FindFlags flags = NoFlagsFind) = 0; virtual void showContextMenu(const QPoint &position = {}); virtual void setActiveStyleSheet(const QString &styleSheet); virtual void setPermission(FeaturePermission feature, const QUrl &url, PermissionPolicies policies); @@ -338,6 +338,7 @@ protected slots: void requestedGeometryChange(const QRect &geometry); void requestedInspectorVisibilityChange(bool isVisible); void geometryChanged(); + void findInPageResultsChanged(const QString &text, int matchesAmount, int activeResult); void statusMessageChanged(const QString &message); void titleChanged(const QString &title); void urlChanged(const QUrl &url); From 12bd52374df79b85254e7d5f4fe45acd9a74617b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Fri, 13 Dec 2019 18:00:48 +0100 Subject: [PATCH 55/71] Initial update to new API --- src/modules/windows/web/SearchBarWidget.cpp | 36 ++++++++++--------- src/modules/windows/web/SearchBarWidget.h | 4 +-- src/modules/windows/web/WebContentsWidget.cpp | 1 + 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/modules/windows/web/SearchBarWidget.cpp b/src/modules/windows/web/SearchBarWidget.cpp index 025ca2fb99..2367aceafa 100644 --- a/src/modules/windows/web/SearchBarWidget.cpp +++ b/src/modules/windows/web/SearchBarWidget.cpp @@ -1,6 +1,6 @@ /************************************************************************** * Otter Browser: Web browser controlled by the user, not vice-versa. -* Copyright (C) 2013 - 2018 Michal Dutkiewicz aka Emdek +* Copyright (C) 2013 - 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 @@ -104,27 +104,14 @@ void SearchBarWidget::selectAll() m_ui->queryLineEditWidget->selectAll(); } -void SearchBarWidget::setQuery(const QString &query) -{ - m_ui->queryLineEditWidget->setText(query); -} - -void SearchBarWidget::setVisible(bool visible) +void SearchBarWidget::updateResults(const QString &query, int matchesAmount, int activeResult) { - QWidget::setVisible(visible); + Q_UNUSED(activeResult) - if (!visible && parentWidget()) - { - parentWidget()->setFocus(); - } -} - -void SearchBarWidget::setMatchesAmount(int matchesAmount) -{ QPalette palette(this->palette()); const bool hasMatches(matchesAmount != 0); - if (!m_ui->queryLineEditWidget->text().isEmpty()) + if (m_ui->queryLineEditWidget->text() == query) { //TODO Ensure that text is readable if (hasMatches) @@ -142,6 +129,21 @@ void SearchBarWidget::setMatchesAmount(int matchesAmount) m_ui->previousButton->setEnabled(hasMatches); } +void SearchBarWidget::setQuery(const QString &query) +{ + m_ui->queryLineEditWidget->setText(query); +} + +void SearchBarWidget::setVisible(bool visible) +{ + QWidget::setVisible(visible); + + if (!visible && parentWidget()) + { + parentWidget()->setFocus(); + } +} + QString SearchBarWidget::getQuery() const { return m_ui->queryLineEditWidget->text(); diff --git a/src/modules/windows/web/SearchBarWidget.h b/src/modules/windows/web/SearchBarWidget.h index 73e046bc65..86a03f50fe 100644 --- a/src/modules/windows/web/SearchBarWidget.h +++ b/src/modules/windows/web/SearchBarWidget.h @@ -1,6 +1,6 @@ /************************************************************************** * Otter Browser: Web browser controlled by the user, not vice-versa. -* Copyright (C) 2013 - 2018 Michal Dutkiewicz aka Emdek +* Copyright (C) 2013 - 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 @@ -45,7 +45,7 @@ class SearchBarWidget final : public QWidget WebWidget::FindFlags getFlags() const; public slots: - void setMatchesAmount(int matchesAmount); + void updateResults(const QString &query, int matchesAmount, int activeResult); protected: void changeEvent(QEvent *event) override; diff --git a/src/modules/windows/web/WebContentsWidget.cpp b/src/modules/windows/web/WebContentsWidget.cpp index a4c37a59f2..d4a57840bd 100644 --- a/src/modules/windows/web/WebContentsWidget.cpp +++ b/src/modules/windows/web/WebContentsWidget.cpp @@ -475,6 +475,7 @@ void WebContentsWidget::triggerAction(int identifier, const QVariantMap ¶met connect(m_searchBarWidget, &SearchBarWidget::requestedSearch, this, &WebContentsWidget::findInPage); connect(m_searchBarWidget, &SearchBarWidget::flagsChanged, this, &WebContentsWidget::updateFindHighlight); + connect(m_webWidget, &WebWidget::findInPageResultsChanged, m_searchBarWidget, &SearchBarWidget::updateResults); if (SettingsManager::getOption(SettingsManager::Search_EnableFindInPageAsYouTypeOption).toBool()) { From 10516a6f5baeb41788f477037903df19533d58aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Fri, 13 Dec 2019 18:03:36 +0100 Subject: [PATCH 56/71] [QtWebKit] Emit findInPageResultsChanged() --- src/modules/backends/web/qtwebkit/QtWebKitWebWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/backends/web/qtwebkit/QtWebKitWebWidget.cpp b/src/modules/backends/web/qtwebkit/QtWebKitWebWidget.cpp index e153dfaed9..4cf93bdd0c 100644 --- a/src/modules/backends/web/qtwebkit/QtWebKitWebWidget.cpp +++ b/src/modules/backends/web/qtwebkit/QtWebKitWebWidget.cpp @@ -1135,7 +1135,7 @@ void QtWebKitWebWidget::findInPage(const QString &text, FindFlags flags) m_page->findText(text, (nativeFlags | QWebPage::HighlightAllOccurrences)); } - m_page->findText(text, nativeFlags); + emit findInPageResultsChanged(text, (m_page->findText(text, nativeFlags) ? -1 : 0), -1); } void QtWebKitWebWidget::search(const QString &query, const QString &searchEngine) From fd90a18529e77c5b1b5b154452209fbd9d2de736 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Fri, 13 Dec 2019 19:30:38 +0100 Subject: [PATCH 57/71] [QtWebEngine] Emit findInPageResultsChanged() --- .../web/qtwebengine/QtWebEngineWebWidget.cpp | 13 +++++++++++++ .../backends/web/qtwebengine/QtWebEngineWebWidget.h | 3 +++ 2 files changed, 16 insertions(+) diff --git a/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp b/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp index 7d99ffbfb9..3793d325bf 100644 --- a/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp +++ b/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp @@ -54,6 +54,9 @@ #include #include #include +#if QTWEBENGINECORE_VERSION >= 0x050E00 +#include +#endif #include #include #include @@ -112,6 +115,12 @@ QtWebEngineWebWidget::QtWebEngineWebWidget(const QVariantMap ¶meters, WebBac { notifyPermissionRequested(url, feature, true); }); +#if QTWEBENGINECORE_VERSION >= 0x050E00 + connect(m_page, &QtWebEnginePage::findTextFinished, [&](const QWebEngineFindTextResult &result) + { + emit findInPageResultsChanged(m_findInPageText, result.numberOfMatches(), result.activeMatch()); + }); +#endif connect(m_page, &QtWebEnginePage::recentlyAudibleChanged, this, &QtWebEngineWebWidget::isAudibleChanged); connect(m_page, &QtWebEnginePage::viewingMediaChanged, this, &QtWebEngineWebWidget::notifyNavigationActionsChanged); connect(m_page, &QtWebEnginePage::titleChanged, this, &QtWebEngineWebWidget::notifyTitleChanged); @@ -844,6 +853,10 @@ void QtWebEngineWebWidget::clearOptions() void QtWebEngineWebWidget::findInPage(const QString &text, FindFlags flags) { +#if QTWEBENGINECORE_VERSION >= 0x050E00 + m_findInPageText = text; +#endif + if (text.isEmpty()) { m_page->findText(text); diff --git a/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.h b/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.h index 5e37ab7750..8ce6322398 100644 --- a/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.h +++ b/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.h @@ -166,6 +166,9 @@ protected slots: QtWebEnginePage *m_page; #if QTWEBENGINECORE_VERSION >= 0x050D00 QtWebEngineUrlRequestInterceptor *m_requestInterceptor; +#endif +#if QTWEBENGINECORE_VERSION >= 0x050E00 + QString m_findInPageText; #endif QDateTime m_lastUrlClickTime; QPixmap m_thumbnail; From c2381864535e66211895c51240ff46662227382e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Fri, 13 Dec 2019 19:41:54 +0100 Subject: [PATCH 58/71] Emit findInPageResultsChanged() for Source Viewer --- src/ui/SourceViewerWebWidget.cpp | 1 + src/ui/SourceViewerWidget.cpp | 150 +++++++++++++++---------------- src/ui/SourceViewerWidget.h | 4 +- 3 files changed, 78 insertions(+), 77 deletions(-) diff --git a/src/ui/SourceViewerWebWidget.cpp b/src/ui/SourceViewerWebWidget.cpp index 6b5e8eb4f0..e60ae34e2a 100644 --- a/src/ui/SourceViewerWebWidget.cpp +++ b/src/ui/SourceViewerWebWidget.cpp @@ -55,6 +55,7 @@ SourceViewerWebWidget::SourceViewerWebWidget(bool isPrivate, ContentsWidget *par setContextMenuPolicy(Qt::CustomContextMenu); connect(this, &SourceViewerWebWidget::customContextMenuRequested, this, &SourceViewerWebWidget::showContextMenu); + connect(m_sourceViewer, &SourceViewerWidget::findTextResultsChanged, this, &SourceViewerWebWidget::findInPageResultsChanged); connect(m_sourceViewer, &SourceViewerWidget::zoomChanged, this, &SourceViewerWebWidget::zoomChanged); connect(m_sourceViewer, &SourceViewerWidget::zoomChanged, this, &SourceViewerWebWidget::handleZoomChanged); connect(m_sourceViewer, &SourceViewerWidget::redoAvailable, this, &SourceViewerWebWidget::notifyRedoActionStateChanged); diff --git a/src/ui/SourceViewerWidget.cpp b/src/ui/SourceViewerWidget.cpp index 4ca96cbb7f..7e49e00bbc 100644 --- a/src/ui/SourceViewerWidget.cpp +++ b/src/ui/SourceViewerWidget.cpp @@ -330,7 +330,6 @@ bool MarginWidget::event(QEvent *event) SourceViewerWidget::SourceViewerWidget(QWidget *parent) : QPlainTextEdit(parent), m_marginWidget(nullptr), m_findFlags(WebWidget::NoFlagsFind), - m_findTextResultsAmount(0), m_zoom(100) { new SyntaxHighlighter(document()); @@ -379,6 +378,72 @@ void SourceViewerWidget::wheelEvent(QWheelEvent *event) QPlainTextEdit::wheelEvent(event); } +void SourceViewerWidget::findText(const QString &text, WebWidget::FindFlags flags) +{ + const bool isTheSame(text == m_findText); + + m_findText = text; + m_findFlags = flags; + + if (!text.isEmpty()) + { + QTextDocument::FindFlags nativeFlags; + + if (flags.testFlag(WebWidget::BackwardFind)) + { + nativeFlags |= QTextDocument::FindBackward; + } + + if (flags.testFlag(WebWidget::CaseSensitiveFind)) + { + nativeFlags |= QTextDocument::FindCaseSensitively; + } + + QTextCursor findTextCursor(m_findTextAnchor); + + if (!isTheSame) + { + findTextCursor = textCursor(); + } + else if (!flags.testFlag(WebWidget::BackwardFind)) + { + findTextCursor.setPosition(findTextCursor.selectionEnd(), QTextCursor::MoveAnchor); + } + + m_findTextAnchor = document()->find(text, findTextCursor, nativeFlags); + + if (m_findTextAnchor.isNull()) + { + m_findTextAnchor = textCursor(); + m_findTextAnchor.setPosition((flags.testFlag(WebWidget::BackwardFind) ? (document()->characterCount() - 1) : 0), QTextCursor::MoveAnchor); + m_findTextAnchor = document()->find(text, m_findTextAnchor, nativeFlags); + } + + if (!m_findTextAnchor.isNull()) + { + const QTextCursor currentTextCursor(textCursor()); + + disconnect(this, &SourceViewerWidget::cursorPositionChanged, this, &SourceViewerWidget::updateTextCursor); + + setTextCursor(m_findTextAnchor); + ensureCursorVisible(); + + const QPoint position(horizontalScrollBar()->value(), verticalScrollBar()->value()); + + setTextCursor(currentTextCursor); + + horizontalScrollBar()->setValue(position.x()); + verticalScrollBar()->setValue(position.y()); + + connect(this, &SourceViewerWidget::cursorPositionChanged, this, &SourceViewerWidget::updateTextCursor); + } + } + + m_findTextSelection = m_findTextAnchor; + + updateSelection(); +} + void SourceViewerWidget::handleOptionChanged(int identifier, const QVariant &value) { switch (identifier) @@ -424,14 +489,13 @@ void SourceViewerWidget::updateSelection() if (m_findText.isEmpty()) { - m_findTextResultsAmount = 0; - setExtraSelections(extraSelections); return; } - int findTextResultsAmount(0); + int findTextMatchesAmount(0); + int findTextActiveResult(0); QTextEdit::ExtraSelection currentResultSelection; currentResultSelection.format.setBackground(QColor(255, 150, 50)); currentResultSelection.format.setProperty(QTextFormat::FullWidthSelection, true); @@ -457,7 +521,11 @@ void SourceViewerWidget::updateSelection() if (!textCursor.isNull()) { - if (textCursor != m_findTextSelection) + if (textCursor == m_findTextSelection) + { + findTextActiveResult = findTextMatchesAmount; + } + else { QTextEdit::ExtraSelection extraResultSelection; extraResultSelection.format.setBackground(QColor(255, 255, 0)); @@ -466,12 +534,12 @@ void SourceViewerWidget::updateSelection() extraSelections.append(extraResultSelection); } - ++findTextResultsAmount; + ++findTextMatchesAmount; } } } - m_findTextResultsAmount = findTextResultsAmount; + emit findTextResultsChanged(m_findText, findTextMatchesAmount, findTextActiveResult); setExtraSelections(extraSelections); } @@ -501,72 +569,4 @@ int SourceViewerWidget::getZoom() const return m_zoom; } -int SourceViewerWidget::findText(const QString &text, WebWidget::FindFlags flags) -{ - const bool isTheSame(text == m_findText); - - m_findText = text; - m_findFlags = flags; - - if (!text.isEmpty()) - { - QTextDocument::FindFlags nativeFlags; - - if (flags.testFlag(WebWidget::BackwardFind)) - { - nativeFlags |= QTextDocument::FindBackward; - } - - if (flags.testFlag(WebWidget::CaseSensitiveFind)) - { - nativeFlags |= QTextDocument::FindCaseSensitively; - } - - QTextCursor findTextCursor(m_findTextAnchor); - - if (!isTheSame) - { - findTextCursor = textCursor(); - } - else if (!flags.testFlag(WebWidget::BackwardFind)) - { - findTextCursor.setPosition(findTextCursor.selectionEnd(), QTextCursor::MoveAnchor); - } - - m_findTextAnchor = document()->find(text, findTextCursor, nativeFlags); - - if (m_findTextAnchor.isNull()) - { - m_findTextAnchor = textCursor(); - m_findTextAnchor.setPosition((flags.testFlag(WebWidget::BackwardFind) ? (document()->characterCount() - 1) : 0), QTextCursor::MoveAnchor); - m_findTextAnchor = document()->find(text, m_findTextAnchor, nativeFlags); - } - - if (!m_findTextAnchor.isNull()) - { - const QTextCursor currentTextCursor(textCursor()); - - disconnect(this, &SourceViewerWidget::cursorPositionChanged, this, &SourceViewerWidget::updateTextCursor); - - setTextCursor(m_findTextAnchor); - ensureCursorVisible(); - - const QPoint position(horizontalScrollBar()->value(), verticalScrollBar()->value()); - - setTextCursor(currentTextCursor); - - horizontalScrollBar()->setValue(position.x()); - verticalScrollBar()->setValue(position.y()); - - connect(this, &SourceViewerWidget::cursorPositionChanged, this, &SourceViewerWidget::updateTextCursor); - } - } - - m_findTextSelection = m_findTextAnchor; - - updateSelection(); - - return m_findTextResultsAmount; -} - } diff --git a/src/ui/SourceViewerWidget.h b/src/ui/SourceViewerWidget.h index ab5f541905..9d20824049 100644 --- a/src/ui/SourceViewerWidget.h +++ b/src/ui/SourceViewerWidget.h @@ -104,9 +104,9 @@ class SourceViewerWidget final : public QPlainTextEdit public: explicit SourceViewerWidget(QWidget *parent = nullptr); + void findText(const QString &text, WebWidget::FindFlags flags = WebWidget::NoFlagsFind); void setZoom(int zoom); int getZoom() const; - int findText(const QString &text, WebWidget::FindFlags flags = WebWidget::NoFlagsFind); protected: void resizeEvent(QResizeEvent *event) override; @@ -124,10 +124,10 @@ protected slots: QTextCursor m_findTextAnchor; QTextCursor m_findTextSelection; WebWidget::FindFlags m_findFlags; - int m_findTextResultsAmount; int m_zoom; signals: + void findTextResultsChanged(const QString &text, int matchesAmount, int activeResult); void zoomChanged(int zoom); friend class MarginWidget; From 5a8f33a5c2a1596d2b5139c9b55a53fff058e6e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Fri, 13 Dec 2019 19:56:24 +0100 Subject: [PATCH 59/71] Start from 1 --- src/ui/SourceViewerWidget.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/SourceViewerWidget.cpp b/src/ui/SourceViewerWidget.cpp index 7e49e00bbc..46fe46582f 100644 --- a/src/ui/SourceViewerWidget.cpp +++ b/src/ui/SourceViewerWidget.cpp @@ -495,7 +495,7 @@ void SourceViewerWidget::updateSelection() } int findTextMatchesAmount(0); - int findTextActiveResult(0); + int findTextActiveResult(1); QTextEdit::ExtraSelection currentResultSelection; currentResultSelection.format.setBackground(QColor(255, 150, 50)); currentResultSelection.format.setProperty(QTextFormat::FullWidthSelection, true); @@ -523,7 +523,7 @@ void SourceViewerWidget::updateSelection() { if (textCursor == m_findTextSelection) { - findTextActiveResult = findTextMatchesAmount; + findTextActiveResult = (findTextMatchesAmount + 1); } else { From 0536a5314a803a68da4bc4f3040dba85cdb173a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Fri, 13 Dec 2019 20:49:23 +0100 Subject: [PATCH 60/71] Show results amount if available --- src/modules/windows/web/SearchBarWidget.cpp | 15 ++++++++++++--- src/modules/windows/web/SearchBarWidget.ui | 3 +++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/modules/windows/web/SearchBarWidget.cpp b/src/modules/windows/web/SearchBarWidget.cpp index 2367aceafa..e71d8f040f 100644 --- a/src/modules/windows/web/SearchBarWidget.cpp +++ b/src/modules/windows/web/SearchBarWidget.cpp @@ -106,12 +106,11 @@ void SearchBarWidget::selectAll() void SearchBarWidget::updateResults(const QString &query, int matchesAmount, int activeResult) { - Q_UNUSED(activeResult) - + QString resultsText; QPalette palette(this->palette()); const bool hasMatches(matchesAmount != 0); - if (m_ui->queryLineEditWidget->text() == query) + if (!query.isEmpty() && m_ui->queryLineEditWidget->text() == query) { //TODO Ensure that text is readable if (hasMatches) @@ -122,8 +121,18 @@ void SearchBarWidget::updateResults(const QString &query, int matchesAmount, int { palette.setColor(QPalette::Base, QColor(0xF1, 0xE7, 0xE4)); } + + if (matchesAmount > 0 && activeResult > 0) + { + resultsText = tr("%1 of %n result(s)", "", matchesAmount).arg(activeResult); + } + else if (matchesAmount == 0) + { + resultsText = tr("Phrase not found"); + } } + m_ui->resultsLabel->setText(resultsText); m_ui->queryLineEditWidget->setPalette(palette); m_ui->nextButton->setEnabled(hasMatches); m_ui->previousButton->setEnabled(hasMatches); diff --git a/src/modules/windows/web/SearchBarWidget.ui b/src/modules/windows/web/SearchBarWidget.ui index 16336ee60a..8505f5ddd3 100644 --- a/src/modules/windows/web/SearchBarWidget.ui +++ b/src/modules/windows/web/SearchBarWidget.ui @@ -56,6 +56,9 @@ + + + From 8ba8c861b79e4fefaaccf81e49c486b958c4c68b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Sat, 14 Dec 2019 18:30:54 +0100 Subject: [PATCH 61/71] Set active match to 0 for no matches --- src/modules/backends/web/qtwebkit/QtWebKitWebWidget.cpp | 4 +++- src/ui/SourceViewerWidget.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/modules/backends/web/qtwebkit/QtWebKitWebWidget.cpp b/src/modules/backends/web/qtwebkit/QtWebKitWebWidget.cpp index 4cf93bdd0c..9c747b99e8 100644 --- a/src/modules/backends/web/qtwebkit/QtWebKitWebWidget.cpp +++ b/src/modules/backends/web/qtwebkit/QtWebKitWebWidget.cpp @@ -1135,7 +1135,9 @@ void QtWebKitWebWidget::findInPage(const QString &text, FindFlags flags) m_page->findText(text, (nativeFlags | QWebPage::HighlightAllOccurrences)); } - emit findInPageResultsChanged(text, (m_page->findText(text, nativeFlags) ? -1 : 0), -1); + const bool hasMatches(m_page->findText(text, nativeFlags)); + + emit findInPageResultsChanged(text, (hasMatches ? -1 : 0), (hasMatches ? -1 : 0)); } void QtWebKitWebWidget::search(const QString &query, const QString &searchEngine) diff --git a/src/ui/SourceViewerWidget.cpp b/src/ui/SourceViewerWidget.cpp index 46fe46582f..47c4a4bd9d 100644 --- a/src/ui/SourceViewerWidget.cpp +++ b/src/ui/SourceViewerWidget.cpp @@ -495,7 +495,7 @@ void SourceViewerWidget::updateSelection() } int findTextMatchesAmount(0); - int findTextActiveResult(1); + int findTextActiveResult(0); QTextEdit::ExtraSelection currentResultSelection; currentResultSelection.format.setBackground(QColor(255, 150, 50)); currentResultSelection.format.setProperty(QTextFormat::FullWidthSelection, true); From f18a8f118ff35297e6a5abbf291e16c2ea36bc17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Sat, 14 Dec 2019 19:10:35 +0100 Subject: [PATCH 62/71] [QtWebEngine] Add fallback for older versions --- .../backends/web/qtwebengine/QtWebEngineWebWidget.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp b/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp index 3793d325bf..d2700b24e7 100644 --- a/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp +++ b/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp @@ -861,6 +861,10 @@ void QtWebEngineWebWidget::findInPage(const QString &text, FindFlags flags) { m_page->findText(text); +#if QTWEBENGINECORE_VERSION <= 0x050E00 + emit findInPageResultsChanged(text, 0, 0); +#endif + return; } @@ -876,7 +880,14 @@ void QtWebEngineWebWidget::findInPage(const QString &text, FindFlags flags) nativeFlags |= QWebEnginePage::FindCaseSensitively; } +#if QTWEBENGINECORE_VERSION >= 0x050E00 m_page->findText(text, nativeFlags); +#else + m_page->findText(text, nativeFlags, [&](bool hasMatches) + { + emit findInPageResultsChanged(text, (hasMatches ? -1 : 0), (hasMatches ? -1 : 0)); + }); +#endif } void QtWebEngineWebWidget::search(const QString &query, const QString &searchEngine) From 4068910ae43e9b119cc6c60c07cc6df0e97b819d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Sun, 15 Dec 2019 17:57:12 +0100 Subject: [PATCH 63/71] [QtWebEngine] Allow for exceptions for SSL errors --- .../web/qtwebengine/QtWebEnginePage.cpp | 24 +++++++++++++++++++ .../web/qtwebengine/QtWebEnginePage.h | 7 ++++++ 2 files changed, 31 insertions(+) diff --git a/src/modules/backends/web/qtwebengine/QtWebEnginePage.cpp b/src/modules/backends/web/qtwebengine/QtWebEnginePage.cpp index 623b69d00d..e7d2fdccf7 100644 --- a/src/modules/backends/web/qtwebengine/QtWebEnginePage.cpp +++ b/src/modules/backends/web/qtwebengine/QtWebEnginePage.cpp @@ -586,6 +586,30 @@ bool QtWebEnginePage::acceptNavigationRequest(const QUrl &url, NavigationType ty return true; } +#if QTWEBENGINECORE_VERSION >= 0x050E00 +bool QtWebEnginePage::certificateError(const QWebEngineCertificateError &error) +{ + if (!m_widget || error.certificateChain().isEmpty()) + { + return false; + } + + const QString firstPartyUrl(m_widget->getUrl().toString()); + const QString thirdPartyUrl(error.url().toString()); + + if (m_widget->getOption(SettingsManager::Security_IgnoreSslErrorsOption, m_widget->getUrl()).toStringList().contains(QString::fromLatin1(error.certificateChain().first().digest().toBase64()))) + { + Console::addMessage(QStringLiteral("[accepted] The page at %1 was allowed to display insecure content from %2").arg(firstPartyUrl, thirdPartyUrl), Console::SecurityCategory, Console::WarningLevel, thirdPartyUrl, -1, m_widget->getWindowIdentifier()); + + return true; + } + + Console::addMessage(QStringLiteral("[blocked] The page at %1 was not allowed to display insecure content from %2").arg(firstPartyUrl, thirdPartyUrl), Console::SecurityCategory, Console::WarningLevel, thirdPartyUrl, -1, m_widget->getWindowIdentifier()); + + return false; +} +#endif + bool QtWebEnginePage::javaScriptConfirm(const QUrl &url, const QString &message) { if (m_isIgnoringJavaScriptPopups) diff --git a/src/modules/backends/web/qtwebengine/QtWebEnginePage.h b/src/modules/backends/web/qtwebengine/QtWebEnginePage.h index 603be4c57f..2d7fc176dd 100644 --- a/src/modules/backends/web/qtwebengine/QtWebEnginePage.h +++ b/src/modules/backends/web/qtwebengine/QtWebEnginePage.h @@ -23,6 +23,10 @@ #include "../../../../core/SessionsManager.h" +#include +#if QTWEBENGINECORE_VERSION >= 0x050E00 +#include +#endif #include namespace Otter @@ -66,6 +70,9 @@ class QtWebEnginePage final : public QWebEnginePage QString createJavaScriptList(const QStringList &rules) const; QStringList chooseFiles(FileSelectionMode mode, const QStringList &oldFiles, const QStringList &acceptedMimeTypes) override; bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame) override; +#if QTWEBENGINECORE_VERSION >= 0x050E00 + bool certificateError(const QWebEngineCertificateError &error) override; +#endif bool javaScriptConfirm(const QUrl &url, const QString &message) override; bool javaScriptPrompt(const QUrl &url, const QString &message, const QString &defaultValue, QString *result) override; From d8bcd8fa4de3ad652060657e0c3b92454321849a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Sun, 15 Dec 2019 18:25:42 +0100 Subject: [PATCH 64/71] [QtWebEngine] Store SSL errors --- .../web/qtwebengine/QtWebEnginePage.cpp | 20 +++++++++++++++++++ .../web/qtwebengine/QtWebEnginePage.h | 7 +++++++ .../web/qtwebengine/QtWebEngineWebWidget.cpp | 7 +++++++ .../web/qtwebengine/QtWebEngineWebWidget.h | 3 +++ 4 files changed, 37 insertions(+) diff --git a/src/modules/backends/web/qtwebengine/QtWebEnginePage.cpp b/src/modules/backends/web/qtwebengine/QtWebEnginePage.cpp index e7d2fdccf7..930c4dc9b8 100644 --- a/src/modules/backends/web/qtwebengine/QtWebEnginePage.cpp +++ b/src/modules/backends/web/qtwebengine/QtWebEnginePage.cpp @@ -404,6 +404,13 @@ QVariant QtWebEnginePage::runScriptFile(const QString &path, const QStringList & return runScriptSource(createScriptSource(path, parameters)); } +#if QTWEBENGINECORE_VERSION >= 0x050E00 +WebWidget::SslInformation QtWebEnginePage::getSslInformation() const +{ + return m_sslInformation; +} +#endif + Session::Window::History QtWebEnginePage::getHistory() const { QWebEngineHistory *pageHistory(history()); @@ -528,6 +535,10 @@ bool QtWebEnginePage::acceptNavigationRequest(const QUrl &url, NavigationType ty } } +#if QTWEBENGINECORE_VERSION >= 0x050E00 + m_sslInformation = {}; +#endif + if (type != NavigationTypeReload) { m_previousNavigationType = type; @@ -594,6 +605,15 @@ bool QtWebEnginePage::certificateError(const QWebEngineCertificateError &error) return false; } + const QList errors(QSslCertificate::verify(error.certificateChain(), error.url().host())); + + m_sslInformation.errors.reserve(m_sslInformation.errors.count() + errors.count()); + + for (int i = 0; i < errors.count(); ++i) + { + m_sslInformation.errors.append({errors.at(i), error.url()}); + } + const QString firstPartyUrl(m_widget->getUrl().toString()); const QString thirdPartyUrl(error.url().toString()); diff --git a/src/modules/backends/web/qtwebengine/QtWebEnginePage.h b/src/modules/backends/web/qtwebengine/QtWebEnginePage.h index 2d7fc176dd..04f29101ca 100644 --- a/src/modules/backends/web/qtwebengine/QtWebEnginePage.h +++ b/src/modules/backends/web/qtwebengine/QtWebEnginePage.h @@ -22,6 +22,7 @@ #define OTTER_QTWEBENGINEPAGE_H #include "../../../../core/SessionsManager.h" +#include "../../../../ui/WebWidget.h" #include #if QTWEBENGINECORE_VERSION >= 0x050E00 @@ -57,6 +58,9 @@ class QtWebEnginePage final : public QWebEnginePage QString createScriptSource(const QString &path, const QStringList ¶meters = {}) const; QVariant runScriptSource(const QString &script); QVariant runScriptFile(const QString &path, const QStringList ¶meters = {}); +#if QTWEBENGINECORE_VERSION >= 0x050E00 + WebWidget::SslInformation getSslInformation() const; +#endif Session::Window::History getHistory() const; bool isPopup() const; bool isViewingMedia() const; @@ -82,6 +86,9 @@ protected slots: private: QtWebEngineWebWidget *m_widget; +#if QTWEBENGINECORE_VERSION >= 0x050E00 + WebWidget::SslInformation m_sslInformation; +#endif QVector m_popups; QVector m_history; NavigationType m_previousNavigationType; diff --git a/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp b/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp index d2700b24e7..451ee16e9e 100644 --- a/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp +++ b/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.cpp @@ -1699,6 +1699,13 @@ WebWidget::LinkUrl QtWebEngineWebWidget::getActiveMedia() const return link; } +#if QTWEBENGINECORE_VERSION >= 0x050E00 +WebWidget::SslInformation QtWebEngineWebWidget::getSslInformation() const +{ + return m_page->getSslInformation(); +} +#endif + Session::Window::History QtWebEngineWebWidget::getHistory() const { return m_page->getHistory(); diff --git a/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.h b/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.h index 8ce6322398..cdb252b2fa 100644 --- a/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.h +++ b/src/modules/backends/web/qtwebengine/QtWebEngineWebWidget.h @@ -80,6 +80,9 @@ class QtWebEngineWebWidget final : public WebWidget LinkUrl getActiveImage() const override; LinkUrl getActiveLink() const override; LinkUrl getActiveMedia() const override; +#if QTWEBENGINECORE_VERSION >= 0x050E00 + SslInformation getSslInformation() const override; +#endif Session::Window::History getHistory() const override; HitTestResult getHitTestResult(const QPoint &position) override; QStringList getStyleSheets() const override; From 225e66b93b9e2e0040319bfbceea21a05c39a605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Sun, 15 Dec 2019 18:29:48 +0100 Subject: [PATCH 65/71] [QtWebKit] Handle form resubmitting first --- .../backends/web/qtwebkit/QtWebKitPage.cpp | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/modules/backends/web/qtwebkit/QtWebKitPage.cpp b/src/modules/backends/web/qtwebkit/QtWebKitPage.cpp index 8517705cd4..5f765d88ff 100644 --- a/src/modules/backends/web/qtwebkit/QtWebKitPage.cpp +++ b/src/modules/backends/web/qtwebkit/QtWebKitPage.cpp @@ -577,28 +577,6 @@ bool QtWebKitPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkReque return false; } - const bool isAnchorNavigation(frame && (type == NavigationTypeLinkClicked || type == NavigationTypeOther) && frame->url().matches(request.url(), QUrl::RemoveFragment)); - - if (mainFrame() == frame) - { - if (m_widget && !isAnchorNavigation) - { - if (frame->url().isEmpty()) - { - m_widget->setRequestedUrl(request.url(), false, true); - } - - m_widget->handleNavigationRequest(request.url(), type); - } - - m_networkManager->setMainRequest(request.url()); - } - - if (type == NavigationTypeFormSubmitted && QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier)) - { - m_networkManager->setFormRequest(request.url()); - } - if (type == NavigationTypeFormResubmitted && SettingsManager::getOption(SettingsManager::Choices_WarnFormResendOption).toBool()) { bool shouldCancelRequest(false); @@ -639,6 +617,28 @@ bool QtWebKitPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkReque } } + const bool isAnchorNavigation(frame && (type == NavigationTypeLinkClicked || type == NavigationTypeOther) && frame->url().matches(request.url(), QUrl::RemoveFragment)); + + if (mainFrame() == frame) + { + if (m_widget && !isAnchorNavigation) + { + if (frame->url().isEmpty()) + { + m_widget->setRequestedUrl(request.url(), false, true); + } + + m_widget->handleNavigationRequest(request.url(), type); + } + + m_networkManager->setMainRequest(request.url()); + } + + if (type == NavigationTypeFormSubmitted && QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier)) + { + m_networkManager->setFormRequest(request.url()); + } + if (type != NavigationTypeOther) { emit isDisplayingErrorPageChanged(frame, false); From 891624ee7cc350238d45095afbd9164bf5ca0648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Mon, 16 Dec 2019 21:45:36 +0100 Subject: [PATCH 66/71] Do not store URLs with schemes other than http(s) --- src/core/TransfersManager.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/core/TransfersManager.cpp b/src/core/TransfersManager.cpp index 3b83bac996..ccf727ebb0 100644 --- a/src/core/TransfersManager.cpp +++ b/src/core/TransfersManager.cpp @@ -1046,7 +1046,12 @@ void TransfersManager::addTransfer(Transfer *transfer) } else { - HistoryManager::addEntry(transfer->getSource()); + const QString scheme(transfer->getSource().scheme()); + + if (scheme == QLatin1String("http") || scheme == QLatin1String("https")) + { + HistoryManager::addEntry(transfer->getSource()); + } } } From 390ba1262aec90fb9349c108e567dc4b2fc5bb5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Tue, 17 Dec 2019 20:59:09 +0100 Subject: [PATCH 67/71] [QtWebEngine] Use suggestedFileName() when available --- .../web/qtwebengine/QtWebEngineTransfer.cpp | 15 +++++++++++++-- .../web/qtwebengine/QtWebEngineTransfer.h | 3 +++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.cpp b/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.cpp index 21aa8706f3..80cb93dad8 100644 --- a/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.cpp +++ b/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.cpp @@ -26,8 +26,10 @@ namespace Otter { QtWebEngineTransfer::QtWebEngineTransfer(QWebEngineDownloadItem *item, TransferOptions options, QObject *parent) : Transfer(options, parent), - m_item(item), - m_suggestedFileName(QFileInfo(item->path()).fileName()) + m_item(item) +#if QTWEBENGINECORE_VERSION < 0x050E00 + , m_suggestedFileName(QFileInfo(item->path()).fileName()) +#endif { m_item->accept(); m_item->setParent(this); @@ -79,7 +81,16 @@ QUrl QtWebEngineTransfer::getSource() const QString QtWebEngineTransfer::getSuggestedFileName() { +#if QTWEBENGINECORE_VERSION >= 0x050E00 + if (!m_item) + { + return {}; + } + + return m_item->suggestedFileName(); +#else return m_suggestedFileName; +#endif } QString QtWebEngineTransfer::getTarget() const diff --git a/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.h b/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.h index 52981d8bc7..df23bd91ee 100644 --- a/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.h +++ b/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.h @@ -22,6 +22,7 @@ #include "../../../../core/TransfersManager.h" +#include #include namespace Otter @@ -48,7 +49,9 @@ public slots: private: QPointer m_item; +#if QTWEBENGINECORE_VERSION < 0x050E00 QString m_suggestedFileName; +#endif }; } From 9291bff3c85c9ebb0fd89e0c5cf2d694a9f96beb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Wed, 18 Dec 2019 22:17:49 +0100 Subject: [PATCH 68/71] [QtWebEngine] Use new API to get download path --- .../backends/web/qtwebengine/QtWebEngineTransfer.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.cpp b/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.cpp index 80cb93dad8..b9b0680cdb 100644 --- a/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.cpp +++ b/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.cpp @@ -19,6 +19,9 @@ #include "QtWebEngineTransfer.h" +#if QTWEBENGINECORE_VERSION >= 0x050E00 +#include +#endif #include #include @@ -100,7 +103,11 @@ QString QtWebEngineTransfer::getTarget() const return Transfer::getTarget(); } +#if QTWEBENGINECORE_VERSION >= 0x050E00 + return QDir(m_item->downloadDirectory()).absoluteFilePath(m_item->downloadFileName()); +#else return m_item->path(); +#endif } QMimeType QtWebEngineTransfer::getMimeType() const From 1a6f3e9a029bdd24b564fabe734064a29721f260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Thu, 19 Dec 2019 20:11:43 +0100 Subject: [PATCH 69/71] [QtWebEngine] Use new API to set download path --- .../backends/web/qtwebengine/QtWebEngineTransfer.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.cpp b/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.cpp index b9b0680cdb..b90b10638b 100644 --- a/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.cpp +++ b/src/modules/backends/web/qtwebengine/QtWebEngineTransfer.cpp @@ -172,7 +172,14 @@ bool QtWebEngineTransfer::setTarget(const QString &target, bool canOverwriteExis return Transfer::setTarget(target, canOverwriteExisting); } +#if QTWEBENGINECORE_VERSION >= 0x050E00 + QFileInfo fileInformation(target); + + m_item->setDownloadDirectory(fileInformation.path()); + m_item->setDownloadFileName(fileInformation.fileName()); +#else m_item->setPath(target); +#endif return true; } From 2d2fe8f2d7f96f688d7c1f61d99d1cc50ac2a730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Fri, 20 Dec 2019 19:43:41 +0100 Subject: [PATCH 70/71] Fix warning --- src/ui/WebWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/WebWidget.cpp b/src/ui/WebWidget.cpp index e729566590..295072c9d1 100644 --- a/src/ui/WebWidget.cpp +++ b/src/ui/WebWidget.cpp @@ -867,7 +867,7 @@ QString WebWidget::getFastForwardScript(bool isSelectingTheBestLink) for (int j = 0; j < keys.count(); ++j) { - tokensArray.append(QJsonObject({{QLatin1Literal("value"), keys.at(j).toUpper()}, {QLatin1Literal("score"), settings.getValue(keys.at(j)).toInt()}})); + tokensArray.append(QJsonObject({{QLatin1String("value"), keys.at(j).toUpper()}, {QLatin1String("score"), settings.getValue(keys.at(j)).toInt()}})); } settings.endGroup(); From f71ad91895c9bece32276ccbeffb0f4dfd33bf47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dutkiewicz?= Date: Sat, 21 Dec 2019 21:05:20 +0100 Subject: [PATCH 71/71] Switch away from deprecated API --- src/ui/WebWidget.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/ui/WebWidget.cpp b/src/ui/WebWidget.cpp index 295072c9d1..e6b452eca4 100644 --- a/src/ui/WebWidget.cpp +++ b/src/ui/WebWidget.cpp @@ -650,7 +650,18 @@ void WebWidget::setOption(int identifier, const QVariant &value) void WebWidget::setOptions(const QHash &options, const QStringList &excludedOptions) { - const QList identifiers((m_options.keys() + options.keys()).toSet().toList()); + QList identifiers(m_options.keys()); + identifiers.reserve(identifiers.count() + options.count()); + + QHash::const_iterator iterator; + + for (iterator = options.begin(); iterator != options.end(); ++iterator) + { + if (!identifiers.contains(iterator.key())) + { + identifiers.append(iterator.key()); + } + } m_options = options;