File: searchproviderdlg.cpp

package info (click to toggle)
kio-extras 4%3A25.04.2-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 31,928 kB
  • sloc: cpp: 28,852; ansic: 3,084; perl: 1,048; xml: 116; sh: 92; python: 28; makefile: 9
file content (179 lines) | stat: -rw-r--r-- 7,749 bytes parent folder | download
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"