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 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
|
/*
SPDX-FileCopyrightText: 2000 Malte Starostik <malte@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "searchproviderdlg.h"
#include "searchprovider.h"
#include <QClipboard>
#include <KLocalizedString>
#include <KMessageBox>
#include <QApplication>
#include <QTextCodec>
#include <QVBoxLayout>
static const QString PLACEHOLDER_TOKEN = QStringLiteral("\\{@}");
SearchProviderDialog::SearchProviderDialog(SearchProvider *provider, QList<SearchProvider *> &providers, QWidget *parent)
: QDialog(parent)
, m_provider(provider)
{
setModal(true);
m_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
connect(m_buttons, &QDialogButtonBox::accepted, this, &SearchProviderDialog::accept);
connect(m_buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
QWidget *mainWidget = new QWidget(this);
m_dlg.setupUi(mainWidget);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(mainWidget);
layout->addWidget(m_buttons);
m_dlg.leQuery->setMinimumWidth(m_dlg.leQuery->fontMetrics().averageCharWidth() * 50);
connect(m_dlg.leName, &QLineEdit::textChanged, this, &SearchProviderDialog::slotChanged);
connect(m_dlg.leQuery, &QLineEdit::textChanged, this, &SearchProviderDialog::slotChanged);
connect(m_dlg.leShortcut, &QLineEdit::textChanged, this, &SearchProviderDialog::slotChanged);
connect(m_dlg.leShortcut, &QLineEdit::textChanged, this, &SearchProviderDialog::shortcutsChanged);
connect(m_dlg.pbPaste, &QAbstractButton::clicked, this, &SearchProviderDialog::pastePlaceholder);
// Data init
m_providers = providers;
QStringList charsets;
for (const auto &codec : QTextCodec::availableCodecs()) {
charsets << QString::fromUtf8(codec);
}
charsets.prepend(i18nc("@item:inlistbox The default character set", "Default"));
m_dlg.cbCharset->addItems(charsets);
if (m_provider) {
setWindowTitle(i18n("Edit Web Search Keyword"));
m_dlg.leName->setText(m_provider->name());
m_dlg.leQuery->setText(m_provider->query());
m_dlg.leShortcut->setText(m_provider->keys().join(QLatin1Char(',')));
m_dlg.cbCharset->setCurrentIndex(m_provider->charset().isEmpty() ? 0 : charsets.indexOf(m_provider->charset()));
m_dlg.leName->setEnabled(false);
m_dlg.leQuery->setFocus();
} else {
setWindowTitle(i18n("New Web Search Keyword"));
m_dlg.leName->setFocus();
// If the clipboard contains a url copy it to the query lineedit
const QClipboard *clipboard = QApplication::clipboard();
const QString url = clipboard->text();
if (!QUrl(url).host().isEmpty()) {
m_dlg.leQuery->setText(url);
}
m_buttons->button(QDialogButtonBox::Ok)->setEnabled(false);
}
}
void SearchProviderDialog::slotChanged()
{
m_buttons->button(QDialogButtonBox::Ok)
->setEnabled(!(m_dlg.leName->text().isEmpty() || m_dlg.leShortcut->text().isEmpty() || m_dlg.leQuery->text().isEmpty())
&& m_dlg.noteLabel->text().isEmpty());
}
// Check if the user wants to assign shorthands that are already assigned to
// another search provider. Invoked on every change to the shortcuts field.
void SearchProviderDialog::shortcutsChanged(const QString &newShorthands)
{
// Convert all spaces to commas. A shorthand should be a single word.
// Assume that the user wanted to enter an alternative shorthand and hit
// space instead of the comma key. Save cursor position beforehand because
// setText() will reset it to the end, which is not what we want when
// backspacing something in the middle.
int savedCursorPosition = m_dlg.leShortcut->cursorPosition();
QString normalizedShorthands = QString(newShorthands).replace(QLatin1Char(' '), QLatin1Char(','));
m_dlg.leShortcut->setText(normalizedShorthands);
m_dlg.leShortcut->setCursorPosition(savedCursorPosition);
QHash<QString, const SearchProvider *> contenders;
const QStringList normList = normalizedShorthands.split(QLatin1Char(','));
const QSet<QString> shorthands(normList.begin(), normList.end());
auto findProvider = [this](const QString &shorthand) {
return std::find_if(m_providers.cbegin(), m_providers.cend(), [this, &shorthand](const SearchProvider *provider) {
return provider != m_provider && provider->keys().contains(shorthand);
});
};
// Look at each shorthand the user entered and wade through the search
// provider list in search of a conflicting shorthand. Do not continue
// search after finding one, because shorthands should be assigned only
// once. Act like data inconsistencies regarding this don't exist (should
// probably be handled on load).
for (const QString &shorthand : shorthands) {
auto it = findProvider(shorthand);
if (it != m_providers.cend()) {
contenders.insert(shorthand, *it);
}
}
const int contendersSize = contenders.size();
if (contendersSize != 0) {
if (contendersSize == 1) {
auto it = contenders.cbegin();
m_dlg.noteLabel->setText(i18n("The keyword \"%1\" is already assigned to \"%2\". Please choose a different one.", it.key(), it.value()->name()));
} else {
QStringList contenderList;
contenderList.reserve(contendersSize);
for (auto it = contenders.cbegin(); it != contenders.cend(); ++it) {
contenderList.append(i18nc("- web short cut (e.g. gg): what it refers to (e.g. Google)", "- %1: \"%2\"", it.key(), it.value()->name()));
}
m_dlg.noteLabel->setText(
i18n("The following keywords are already assigned. Please choose different ones.\n%1", contenderList.join(QLatin1Char('\n'))));
}
m_buttons->button(QDialogButtonBox::Ok)->setEnabled(false);
} else {
m_dlg.noteLabel->clear();
}
slotChanged();
}
void SearchProviderDialog::accept()
{
if ((m_dlg.leQuery->text().indexOf(QLatin1String("\\{")) == -1)
&& KMessageBox::warningContinueCancel(nullptr,
i18n("The URL does not contain a %1 placeholder for the user query.\n"
"This means that the same page is always going to be visited, "
"regardless of the text typed in with the keyword.",
PLACEHOLDER_TOKEN),
QString(),
KGuiItem(i18n("Keep It")))
== KMessageBox::Cancel) {
return;
}
if (!m_provider) {
m_provider = new SearchProvider;
}
const QString name = m_dlg.leName->text().trimmed();
const QString query = m_dlg.leQuery->text().trimmed();
QStringList keys = m_dlg.leShortcut->text().trimmed().toLower().split(QLatin1Char(','), Qt::SkipEmptyParts);
keys.removeDuplicates(); // #169801. Remove duplicates...
const QString charset = (m_dlg.cbCharset->currentIndex() ? m_dlg.cbCharset->currentText().trimmed() : QString());
m_provider->setDirty((name != m_provider->name() || query != m_provider->query() || keys != m_provider->keys() || charset != m_provider->charset()));
m_provider->setName(name);
m_provider->setQuery(query);
m_provider->setKeys(keys);
m_provider->setCharset(charset);
QDialog::accept();
}
void SearchProviderDialog::pastePlaceholder()
{
m_dlg.leQuery->insert(PLACEHOLDER_TOKEN);
m_dlg.leQuery->setFocus();
}
#include "moc_searchproviderdlg.cpp"
|