diff --git a/src/urifilters/fixhost/fixhosturifilter.cpp b/src/urifilters/fixhost/fixhosturifilter.cpp index eedb1471..79f2479f 100644 --- a/src/urifilters/fixhost/fixhosturifilter.cpp +++ b/src/urifilters/fixhost/fixhosturifilter.cpp @@ -1,95 +1,95 @@ /* fixhostfilter.cpp This file is part of the KDE project Copyright (C) 2007 Lubos Lunak Copyright (C) 2010 Dawit Alemayehu 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 2 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 "fixhosturifilter.h" #include #include #define QL1S(x) QLatin1String(x) #define QL1C(x) QLatin1Char(x) /** * IMPORTANT: If you change anything here, make sure you run the kurifiltertest * regression test (this should be included as part of "make test"). */ FixHostUriFilter::FixHostUriFilter(QObject *parent, const QVariantList & /*args*/) - :KUriFilterPlugin(QStringLiteral("fixhosturifilter"), parent) + : KUriFilterPlugin(QStringLiteral("fixhosturifilter"), parent) { } -static bool isHttpUrl(const QString& scheme) +static bool isHttpUrl(const QString &scheme) { - return (scheme.compare(QL1S("http"), Qt::CaseInsensitive) == 0 || - scheme.compare(QL1S("https"), Qt::CaseInsensitive) == 0 || - scheme.compare(QL1S("webdav"), Qt::CaseInsensitive) == 0 || - scheme.compare(QL1S("webdavs"), Qt::CaseInsensitive) == 0); + return scheme.compare(QL1S("http"), Qt::CaseInsensitive) == 0 + || scheme.compare(QL1S("https"), Qt::CaseInsensitive) == 0 + || scheme.compare(QL1S("webdav"), Qt::CaseInsensitive) == 0 + || scheme.compare(QL1S("webdavs"), Qt::CaseInsensitive) == 0; } -static bool hasCandidateHostName(const QString& host) +static bool hasCandidateHostName(const QString &host) { - return (host.contains(QL1C('.')) && - !host.startsWith(QL1S("www."), Qt::CaseInsensitive)); + return host.contains(QL1C('.')) + && !host.startsWith(QL1S("www."), Qt::CaseInsensitive); } -bool FixHostUriFilter::filterUri( KUriFilterData& data ) const +bool FixHostUriFilter::filterUri(KUriFilterData &data) const { QUrl url = data.uri(); const QString protocol = url.scheme(); const bool isHttp = isHttpUrl(protocol); if (isHttp || protocol == data.defaultUrlScheme()) { const QString host = url.host(); if (hasCandidateHostName(host) && !isResolvable(host)) { if (isHttp) { url.setHost((QL1S("www.") + host)); if (exists(url.host())) { setFilteredUri(data, url); setUriType(data, KUriFilterData::NetProtocol); return true; } } } } return false; } -bool FixHostUriFilter::isResolvable(const QString& host) const +bool FixHostUriFilter::isResolvable(const QString &host) const { // Unlike exists, this function returns true if the lookup timeout out. QHostInfo info = resolveName(host, 1500); - return (info.error() == QHostInfo::NoError || - info.error() == QHostInfo::UnknownError); + return info.error() == QHostInfo::NoError + || info.error() == QHostInfo::UnknownError; } -bool FixHostUriFilter::exists(const QString& host) const +bool FixHostUriFilter::exists(const QString &host) const { QHostInfo info = resolveName(host, 1500); - return (info.error() == QHostInfo::NoError); + return info.error() == QHostInfo::NoError; } K_PLUGIN_CLASS_WITH_JSON(FixHostUriFilter, "fixhosturifilter.json") #include "fixhosturifilter.moc" diff --git a/src/urifilters/fixhost/fixhosturifilter.h b/src/urifilters/fixhost/fixhosturifilter.h index 4cfc7ac3..632a0a6f 100644 --- a/src/urifilters/fixhost/fixhosturifilter.h +++ b/src/urifilters/fixhost/fixhosturifilter.h @@ -1,45 +1,45 @@ /* fixhosturifilter.h This file is part of the KDE project Copyright (C) 2007 Lubos Lunak 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 2 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 FIXHOSTURIFILTER_H #define FIXHOSTURIFILTER_H #include class QHostInfo; class QEventLoop; /** This filter tries to automatically prepend www. to http URLs that need it. */ class FixHostUriFilter : public KUriFilterPlugin { Q_OBJECT public: - FixHostUriFilter(QObject* parent, const QVariantList& args); + FixHostUriFilter(QObject *parent, const QVariantList &args); bool filterUri(KUriFilterData &data) const override; private: - bool exists(const QString& host) const; - bool isResolvable(const QString& host) const; + bool exists(const QString &host) const; + bool isResolvable(const QString &host) const; }; #endif diff --git a/src/urifilters/ikws/ikwsopts.cpp b/src/urifilters/ikws/ikwsopts.cpp index 42b308dc..edbad37a 100644 --- a/src/urifilters/ikws/ikwsopts.cpp +++ b/src/urifilters/ikws/ikwsopts.cpp @@ -1,453 +1,457 @@ /* * Copyright (c) 2000 Yves Arrouye * Copyright (c) 2001, 2002 Dawit Alemayehu * Copyright (c) 2009 Nick Shaforostoff * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "ikwsopts.h" #include "ikwsopts_p.h" #include "kuriikwsfiltereng.h" #include "searchprovider.h" #include "searchproviderdlg.h" #include #include #include #include #include #include #include #include - - //BEGIN ProvidersModel ProvidersModel::~ProvidersModel() { - } -QVariant ProvidersModel::headerData(int section, Qt::Orientation orientation, int role ) const +QVariant ProvidersModel::headerData(int section, Qt::Orientation orientation, int role) const { - Q_UNUSED(orientation); - if (role == Qt::DisplayRole) - { - switch (section) { - case Name: - return i18nc("@title:column Name label from web shortcuts column", "Name"); - case Shortcuts: - return i18nc("@title:column", "Shortcuts"); - case Preferred: - return i18nc("@title:column", "Preferred"); - default: - break; + Q_UNUSED(orientation); + if (role == Qt::DisplayRole) { + switch (section) { + case Name: + return i18nc("@title:column Name label from web shortcuts column", "Name"); + case Shortcuts: + return i18nc("@title:column", "Shortcuts"); + case Preferred: + return i18nc("@title:column", "Preferred"); + default: + break; + } } - } - return QVariant(); + return QVariant(); } -Qt::ItemFlags ProvidersModel::flags(const QModelIndex& index) const +Qt::ItemFlags ProvidersModel::flags(const QModelIndex &index) const { - if (!index.isValid()) - return Qt::ItemIsEnabled; - if (index.column()==Preferred) - return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable; - return Qt::ItemIsEnabled | Qt::ItemIsSelectable; + if (!index.isValid()) { + return Qt::ItemIsEnabled; + } + if (index.column() == Preferred) { + return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable; + } + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } -bool ProvidersModel::setData (const QModelIndex& index, const QVariant& value, int role) +bool ProvidersModel::setData(const QModelIndex &index, const QVariant &value, int role) { - if (role==Qt::CheckStateRole) - { - if (value.toInt() == Qt::Checked) - m_favoriteEngines.insert(m_providers.at(index.row())->desktopEntryName()); - else - m_favoriteEngines.remove(m_providers.at(index.row())->desktopEntryName()); - emit dataModified(); - return true; - } - return false; + if (role == Qt::CheckStateRole) { + if (value.toInt() == Qt::Checked) { + m_favoriteEngines.insert(m_providers.at(index.row())->desktopEntryName()); + } else { + m_favoriteEngines.remove(m_providers.at(index.row())->desktopEntryName()); + } + emit dataModified(); + return true; + } + return false; } -QVariant ProvidersModel::data(const QModelIndex& index, int role) const +QVariant ProvidersModel::data(const QModelIndex &index, int role) const { - if (index.isValid()) - { - if (role == Qt::CheckStateRole && index.column()==Preferred) - return (m_favoriteEngines.contains(m_providers.at(index.row())->desktopEntryName()) ? Qt::Checked : Qt::Unchecked); - - if (role == Qt::DisplayRole) - { - if (index.column()==Name) - return m_providers.at(index.row())->name(); - if (index.column()==Shortcuts) - return m_providers.at(index.row())->keys().join(QLatin1Char(',')); - } - - if (role == Qt::ToolTipRole || role == Qt::WhatsThisRole) - { - if (index.column() == Preferred) - return xi18nc("@info:tooltip", "Check this box to select the highlighted web shortcut " - "as preferred.Preferred web shortcuts are used in " - "places where only a few select shortcuts can be shown " - "at one time."); + if (index.isValid()) { + if (role == Qt::CheckStateRole && index.column() == Preferred) { + return m_favoriteEngines.contains(m_providers.at(index.row())->desktopEntryName()) ? Qt::Checked : Qt::Unchecked; + } + + if (role == Qt::DisplayRole) { + if (index.column() == Name) { + return m_providers.at(index.row())->name(); + } + if (index.column() == Shortcuts) { + return m_providers.at(index.row())->keys().join(QLatin1Char(',')); + } + } + + if (role == Qt::ToolTipRole || role == Qt::WhatsThisRole) { + if (index.column() == Preferred) { + return xi18nc("@info:tooltip", "Check this box to select the highlighted web shortcut " + "as preferred.Preferred web shortcuts are used in " + "places where only a few select shortcuts can be shown " + "at one time."); + } + } + + if (role == Qt::UserRole) { + return index.row();//a nice way to bypass proxymodel + } } - if (role == Qt::UserRole) - return index.row();//a nice way to bypass proxymodel - } - - return QVariant(); + return QVariant(); } -void ProvidersModel::setProviders(const QList& providers, const QStringList& favoriteEngines) +void ProvidersModel::setProviders(const QList &providers, const QStringList &favoriteEngines) { - m_providers = providers; - setFavoriteProviders(favoriteEngines); + m_providers = providers; + setFavoriteProviders(favoriteEngines); } -void ProvidersModel::setFavoriteProviders(const QStringList& favoriteEngines) +void ProvidersModel::setFavoriteProviders(const QStringList &favoriteEngines) { - beginResetModel(); - m_favoriteEngines = QSet::fromList(favoriteEngines); - endResetModel(); + beginResetModel(); + m_favoriteEngines = QSet::fromList(favoriteEngines); + endResetModel(); } -int ProvidersModel::rowCount(const QModelIndex & parent) const +int ProvidersModel::rowCount(const QModelIndex &parent) const { - if (parent.isValid()) - return 0; - return m_providers.size(); + if (parent.isValid()) { + return 0; + } + return m_providers.size(); } -QAbstractListModel* ProvidersModel::createListModel() +QAbstractListModel *ProvidersModel::createListModel() { - ProvidersListModel* pListModel = new ProvidersListModel(m_providers, this); - connect(this, &QAbstractItemModel::modelAboutToBeReset, pListModel, &QAbstractItemModel::modelAboutToBeReset); - connect(this, &QAbstractItemModel::modelReset, pListModel, &QAbstractItemModel::modelReset); - // TODO: next two are private signals, does this still work? and is this needed? - connect(this, SIGNAL(layoutAboutToBeChanged()), pListModel, SIGNAL(modelReset())); - connect(this, SIGNAL(layoutChanged()), pListModel, SIGNAL(modelReset())); - connect(this, &QAbstractItemModel::dataChanged, pListModel, &ProvidersListModel::emitDataChanged); - connect(this, &QAbstractItemModel::rowsAboutToBeInserted, pListModel, &ProvidersListModel::emitRowsAboutToBeInserted); - connect(this, &QAbstractItemModel::rowsAboutToBeRemoved, pListModel, &ProvidersListModel::emitRowsAboutToBeRemoved); - connect(this, &QAbstractItemModel::rowsInserted, pListModel, &ProvidersListModel::emitRowsInserted); - connect(this, &QAbstractItemModel::rowsRemoved, pListModel, &ProvidersListModel::emitRowsRemoved); - - return pListModel; + ProvidersListModel *pListModel = new ProvidersListModel(m_providers, this); + connect(this, &QAbstractItemModel::modelAboutToBeReset, pListModel, &QAbstractItemModel::modelAboutToBeReset); + connect(this, &QAbstractItemModel::modelReset, pListModel, &QAbstractItemModel::modelReset); + // TODO: next two are private signals, does this still work? and is this needed? + connect(this, SIGNAL(layoutAboutToBeChanged()), pListModel, SIGNAL(modelReset())); + connect(this, SIGNAL(layoutChanged()), pListModel, SIGNAL(modelReset())); + connect(this, &QAbstractItemModel::dataChanged, pListModel, &ProvidersListModel::emitDataChanged); + connect(this, &QAbstractItemModel::rowsAboutToBeInserted, pListModel, &ProvidersListModel::emitRowsAboutToBeInserted); + connect(this, &QAbstractItemModel::rowsAboutToBeRemoved, pListModel, &ProvidersListModel::emitRowsAboutToBeRemoved); + connect(this, &QAbstractItemModel::rowsInserted, pListModel, &ProvidersListModel::emitRowsInserted); + connect(this, &QAbstractItemModel::rowsRemoved, pListModel, &ProvidersListModel::emitRowsRemoved); + + return pListModel; } -void ProvidersModel::deleteProvider(SearchProvider* p) +void ProvidersModel::deleteProvider(SearchProvider *p) { - const int row = m_providers.indexOf(p); - beginRemoveRows(QModelIndex(), row, row); - m_favoriteEngines.remove(m_providers.takeAt(row)->desktopEntryName()); - endRemoveRows(); - delete p; - emit dataModified(); + const int row = m_providers.indexOf(p); + beginRemoveRows(QModelIndex(), row, row); + m_favoriteEngines.remove(m_providers.takeAt(row)->desktopEntryName()); + endRemoveRows(); + delete p; + emit dataModified(); } -void ProvidersModel::addProvider(SearchProvider* p) +void ProvidersModel::addProvider(SearchProvider *p) { - beginInsertRows(QModelIndex(), m_providers.size(), m_providers.size()); - m_providers.append(p); - endInsertRows(); - emit dataModified(); + beginInsertRows(QModelIndex(), m_providers.size(), m_providers.size()); + m_providers.append(p); + endInsertRows(); + emit dataModified(); } -void ProvidersModel::changeProvider(SearchProvider* p) +void ProvidersModel::changeProvider(SearchProvider *p) { - const int row = m_providers.indexOf(p); - emit dataChanged(index(row,0),index(row,ColumnCount-1)); - emit dataModified(); + const int row = m_providers.indexOf(p); + emit dataChanged(index(row, 0), index(row, ColumnCount-1)); + emit dataModified(); } QStringList ProvidersModel::favoriteEngines() const { - return m_favoriteEngines.toList(); + return m_favoriteEngines.toList(); } + //END ProvidersModel //BEGIN ProvidersListModel -ProvidersListModel::ProvidersListModel(QList& providers, QObject* parent) +ProvidersListModel::ProvidersListModel(QList &providers, QObject *parent) : QAbstractListModel(parent) , m_providers(providers) -{} - -QVariant ProvidersListModel::data(const QModelIndex& index, int role) const { - if (index.isValid()) - { - if (role==Qt::DisplayRole) - { - if (index.row() == m_providers.size()) - return i18nc("@item:inlistbox No default web shortcut", "None"); - return m_providers.at(index.row())->name(); - } +} - if (role==ShortNameRole) - { - if (index.row() == m_providers.size()) - return QString(); - return m_providers.at(index.row())->desktopEntryName(); +QVariant ProvidersListModel::data(const QModelIndex &index, int role) const +{ + if (index.isValid()) { + if (role == Qt::DisplayRole) { + if (index.row() == m_providers.size()) { + return i18nc("@item:inlistbox No default web shortcut", "None"); + } + return m_providers.at(index.row())->name(); + } + + if (role == ShortNameRole) { + if (index.row() == m_providers.size()) { + return QString(); + } + return m_providers.at(index.row())->desktopEntryName(); + } } - } - return QVariant(); + return QVariant(); } -int ProvidersListModel::rowCount (const QModelIndex& parent) const +int ProvidersListModel::rowCount(const QModelIndex &parent) const { - if (parent.isValid()) - return 0; - return m_providers.size() + 1; + if (parent.isValid()) { + return 0; + } + return m_providers.size() + 1; } + //END ProvidersListModel -static QSortFilterProxyModel* wrapInProxyModel(QAbstractItemModel* model) +static QSortFilterProxyModel *wrapInProxyModel(QAbstractItemModel *model) { - QSortFilterProxyModel* proxyModel = new QSortFilterProxyModel(model); - proxyModel->setSourceModel(model); - proxyModel->setDynamicSortFilter(true); - proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); - proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); - proxyModel->setFilterKeyColumn(-1); - return proxyModel; + QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(model); + proxyModel->setSourceModel(model); + proxyModel->setDynamicSortFilter(true); + proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); + proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + proxyModel->setFilterKeyColumn(-1); + return proxyModel; } -FilterOptions::FilterOptions(const KAboutData* about, QWidget *parent) - : KCModule(about, parent), - m_providersModel(new ProvidersModel(this)) +FilterOptions::FilterOptions(const KAboutData *about, QWidget *parent) + : KCModule(about, parent) + , m_providersModel(new ProvidersModel(this)) { - m_dlg.setupUi(this); - - QSortFilterProxyModel* searchProviderModel = wrapInProxyModel(m_providersModel); - m_dlg.lvSearchProviders->setModel(searchProviderModel); - m_dlg.cmbDefaultEngine->setModel(wrapInProxyModel(m_providersModel->createListModel())); - - // Connect all the signals/slots... - connect(m_dlg.cbEnableShortcuts, &QAbstractButton::toggled, this, QOverload<>::of(&FilterOptions::changed)); - connect(m_dlg.cbEnableShortcuts, &QAbstractButton::toggled, this, &FilterOptions::updateSearchProviderEditingButons); - connect(m_dlg.cbUseSelectedShortcutsOnly, &QAbstractButton::toggled, this, QOverload<>::of(&FilterOptions::changed)); - - connect(m_providersModel, &ProvidersModel::dataModified, this, QOverload<>::of(&FilterOptions::changed)); - connect(m_dlg.cmbDefaultEngine, QOverload::of(&QComboBox::currentIndexChanged), this, QOverload<>::of(&FilterOptions::changed)); - connect(m_dlg.cmbDelimiter, QOverload::of(&QComboBox::currentIndexChanged), this, QOverload<>::of(&FilterOptions::changed)); - - connect(m_dlg.pbNew, &QAbstractButton::clicked, this, &FilterOptions::addSearchProvider); - connect(m_dlg.pbDelete, &QAbstractButton::clicked, this, &FilterOptions::deleteSearchProvider); - connect(m_dlg.pbChange, &QAbstractButton::clicked, this, &FilterOptions::changeSearchProvider); - connect(m_dlg.lvSearchProviders->selectionModel(), &QItemSelectionModel::currentChanged, - this, &FilterOptions::updateSearchProviderEditingButons); - connect(m_dlg.lvSearchProviders, &QAbstractItemView::doubleClicked,this, &FilterOptions::changeSearchProvider); - connect(m_dlg.searchLineEdit, &QLineEdit::textEdited, searchProviderModel, &QSortFilterProxyModel::setFilterFixedString); + m_dlg.setupUi(this); + + QSortFilterProxyModel *searchProviderModel = wrapInProxyModel(m_providersModel); + m_dlg.lvSearchProviders->setModel(searchProviderModel); + m_dlg.cmbDefaultEngine->setModel(wrapInProxyModel(m_providersModel->createListModel())); + + // Connect all the signals/slots... + connect(m_dlg.cbEnableShortcuts, &QAbstractButton::toggled, this, QOverload<>::of(&FilterOptions::changed)); + connect(m_dlg.cbEnableShortcuts, &QAbstractButton::toggled, this, &FilterOptions::updateSearchProviderEditingButons); + connect(m_dlg.cbUseSelectedShortcutsOnly, &QAbstractButton::toggled, this, QOverload<>::of(&FilterOptions::changed)); + + connect(m_providersModel, &ProvidersModel::dataModified, this, QOverload<>::of(&FilterOptions::changed)); + connect(m_dlg.cmbDefaultEngine, QOverload::of(&QComboBox::currentIndexChanged), this, QOverload<>::of(&FilterOptions::changed)); + connect(m_dlg.cmbDelimiter, QOverload::of(&QComboBox::currentIndexChanged), this, QOverload<>::of(&FilterOptions::changed)); + + connect(m_dlg.pbNew, &QAbstractButton::clicked, this, &FilterOptions::addSearchProvider); + connect(m_dlg.pbDelete, &QAbstractButton::clicked, this, &FilterOptions::deleteSearchProvider); + connect(m_dlg.pbChange, &QAbstractButton::clicked, this, &FilterOptions::changeSearchProvider); + connect(m_dlg.lvSearchProviders->selectionModel(), &QItemSelectionModel::currentChanged, + this, &FilterOptions::updateSearchProviderEditingButons); + connect(m_dlg.lvSearchProviders, &QAbstractItemView::doubleClicked, this, &FilterOptions::changeSearchProvider); + connect(m_dlg.searchLineEdit, &QLineEdit::textEdited, searchProviderModel, &QSortFilterProxyModel::setFilterFixedString); } QString FilterOptions::quickHelp() const { - return xi18nc("@info:whatsthis", "In this module you can configure the web shortcuts feature. " - "Web shortcuts allow you to quickly search or lookup words on " - "the Internet. For example, to search for information about the " - "KDE project using the Google engine, you simply type gg:KDE " - "or google:KDE." - "If you select a default search engine, then you can search for " - "normal words or phrases by simply typing them into the input widget " - "of applications that have built-in support for such a feature, e.g " - "Konqueror."); + return xi18nc("@info:whatsthis", "In this module you can configure the web shortcuts feature. " + "Web shortcuts allow you to quickly search or lookup words on " + "the Internet. For example, to search for information about the " + "KDE project using the Google engine, you simply type gg:KDE " + "or google:KDE." + "If you select a default search engine, then you can search for " + "normal words or phrases by simply typing them into the input widget " + "of applications that have built-in support for such a feature, e.g " + "Konqueror."); } void FilterOptions::setDefaultEngine(int index) { - QSortFilterProxyModel* proxy = qobject_cast(m_dlg.cmbDefaultEngine->model()); - if (index == -1) - index = proxy->rowCount()-1;//"None" is the last - - const QModelIndex modelIndex = proxy->mapFromSource(proxy->sourceModel()->index(index,0)); - m_dlg.cmbDefaultEngine->setCurrentIndex(modelIndex.row()); - m_dlg.cmbDefaultEngine->view()->setCurrentIndex(modelIndex); //TODO: remove this when Qt bug is fixed + QSortFilterProxyModel *proxy = qobject_cast(m_dlg.cmbDefaultEngine->model()); + if (index == -1) { + index = proxy->rowCount()-1;//"None" is the last + } + const QModelIndex modelIndex = proxy->mapFromSource(proxy->sourceModel()->index(index, 0)); + m_dlg.cmbDefaultEngine->setCurrentIndex(modelIndex.row()); + m_dlg.cmbDefaultEngine->view()->setCurrentIndex(modelIndex); //TODO: remove this when Qt bug is fixed } void FilterOptions::load() { - KConfig config(QString::fromUtf8(KURISearchFilterEngine::self()->name()) + QLatin1String("rc"), KConfig::NoGlobals); - KConfigGroup group = config.group("General"); + KConfig config(QString::fromUtf8(KURISearchFilterEngine::self()->name()) + QLatin1String("rc"), KConfig::NoGlobals); + KConfigGroup group = config.group("General"); - const QString defaultSearchEngine = group.readEntry("DefaultWebShortcut"); - const QStringList favoriteEngines = group.readEntry("PreferredWebShortcuts", DEFAULT_PREFERRED_SEARCH_PROVIDERS); + const QString defaultSearchEngine = group.readEntry("DefaultWebShortcut"); + const QStringList favoriteEngines = group.readEntry("PreferredWebShortcuts", DEFAULT_PREFERRED_SEARCH_PROVIDERS); - const QList providers = m_registry.findAll(); - int defaultProviderIndex = providers.size(); //default is "None", it is last in the list + const QList providers = m_registry.findAll(); + int defaultProviderIndex = providers.size(); //default is "None", it is last in the list - for (SearchProvider *provider : providers) - { - if (defaultSearchEngine == provider->desktopEntryName()) - defaultProviderIndex = providers.size(); - } + for (SearchProvider *provider : providers) { + if (defaultSearchEngine == provider->desktopEntryName()) { + defaultProviderIndex = providers.size(); + } + } - m_providersModel->setProviders(providers, favoriteEngines); - m_dlg.lvSearchProviders->setColumnWidth(0,200); - m_dlg.lvSearchProviders->resizeColumnToContents(1); - m_dlg.lvSearchProviders->sortByColumn(0,Qt::AscendingOrder); - m_dlg.cmbDefaultEngine->model()->sort(0,Qt::AscendingOrder); - setDefaultEngine(defaultProviderIndex); + m_providersModel->setProviders(providers, favoriteEngines); + m_dlg.lvSearchProviders->setColumnWidth(0, 200); + m_dlg.lvSearchProviders->resizeColumnToContents(1); + m_dlg.lvSearchProviders->sortByColumn(0, Qt::AscendingOrder); + m_dlg.cmbDefaultEngine->model()->sort(0, Qt::AscendingOrder); + setDefaultEngine(defaultProviderIndex); - m_dlg.cbEnableShortcuts->setChecked(group.readEntry("EnableWebShortcuts", true)); - m_dlg.cbUseSelectedShortcutsOnly->setChecked(group.readEntry("UsePreferredWebShortcutsOnly", false)); + m_dlg.cbEnableShortcuts->setChecked(group.readEntry("EnableWebShortcuts", true)); + m_dlg.cbUseSelectedShortcutsOnly->setChecked(group.readEntry("UsePreferredWebShortcutsOnly", false)); - const QString delimiter = group.readEntry ("KeywordDelimiter", ":"); - setDelimiter(delimiter.at(0).toLatin1()); + const QString delimiter = group.readEntry("KeywordDelimiter", ":"); + setDelimiter(delimiter.at(0).toLatin1()); } char FilterOptions::delimiter() { - const char delimiters[]={':',' '}; - return delimiters[m_dlg.cmbDelimiter->currentIndex()]; + const char delimiters[] = {':', ' '}; + return delimiters[m_dlg.cmbDelimiter->currentIndex()]; } -void FilterOptions::setDelimiter (char sep) +void FilterOptions::setDelimiter(char sep) { - m_dlg.cmbDelimiter->setCurrentIndex(sep==' '); + m_dlg.cmbDelimiter->setCurrentIndex(sep == ' '); } void FilterOptions::save() { - KConfig config(QString::fromUtf8(KURISearchFilterEngine::self()->name()) + QLatin1String("rc"), KConfig::NoGlobals ); - - KConfigGroup group = config.group("General"); - group.writeEntry("EnableWebShortcuts", m_dlg.cbEnableShortcuts->isChecked()); - group.writeEntry("KeywordDelimiter", QString(QLatin1Char(delimiter()))); - group.writeEntry("DefaultWebShortcut", m_dlg.cmbDefaultEngine->view()->currentIndex().data(ProvidersListModel::ShortNameRole)); - group.writeEntry("PreferredWebShortcuts", m_providersModel->favoriteEngines()); - group.writeEntry("UsePreferredWebShortcutsOnly", m_dlg.cbUseSelectedShortcutsOnly->isChecked()); - - int changedProviderCount = 0; - const QList providers = m_providersModel->providers(); - const QString path = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/kservices5/searchproviders/"); - - for (SearchProvider* provider : providers) - { - if (!provider->isDirty()) - continue; - - changedProviderCount++; - - KConfig _service(path + provider->desktopEntryName() + QLatin1String(".desktop"), KConfig::SimpleConfig); - KConfigGroup service(&_service, "Desktop Entry"); - service.writeEntry("Type", "Service"); - service.writeEntry("X-KDE-ServiceTypes", "SearchProvider"); - service.writeEntry("Name", provider->name()); - service.writeEntry("Query", provider->query()); - service.writeEntry("Keys", provider->keys()); - service.writeEntry("Charset", provider->charset()); - service.writeEntry("Hidden", false); // we might be overwriting a hidden entry - } - - const QStringList servicesDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("kservices5/searchproviders/"), QStandardPaths::LocateDirectory); - Q_FOREACH(const QString& providerName, m_deletedProviders) - { - QStringList matches; - for (const QString& dir : servicesDirs) { - QString current = dir + QLatin1Char('/') + providerName + QLatin1String(".desktop"); - if(QFile::exists(current)) - matches += current; + KConfig config(QString::fromUtf8(KURISearchFilterEngine::self()->name()) + QLatin1String("rc"), KConfig::NoGlobals); + + KConfigGroup group = config.group("General"); + group.writeEntry("EnableWebShortcuts", m_dlg.cbEnableShortcuts->isChecked()); + group.writeEntry("KeywordDelimiter", QString(QLatin1Char(delimiter()))); + group.writeEntry("DefaultWebShortcut", m_dlg.cmbDefaultEngine->view()->currentIndex().data(ProvidersListModel::ShortNameRole)); + group.writeEntry("PreferredWebShortcuts", m_providersModel->favoriteEngines()); + group.writeEntry("UsePreferredWebShortcutsOnly", m_dlg.cbUseSelectedShortcutsOnly->isChecked()); + + int changedProviderCount = 0; + const QList providers = m_providersModel->providers(); + const QString path = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/kservices5/searchproviders/"); + + for (SearchProvider *provider : providers) { + if (!provider->isDirty()) { + continue; + } + + changedProviderCount++; + + KConfig _service(path + provider->desktopEntryName() + QLatin1String(".desktop"), KConfig::SimpleConfig); + KConfigGroup service(&_service, "Desktop Entry"); + service.writeEntry("Type", "Service"); + service.writeEntry("X-KDE-ServiceTypes", "SearchProvider"); + service.writeEntry("Name", provider->name()); + service.writeEntry("Query", provider->query()); + service.writeEntry("Keys", provider->keys()); + service.writeEntry("Charset", provider->charset()); + service.writeEntry("Hidden", false); // we might be overwriting a hidden entry } - // Shouldn't happen - if (matches.isEmpty()) - continue; - - changedProviderCount++; - - if (matches.size() == 1 && matches.first().startsWith(path)) - { - // If only the local copy existed, unlink it - // TODO: error handling - QFile::remove(matches.first()); - continue; + const QStringList servicesDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("kservices5/searchproviders/"), QStandardPaths::LocateDirectory); + Q_FOREACH (const QString &providerName, m_deletedProviders) { + QStringList matches; + for (const QString &dir : servicesDirs) { + QString current = dir + QLatin1Char('/') + providerName + QLatin1String(".desktop"); + if (QFile::exists(current)) { + matches += current; + } + } + + // Shouldn't happen + if (matches.isEmpty()) { + continue; + } + + changedProviderCount++; + + if (matches.size() == 1 && matches.first().startsWith(path)) { + // If only the local copy existed, unlink it + // TODO: error handling + QFile::remove(matches.first()); + continue; + } + + KConfig _service(path + providerName + QLatin1String(".desktop"), KConfig::SimpleConfig); + KConfigGroup service(&_service, "Desktop Entry"); + service.writeEntry("Type", "Service"); + service.writeEntry("X-KDE-ServiceTypes", "SearchProvider"); + service.writeEntry("Hidden", true); } - KConfig _service(path + providerName + QLatin1String(".desktop"), KConfig::SimpleConfig); - KConfigGroup service(&_service, "Desktop Entry"); - service.writeEntry("Type", "Service"); - service.writeEntry("X-KDE-ServiceTypes", "SearchProvider"); - service.writeEntry("Hidden", true); - } + config.sync(); - config.sync(); + emit changed(false); - emit changed(false); + // Update filters in running applications... + QDBusMessage msg = QDBusMessage::createSignal(QStringLiteral("/"), QStringLiteral("org.kde.KUriFilterPlugin"), QStringLiteral("configure")); + QDBusConnection::sessionBus().send(msg); - // Update filters in running applications... - QDBusMessage msg = QDBusMessage::createSignal(QStringLiteral("/"), QStringLiteral("org.kde.KUriFilterPlugin"), QStringLiteral("configure")); - QDBusConnection::sessionBus().send(msg); - - // If the providers changed, tell sycoca to rebuild its database... - if (changedProviderCount) - KBuildSycocaProgressDialog::rebuildKSycoca(this); + // If the providers changed, tell sycoca to rebuild its database... + if (changedProviderCount) { + KBuildSycocaProgressDialog::rebuildKSycoca(this); + } } void FilterOptions::defaults() { - m_dlg.cbEnableShortcuts->setChecked(true); - m_dlg.cbUseSelectedShortcutsOnly->setChecked(false); - m_providersModel->setFavoriteProviders(DEFAULT_PREFERRED_SEARCH_PROVIDERS); - setDelimiter(':'); - setDefaultEngine(-1); + m_dlg.cbEnableShortcuts->setChecked(true); + m_dlg.cbUseSelectedShortcutsOnly->setChecked(false); + m_providersModel->setFavoriteProviders(DEFAULT_PREFERRED_SEARCH_PROVIDERS); + setDelimiter(':'); + setDefaultEngine(-1); } void FilterOptions::addSearchProvider() { - QList providers = m_providersModel->providers(); - QPointer dlg = new SearchProviderDialog(nullptr, providers, this); - - if (dlg->exec()) { - m_providersModel->addProvider(dlg->provider()); - m_providersModel->changeProvider(dlg->provider()); - } - delete dlg; + QList providers = m_providersModel->providers(); + QPointer dlg = new SearchProviderDialog(nullptr, providers, this); + + if (dlg->exec()) { + m_providersModel->addProvider(dlg->provider()); + m_providersModel->changeProvider(dlg->provider()); + } + delete dlg; } void FilterOptions::changeSearchProvider() { - QList providers = m_providersModel->providers(); - SearchProvider* provider = providers.at(m_dlg.lvSearchProviders->currentIndex().data(Qt::UserRole).toInt()); - QPointer dlg = new SearchProviderDialog(provider, providers, this); + QList providers = m_providersModel->providers(); + SearchProvider *provider = providers.at(m_dlg.lvSearchProviders->currentIndex().data(Qt::UserRole).toInt()); + QPointer dlg = new SearchProviderDialog(provider, providers, this); - if (dlg->exec()) - m_providersModel->changeProvider(dlg->provider()); + if (dlg->exec()) { + m_providersModel->changeProvider(dlg->provider()); + } - delete dlg; + delete dlg; } void FilterOptions::deleteSearchProvider() { - SearchProvider* provider = m_providersModel->providers().at(m_dlg.lvSearchProviders->currentIndex().data(Qt::UserRole).toInt()); - m_deletedProviders.append(provider->desktopEntryName()); - m_providersModel->deleteProvider(provider); + SearchProvider *provider = m_providersModel->providers().at(m_dlg.lvSearchProviders->currentIndex().data(Qt::UserRole).toInt()); + m_deletedProviders.append(provider->desktopEntryName()); + m_providersModel->deleteProvider(provider); } void FilterOptions::updateSearchProviderEditingButons() { - const bool enable = (m_dlg.cbEnableShortcuts->isChecked() && - m_dlg.lvSearchProviders->currentIndex().isValid()); - m_dlg.pbChange->setEnabled(enable); - m_dlg.pbDelete->setEnabled(enable); + const bool enable = (m_dlg.cbEnableShortcuts->isChecked() + && m_dlg.lvSearchProviders->currentIndex().isValid()); + m_dlg.pbChange->setEnabled(enable); + m_dlg.pbDelete->setEnabled(enable); } - -// kate: replace-tabs 1; indent-width 2; diff --git a/src/urifilters/ikws/ikwsopts.h b/src/urifilters/ikws/ikwsopts.h index d0f98ce0..e5e21be6 100644 --- a/src/urifilters/ikws/ikwsopts.h +++ b/src/urifilters/ikws/ikwsopts.h @@ -1,69 +1,68 @@ /* * Copyright (c) 2000 Yves Arrouye * Copyright (c) 2002, 2003 Dawit Alemayehu * Copyright (c) 2009 Nick Shaforostoff * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef IKWSOPTS_H #define IKWSOPTS_H #include #include #include #include "ui_ikwsopts_ui.h" #include "searchproviderregistry.h" class SearchProvider; class ProvidersModel; class FilterOptions : public KCModule { Q_OBJECT public: - explicit FilterOptions(const KAboutData* about, QWidget *parent = nullptr); + explicit FilterOptions(const KAboutData *about, QWidget *parent = nullptr); void load() override; void save() override; void defaults() override; QString quickHelp() const override; - private Q_SLOTS: void updateSearchProviderEditingButons(); void addSearchProvider(); void changeSearchProvider(); void deleteSearchProvider(); - + private: void setDelimiter(char); char delimiter(); void setDefaultEngine(int); // The names of the providers that the user deleted, // these are marked as deleted in the user's homedirectory // on save if a global service file exists for it. QStringList m_deletedProviders; - ProvidersModel* m_providersModel; + ProvidersModel *m_providersModel; SearchProviderRegistry m_registry; Ui::FilterOptionsUI m_dlg; }; #endif diff --git a/src/urifilters/ikws/ikwsopts_p.h b/src/urifilters/ikws/ikwsopts_p.h index 7a7330b6..e41a919c 100644 --- a/src/urifilters/ikws/ikwsopts_p.h +++ b/src/urifilters/ikws/ikwsopts_p.h @@ -1,91 +1,120 @@ /* * Copyright (c) 2009 Nick Shaforostoff * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef IKWSOPTS_P_H #define IKWSOPTS_P_H #include class SearchProvider; -class ProvidersModel: public QAbstractTableModel +class ProvidersModel : public QAbstractTableModel { Q_OBJECT public: - enum {Name,Shortcuts,Preferred,ColumnCount}; - explicit ProvidersModel(QObject* parent = nullptr): QAbstractTableModel(parent){} + enum {Name, Shortcuts, Preferred, ColumnCount}; + explicit ProvidersModel(QObject *parent = nullptr) : QAbstractTableModel(parent) + { + } + ~ProvidersModel(); - Qt::ItemFlags flags(const QModelIndex& index) const override; + Qt::ItemFlags flags(const QModelIndex &index) const override; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - bool setData (const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - int rowCount(const QModelIndex& parent = QModelIndex()) const override; - int columnCount(const QModelIndex& parent = QModelIndex()) const override{Q_UNUSED(parent); return ColumnCount;} - - void setProviders(const QList&, const QStringList&); - void setFavoriteProviders(const QStringList&); - void addProvider(SearchProvider* p); - void deleteProvider(SearchProvider* p); - void changeProvider(SearchProvider* p); + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override + { + Q_UNUSED(parent); + return ColumnCount; + } + + void setProviders(const QList &, const QStringList &); + void setFavoriteProviders(const QStringList &); + void addProvider(SearchProvider *p); + void deleteProvider(SearchProvider *p); + void changeProvider(SearchProvider *p); QStringList favoriteEngines() const; - QList providers() const{ return m_providers;} + QList providers() const + { + return m_providers; + } ///Creates new ProvidersListModel which directly uses data of this model. - QAbstractListModel* createListModel(); + QAbstractListModel *createListModel(); Q_SIGNALS: void dataModified(); private: QSet m_favoriteEngines; - QList m_providers; + QList m_providers; }; /** * A model for kcombobox of default search engine. * It is created via ProvidersModel::createListModel() and uses createListModel's data directly, * just forwarding all the signals */ -class ProvidersListModel: public QAbstractListModel +class ProvidersListModel : public QAbstractListModel { Q_OBJECT public: - enum{ShortNameRole = Qt::UserRole}; + enum {ShortNameRole = Qt::UserRole}; private: - explicit ProvidersListModel(QList& providers, QObject* parent = nullptr) ; + explicit ProvidersListModel(QList &providers, QObject *parent = nullptr); public: - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - int rowCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; public Q_SLOTS: - void emitDataChanged(const QModelIndex& start, const QModelIndex& end){emit dataChanged(index(start.row(),0),index(end.row(),0));} - void emitRowsAboutToBeInserted(const QModelIndex&, int start, int end){beginInsertRows(QModelIndex(),start,end);} - void emitRowsAboutToBeRemoved(const QModelIndex&, int start, int end){beginRemoveRows(QModelIndex(),start,end);} - void emitRowsInserted(const QModelIndex&, int , int){endInsertRows();} - void emitRowsRemoved(const QModelIndex& , int , int){endRemoveRows();} + void emitDataChanged(const QModelIndex &start, const QModelIndex &end) + { + emit dataChanged(index(start.row(), 0), index(end.row(), 0)); + } + + void emitRowsAboutToBeInserted(const QModelIndex &, int start, int end) + { + beginInsertRows(QModelIndex(), start, end); + } + + void emitRowsAboutToBeRemoved(const QModelIndex &, int start, int end) + { + beginRemoveRows(QModelIndex(), start, end); + } + + void emitRowsInserted(const QModelIndex &, int, int) + { + endInsertRows(); + } + + void emitRowsRemoved(const QModelIndex &, int, int) + { + endRemoveRows(); + } private: - QList& m_providers; + QList &m_providers; friend class ProvidersModel; }; #endif diff --git a/src/urifilters/ikws/kuriikwsfilter.cpp b/src/urifilters/ikws/kuriikwsfilter.cpp index 70c720f4..ec472207 100644 --- a/src/urifilters/ikws/kuriikwsfilter.cpp +++ b/src/urifilters/ikws/kuriikwsfilter.cpp @@ -1,172 +1,162 @@ /* This file is part of the KDE project Copyright (C) 1999 Simon Hausmann Copyright (C) 2000 Yves Arrouye Copyright (C) 2002, 2003 Dawit Alemayehu 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 2 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kuriikwsfilter.h" #include "kuriikwsfiltereng.h" #include "searchprovider.h" #include "ikwsopts.h" #include #include #include #include #define QL1S(x) QLatin1String(x) #define QL1C(x) QLatin1Char(x) namespace { QLoggingCategory category("org.kde.kurifilter-ikws", QtWarningMsg); } /** * IMPORTANT: If you change anything here, make sure you run the kurifiltertest * regression test (this should be included as part of "make test"). */ K_PLUGIN_CLASS_WITH_JSON(KAutoWebSearch, "kuriikwsfilter.json") -KAutoWebSearch::KAutoWebSearch(QObject *parent, const QVariantList&) - :KUriFilterPlugin( QStringLiteral("kuriikwsfilter"), parent ) +KAutoWebSearch::KAutoWebSearch(QObject *parent, const QVariantList &) + : KUriFilterPlugin(QStringLiteral("kuriikwsfilter"), parent) { - KLocalizedString::insertQtDomain("kurifilter"); - QDBusConnection::sessionBus().connect(QString(), QStringLiteral("/"), QStringLiteral("org.kde.KUriFilterPlugin"), - QStringLiteral("configure"), this, SLOT(configure())); + KLocalizedString::insertQtDomain("kurifilter"); + QDBusConnection::sessionBus().connect(QString(), QStringLiteral("/"), QStringLiteral("org.kde.KUriFilterPlugin"), + QStringLiteral("configure"), this, SLOT(configure())); } KAutoWebSearch::~KAutoWebSearch() { } void KAutoWebSearch::configure() { - qCDebug(category) << "Config reload requested..."; - KURISearchFilterEngine::self()->loadConfig(); + qCDebug(category) << "Config reload requested..."; + KURISearchFilterEngine::self()->loadConfig(); } -void KAutoWebSearch::populateProvidersList(QList& searchProviders, - const KUriFilterData& data, bool allproviders) const +void KAutoWebSearch::populateProvidersList(QList &searchProviders, const KUriFilterData &data, bool allproviders) const { - QList providers; - KURISearchFilterEngine *filter = KURISearchFilterEngine::self(); - - if (allproviders) - providers = filter->registry()->findAll(); - else - { - // Start with the search engines marked as preferred... - QStringList favEngines = filter->favoriteEngineList(); - if (favEngines.isEmpty()) - favEngines = data.alternateSearchProviders(); - - // Get rid of duplicates... - favEngines.removeDuplicates(); - - // Sort the items... - std::stable_sort(favEngines.begin(), favEngines.end()); - - // Add the search engine set as the default provider... - const QString defaultEngine = filter->defaultSearchEngine(); - if (!defaultEngine.isEmpty()) { - favEngines.removeAll(defaultEngine); - favEngines.insert(0, defaultEngine); - } + QList providers; + KURISearchFilterEngine *filter = KURISearchFilterEngine::self(); - QStringListIterator it (favEngines); - while (it.hasNext()) - { - SearchProvider *favProvider = filter->registry()->findByDesktopName(it.next()); - if (favProvider) - providers << favProvider; + if (allproviders) { + providers = filter->registry()->findAll(); + } else { + // Start with the search engines marked as preferred... + QStringList favEngines = filter->favoriteEngineList(); + if (favEngines.isEmpty()) { + favEngines = data.alternateSearchProviders(); + } + + // Get rid of duplicates... + favEngines.removeDuplicates(); + + // Sort the items... + std::stable_sort(favEngines.begin(), favEngines.end()); + + // Add the search engine set as the default provider... + const QString defaultEngine = filter->defaultSearchEngine(); + if (!defaultEngine.isEmpty()) { + favEngines.removeAll(defaultEngine); + favEngines.insert(0, defaultEngine); + } + + QStringListIterator it(favEngines); + while (it.hasNext()) + { + SearchProvider *favProvider = filter->registry()->findByDesktopName(it.next()); + if (favProvider) { + providers << favProvider; + } + } } - } - for (int i = 0, count = providers.count(); i < count; ++i) - { - searchProviders << providers[i]; - } + for (int i = 0, count = providers.count(); i < count; ++i) { + searchProviders << providers[i]; + } } -bool KAutoWebSearch::filterUri( KUriFilterData &data ) const +bool KAutoWebSearch::filterUri(KUriFilterData &data) const { - qCDebug(category) << data.typedString(); - - KUriFilterData::SearchFilterOptions option = data.searchFilteringOptions(); - - // Handle the flag to retrieve only preferred providers, no filtering... - if (option & KUriFilterData::RetrievePreferredSearchProvidersOnly) - { - QList searchProviders; - populateProvidersList(searchProviders, data); - if (searchProviders.isEmpty()) - { - if (!(option & KUriFilterData::RetrieveSearchProvidersOnly)) - { - setUriType(data, KUriFilterData::Error); - setErrorMsg(data, i18n("No preferred search providers were found.")); - return false; - } - } - else - { - setSearchProvider(data, QString(), data.typedString(), QL1C(KURISearchFilterEngine::self()->keywordDelimiter())); - setSearchProviders(data, searchProviders); - return true; - } - } - - if (option & KUriFilterData::RetrieveSearchProvidersOnly) - { - QList searchProviders; - populateProvidersList(searchProviders, data, true); - if (searchProviders.isEmpty()) - { - setUriType(data, KUriFilterData::Error); - setErrorMsg(data, i18n("No search providers were found.")); - return false; + qCDebug(category) << data.typedString(); + + KUriFilterData::SearchFilterOptions option = data.searchFilteringOptions(); + + // Handle the flag to retrieve only preferred providers, no filtering... + if (option & KUriFilterData::RetrievePreferredSearchProvidersOnly) { + QList searchProviders; + populateProvidersList(searchProviders, data); + if (searchProviders.isEmpty()) { + if (!(option & KUriFilterData::RetrieveSearchProvidersOnly)) { + setUriType(data, KUriFilterData::Error); + setErrorMsg(data, i18n("No preferred search providers were found.")); + return false; + } + } else { + setSearchProvider(data, QString(), data.typedString(), QL1C(KURISearchFilterEngine::self()->keywordDelimiter())); + setSearchProviders(data, searchProviders); + return true; + } } - setSearchProvider(data, QString(), data.typedString(), QL1C(KURISearchFilterEngine::self()->keywordDelimiter())); - setSearchProviders(data, searchProviders); - return true; - } + if (option & KUriFilterData::RetrieveSearchProvidersOnly) { + QList searchProviders; + populateProvidersList(searchProviders, data, true); + if (searchProviders.isEmpty()) { + setUriType(data, KUriFilterData::Error); + setErrorMsg(data, i18n("No search providers were found.")); + return false; + } + + setSearchProvider(data, QString(), data.typedString(), QL1C(KURISearchFilterEngine::self()->keywordDelimiter())); + setSearchProviders(data, searchProviders); + return true; + } - if ( data.uriType() == KUriFilterData::Unknown && data.uri().password().isEmpty() ) - { - KURISearchFilterEngine *filter = KURISearchFilterEngine::self(); - SearchProvider *provider = filter->autoWebSearchQuery( data.typedString(), data.alternateDefaultSearchProvider() ); - if( provider ) - { - const QUrl result = filter->formatResult(provider->query(), provider->charset(), - QString(), data.typedString(), true); - setFilteredUri(data, result); - setUriType( data, KUriFilterData::NetProtocol ); - setSearchProvider(data, provider->name(), data.typedString(), QL1C(filter->keywordDelimiter())); - - QList searchProviders; - populateProvidersList(searchProviders, data); - setSearchProviders(data, searchProviders); - return true; + if (data.uriType() == KUriFilterData::Unknown && data.uri().password().isEmpty()) { + KURISearchFilterEngine *filter = KURISearchFilterEngine::self(); + SearchProvider *provider = filter->autoWebSearchQuery(data.typedString(), data.alternateDefaultSearchProvider()); + if (provider) { + const QUrl result = filter->formatResult(provider->query(), provider->charset(), + QString(), data.typedString(), true); + setFilteredUri(data, result); + setUriType(data, KUriFilterData::NetProtocol); + setSearchProvider(data, provider->name(), data.typedString(), QL1C(filter->keywordDelimiter())); + + QList searchProviders; + populateProvidersList(searchProviders, data); + setSearchProviders(data, searchProviders); + return true; + } } - } - return false; + return false; } #include "kuriikwsfilter.moc" diff --git a/src/urifilters/ikws/kuriikwsfilter.h b/src/urifilters/ikws/kuriikwsfilter.h index d4310dc3..0dc5f953 100644 --- a/src/urifilters/ikws/kuriikwsfilter.h +++ b/src/urifilters/ikws/kuriikwsfilter.h @@ -1,43 +1,43 @@ /* This file is part of the KDE project Copyright (C) 1999 Simon Hausmann Copyright (C) 2000 Yves Arrouye Copyright (C) 2002, 2003 Dawit Alemayehu 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 2 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KURIIKWSFILTER_H #define KURIIKWSFILTER_H #include #include class KAutoWebSearch : public KUriFilterPlugin { Q_OBJECT public: - explicit KAutoWebSearch(QObject *parent = nullptr, const QVariantList &args = QVariantList() ); + explicit KAutoWebSearch(QObject *parent = nullptr, const QVariantList &args = QVariantList()); ~KAutoWebSearch(); - bool filterUri( KUriFilterData& ) const override; + bool filterUri(KUriFilterData &) const override; public Q_SLOTS: void configure(); private: - void populateProvidersList(QList& searchProviders, const KUriFilterData&, bool allproviders = false) const; + void populateProvidersList(QList &searchProviders, const KUriFilterData &, bool allproviders = false) const; }; #endif diff --git a/src/urifilters/ikws/kuriikwsfiltereng.cpp b/src/urifilters/ikws/kuriikwsfiltereng.cpp index 8c8c92ad..a36f98ee 100644 --- a/src/urifilters/ikws/kuriikwsfiltereng.cpp +++ b/src/urifilters/ikws/kuriikwsfiltereng.cpp @@ -1,449 +1,428 @@ - /* This file is part of the KDE project Copyright (C) 2002, 2003 Dawit Alemayehu Copyright (C) 2000 Yves Arrouye Copyright (C) 1999 Simon Hausmann Advanced web shortcuts: Copyright (C) 2001 Andreas Hochsteger - 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 2 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kuriikwsfiltereng.h" #include "searchprovider.h" #include #include #include #include #include namespace { QLoggingCategory category("org.kde.kurifilter-ikws", QtWarningMsg); } -#define PDVAR(n,v) qCDebug(category) << n << " = '" << v << "'" +#define PDVAR(n, v) qCDebug(category) << n << " = '" << v << "'" /** * IMPORTANT: If you change anything here, make sure you run the kurifiltertest * regression test (this should be included as part of "make test"). */ KURISearchFilterEngine::KURISearchFilterEngine() { - loadConfig(); + loadConfig(); } KURISearchFilterEngine::~KURISearchFilterEngine() { } -SearchProvider* KURISearchFilterEngine::webShortcutQuery(const QString& typedString, QString &searchTerm) const +SearchProvider *KURISearchFilterEngine::webShortcutQuery(const QString &typedString, QString &searchTerm) const { - SearchProvider *provider = nullptr; + SearchProvider *provider = nullptr; - if (m_bWebShortcutsEnabled) - { - const int pos = typedString.indexOf(QLatin1Char(m_cKeywordDelimiter)); + if (m_bWebShortcutsEnabled) { + const int pos = typedString.indexOf(QLatin1Char(m_cKeywordDelimiter)); - QString key; - if ( pos > -1 ) - key = typedString.left(pos).toLower(); // #169801 - else if ( !typedString.isEmpty() && m_cKeywordDelimiter == ' ') - key = typedString; - - qCDebug(category) << "m_cKeywordDelimiter=" << QLatin1Char(m_cKeywordDelimiter) << "pos=" << pos << "key=" << key; + QString key; + if (pos > -1) { + key = typedString.left(pos).toLower(); // #169801 + } else if (!typedString.isEmpty() && m_cKeywordDelimiter == ' ') { + key = typedString; + } - if (!key.isEmpty() && !KProtocolInfo::isKnownProtocol(key)) - { - provider = m_registry.findByKey(key); - if (provider) - { - if (!m_bUseOnlyPreferredWebShortcuts || m_preferredWebShortcuts.contains(provider->desktopEntryName())) { - searchTerm = typedString.mid(pos+1); - qCDebug(category) << "found provider" << provider->desktopEntryName() << "searchTerm=" << searchTerm; - } else { - provider = nullptr; + qCDebug(category) << "m_cKeywordDelimiter=" << QLatin1Char(m_cKeywordDelimiter) << "pos=" << pos << "key=" << key; + + if (!key.isEmpty() && !KProtocolInfo::isKnownProtocol(key)) { + provider = m_registry.findByKey(key); + if (provider) { + if (!m_bUseOnlyPreferredWebShortcuts || m_preferredWebShortcuts.contains(provider->desktopEntryName())) { + searchTerm = typedString.mid(pos+1); + qCDebug(category) << "found provider" << provider->desktopEntryName() << "searchTerm=" << searchTerm; + } else { + provider = nullptr; + } + } } - } } - } - return provider; + return provider; } - -SearchProvider* KURISearchFilterEngine::autoWebSearchQuery(const QString& typedString, const QString &defaultShortcut) const +SearchProvider *KURISearchFilterEngine::autoWebSearchQuery(const QString &typedString, const QString &defaultShortcut) const { - SearchProvider *provider = nullptr; - const QString defaultSearchProvider = (m_defaultWebShortcut.isEmpty() ? defaultShortcut : m_defaultWebShortcut); + SearchProvider *provider = nullptr; + const QString defaultSearchProvider = (m_defaultWebShortcut.isEmpty() ? defaultShortcut : m_defaultWebShortcut); - if (m_bWebShortcutsEnabled && !defaultSearchProvider.isEmpty()) - { - // Make sure we ignore supported protocols, e.g. "smb:", "http:" - const int pos = typedString.indexOf(QLatin1Char(':')); + if (m_bWebShortcutsEnabled && !defaultSearchProvider.isEmpty()) { + // Make sure we ignore supported protocols, e.g. "smb:", "http:" + const int pos = typedString.indexOf(QLatin1Char(':')); - if (pos == -1 || !KProtocolInfo::isKnownProtocol(typedString.left(pos))) { - provider = m_registry.findByDesktopName(defaultSearchProvider); + if (pos == -1 || !KProtocolInfo::isKnownProtocol(typedString.left(pos))) { + provider = m_registry.findByDesktopName(defaultSearchProvider); + } } - } - return provider; + return provider; } QByteArray KURISearchFilterEngine::name() const { - return "kuriikwsfilter"; + return "kuriikwsfilter"; } char KURISearchFilterEngine::keywordDelimiter() const { - return m_cKeywordDelimiter; + return m_cKeywordDelimiter; } QString KURISearchFilterEngine::defaultSearchEngine() const { - return m_defaultWebShortcut; + return m_defaultWebShortcut; } QStringList KURISearchFilterEngine::favoriteEngineList() const { - return m_preferredWebShortcuts; + return m_preferredWebShortcuts; } Q_GLOBAL_STATIC(KURISearchFilterEngine, sSelfPtr) -KURISearchFilterEngine* KURISearchFilterEngine::self() +KURISearchFilterEngine *KURISearchFilterEngine::self() { - return sSelfPtr; + return sSelfPtr; } -QStringList KURISearchFilterEngine::modifySubstitutionMap(SubstMap& map, - const QString& query) const +QStringList KURISearchFilterEngine::modifySubstitutionMap(SubstMap &map, const QString &query) const { - // Returns the number of query words - QString userquery = query; - - // Do some pre-encoding, before we can start the work: - { - int start = 0; - int pos = 0; - QRegExp qsexpr(QStringLiteral("\\\"[^\\\"]*\\\"")); - - // Temporary substitute spaces in quoted strings (" " -> "%20") - // Needed to split user query into StringList correctly. - while ((pos = qsexpr.indexIn(userquery, start)) >= 0) + // Returns the number of query words + QString userquery = query; + + // Do some pre-encoding, before we can start the work: { - QString s = userquery.mid (pos, qsexpr.matchedLength()); - s.replace(QLatin1Char(' '), QLatin1String("%20")); - start = pos + s.length(); // Move after last quote - userquery.replace (pos, qsexpr.matchedLength(), s); + int start = 0; + int pos = 0; + QRegExp qsexpr(QStringLiteral("\\\"[^\\\"]*\\\"")); + + // Temporary substitute spaces in quoted strings (" " -> "%20") + // Needed to split user query into StringList correctly. + while ((pos = qsexpr.indexIn(userquery, start)) >= 0) + { + QString s = userquery.mid(pos, qsexpr.matchedLength()); + s.replace(QLatin1Char(' '), QLatin1String("%20")); + start = pos + s.length(); // Move after last quote + userquery.replace(pos, qsexpr.matchedLength(), s); + } } - } - - // Split user query between spaces: - QStringList l = userquery.simplified().split(QLatin1Char(' '), QString::SkipEmptyParts); - - // Back-substitute quoted strings (%20 -> " "): - userquery.replace (QLatin1String("%20"), QLatin1String(" ")); - l.replaceInStrings(QStringLiteral("%20"), QStringLiteral(" ")); - - qCDebug(category) << "Generating substitution map:\n"; - // Generate substitution map from user query: - for (int i=0; i<=l.count(); i++) - { - int pos = 0; - QString v; - QString nr = QString::number(i); - - // Add whole user query (\{0}) to substitution map: - if (i==0) - v = userquery; - // Add partial user query items to substitution map: - else - v = l[i-1]; - - // Insert partial queries (referenced by \1 ... \n) to map: - map.insert(QString::number(i), v); - PDVAR (QLatin1String(" map['") + nr + QLatin1String("']"), map[nr]); - - // Insert named references (referenced by \name) to map: - if ((i>0) && (pos = v.indexOf(QLatin1Char('='))) > 0) - { - QString s = v.mid(pos + 1); - QString k = v.left(pos); - // Back-substitute references contained in references (e.g. '\refname' substitutes to 'thisquery=\0') - s.replace(QLatin1String("%5C"), QLatin1String("\\")); - map.insert(k, s); - PDVAR (QLatin1String(" map['") + k + QLatin1String("']"), map[k]); + // Split user query between spaces: + QStringList l = userquery.simplified().split(QLatin1Char(' '), QString::SkipEmptyParts); + + // Back-substitute quoted strings (%20 -> " "): + userquery.replace(QLatin1String("%20"), QLatin1String(" ")); + l.replaceInStrings(QStringLiteral("%20"), QStringLiteral(" ")); + + qCDebug(category) << "Generating substitution map:\n"; + // Generate substitution map from user query: + for (int i = 0; i <= l.count(); i++) { + int pos = 0; + QString v; + QString nr = QString::number(i); + + // Add whole user query (\{0}) to substitution map: + if (i == 0) { + v = userquery; + } + // Add partial user query items to substitution map: + else { + v = l[i-1]; + } + + // Insert partial queries (referenced by \1 ... \n) to map: + map.insert(QString::number(i), v); + PDVAR(QLatin1String(" map['") + nr + QLatin1String("']"), map[nr]); + + // Insert named references (referenced by \name) to map: + if ((i > 0) && (pos = v.indexOf(QLatin1Char('='))) > 0) { + QString s = v.mid(pos + 1); + QString k = v.left(pos); + + // Back-substitute references contained in references (e.g. '\refname' substitutes to 'thisquery=\0') + s.replace(QLatin1String("%5C"), QLatin1String("\\")); + map.insert(k, s); + PDVAR(QLatin1String(" map['") + k + QLatin1String("']"), map[k]); + } } - } - return l; + return l; } -static QString encodeString(const QString& s, QTextCodec *codec) +static QString encodeString(const QString &s, QTextCodec *codec) { // don't encode the space character, we replace it with + after the encoding QByteArray encoded = codec->fromUnicode(s).toPercentEncoding(QByteArrayLiteral(" ")); encoded.replace(' ', '+'); return QString::fromUtf8(encoded); } -QString KURISearchFilterEngine::substituteQuery(const QString& url, SubstMap &map, const QString& userquery, QTextCodec *codec) const +QString KURISearchFilterEngine::substituteQuery(const QString &url, SubstMap &map, const QString &userquery, QTextCodec *codec) const { - QString newurl = url; - QStringList ql = modifySubstitutionMap (map, userquery); - int count = ql.count(); - - // Check, if old style '\1' is found and replace it with \{@} (compatibility mode): - { - int pos = -1; - if ((pos = newurl.indexOf(QLatin1String("\\1"))) >= 0) + QString newurl = url; + QStringList ql = modifySubstitutionMap(map, userquery); + int count = ql.count(); + + // Check, if old style '\1' is found and replace it with \{@} (compatibility mode): { - qCWarning(category) << "WARNING: Using compatibility mode for newurl='" << newurl - << "'. Please replace old style '\\1' with new style '\\{0}' " - "in the query definition.\n"; - newurl.replace(pos, 2, QStringLiteral("\\{@}")); + int pos = -1; + if ((pos = newurl.indexOf(QLatin1String("\\1"))) >= 0) { + qCWarning(category) << "WARNING: Using compatibility mode for newurl='" << newurl + << "'. Please replace old style '\\1' with new style '\\{0}' " + "in the query definition.\n"; + newurl.replace(pos, 2, QStringLiteral("\\{@}")); + } } - } - qCDebug(category) << "Substitute references:\n"; - // Substitute references (\{ref1,ref2,...}) with values from user query: - { - int pos = 0; - QRegExp reflist(QStringLiteral("\\\\\\{[^\\}]+\\}")); - - // Substitute reflists (\{ref1,ref2,...}): - while ((pos = reflist.indexIn(newurl)) >= 0) + qCDebug(category) << "Substitute references:\n"; + // Substitute references (\{ref1,ref2,...}) with values from user query: { - bool found = false; - - //bool rest = false; - QString v; - QString rlstring = newurl.mid(pos + 2, reflist.matchedLength() - 3); - PDVAR (" reference list", rlstring); - - // \{@} gets a special treatment later - if (rlstring == QLatin1String("@")) - { - v = QStringLiteral("\\@"); - found = true; - } - - // TODO: strip whitespaces around commas - QStringList rl = rlstring.split(QLatin1Char(','), QString::SkipEmptyParts); - int i = 0; - - while ((i= 0) + int pos = 0; + QRegExp reflist(QStringLiteral("\\\\\\{[^\\}]+\\}")); + + // Substitute reflists (\{ref1,ref2,...}): + while ((pos = reflist.indexIn(newurl)) >= 0) { - int pos = rlitem.indexOf(QLatin1Char('-')); - int first = rlitem.leftRef(pos).toInt(); - int last = rlitem.rightRef(rlitem.length()-pos-1).toInt(); + bool found = false; + + //bool rest = false; + QString v; + QString rlstring = newurl.mid(pos + 2, reflist.matchedLength() - 3); + PDVAR(" reference list", rlstring); + + // \{@} gets a special treatment later + if (rlstring == QLatin1String("@")) { + v = QStringLiteral("\\@"); + found = true; + } + + // TODO: strip whitespaces around commas + QStringList rl = rlstring.split(QLatin1Char(','), QString::SkipEmptyParts); + int i = 0; + + while ((i < rl.count()) && !found) + { + QString rlitem = rl[i]; + QRegExp range(QStringLiteral("[0-9]*\\-[0-9]*")); + + // Substitute a range of keywords + if (range.indexIn(rlitem) >= 0) { + int pos = rlitem.indexOf(QLatin1Char('-')); + int first = rlitem.leftRef(pos).toInt(); + int last = rlitem.rightRef(rlitem.length()-pos-1).toInt(); + + if (first == 0) { + first = 1; + } + + if (last == 0) { + last = count; + } + + for (int i = first; i <= last; i++) { + v += map[QString::number(i)] + QLatin1Char(' '); + // Remove used value from ql (needed for \{@}): + ql[i-1] = QLatin1String(""); + } + + v = v.trimmed(); + if (!v.isEmpty()) { + found = true; + } + + PDVAR(QLatin1String(" range"), QString::number(first) + QLatin1Char('-') + QString::number(last) + QLatin1String(" => '") + v + QLatin1Char('\'')); + v = encodeString(v, codec); + } else if (rlitem.startsWith(QLatin1Char('\"')) && rlitem.endsWith(QLatin1Char('\"'))) { + // Use default string from query definition: + found = true; + QString s = rlitem.mid(1, rlitem.length() - 2); + v = encodeString(s, codec); + PDVAR(" default", s); + } else if (map.contains(rlitem)) { + // Use value from substitution map: + found = true; + PDVAR(QLatin1String(" map['") + rlitem + QLatin1String("']"), map[rlitem]); + v = encodeString(map[rlitem], codec); + + // Remove used value from ql (needed for \{@}): + QString c = rlitem.left(1); + if (c == QLatin1Char('0')) { + // It's a numeric reference to '0' + for (QStringList::Iterator it = ql.begin(); it != ql.end(); ++it) { + (*it) = QLatin1String(""); + } + } else if ((c >= QLatin1String("0")) && (c <= QLatin1String("9"))) { // krazy:excludeall=doublequote_chars + // It's a numeric reference > '0' + int n = rlitem.toInt(); + ql[n-1] = QLatin1String(""); + } else { + // It's a alphanumeric reference + QStringList::Iterator it = ql.begin(); + while ((it != ql.end()) && !it->startsWith(rlitem + QLatin1Char('='))) { + ++it; + } + if (it != ql.end()) { + it->clear(); + } + } + + // Encode '+', otherwise it would be interpreted as space in the resulting url: + v.replace(QLatin1Char('+'), QLatin1String("%2B")); + } else if (rlitem == QLatin1String("@")) { + v = QStringLiteral("\\@"); + PDVAR(" v", v); + } + + i++; + } + + newurl.replace(pos, reflist.matchedLength(), v); + } - if (first == 0) - first = 1; + // Special handling for \{@}; + { + PDVAR(" newurl", newurl); + // Generate list of unmatched strings: + QString v = ql.join(QLatin1Char(' ')).simplified(); - if (last == 0) - last = count; + PDVAR(" rest", v); + v = encodeString(v, codec); - for (int i=first; i<=last; i++) - { - v += map[QString::number(i)] + QLatin1Char(' '); - // Remove used value from ql (needed for \{@}): - ql[i-1] = QLatin1String(""); - } + // Substitute \{@} with list of unmatched query strings + newurl.replace(QLatin1String("\\@"), v); + } + } - v = v.trimmed(); - if (!v.isEmpty()) - found = true; + return newurl; +} - PDVAR (QLatin1String(" range"), QString::number(first) + QLatin1Char('-') + QString::number(last) + QLatin1String(" => '") + v + QLatin1Char('\'')); - v = encodeString(v, codec); - } - else if (rlitem.startsWith(QLatin1Char('\"')) && rlitem.endsWith(QLatin1Char('\"'))) - { - // Use default string from query definition: - found = true; - QString s = rlitem.mid(1, rlitem.length() - 2); - v = encodeString(s, codec); - PDVAR (" default", s); - } - else if (map.contains(rlitem)) - { - // Use value from substitution map: - found = true; - PDVAR (QLatin1String(" map['") + rlitem + QLatin1String("']"), map[rlitem]); - v = encodeString(map[rlitem], codec); - - // Remove used value from ql (needed for \{@}): - QString c = rlitem.left(1); - if (c== QLatin1Char('0')) - { - // It's a numeric reference to '0' - for (QStringList::Iterator it = ql.begin(); it!=ql.end(); ++it) - (*it) = QLatin1String(""); - } - else if ((c>=QLatin1String("0")) && (c<=QLatin1String("9"))) // krazy:excludeall=doublequote_chars - { - // It's a numeric reference > '0' - int n = rlitem.toInt(); - ql[n-1] = QLatin1String(""); - } - else - { - // It's a alphanumeric reference - QStringList::Iterator it = ql.begin(); - while ((it != ql.end()) && !it->startsWith(rlitem + QLatin1Char('='))) - ++it; - if (it != ql.end()) - it->clear(); - } - - // Encode '+', otherwise it would be interpreted as space in the resulting url: - v.replace(QLatin1Char('+'), QLatin1String("%2B")); - } - else if (rlitem == QLatin1String("@")) - { - v = QStringLiteral("\\@"); - PDVAR (" v", v); +QUrl KURISearchFilterEngine::formatResult(const QString &url, const QString &cset1, const QString &cset2, const QString &query, bool isMalformed) const +{ + SubstMap map; + return formatResult(url, cset1, cset2, query, isMalformed, map); +} + +QUrl KURISearchFilterEngine::formatResult(const QString &url, const QString &cset1, const QString &cset2, const QString &userquery, bool /* isMalformed */, SubstMap &map) const +{ + // Return nothing if userquery is empty and it contains + // substitution strings... + if (userquery.isEmpty() && url.indexOf(QLatin1String("\\{")) > 0) { + return QUrl(); + } + + // Debug info of map: + if (!map.isEmpty()) { + qCDebug(category) << "Got non-empty substitution map:\n"; + for (SubstMap::Iterator it = map.begin(); it != map.end(); ++it) { + PDVAR(QLatin1String(" map['") + it.key() + QLatin1String("']"), it.value()); } + } - i++; - } + // Create a codec for the desired encoding so that we can transcode the user's "url". + QString cseta = cset1; + if (cseta.isEmpty()) { + cseta = QStringLiteral("UTF-8"); + } - newurl.replace(pos, reflist.matchedLength(), v); + QTextCodec *csetacodec = QTextCodec::codecForName(cseta.toLatin1()); + if (!csetacodec) { + cseta = QStringLiteral("UTF-8"); + csetacodec = QTextCodec::codecForName(cseta.toLatin1()); } - // Special handling for \{@}; - { - PDVAR (" newurl", newurl); - // Generate list of unmatched strings: - QString v = ql.join(QLatin1Char(' ')).simplified(); + PDVAR("user query", userquery); + PDVAR("query definition", url); - PDVAR (" rest", v); - v = encodeString(v, codec); + // Add charset indicator for the query to substitution map: + map.insert(QStringLiteral("ikw_charset"), cseta); - // Substitute \{@} with list of unmatched query strings - newurl.replace(QLatin1String("\\@"), v); + // Add charset indicator for the fallback query to substitution map: + QString csetb = cset2; + if (csetb.isEmpty()) { + csetb = QStringLiteral("UTF-8"); } - } + map.insert(QStringLiteral("wsc_charset"), csetb); - return newurl; -} + QString newurl = substituteQuery(url, map, userquery, csetacodec); -QUrl KURISearchFilterEngine::formatResult( const QString& url, - const QString& cset1, - const QString& cset2, - const QString& query, - bool isMalformed ) const -{ - SubstMap map; - return formatResult (url, cset1, cset2, query, isMalformed, map); -} + PDVAR("substituted query", newurl); -QUrl KURISearchFilterEngine::formatResult( const QString& url, - const QString& cset1, - const QString& cset2, - const QString& userquery, - bool /* isMalformed */, - SubstMap& map ) const -{ - // Return nothing if userquery is empty and it contains - // substitution strings... - if (userquery.isEmpty() && url.indexOf(QLatin1String("\\{")) > 0) - return QUrl(); - - // Debug info of map: - if (!map.isEmpty()) - { - qCDebug(category) << "Got non-empty substitution map:\n"; - for(SubstMap::Iterator it = map.begin(); it != map.end(); ++it) - PDVAR (QLatin1String(" map['") + it.key() + QLatin1String("']"), it.value()); - } - - // Create a codec for the desired encoding so that we can transcode the user's "url". - QString cseta = cset1; - if (cseta.isEmpty()) - cseta = QStringLiteral("UTF-8"); - - QTextCodec *csetacodec = QTextCodec::codecForName(cseta.toLatin1()); - if (!csetacodec) - { - cseta = QStringLiteral("UTF-8"); - csetacodec = QTextCodec::codecForName(cseta.toLatin1()); - } - - PDVAR ("user query", userquery); - PDVAR ("query definition", url); - - // Add charset indicator for the query to substitution map: - map.insert(QStringLiteral("ikw_charset"), cseta); - - // Add charset indicator for the fallback query to substitution map: - QString csetb = cset2; - if (csetb.isEmpty()) - csetb = QStringLiteral("UTF-8"); - map.insert(QStringLiteral("wsc_charset"), csetb); - - QString newurl = substituteQuery (url, map, userquery, csetacodec); - - PDVAR ("substituted query", newurl); - - return QUrl(newurl, QUrl::StrictMode); + return QUrl(newurl, QUrl::StrictMode); } void KURISearchFilterEngine::loadConfig() { - qCDebug(category) << "Keywords Engine: Loading config..."; + qCDebug(category) << "Keywords Engine: Loading config..."; - // Load the config. - KConfig config(QString::fromUtf8(name()) + QLatin1String("rc"), KConfig::NoGlobals); - KConfigGroup group = config.group( "General" ); + // Load the config. + KConfig config(QString::fromUtf8(name()) + QLatin1String("rc"), KConfig::NoGlobals); + KConfigGroup group = config.group("General"); - m_cKeywordDelimiter = QString(group.readEntry("KeywordDelimiter", ":")).at(0).toLatin1(); - m_bWebShortcutsEnabled = group.readEntry("EnableWebShortcuts", true); - m_defaultWebShortcut = group.readEntry("DefaultWebShortcut"); - m_bUseOnlyPreferredWebShortcuts = group.readEntry("UsePreferredWebShortcutsOnly", false); + m_cKeywordDelimiter = QString(group.readEntry("KeywordDelimiter", ":")).at(0).toLatin1(); + m_bWebShortcutsEnabled = group.readEntry("EnableWebShortcuts", true); + m_defaultWebShortcut = group.readEntry("DefaultWebShortcut"); + m_bUseOnlyPreferredWebShortcuts = group.readEntry("UsePreferredWebShortcutsOnly", false); - QStringList defaultPreferredShortcuts; - if (!group.hasKey("PreferredWebShortcuts")) - defaultPreferredShortcuts = DEFAULT_PREFERRED_SEARCH_PROVIDERS; - m_preferredWebShortcuts = group.readEntry("PreferredWebShortcuts", defaultPreferredShortcuts); + QStringList defaultPreferredShortcuts; + if (!group.hasKey("PreferredWebShortcuts")) { + defaultPreferredShortcuts = DEFAULT_PREFERRED_SEARCH_PROVIDERS; + } + m_preferredWebShortcuts = group.readEntry("PreferredWebShortcuts", defaultPreferredShortcuts); - // Use either a white space or a : as the keyword delimiter... - if (strchr (" :", m_cKeywordDelimiter) == nullptr) - m_cKeywordDelimiter = ':'; + // Use either a white space or a : as the keyword delimiter... + if (strchr(" :", m_cKeywordDelimiter) == nullptr) { + m_cKeywordDelimiter = ':'; + } - qCDebug(category) << "Web Shortcuts Enabled: " << m_bWebShortcutsEnabled; - qCDebug(category) << "Default Shortcut: " << m_defaultWebShortcut; - qCDebug(category) << "Keyword Delimiter: " << m_cKeywordDelimiter; + qCDebug(category) << "Web Shortcuts Enabled: " << m_bWebShortcutsEnabled; + qCDebug(category) << "Default Shortcut: " << m_defaultWebShortcut; + qCDebug(category) << "Keyword Delimiter: " << m_cKeywordDelimiter; } -SearchProviderRegistry * KURISearchFilterEngine::registry() +SearchProviderRegistry *KURISearchFilterEngine::registry() { - return &m_registry; + return &m_registry; } diff --git a/src/urifilters/ikws/kuriikwsfiltereng.h b/src/urifilters/ikws/kuriikwsfiltereng.h index 46f8b0ff..2b5662b1 100644 --- a/src/urifilters/ikws/kuriikwsfiltereng.h +++ b/src/urifilters/ikws/kuriikwsfiltereng.h @@ -1,80 +1,77 @@ /* This file is part of the KDE project Copyright (C) 2002,2003 Dawit Alemayehu Copyright (C) 1999 Simon Hausmann Copyright (C) 1999 Yves Arrouye Advanced web shortcuts Copyright (C) 2001 Andreas Hochsteger 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 2 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KURIIKWSFILTERENG_H #define KURIIKWSFILTERENG_H #include #include #include #include "searchproviderregistry.h" #define DEFAULT_PREFERRED_SEARCH_PROVIDERS \ -QStringList() << QStringLiteral("google") << QStringLiteral("youtube") << QStringLiteral("yahoo") << QStringLiteral("wikipedia") << QStringLiteral("wikit") + QStringList() << QStringLiteral("google") << QStringLiteral("youtube") << QStringLiteral("yahoo") << QStringLiteral("wikipedia") << QStringLiteral("wikit") class SearchProvider; class KURISearchFilterEngine { public: - typedef QMap SubstMap; + typedef QMap SubstMap; - KURISearchFilterEngine(); - ~KURISearchFilterEngine(); + KURISearchFilterEngine(); + ~KURISearchFilterEngine(); - QByteArray name() const; - char keywordDelimiter() const; - QString defaultSearchEngine() const; - QStringList favoriteEngineList() const; - SearchProvider* webShortcutQuery (const QString& typedString, QString& searchTerm) const; - SearchProvider* autoWebSearchQuery (const QString& typedString, const QString& defaultShortcut = QString()) const; - QUrl formatResult (const QString& url, const QString& cset1, const QString& cset2, - const QString& query, bool isMalformed) const; + QByteArray name() const; + char keywordDelimiter() const; + QString defaultSearchEngine() const; + QStringList favoriteEngineList() const; + SearchProvider *webShortcutQuery(const QString &typedString, QString &searchTerm) const; + SearchProvider *autoWebSearchQuery(const QString &typedString, const QString &defaultShortcut = QString()) const; + QUrl formatResult(const QString &url, const QString &cset1, const QString &cset2, const QString &query, bool isMalformed) const; - SearchProviderRegistry *registry(); + SearchProviderRegistry *registry(); + + static KURISearchFilterEngine *self(); + void loadConfig(); - static KURISearchFilterEngine *self(); - void loadConfig(); - protected: - QUrl formatResult (const QString& url, const QString& cset1, const QString& cset2, - const QString& query, bool isMalformed, SubstMap& map) const; + QUrl formatResult(const QString &url, const QString &cset1, const QString &cset2, const QString &query, bool isMalformed, SubstMap &map) const; private: - KURISearchFilterEngine(const KURISearchFilterEngine&) = delete; - KURISearchFilterEngine& operator= (const KURISearchFilterEngine&) = delete; - - QStringList modifySubstitutionMap (SubstMap& map, const QString& query) const; - QString substituteQuery (const QString& url, SubstMap &map, - const QString& userquery, QTextCodec *codec) const; - - SearchProviderRegistry m_registry; - QString m_defaultWebShortcut; - QStringList m_preferredWebShortcuts; - bool m_bWebShortcutsEnabled; - bool m_bUseOnlyPreferredWebShortcuts; - char m_cKeywordDelimiter; + KURISearchFilterEngine(const KURISearchFilterEngine &) = delete; + KURISearchFilterEngine &operator=(const KURISearchFilterEngine &) = delete; + + QStringList modifySubstitutionMap(SubstMap &map, const QString &query) const; + QString substituteQuery(const QString &url, SubstMap &map, const QString &userquery, QTextCodec *codec) const; + + SearchProviderRegistry m_registry; + QString m_defaultWebShortcut; + QStringList m_preferredWebShortcuts; + bool m_bWebShortcutsEnabled; + bool m_bUseOnlyPreferredWebShortcuts; + char m_cKeywordDelimiter; }; #endif // KURIIKWSFILTERENG_H diff --git a/src/urifilters/ikws/kurisearchfilter.cpp b/src/urifilters/ikws/kurisearchfilter.cpp index 08e79041..e47aded8 100644 --- a/src/urifilters/ikws/kurisearchfilter.cpp +++ b/src/urifilters/ikws/kurisearchfilter.cpp @@ -1,98 +1,97 @@ /* This file is part of the KDE project Copyright (C) 1999 Simon Hausmann Copyright (C) 2000 Yves Arrouye Copyright (C) 2002, 2003 Dawit Alemayehu 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 2 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kurisearchfilter.h" #include "kuriikwsfiltereng.h" #include "searchprovider.h" #include "ikwsopts.h" #include #include #include #include #include /** * IMPORTANT: If you change anything here, make sure you run the kurifiltertest * regression test (this should be included as part of "make test"). */ K_PLUGIN_CLASS_WITH_JSON(KUriSearchFilter, "kurisearchfilter.json") namespace { QLoggingCategory category("org.kde.kurifilter-ikws", QtWarningMsg); } KUriSearchFilter::KUriSearchFilter(QObject *parent, const QVariantList &) - :KUriFilterPlugin( QStringLiteral("kurisearchfilter"), parent ) + : KUriFilterPlugin(QStringLiteral("kurisearchfilter"), parent) { - KLocalizedString::insertQtDomain("kurifilter"); - QDBusConnection::sessionBus().connect(QString(), QStringLiteral("/"), QStringLiteral("org.kde.KUriFilterPlugin"), - QStringLiteral("configure"), this, SLOT(configure())); + KLocalizedString::insertQtDomain("kurifilter"); + QDBusConnection::sessionBus().connect(QString(), QStringLiteral("/"), QStringLiteral("org.kde.KUriFilterPlugin"), + QStringLiteral("configure"), this, SLOT(configure())); } KUriSearchFilter::~KUriSearchFilter() { } void KUriSearchFilter::configure() { - qCDebug(category) << "Config reload requested..."; - KURISearchFilterEngine::self()->loadConfig(); + qCDebug(category) << "Config reload requested..."; + KURISearchFilterEngine::self()->loadConfig(); } -bool KUriSearchFilter::filterUri( KUriFilterData &data ) const +bool KUriSearchFilter::filterUri(KUriFilterData &data) const { - qCDebug(category) << data.typedString() << ":" << data.uri() << ", type =" << data.uriType(); - - - // some URLs like gg:www.kde.org are not accepted by QUrl, but we still want them - // This means we also have to allow KUriFilterData::Error - if (data.uriType() != KUriFilterData::Unknown && data.uriType() != KUriFilterData::Error) { - return false; - } - - QString searchTerm; - KURISearchFilterEngine *filter = KURISearchFilterEngine::self(); - SearchProvider* provider(filter->webShortcutQuery(data.typedString(), searchTerm)); - if (!provider) { - return false; - } - - const QUrl result = filter->formatResult(provider->query(), provider->charset(), QString(), searchTerm, true ); - setFilteredUri(data, result); - setUriType( data, KUriFilterData::NetProtocol ); - setSearchProvider( data, provider->name(), searchTerm, QLatin1Char(filter->keywordDelimiter())); - return true; + qCDebug(category) << data.typedString() << ":" << data.uri() << ", type =" << data.uriType(); + + // some URLs like gg:www.kde.org are not accepted by QUrl, but we still want them + // This means we also have to allow KUriFilterData::Error + if (data.uriType() != KUriFilterData::Unknown && data.uriType() != KUriFilterData::Error) { + return false; + } + + QString searchTerm; + KURISearchFilterEngine *filter = KURISearchFilterEngine::self(); + SearchProvider *provider(filter->webShortcutQuery(data.typedString(), searchTerm)); + if (!provider) { + return false; + } + + const QUrl result = filter->formatResult(provider->query(), provider->charset(), QString(), searchTerm, true); + setFilteredUri(data, result); + setUriType(data, KUriFilterData::NetProtocol); + setSearchProvider(data, provider->name(), searchTerm, QLatin1Char(filter->keywordDelimiter())); + return true; } KCModule *KUriSearchFilter::configModule(QWidget *parent, const char *) const { - return new FilterOptions( KAboutData::pluginData(QStringLiteral("kcmkurifilt")), parent); + return new FilterOptions(KAboutData::pluginData(QStringLiteral("kcmkurifilt")), parent); } QString KUriSearchFilter::configName() const { - return i18n("Search F&ilters"); + return i18n("Search F&ilters"); } #include "kurisearchfilter.moc" diff --git a/src/urifilters/ikws/kurisearchfilter.h b/src/urifilters/ikws/kurisearchfilter.h index 705eb3ac..8ed83145 100644 --- a/src/urifilters/ikws/kurisearchfilter.h +++ b/src/urifilters/ikws/kurisearchfilter.h @@ -1,42 +1,42 @@ /* This file is part of the KDE project Copyright (C) 1999 Simon Hausmann Copyright (C) 2000 Yves Arrouye Copyright (C) 2002, 2003 Dawit Alemayehu 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 2 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KURISEARCHFILTER_H #define KURISEARCHFILTER_H #include class KUriSearchFilter : public KUriFilterPlugin { Q_OBJECT public: - explicit KUriSearchFilter(QObject *parent = nullptr, const QVariantList &args = QVariantList() ); + explicit KUriSearchFilter(QObject *parent = nullptr, const QVariantList &args = QVariantList()); ~KUriSearchFilter(); - bool filterUri( KUriFilterData& ) const override; + bool filterUri(KUriFilterData &) const override; KCModule *configModule(QWidget *parent = nullptr, const char *name = nullptr) const override; QString configName() const override; public Q_SLOTS: void configure(); // maybe move to KUriFilterPlugin? }; #endif diff --git a/src/urifilters/ikws/searchprovider.cpp b/src/urifilters/ikws/searchprovider.cpp index b4570b16..d408f0dd 100644 --- a/src/urifilters/ikws/searchprovider.cpp +++ b/src/urifilters/ikws/searchprovider.cpp @@ -1,132 +1,136 @@ /* * Copyright (c) 2000 Malte Starostik * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "searchprovider.h" #include #include #include #include // KIO::iconNameForUrl #include #include #include SearchProvider::SearchProvider(const QString &servicePath) - : m_dirty(false) + : m_dirty(false) { setDesktopEntryName(QFileInfo(servicePath).baseName()); KDesktopFile parser(servicePath); setName(parser.readName()); KConfigGroup group(parser.desktopGroup()); setKeys(group.readEntry(QStringLiteral("Keys"), QStringList())); m_query = group.readEntry(QStringLiteral("Query")); m_charset = group.readEntry(QStringLiteral("Charset")); m_iconName = group.readEntry(QStringLiteral("Icon")); } SearchProvider::~SearchProvider() { } void SearchProvider::setName(const QString &name) { - if (KUriFilterSearchProvider::name() == name) + if (KUriFilterSearchProvider::name() == name) { return; + } KUriFilterSearchProvider::setName(name); } void SearchProvider::setQuery(const QString &query) { - if (m_query == query) + if (m_query == query) { return; + } m_query = query; } void SearchProvider::setKeys(const QStringList &keys) { - if (KUriFilterSearchProvider::keys() == keys) + if (KUriFilterSearchProvider::keys() == keys) { return; + } - KUriFilterSearchProvider::setKeys(keys); - - QString name = desktopEntryName(); - if (!name.isEmpty()) - return; - - // New provider. Set the desktopEntryName. - // Take the longest search shortcut as filename, - // if such a file already exists, append a number and increase it - // until the name is unique - for (const QString& key : keys) - { - if (key.length() > name.length()) - name = key.toLower(); - } + KUriFilterSearchProvider::setKeys(keys); - const QString path = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/kservices5/searchproviders/"); - bool firstRun = true; + QString name = desktopEntryName(); + if (!name.isEmpty()) { + return; + } - while (true) - { - QString check(name); + // New provider. Set the desktopEntryName. + // Take the longest search shortcut as filename, + // if such a file already exists, append a number and increase it + // until the name is unique + for (const QString &key : keys) { + if (key.length() > name.length()) { + name = key.toLower(); + } + } - if (!firstRun) - check += KRandom::randomString(4); + const QString path = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/kservices5/searchproviders/"); + bool firstRun = true; - const QString located = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("kservices5/searchproviders/") + check + QLatin1String(".desktop")); - if (located.isEmpty()) + while (true) { - name = check; - break; + QString check(name); + + if (!firstRun) { + check += KRandom::randomString(4); + } + + const QString located = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("kservices5/searchproviders/") + check + QLatin1String(".desktop")); + if (located.isEmpty()) { + name = check; + break; + } else if (located.startsWith(path)) { + // If it's a deleted (hidden) entry, overwrite it + if (KService(located).isDeleted()) { + break; + } + } + firstRun = false; } - else if (located.startsWith(path)) - { - // If it's a deleted (hidden) entry, overwrite it - if (KService(located).isDeleted()) - break; - } - firstRun = false; - } - setDesktopEntryName(name); + setDesktopEntryName(name); } void SearchProvider::setCharset(const QString &charset) { - if (m_charset == charset) + if (m_charset == charset) { return; + } m_charset = charset; } QString SearchProvider::iconName() const { if (!m_iconName.isEmpty()) { return m_iconName; } return KIO::iconNameForUrl(QUrl(m_query)); } void SearchProvider::setDirty(bool dirty) { m_dirty = dirty; } diff --git a/src/urifilters/ikws/searchprovider.h b/src/urifilters/ikws/searchprovider.h index bad149ec..08f4e6f7 100644 --- a/src/urifilters/ikws/searchprovider.h +++ b/src/urifilters/ikws/searchprovider.h @@ -1,51 +1,64 @@ /* * Copyright (c) 2000 Malte Starostik * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - #ifndef SEARCHPROVIDER_H #define SEARCHPROVIDER_H #include class SearchProvider : public KUriFilterSearchProvider { public: - SearchProvider() : m_dirty(false) {} + SearchProvider() : m_dirty(false) + { + } + explicit SearchProvider(const QString &servicePath); ~SearchProvider(); - const QString& charset() const { return m_charset; } - const QString& query() const { return m_query; } - bool isDirty() const { return m_dirty; } + const QString &charset() const + { + return m_charset; + } + + const QString &query() const + { + return m_query; + } + + bool isDirty() const + { + return m_dirty; + } - void setName(const QString&); - void setQuery(const QString&); - void setKeys(const QStringList&); - void setCharset(const QString&); + void setName(const QString &); + void setQuery(const QString &); + void setKeys(const QStringList &); + void setCharset(const QString &); void setDirty(bool dirty); QString iconName() const override; private: QString m_query; QString m_charset; QString m_iconName; bool m_dirty; }; #endif diff --git a/src/urifilters/ikws/searchproviderdlg.cpp b/src/urifilters/ikws/searchproviderdlg.cpp index 30614532..0b138c1d 100644 --- a/src/urifilters/ikws/searchproviderdlg.cpp +++ b/src/urifilters/ikws/searchproviderdlg.cpp @@ -1,175 +1,175 @@ /* * Copyright (c) 2000 Malte Starostik * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "searchproviderdlg.h" #include "searchprovider.h" #include #include #include #include #include #include -SearchProviderDialog::SearchProviderDialog(SearchProvider *provider, QList &providers, QWidget *parent) - : QDialog( parent ) +SearchProviderDialog::SearchProviderDialog(SearchProvider *provider, QList &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); + QWidget *mainWidget = new QWidget(this); m_dlg.setupUi(mainWidget); - QVBoxLayout* layout = new QVBoxLayout(this); + 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); + 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 = KCharsets::charsets()->availableEncodingNames(); charsets.prepend(i18nc("@item:inlistbox The default character set", "Default")); m_dlg.cbCharset->addItems(charsets); - if (m_provider) - { + if (m_provider) { setWindowTitle(i18n("Modify Web Shortcut")); 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 - { + } else { setWindowTitle(i18n("New Web Shortcut")); 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()) + 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.leShortcut->text().isEmpty() + || m_dlg.leQuery->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) { +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 contenders; + QHash contenders; const QSet shorthands = normalizedShorthands.split(QLatin1Char(',')).toSet(); // 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) { - Q_FOREACH (const SearchProvider* provider, m_providers) { + Q_FOREACH (const SearchProvider *provider, m_providers) { if (provider != m_provider && provider->keys().contains(shorthand)) { contenders.insert(shorthand, provider); break; } } } if (!contenders.isEmpty()) { if (contenders.size() == 1) { m_dlg.noteLabel->setText(i18n("The shortcut \"%1\" is already assigned to \"%2\". Please choose a different one.", contenders.keys().at(0), contenders.values().at(0)->name())); } else { QStringList contenderList; - QHash::const_iterator i = contenders.constBegin(); + QHash::const_iterator i = contenders.constBegin(); while (i != contenders.constEnd()) { contenderList.append(i18nc("- web short cut (e.g. gg): what it refers to (e.g. Google)", "- %1: \"%2\"", i.key(), i.value()->name())); ++i; } m_dlg.noteLabel->setText(i18n("The following shortcuts 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(); } } void SearchProviderDialog::accept() { if ((m_dlg.leQuery->text().indexOf(QLatin1String("\\{")) == -1) && KMessageBox::warningContinueCancel(nullptr, - i18n("The Shortcut URL does not contain a \\{...} 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 shortcut."), - QString(), KGuiItem(i18n("Keep It"))) == KMessageBox::Cancel) { + i18n("The Shortcut URL does not contain a \\{...} 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 shortcut."), + QString(), KGuiItem(i18n("Keep It"))) == KMessageBox::Cancel) { return; } - if (!m_provider) + 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(','), QString::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->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() { +void SearchProviderDialog::pastePlaceholder() +{ m_dlg.leQuery->insert(QStringLiteral("\\{@}")); m_dlg.leQuery->setFocus(); } - diff --git a/src/urifilters/ikws/searchproviderdlg.h b/src/urifilters/ikws/searchproviderdlg.h index 6a814e70..08d1f2c4 100644 --- a/src/urifilters/ikws/searchproviderdlg.h +++ b/src/urifilters/ikws/searchproviderdlg.h @@ -1,54 +1,56 @@ /* * Copyright (c) 2000 Malte Starostik * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - #ifndef SEARCHPROVIDERDLG_H #define SEARCHPROVIDERDLG_H #include #include "ui_searchproviderdlg_ui.h" class QDialogButtonBox; class SearchProvider; class SearchProviderDialog : public QDialog { Q_OBJECT public: - explicit SearchProviderDialog(SearchProvider *provider, QList &providers, QWidget *parent = nullptr); + explicit SearchProviderDialog(SearchProvider *provider, QList &providers, QWidget *parent = nullptr); - SearchProvider *provider() { return m_provider; } + SearchProvider *provider() + { + return m_provider; + } public Q_SLOTS: void accept() override; protected Q_SLOTS: void slotChanged(); - void shortcutsChanged(const QString& newShorthands); + void shortcutsChanged(const QString &newShorthands); void pastePlaceholder(); private: SearchProvider *m_provider; - QList m_providers; // The list of all search providers, used for checking for already assigned shortcuts. + QList m_providers; // The list of all search providers, used for checking for already assigned shortcuts. Ui::SearchProviderDlgUI m_dlg; - QDialogButtonBox* m_buttons; + QDialogButtonBox *m_buttons; }; #endif diff --git a/src/urifilters/ikws/searchproviderregistry.cpp b/src/urifilters/ikws/searchproviderregistry.cpp index 1c8cc24e..5bef6082 100644 --- a/src/urifilters/ikws/searchproviderregistry.cpp +++ b/src/urifilters/ikws/searchproviderregistry.cpp @@ -1,85 +1,86 @@ /* * This file is part of the KDE project * Copyright 2017 David Faure * * 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 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * 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 "searchproviderregistry.h" #include "searchprovider.h" #include #include SearchProviderRegistry::SearchProviderRegistry() { reload(); } SearchProviderRegistry::~SearchProviderRegistry() { qDeleteAll(m_searchProviders); } QStringList SearchProviderRegistry::directories() const { const QString testDir = QFile::decodeName(qgetenv("KIO_SEARCHPROVIDERS_DIR")); // for unittests - if (!testDir.isEmpty()) + if (!testDir.isEmpty()) { return { testDir }; + } return QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("kservices5/searchproviders/"), QStandardPaths::LocateDirectory); } void SearchProviderRegistry::reload() { m_searchProvidersByKey.clear(); m_searchProvidersByDesktopName.clear(); qDeleteAll(m_searchProviders); m_searchProviders.clear(); const QStringList servicesDirs = directories(); for (const QString &dirPath : servicesDirs) { QDir dir(dirPath); const auto files = dir.entryList({QStringLiteral("*.desktop")}, QDir::Files); for (const QString &file : files) { if (!m_searchProvidersByDesktopName.contains(file)) { const QString filePath = dir.path() + QLatin1Char('/') + file; auto *provider = new SearchProvider(filePath); m_searchProvidersByDesktopName.insert(file, provider); m_searchProviders.append(provider); const auto keys = provider->keys(); for (const QString &key : keys) { m_searchProvidersByKey.insert(key, provider); } } } } } QList SearchProviderRegistry::findAll() { return m_searchProviders; } -SearchProvider* SearchProviderRegistry::findByKey(const QString& key) const +SearchProvider *SearchProviderRegistry::findByKey(const QString &key) const { return m_searchProvidersByKey.value(key); } -SearchProvider* SearchProviderRegistry::findByDesktopName(const QString &name) const +SearchProvider *SearchProviderRegistry::findByDesktopName(const QString &name) const { return m_searchProvidersByDesktopName.value(name + QLatin1String(".desktop")); } diff --git a/src/urifilters/ikws/searchproviderregistry.h b/src/urifilters/ikws/searchproviderregistry.h index 321d1218..1e8879fe 100644 --- a/src/urifilters/ikws/searchproviderregistry.h +++ b/src/urifilters/ikws/searchproviderregistry.h @@ -1,64 +1,64 @@ /* * This file is part of the KDE project * Copyright 2017 David Faure * * 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 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * 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 SEARCHPROVIDERREGISTRY_H #define SEARCHPROVIDERREGISTRY_H #include #include class SearchProvider; /** * Memory cache for search provider desktop files */ class SearchProviderRegistry { public: /** * Default constructor */ SearchProviderRegistry(); /** * Destructor */ ~SearchProviderRegistry(); SearchProviderRegistry(const SearchProviderRegistry &) = delete; - SearchProviderRegistry& operator=(const SearchProviderRegistry &) = delete; + SearchProviderRegistry &operator=(const SearchProviderRegistry &) = delete; QList findAll(); SearchProvider *findByKey(const QString &key) const; SearchProvider *findByDesktopName(const QString &desktopName) const; private: void reload(); QStringList directories() const; QList m_searchProviders; QMap m_searchProvidersByKey; QMap m_searchProvidersByDesktopName; }; #endif // SEARCHPROVIDERREGISTRY_H diff --git a/src/urifilters/localdomain/localdomainurifilter.cpp b/src/urifilters/localdomain/localdomainurifilter.cpp index 3685ac33..9805949c 100644 --- a/src/urifilters/localdomain/localdomainurifilter.cpp +++ b/src/urifilters/localdomain/localdomainurifilter.cpp @@ -1,88 +1,87 @@ /* localdomainfilter.cpp This file is part of the KDE project Copyright (C) 2002 Lubos Lunak Copyright (C) 2010 Dawit Alemayehu 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 2 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 "localdomainurifilter.h" #include #include #include #include #define QL1C(x) QLatin1Char(x) #define QL1S(x) QLatin1String(x) #define HOSTPORT_PATTERN "[a-zA-Z0-9][a-zA-Z0-9+-]*(?:\\:[0-9]{1,5})?(?:/[\\w:@&=+$,-.!~*'()]*)*" namespace { QLoggingCategory category("org.kde.kurifilter-localdomain", QtWarningMsg); } /** * IMPORTANT: If you change anything here, make sure you run the kurifiltertest * regression test (this should be included as part of "make test"). */ -LocalDomainUriFilter::LocalDomainUriFilter( QObject *parent, const QVariantList & /*args*/ ) - :KUriFilterPlugin( QStringLiteral("localdomainurifilter"), parent ), - m_hostPortPattern(QL1S(HOSTPORT_PATTERN)) +LocalDomainUriFilter::LocalDomainUriFilter(QObject *parent, const QVariantList & /*args*/) + : KUriFilterPlugin(QStringLiteral("localdomainurifilter"), parent) + , m_hostPortPattern(QL1S(HOSTPORT_PATTERN)) { } -bool LocalDomainUriFilter::filterUri(KUriFilterData& data) const +bool LocalDomainUriFilter::filterUri(KUriFilterData &data) const { const QUrl url = data.uri(); const QString protocol = url.scheme(); // When checking for local domain just validate it is indeed a local domain, // but do not modify the hostname! See bug# - if ((protocol.isEmpty() || !KProtocolInfo::isKnownProtocol(protocol)) && - m_hostPortPattern.exactMatch(data.typedString())) { - - QString host (data.typedString().left(data.typedString().indexOf(QL1C('/')))); + if ((protocol.isEmpty() || !KProtocolInfo::isKnownProtocol(protocol)) + && m_hostPortPattern.exactMatch(data.typedString())) { + QString host(data.typedString().left(data.typedString().indexOf(QL1C('/')))); const int pos = host.indexOf(QL1C(':')); - if (pos > -1) + if (pos > -1) { host.truncate(pos); // Remove port number - + } if (exists(host)) { qCDebug(category) << "QHostInfo found a host called" << host; - QString scheme (data.defaultUrlScheme()); - if (scheme.isEmpty()) + QString scheme(data.defaultUrlScheme()); + if (scheme.isEmpty()) { scheme = QStringLiteral("http://"); + } setFilteredUri(data, QUrl(scheme + data.typedString())); setUriType(data, KUriFilterData::NetProtocol); return true; } } return false; } -bool LocalDomainUriFilter::exists(const QString& host) const +bool LocalDomainUriFilter::exists(const QString &host) const { qCDebug(category) << "Checking if a host called" << host << "exists"; - QHostInfo hostInfo = resolveName (host, 1500); - return (hostInfo.error() == QHostInfo::NoError); + QHostInfo hostInfo = resolveName(host, 1500); + return hostInfo.error() == QHostInfo::NoError; } - K_PLUGIN_CLASS_WITH_JSON(LocalDomainUriFilter, "localdomainurifilter.json") #include "localdomainurifilter.moc" diff --git a/src/urifilters/localdomain/localdomainurifilter.h b/src/urifilters/localdomain/localdomainurifilter.h index d12bf742..fc4f10a8 100644 --- a/src/urifilters/localdomain/localdomainurifilter.h +++ b/src/urifilters/localdomain/localdomainurifilter.h @@ -1,51 +1,51 @@ /* localdomainurifilter.h This file is part of the KDE project Copyright (C) 2002 Lubos Lunak 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 2 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 LOCALDOMAINURIFILTER_H #define LOCALDOMAINURIFILTER_H #include #include class QHostInfo; class QEventLoop; /** This filter takes care of hostnames in the local search domain. If you're in domain domain.org which has a host intranet.domain.org and the typed URI is just intranet, check if there's a host intranet.domain.org and if yes, it's a network URI. */ class LocalDomainUriFilter : public KUriFilterPlugin { - Q_OBJECT + Q_OBJECT - public: - LocalDomainUriFilter( QObject* parent, const QVariantList& args ); - bool filterUri( KUriFilterData &data ) const override; +public: + LocalDomainUriFilter(QObject *parent, const QVariantList &args); + bool filterUri(KUriFilterData &data) const override; - private: - bool exists(const QString&) const; +private: + bool exists(const QString &) const; QRegExp m_hostPortPattern; }; #endif diff --git a/src/urifilters/shorturi/kshorturifilter.cpp b/src/urifilters/shorturi/kshorturifilter.cpp index 80c022bc..9f10276e 100644 --- a/src/urifilters/shorturi/kshorturifilter.cpp +++ b/src/urifilters/shorturi/kshorturifilter.cpp @@ -1,567 +1,533 @@ -/* -*- c-basic-offset: 2 -*- +/* kshorturifilter.h This file is part of the KDE project Copyright (C) 2000 Dawit Alemayehu Copyright (C) 2000 Malte Starostik 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 2 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kshorturifilter.h" #include "../../pathhelpers_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace { QLoggingCategory category("org.kde.kurifilter-shorturi", QtWarningMsg); } /** * IMPORTANT: If you change anything here, make sure you run the kurifiltertest * regression test (this should be included as part of "make test"). * * If you add anything, make sure to extend kurifiltertest to make sure it is * covered. */ -typedef QMap EntryMap; +typedef QMap EntryMap; -static QRegularExpression sEnvVarExp (QStringLiteral("\\$[a-zA-Z_][a-zA-Z0-9_]*")); +static QRegularExpression sEnvVarExp(QStringLiteral("\\$[a-zA-Z_][a-zA-Z0-9_]*")); -static bool isPotentialShortURL(const QString& cmd) +static bool isPotentialShortURL(const QString &cmd) { // Host names and IPv4 address... if (cmd.contains(QLatin1Char('.'))) { return true; } // IPv6 Address... if (cmd.startsWith(QLatin1Char('[')) && cmd.contains(QLatin1Char(':'))) { return true; } return false; } -static QString removeArgs( const QString& _cmd ) +static QString removeArgs(const QString &_cmd) { - QString cmd( _cmd ); - - if( cmd[0] != QLatin1Char('\'') && cmd[0] != QLatin1Char('"')) - { - // Remove command-line options (look for first non-escaped space) - int spacePos = 0; - - do - { - spacePos = cmd.indexOf(QLatin1Char(' '), spacePos+1 ); - } while (spacePos > 1 && cmd[spacePos - 1] == QLatin1Char('\\')); - - if( spacePos > 0 ) - { - cmd.truncate(spacePos); - qCDebug(category) << "spacePos=" << spacePos << " returning " << cmd; + QString cmd(_cmd); + + if (cmd[0] != QLatin1Char('\'') && cmd[0] != QLatin1Char('"')) { + // Remove command-line options (look for first non-escaped space) + int spacePos = 0; + + do { + spacePos = cmd.indexOf(QLatin1Char(' '), spacePos+1); + } while (spacePos > 1 && cmd[spacePos - 1] == QLatin1Char('\\')); + + if (spacePos > 0) { + cmd.truncate(spacePos); + qCDebug(category) << "spacePos=" << spacePos << " returning " << cmd; + } } - } - return cmd; + return cmd; } static bool isKnownProtocol(const QString &protocol) { if (KProtocolInfo::isKnownProtocol(protocol) || protocol == QLatin1String("mailto")) { return true; } const KService::Ptr service = KMimeTypeTrader::self()->preferredService(QLatin1String("x-scheme-handler/") + protocol); return service; } -KShortUriFilter::KShortUriFilter( QObject *parent, const QVariantList & /*args*/ ) - :KUriFilterPlugin( QStringLiteral("kshorturifilter"), parent ) +KShortUriFilter::KShortUriFilter(QObject *parent, const QVariantList & /*args*/) + : KUriFilterPlugin(QStringLiteral("kshorturifilter"), parent) { QDBusConnection::sessionBus().connect(QString(), QStringLiteral("/"), QStringLiteral("org.kde.KUriFilterPlugin"), - QStringLiteral("configure"), this, SLOT(configure())); + QStringLiteral("configure"), this, SLOT(configure())); configure(); } -bool KShortUriFilter::filterUri( KUriFilterData& data ) const +bool KShortUriFilter::filterUri(KUriFilterData &data) const { - /* - * Here is a description of how the shortURI deals with the supplied - * data. First it expands any environment variable settings and then - * deals with special shortURI cases. These special cases are the "smb:" - * URL scheme which is very specific to KDE, "#" and "##" which are - * shortcuts for man:/ and info:/ protocols respectively. It then handles - * local files. Then it checks to see if the URL is valid and one that is - * supported by KDE's IO system. If all the above checks fails, it simply - * lookups the URL in the user-defined list and returns without filtering - * if it is not found. TODO: the user-defined table is currently only manually - * hackable and is missing a config dialog. - */ - - //QUrl url = data.uri(); - QString cmd = data.typedString(); - - int firstNonSlash = 0; - while (firstNonSlash < cmd.length() && (cmd.at(firstNonSlash) == QLatin1Char('/'))) { - firstNonSlash++; - } - if (firstNonSlash > 1) { - cmd.remove(0, firstNonSlash - 1); - } - - // Replicate what KUrl(cmd) did in KDE4. This could later be folded into the checks further down... - QUrl url; - if (QDir::isAbsolutePath(cmd)) { - url = QUrl::fromLocalFile(cmd); - } else { - url.setUrl(cmd); - } - - // WORKAROUND: Allow the use of '@' in the username component of a URL since - // other browsers such as firefox in their infinite wisdom allow such blatant - // violations of RFC 3986. BR# 69326/118413. - if (cmd.count(QLatin1Char('@')) > 1) { - const int lastIndex = cmd.lastIndexOf(QLatin1Char('@')); - // Percent encode all but the last '@'. - QString encodedCmd = QString::fromUtf8(QUrl::toPercentEncoding(cmd.left(lastIndex), QByteArrayLiteral(":/"))); - encodedCmd += cmd.midRef(lastIndex); - cmd = encodedCmd; - url.setUrl(encodedCmd); - } - - const bool isMalformed = !url.isValid(); - QString protocol = url.scheme(); - - qCDebug(category) << cmd; - - // Fix misparsing of "foo:80", QUrl thinks "foo" is the protocol and "80" is the path. - // However, be careful not to do that for valid hostless URLs, e.g. file:///foo! - if (!protocol.isEmpty() && url.host().isEmpty() && !url.path().isEmpty() - && cmd.contains(QLatin1Char(':')) && !isKnownProtocol(protocol)) { - protocol.clear(); - } - - qCDebug(category) << "url=" << url << "cmd=" << cmd << "isMalformed=" << isMalformed; - - // TODO: Make this a bit more intelligent for Minicli! There - // is no need to make comparisons if the supplied data is a local - // executable and only the argument part, if any, changed! (Dawit) - // You mean caching the last filtering, to try and reuse it, to save stat()s? (David) - - const QString starthere_proto = QStringLiteral("start-here:"); - if (cmd.indexOf(starthere_proto) == 0 ) - { - setFilteredUri( data, QUrl(QStringLiteral("system:/")) ); - setUriType( data, KUriFilterData::LocalDir ); - return true; - } - - // Handle MAN & INFO pages shortcuts... - const QString man_proto = QStringLiteral("man:"); - const QString info_proto = QStringLiteral("info:"); - if( cmd[0] == QLatin1Char('#') || - cmd.indexOf( man_proto ) == 0 || - cmd.indexOf( info_proto ) == 0 ) - { - if( cmd.leftRef(2) == QLatin1String("##") ) - cmd = QLatin1String("info:/") + cmd.midRef(2); - else if ( cmd[0] == QLatin1Char('#') ) - cmd = QLatin1String("man:/") + cmd.midRef(1); - - else if ((cmd==info_proto) || (cmd==man_proto)) - cmd += QLatin1Char('/'); - - setFilteredUri( data, QUrl( cmd )); - setUriType( data, KUriFilterData::Help ); - return true; - } - - // Detect UNC style (aka windows SMB) URLs - if ( cmd.startsWith( QLatin1String( "\\\\") ) ) - { - // make sure path is unix style - cmd.replace(QLatin1Char('\\'), QLatin1Char('/')); - cmd.prepend( QLatin1String( "smb:" ) ); - setFilteredUri( data, QUrl( cmd )); - setUriType( data, KUriFilterData::NetProtocol ); - return true; - } - - bool expanded = false; - - // Expanding shortcut to HOME URL... - QString path; - QString ref; - QString query; - QString nameFilter; - - if (QDir::isRelativePath(cmd) && QUrl(cmd).isRelative()) { - path = cmd; - qCDebug(category) << "path=cmd=" << path; - } else { - if (url.isLocalFile()) - { - qCDebug(category) << "hasRef=" << url.hasFragment(); - // Split path from ref/query - // but not for "/tmp/a#b", if "a#b" is an existing file, - // or for "/tmp/a?b" (#58990) - if( ( url.hasFragment() || !url.query().isEmpty() ) - && !url.path().endsWith(QLatin1Char('/')) ) // /tmp/?foo is a namefilter, not a query - { - path = url.path(); - ref = url.fragment(); - qCDebug(category) << "isLocalFile set path to" << path << "and ref to" << ref; - query = url.query(); - if (path.isEmpty() && !url.host().isEmpty()) - path = QStringLiteral("/"); - } - else - { - if (cmd.startsWith(QLatin1String("file://"))) { - path = cmd.mid(strlen("file://")); - } else { - path = cmd; - } - qCDebug(category) << "(2) path=cmd=" << path; - } + /* + * Here is a description of how the shortURI deals with the supplied + * data. First it expands any environment variable settings and then + * deals with special shortURI cases. These special cases are the "smb:" + * URL scheme which is very specific to KDE, "#" and "##" which are + * shortcuts for man:/ and info:/ protocols respectively. It then handles + * local files. Then it checks to see if the URL is valid and one that is + * supported by KDE's IO system. If all the above checks fails, it simply + * lookups the URL in the user-defined list and returns without filtering + * if it is not found. TODO: the user-defined table is currently only manually + * hackable and is missing a config dialog. + */ + + //QUrl url = data.uri(); + QString cmd = data.typedString(); + + int firstNonSlash = 0; + while (firstNonSlash < cmd.length() && (cmd.at(firstNonSlash) == QLatin1Char('/'))) { + firstNonSlash++; + } + if (firstNonSlash > 1) { + cmd.remove(0, firstNonSlash - 1); + } + + // Replicate what KUrl(cmd) did in KDE4. This could later be folded into the checks further down... + QUrl url; + if (QDir::isAbsolutePath(cmd)) { + url = QUrl::fromLocalFile(cmd); + } else { + url.setUrl(cmd); + } + + // WORKAROUND: Allow the use of '@' in the username component of a URL since + // other browsers such as firefox in their infinite wisdom allow such blatant + // violations of RFC 3986. BR# 69326/118413. + if (cmd.count(QLatin1Char('@')) > 1) { + const int lastIndex = cmd.lastIndexOf(QLatin1Char('@')); + // Percent encode all but the last '@'. + QString encodedCmd = QString::fromUtf8(QUrl::toPercentEncoding(cmd.left(lastIndex), QByteArrayLiteral(":/"))); + encodedCmd += cmd.midRef(lastIndex); + cmd = encodedCmd; + url.setUrl(encodedCmd); + } + + const bool isMalformed = !url.isValid(); + QString protocol = url.scheme(); + + qCDebug(category) << cmd; + + // Fix misparsing of "foo:80", QUrl thinks "foo" is the protocol and "80" is the path. + // However, be careful not to do that for valid hostless URLs, e.g. file:///foo! + if (!protocol.isEmpty() && url.host().isEmpty() && !url.path().isEmpty() + && cmd.contains(QLatin1Char(':')) && !isKnownProtocol(protocol)) { + protocol.clear(); } - } - - if( path[0] == QLatin1Char('~')) - { - int slashPos = path.indexOf(QLatin1Char('/')); - if( slashPos == -1 ) - slashPos = path.length(); - if( slashPos == 1 ) // ~/ - { - path.replace ( 0, 1, QDir::homePath() ); + + qCDebug(category) << "url=" << url << "cmd=" << cmd << "isMalformed=" << isMalformed; + + // TODO: Make this a bit more intelligent for Minicli! There + // is no need to make comparisons if the supplied data is a local + // executable and only the argument part, if any, changed! (Dawit) + // You mean caching the last filtering, to try and reuse it, to save stat()s? (David) + + const QString starthere_proto = QStringLiteral("start-here:"); + if (cmd.indexOf(starthere_proto) == 0) { + setFilteredUri(data, QUrl(QStringLiteral("system:/"))); + setUriType(data, KUriFilterData::LocalDir); + return true; } - else // ~username/ - { - const QString userName (path.mid( 1, slashPos-1 )); - KUser user (userName); - if( user.isValid() && !user.homeDir().isEmpty()) - { - path.replace (0, slashPos, user.homeDir()); - } - else - { - if (user.isValid()) { - setErrorMsg(data, i18n("%1 does not have a home folder.", userName)); - } else { - setErrorMsg(data, i18n("There is no user called %1.", userName)); + + // Handle MAN & INFO pages shortcuts... + const QString man_proto = QStringLiteral("man:"); + const QString info_proto = QStringLiteral("info:"); + if (cmd[0] == QLatin1Char('#') + || cmd.indexOf(man_proto) == 0 + || cmd.indexOf(info_proto) == 0) { + if (cmd.leftRef(2) == QLatin1String("##")) { + cmd = QLatin1String("info:/") + cmd.midRef(2); + } else if (cmd[0] == QLatin1Char('#')) { + cmd = QLatin1String("man:/") + cmd.midRef(1); + } else if ((cmd == info_proto) || (cmd == man_proto)) { + cmd += QLatin1Char('/'); } - setUriType( data, KUriFilterData::Error ); - // Always return true for error conditions so - // that other filters will not be invoked !! + + setFilteredUri(data, QUrl(cmd)); + setUriType(data, KUriFilterData::Help); return true; - } } - expanded = true; - } - else if ( path[0] == QLatin1Char('$') ) { - // Environment variable expansion. - auto match = sEnvVarExp.match(path); - if ( match.hasMatch() ) - { - const QByteArray exp = qgetenv(path.midRef(1, match.capturedLength() - 1).toLocal8Bit().data()); - if (!exp.isEmpty()) { - path.replace( 0, match.capturedLength(), QFile::decodeName(exp) ); - expanded = true; - } + + // Detect UNC style (aka windows SMB) URLs + if (cmd.startsWith(QLatin1String("\\\\"))) { + // make sure path is unix style + cmd.replace(QLatin1Char('\\'), QLatin1Char('/')); + cmd.prepend(QLatin1String("smb:")); + setFilteredUri(data, QUrl(cmd)); + setUriType(data, KUriFilterData::NetProtocol); + return true; } - } - - if ( expanded || cmd.startsWith(QLatin1Char('/')) ) - { - // Look for #ref again, after $ and ~ expansion (testcase: $QTDIR/doc/html/functions.html#s) - // Can't use QUrl here, setPath would escape it... - const int pos = path.indexOf(QLatin1Char('#')); - if ( pos > -1 ) - { - const QString newPath = path.left( pos ); - if ( QFile::exists( newPath ) ) - { - ref = path.mid( pos + 1 ); - path = newPath; - qCDebug(category) << "Extracted ref: path=" << path << " ref=" << ref; - } + + bool expanded = false; + + // Expanding shortcut to HOME URL... + QString path; + QString ref; + QString query; + QString nameFilter; + + if (QDir::isRelativePath(cmd) && QUrl(cmd).isRelative()) { + path = cmd; + qCDebug(category) << "path=cmd=" << path; + } else { + if (url.isLocalFile()) { + qCDebug(category) << "hasRef=" << url.hasFragment(); + // Split path from ref/query + // but not for "/tmp/a#b", if "a#b" is an existing file, + // or for "/tmp/a?b" (#58990) + if ((url.hasFragment() || !url.query().isEmpty()) + && !url.path().endsWith(QLatin1Char('/'))) { // /tmp/?foo is a namefilter, not a query + path = url.path(); + ref = url.fragment(); + qCDebug(category) << "isLocalFile set path to" << path << "and ref to" << ref; + query = url.query(); + if (path.isEmpty() && !url.host().isEmpty()) { + path = QStringLiteral("/"); + } + } else { + if (cmd.startsWith(QLatin1String("file://"))) { + path = cmd.mid(strlen("file://")); + } else { + path = cmd; + } + qCDebug(category) << "(2) path=cmd=" << path; + } + } } - } - - - - bool isLocalFullPath = QDir::isAbsolutePath(path); - - // Checking for local resource match... - // Determine if "uri" is an absolute path to a local resource OR - // A local resource with a supplied absolute path in KUriFilterData - const QString abs_path = data.absolutePath(); - - const bool canBeAbsolute = (protocol.isEmpty() && !abs_path.isEmpty()); - const bool canBeLocalAbsolute = (canBeAbsolute && abs_path[0] == QLatin1Char('/') && !isMalformed); - bool exists = false; - - /*qCDebug(category) << "abs_path=" << abs_path - << "protocol=" << protocol - << "canBeAbsolute=" << canBeAbsolute - << "canBeLocalAbsolute=" << canBeLocalAbsolute - << "isLocalFullPath=" << isLocalFullPath;*/ - - QT_STATBUF buff; - if ( canBeLocalAbsolute ) - { - QString abs = QDir::cleanPath( abs_path ); - // combine absolute path (abs_path) and relative path (cmd) into abs_path - int len = path.length(); - if( (len==1 && path[0]==QLatin1Char('.')) || (len==2 && path[0]==QLatin1Char('.') && path[1]==QLatin1Char('.')) ) - path += QLatin1Char('/'); - qCDebug(category) << "adding " << abs << " and " << path; - abs = QDir::cleanPath(abs + QLatin1Char('/') + path); - qCDebug(category) << "checking whether " << abs << " exists."; - // Check if it exists - if(QT_STAT(QFile::encodeName(abs).constData(), &buff) == 0) { - path = abs; // yes -> store as the new cmd - exists = true; - isLocalFullPath = true; + + if (path[0] == QLatin1Char('~')) { + int slashPos = path.indexOf(QLatin1Char('/')); + if (slashPos == -1) { + slashPos = path.length(); + } + if (slashPos == 1) { // ~/ + path.replace(0, 1, QDir::homePath()); + } else { // ~username/ + const QString userName(path.mid(1, slashPos-1)); + KUser user(userName); + if (user.isValid() && !user.homeDir().isEmpty()) { + path.replace(0, slashPos, user.homeDir()); + } else { + if (user.isValid()) { + setErrorMsg(data, i18n("%1 does not have a home folder.", userName)); + } else { + setErrorMsg(data, i18n("There is no user called %1.", userName)); + } + setUriType(data, KUriFilterData::Error); + // Always return true for error conditions so + // that other filters will not be invoked !! + return true; + } + } + expanded = true; + } else if (path[0] == QLatin1Char('$')) { + // Environment variable expansion. + auto match = sEnvVarExp.match(path); + if (match.hasMatch()) { + const QByteArray exp = qgetenv(path.midRef(1, match.capturedLength() - 1).toLocal8Bit().data()); + if (!exp.isEmpty()) { + path.replace(0, match.capturedLength(), QFile::decodeName(exp)); + expanded = true; + } + } } - } - - if (isLocalFullPath && !exists && !isMalformed) { - exists = QT_STAT(QFile::encodeName(path).constData(), &buff) == 0; - - if ( !exists ) { - // Support for name filter (/foo/*.txt), see also KonqMainWindow::detectNameFilter - // If the app using this filter doesn't support it, well, it'll simply error out itself - int lastSlash = path.lastIndexOf(QLatin1Char('/')); - if ( lastSlash > -1 && path.indexOf(QLatin1Char(' '), lastSlash ) == -1 ) // no space after last slash, otherwise it's more likely command-line arguments - { - QString fileName = path.mid( lastSlash + 1 ); - QString testPath = path.left(lastSlash); - if ((fileName.indexOf(QLatin1Char('*')) != -1 || fileName.indexOf(QLatin1Char('[')) != -1 || fileName.indexOf(QLatin1Char('?')) != -1) - && QT_STAT(QFile::encodeName(testPath).constData(), &buff) == 0) { - nameFilter = fileName; - qCDebug(category) << "Setting nameFilter to" << nameFilter << "and path to" << testPath; - path = testPath; - exists = true; + + if (expanded || cmd.startsWith(QLatin1Char('/'))) { + // Look for #ref again, after $ and ~ expansion (testcase: $QTDIR/doc/html/functions.html#s) + // Can't use QUrl here, setPath would escape it... + const int pos = path.indexOf(QLatin1Char('#')); + if (pos > -1) { + const QString newPath = path.left(pos); + if (QFile::exists(newPath)) { + ref = path.mid(pos + 1); + path = newPath; + qCDebug(category) << "Extracted ref: path=" << path << " ref=" << ref; + } } - } } - } - - qCDebug(category) << "path =" << path << " isLocalFullPath=" << isLocalFullPath << " exists=" << exists << " url=" << url; - if( exists ) - { - QUrl u = QUrl::fromLocalFile(path); - qCDebug(category) << "ref=" << ref << "query=" << query; - u.setFragment(ref); - u.setQuery(query); - - if (!KUrlAuthorized::authorizeUrlAction( QStringLiteral("open"), QUrl(), u)) - { - // No authorization, we pretend it's a file will get - // an access denied error later on. - setFilteredUri( data, u ); - setUriType( data, KUriFilterData::LocalFile ); - return true; + + bool isLocalFullPath = QDir::isAbsolutePath(path); + + // Checking for local resource match... + // Determine if "uri" is an absolute path to a local resource OR + // A local resource with a supplied absolute path in KUriFilterData + const QString abs_path = data.absolutePath(); + + const bool canBeAbsolute = (protocol.isEmpty() && !abs_path.isEmpty()); + const bool canBeLocalAbsolute = (canBeAbsolute && abs_path[0] == QLatin1Char('/') && !isMalformed); + bool exists = false; + + /*qCDebug(category) << "abs_path=" << abs_path + << "protocol=" << protocol + << "canBeAbsolute=" << canBeAbsolute + << "canBeLocalAbsolute=" << canBeLocalAbsolute + << "isLocalFullPath=" << isLocalFullPath;*/ + + QT_STATBUF buff; + if (canBeLocalAbsolute) { + QString abs = QDir::cleanPath(abs_path); + // combine absolute path (abs_path) and relative path (cmd) into abs_path + int len = path.length(); + if ((len == 1 && path[0] == QLatin1Char('.')) || (len == 2 && path[0] == QLatin1Char('.') && path[1] == QLatin1Char('.'))) { + path += QLatin1Char('/'); + } + qCDebug(category) << "adding " << abs << " and " << path; + abs = QDir::cleanPath(abs + QLatin1Char('/') + path); + qCDebug(category) << "checking whether " << abs << " exists."; + // Check if it exists + if (QT_STAT(QFile::encodeName(abs).constData(), &buff) == 0) { + path = abs; // yes -> store as the new cmd + exists = true; + isLocalFullPath = true; + } } - // Can be abs path to file or directory, or to executable with args - bool isDir = ((buff.st_mode & QT_STAT_MASK) == QT_STAT_DIR); - if( !isDir && access ( QFile::encodeName(path).data(), X_OK) == 0 ) - { - qCDebug(category) << "Abs path to EXECUTABLE"; - setFilteredUri( data, u ); - setUriType( data, KUriFilterData::Executable ); - return true; + if (isLocalFullPath && !exists && !isMalformed) { + exists = QT_STAT(QFile::encodeName(path).constData(), &buff) == 0; + + if (!exists) { + // Support for name filter (/foo/*.txt), see also KonqMainWindow::detectNameFilter + // If the app using this filter doesn't support it, well, it'll simply error out itself + int lastSlash = path.lastIndexOf(QLatin1Char('/')); + if (lastSlash > -1 && path.indexOf(QLatin1Char(' '), lastSlash) == -1) { // no space after last slash, otherwise it's more likely command-line arguments + QString fileName = path.mid(lastSlash + 1); + QString testPath = path.left(lastSlash); + if ((fileName.indexOf(QLatin1Char('*')) != -1 || fileName.indexOf(QLatin1Char('[')) != -1 || fileName.indexOf(QLatin1Char('?')) != -1) + && QT_STAT(QFile::encodeName(testPath).constData(), &buff) == 0) { + nameFilter = fileName; + qCDebug(category) << "Setting nameFilter to" << nameFilter << "and path to" << testPath; + path = testPath; + exists = true; + } + } + } } - // Open "uri" as file:/xxx if it is a non-executable local resource. - if( isDir || (( buff.st_mode & QT_STAT_MASK ) == QT_STAT_REG) ) - { - qCDebug(category) << "Abs path as local file or directory"; - if ( !nameFilter.isEmpty() ) - u.setPath(concatPaths(u.path(), nameFilter)); - setFilteredUri( data, u ); - setUriType( data, ( isDir ) ? KUriFilterData::LocalDir : KUriFilterData::LocalFile ); - return true; + qCDebug(category) << "path =" << path << " isLocalFullPath=" << isLocalFullPath << " exists=" << exists << " url=" << url; + if (exists) { + QUrl u = QUrl::fromLocalFile(path); + qCDebug(category) << "ref=" << ref << "query=" << query; + u.setFragment(ref); + u.setQuery(query); + + if (!KUrlAuthorized::authorizeUrlAction(QStringLiteral("open"), QUrl(), u)) { + // No authorization, we pretend it's a file will get + // an access denied error later on. + setFilteredUri(data, u); + setUriType(data, KUriFilterData::LocalFile); + return true; + } + + // Can be abs path to file or directory, or to executable with args + bool isDir = ((buff.st_mode & QT_STAT_MASK) == QT_STAT_DIR); + if (!isDir && access(QFile::encodeName(path).data(), X_OK) == 0) { + qCDebug(category) << "Abs path to EXECUTABLE"; + setFilteredUri(data, u); + setUriType(data, KUriFilterData::Executable); + return true; + } + + // Open "uri" as file:/xxx if it is a non-executable local resource. + if (isDir || ((buff.st_mode & QT_STAT_MASK) == QT_STAT_REG)) { + qCDebug(category) << "Abs path as local file or directory"; + if (!nameFilter.isEmpty()) { + u.setPath(concatPaths(u.path(), nameFilter)); + } + setFilteredUri(data, u); + setUriType(data, (isDir) ? KUriFilterData::LocalDir : KUriFilterData::LocalFile); + return true; + } + + // Should we return LOCAL_FILE for non-regular files too? + qCDebug(category) << "File found, but not a regular file nor dir... socket?"; } - // Should we return LOCAL_FILE for non-regular files too? - qCDebug(category) << "File found, but not a regular file nor dir... socket?"; - } - - if( data.checkForExecutables()) - { - // Let us deal with possible relative URLs to see - // if it is executable under the user's $PATH variable. - // We try hard to avoid parsing any possible command - // line arguments or options that might have been supplied. - QString exe = removeArgs( cmd ); - qCDebug(category) << "findExe with" << exe; - - if (!QStandardPaths::findExecutable( exe ).isNull() ) - { - qCDebug(category) << "EXECUTABLE exe=" << exe; - setFilteredUri( data, QUrl::fromLocalFile( exe )); - // check if we have command line arguments - if( exe != cmd ) - setArguments(data, cmd.right(cmd.length() - exe.length())); - setUriType( data, KUriFilterData::Executable ); - return true; + if (data.checkForExecutables()) { + // Let us deal with possible relative URLs to see + // if it is executable under the user's $PATH variable. + // We try hard to avoid parsing any possible command + // line arguments or options that might have been supplied. + QString exe = removeArgs(cmd); + qCDebug(category) << "findExe with" << exe; + + if (!QStandardPaths::findExecutable(exe).isNull()) { + qCDebug(category) << "EXECUTABLE exe=" << exe; + setFilteredUri(data, QUrl::fromLocalFile(exe)); + // check if we have command line arguments + if (exe != cmd) { + setArguments(data, cmd.right(cmd.length() - exe.length())); + } + setUriType(data, KUriFilterData::Executable); + return true; + } } - } - - // Process URLs of known and supported protocols so we don't have - // to resort to the pattern matching scheme below which can possibly - // slow things down... - if ( !isMalformed && !isLocalFullPath && !protocol.isEmpty() ) - { - qCDebug(category) << "looking for protocol" << protocol; - if (isKnownProtocol(protocol)) - { - setFilteredUri( data, url ); - if ( protocol == QLatin1String("man") || protocol == QLatin1String("help") ) - setUriType( data, KUriFilterData::Help ); - else - setUriType( data, KUriFilterData::NetProtocol ); - return true; + + // Process URLs of known and supported protocols so we don't have + // to resort to the pattern matching scheme below which can possibly + // slow things down... + if (!isMalformed && !isLocalFullPath && !protocol.isEmpty()) { + qCDebug(category) << "looking for protocol" << protocol; + if (isKnownProtocol(protocol)) { + setFilteredUri(data, url); + if (protocol == QLatin1String("man") || protocol == QLatin1String("help")) { + setUriType(data, KUriFilterData::Help); + } else { + setUriType(data, KUriFilterData::NetProtocol); + } + return true; + } } - } - - // Short url matches - if (!cmd.contains(QLatin1Char(' '))) { - // Okay this is the code that allows users to supply custom matches for - // specific URLs using Qt's regexp class. This is hard-coded for now. - // TODO: Make configurable at some point... - Q_FOREACH(const URLHint& hint, m_urlHints) - { - qCDebug(category) << "testing regexp for" << hint.prepend; - if (hint.regexp.indexIn(cmd) == 0) - { - const QString cmdStr = hint.prepend + cmd; - QUrl url(cmdStr); - qCDebug(category) << "match - prepending" << hint.prepend << "->" << cmdStr << "->" << url; - setFilteredUri( data, url ); - setUriType( data, hint.type ); - return true; - } + + // Short url matches + if (!cmd.contains(QLatin1Char(' '))) { + // Okay this is the code that allows users to supply custom matches for + // specific URLs using Qt's regexp class. This is hard-coded for now. + // TODO: Make configurable at some point... + Q_FOREACH (const URLHint &hint, m_urlHints) { + qCDebug(category) << "testing regexp for" << hint.prepend; + if (hint.regexp.indexIn(cmd) == 0) { + const QString cmdStr = hint.prepend + cmd; + QUrl url(cmdStr); + qCDebug(category) << "match - prepending" << hint.prepend << "->" << cmdStr << "->" << url; + setFilteredUri(data, url); + setUriType(data, hint.type); + return true; + } + } + + // No protocol and not malformed means a valid short URL such as kde.org or + // user@192.168.0.1. However, it might also be valid only because it lacks + // the scheme component, e.g. www.kde,org (illegal ',' before 'org'). The + // check below properly deciphers the difference between the two and sends + // back the proper result. + if (protocol.isEmpty() && isPotentialShortURL(cmd)) { + QString urlStr = data.defaultUrlScheme(); + if (urlStr.isEmpty()) { + urlStr = m_strDefaultUrlScheme; + } + + const int index = urlStr.indexOf(QLatin1Char(':')); + if (index == -1 || !isKnownProtocol(urlStr.left(index))) { + urlStr += QStringLiteral("://"); + } + urlStr += cmd; + + QUrl url(urlStr); + if (url.isValid()) { + setFilteredUri(data, url); + setUriType(data, KUriFilterData::NetProtocol); + } else if (isKnownProtocol(url.scheme())) { + setFilteredUri(data, data.uri()); + setUriType(data, KUriFilterData::Error); + } + return true; + } } - // No protocol and not malformed means a valid short URL such as kde.org or - // user@192.168.0.1. However, it might also be valid only because it lacks - // the scheme component, e.g. www.kde,org (illegal ',' before 'org'). The - // check below properly deciphers the difference between the two and sends - // back the proper result. - if (protocol.isEmpty() && isPotentialShortURL(cmd)) - { - QString urlStr = data.defaultUrlScheme(); - if (urlStr.isEmpty()) - urlStr = m_strDefaultUrlScheme; - - const int index = urlStr.indexOf(QLatin1Char(':')); - if (index == -1 || !isKnownProtocol(urlStr.left(index))) - urlStr += QStringLiteral("://"); - urlStr += cmd; - - QUrl url (urlStr); - if (url.isValid()) - { - setFilteredUri(data, url); - setUriType(data, KUriFilterData::NetProtocol); - } - else if (isKnownProtocol(url.scheme())) - { - setFilteredUri(data, data.uri()); - setUriType(data, KUriFilterData::Error); - } - return true; + // If we previously determined that the URL might be a file, + // and if it doesn't exist... we'll pretend it exists. + // This allows to use it for completion purposes. + // (If you change this logic again, look at the commit that was testing + // for KUrlAuthorized::authorizeUrlAction("open")) + if (isLocalFullPath && !exists) { + QUrl u = QUrl::fromLocalFile(path); + u.setFragment(ref); + setFilteredUri(data, u); + setUriType(data, KUriFilterData::LocalFile); + return true; } - } - - // If we previously determined that the URL might be a file, - // and if it doesn't exist... we'll pretend it exists. - // This allows to use it for completion purposes. - // (If you change this logic again, look at the commit that was testing - // for KUrlAuthorized::authorizeUrlAction("open")) - if( isLocalFullPath && !exists ) - { - QUrl u = QUrl::fromLocalFile(path); - u.setFragment(ref); - setFilteredUri(data, u); - setUriType(data, KUriFilterData::LocalFile); - return true; - } - - // If we reach this point, we cannot filter this thing so simply return false - // so that other filters, if present, can take a crack at it. - return false; + + // If we reach this point, we cannot filter this thing so simply return false + // so that other filters, if present, can take a crack at it. + return false; } -KCModule* KShortUriFilter::configModule( QWidget*, const char* ) const +KCModule *KShortUriFilter::configModule(QWidget *, const char *) const { return nullptr; //new KShortUriOptions( parent, name ); } QString KShortUriFilter::configName() const { // return i18n("&ShortURLs"); we don't have a configModule so no need for a configName that confuses translators return KUriFilterPlugin::configName(); } void KShortUriFilter::configure() { - KConfig config( objectName() + QStringLiteral( "rc"), KConfig::NoGlobals ); - KConfigGroup cg( config.group("") ); - - m_strDefaultUrlScheme = cg.readEntry( "DefaultProtocol", QStringLiteral("http://") ); - const EntryMap patterns = config.entryMap( QStringLiteral("Pattern") ); - const EntryMap protocols = config.entryMap( QStringLiteral("Protocol") ); - KConfigGroup typeGroup(&config, "Type"); - - for( EntryMap::ConstIterator it = patterns.begin(); it != patterns.end(); ++it ) - { - QString protocol = protocols[it.key()]; - if (!protocol.isEmpty()) - { - int type = typeGroup.readEntry(it.key(), -1); - if (type > -1 && type <= KUriFilterData::Unknown) - m_urlHints.append( URLHint(it.value(), protocol, static_cast(type) ) ); - else - m_urlHints.append( URLHint(it.value(), protocol) ); + KConfig config(objectName() + QStringLiteral("rc"), KConfig::NoGlobals); + KConfigGroup cg(config.group("")); + + m_strDefaultUrlScheme = cg.readEntry("DefaultProtocol", QStringLiteral("http://")); + const EntryMap patterns = config.entryMap(QStringLiteral("Pattern")); + const EntryMap protocols = config.entryMap(QStringLiteral("Protocol")); + KConfigGroup typeGroup(&config, "Type"); + + for (EntryMap::ConstIterator it = patterns.begin(); it != patterns.end(); ++it) { + QString protocol = protocols[it.key()]; + if (!protocol.isEmpty()) { + int type = typeGroup.readEntry(it.key(), -1); + if (type > -1 && type <= KUriFilterData::Unknown) { + m_urlHints.append(URLHint(it.value(), protocol, static_cast(type))); + } else { + m_urlHints.append(URLHint(it.value(), protocol)); + } + } } - } } K_PLUGIN_CLASS_WITH_JSON(KShortUriFilter, "kshorturifilter.json") #include "kshorturifilter.moc" diff --git a/src/urifilters/shorturi/kshorturifilter.h b/src/urifilters/shorturi/kshorturifilter.h index 8e37ab10..21be7d28 100644 --- a/src/urifilters/shorturi/kshorturifilter.h +++ b/src/urifilters/shorturi/kshorturifilter.h @@ -1,108 +1,116 @@ /* kshorturifilter.h This file is part of the KDE project Copyright (C) 2000 Dawit Alemayehu Copyright (C) 2000 Malte Starostik 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 2 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KSHORTURIFILTER_H #define KSHORTURIFILTER_H #include #include #include #include - /** * This is short URL filter class. * * @short A filter that converts short URLs into fully qualified ones. * * @author Dawit Alemayehu * @author Malte Starostik */ class KShortUriFilter : public KUriFilterPlugin { Q_OBJECT public: /** * Creates a Short URI filter object * * @param parent the parent of this class. * @param name the internal name for this object. */ - explicit KShortUriFilter( QObject *parent = nullptr, const QVariantList &args = QVariantList() ); + explicit KShortUriFilter(QObject *parent = nullptr, const QVariantList &args = QVariantList()); /** * Destructor */ - virtual ~KShortUriFilter() {} + virtual ~KShortUriFilter() + { + } /** * Converts short URIs into fully qualified valid URIs * whenever possible. * * Parses any given invalid URI to determine whether it * is a known short URI and converts it to its fully * qualified version. * * @param data the data to be filtered * @return true if the url has been filtered */ - bool filterUri( KUriFilterData &data ) const override; + bool filterUri(KUriFilterData &data) const override; /** * Returns the name of the config module for * this plugin. * * @return the name of the config module. */ QString configName() const override; /** * Returns an instance of the module used to configure * this object. * * @return the config module */ - KCModule* configModule( QWidget*, const char* ) const override; + KCModule *configModule(QWidget *, const char *) const override; public Q_SLOTS: void configure(); private: struct URLHint { - URLHint() {} - URLHint( const QString &r, const QString &p, - KUriFilterData::UriTypes t = KUriFilterData::NetProtocol ) - : regexp(QRegExp(r)), prepend(p), type(t) {} + URLHint() + { + } + + URLHint(const QString &r, const QString &p, KUriFilterData::UriTypes t = KUriFilterData::NetProtocol) + : regexp(QRegExp(r)) + , prepend(p) + , type(t) + { + } + QRegExp regexp; // if this matches, then... QString prepend; // ...prepend this to the url KUriFilterData::UriTypes type; }; QList m_urlHints; QString m_strDefaultUrlScheme; }; #endif