1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
// SPDX-License-Identifier: GPL-3.0-only
// SPDX-FileCopyrightText: 2026 Project Tick
// SPDX-FileContributor: Project Tick Team
#include "HubSearchProvider.h"
#include <QRegularExpression>
namespace
{
const QList<HubSearchProvider> kProviders{
{ QStringLiteral("duckduckgo"), QStringLiteral("DuckDuckGo"), QStringLiteral("https://duckduckgo.com/?q=%1") },
{ QStringLiteral("google"), QStringLiteral("Google"), QStringLiteral("https://www.google.com/search?q=%1") },
{ QStringLiteral("brave"), QStringLiteral("Brave Search"), QStringLiteral("https://search.brave.com/search?q=%1") },
{ QStringLiteral("bing"), QStringLiteral("Bing"), QStringLiteral("https://www.bing.com/search?q=%1") },
{ QStringLiteral("startpage"), QStringLiteral("Startpage"), QStringLiteral("https://www.startpage.com/do/search?query=%1") },
};
bool looksLikeExplicitUrl(const QString& input)
{
static const QRegularExpression kSchemePattern(QStringLiteral(R"(^[a-zA-Z][a-zA-Z0-9+\-.]*:)"));
if (input.startsWith(QLatin1Char('/')) || input.startsWith(QStringLiteral("./"))
|| input.startsWith(QStringLiteral("../")) || input.startsWith(QLatin1Char('~')))
{
return true;
}
if (kSchemePattern.match(input).hasMatch())
{
return true;
}
if (input.compare(QStringLiteral("localhost"), Qt::CaseInsensitive) == 0)
{
return true;
}
return input.contains(QLatin1Char('.')) || input.contains(QLatin1Char(':'));
}
}
const QList<HubSearchProvider>& hubSearchProviders()
{
return kProviders;
}
QString defaultHubSearchProviderId()
{
return QStringLiteral("duckduckgo");
}
QString normalizedHubSearchProviderId(const QString& id)
{
for (const auto& provider : kProviders)
{
if (provider.id == id)
{
return provider.id;
}
}
return defaultHubSearchProviderId();
}
QUrl hubSearchUrlForQuery(const QString& query, const QString& providerId)
{
const QString normalizedId = normalizedHubSearchProviderId(providerId);
for (const auto& provider : kProviders)
{
if (provider.id == normalizedId)
{
return QUrl(provider.templateUrl.arg(QString::fromUtf8(QUrl::toPercentEncoding(query))));
}
}
return QUrl(kProviders.constFirst().templateUrl.arg(QString::fromUtf8(QUrl::toPercentEncoding(query))));
}
QUrl resolveHubInput(const QString& input, const QString& providerId)
{
const QString trimmed = input.trimmed();
if (trimmed.isEmpty())
{
return {};
}
if (looksLikeExplicitUrl(trimmed))
{
const QUrl url = QUrl::fromUserInput(trimmed);
if (url.isValid())
{
return url;
}
}
return hubSearchUrlForQuery(trimmed, providerId);
}
|