summaryrefslogtreecommitdiffstats
path: root/kcontrol/ebrowsing/plugins/ikws/ikwsopts.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kcontrol/ebrowsing/plugins/ikws/ikwsopts.cpp')
-rw-r--r--kcontrol/ebrowsing/plugins/ikws/ikwsopts.cpp492
1 files changed, 492 insertions, 0 deletions
diff --git a/kcontrol/ebrowsing/plugins/ikws/ikwsopts.cpp b/kcontrol/ebrowsing/plugins/ikws/ikwsopts.cpp
new file mode 100644
index 000000000..6c055255d
--- /dev/null
+++ b/kcontrol/ebrowsing/plugins/ikws/ikwsopts.cpp
@@ -0,0 +1,492 @@
+/*
+ * Copyright (c) 2000 Yves Arrouye <yves@realnames.com>
+ * Copyright (c) 2001, 2002 Dawit Alemayehu <adawit@kde.org>
+ *
+ * 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 <qcheckbox.h>
+#include <qfile.h>
+#include <qgroupbox.h>
+#include <qheader.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qvbox.h>
+#include <qwhatsthis.h>
+
+#include <kdebug.h>
+#include <kglobal.h>
+#include <dcopref.h>
+#include <kapplication.h>
+#include <kcombobox.h>
+#include <kconfig.h>
+#include <kiconloader.h>
+#include <klistview.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kservice.h>
+#include <ksimpleconfig.h>
+#include <kstandarddirs.h>
+#include <ktrader.h>
+
+#include "ikwsopts.h"
+#include "ikwsopts_ui.h"
+#include "kuriikwsfiltereng.h"
+#include "searchprovider.h"
+#include "searchproviderdlg.h"
+
+
+class SearchProviderItem : public QCheckListItem
+{
+public:
+ SearchProviderItem(QListView *parent, SearchProvider *provider)
+ :QCheckListItem(parent, provider->name(), CheckBox), m_provider(provider)
+ {
+ update();
+ }
+
+ virtual ~SearchProviderItem()
+ {
+ delete m_provider;
+ }
+
+ void update()
+ {
+ setText(0, m_provider->name());
+ setText(1, m_provider->keys().join(","));
+ }
+
+ SearchProvider *provider() const { return m_provider; }
+
+private:
+ SearchProvider *m_provider;
+};
+
+FilterOptions::FilterOptions(KInstance *instance, QWidget *parent, const char *name)
+ :KCModule(instance, parent, name)
+{
+ QVBoxLayout *mainLayout = new QVBoxLayout( this, KDialog::marginHint(),
+ KDialog::spacingHint());
+
+ m_dlg = new FilterOptionsUI (this);
+ mainLayout->addWidget(m_dlg);
+
+ m_dlg->lvSearchProviders->header()->setLabel(0, SmallIconSet("bookmark"),i18n("Name"));
+ m_dlg->lvSearchProviders->setSorting(0);
+
+ // Load the options
+ load();
+}
+
+QString FilterOptions::quickHelp() const
+{
+ return i18n("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 <b>gg:KDE</b> "
+ "or <b>google:KDE</b>."
+ "<p>If you select a default search engine, normal words or phrases "
+ "will be looked up at the specified search engine by simply typing "
+ "them into applications, such as Konqueror, that have built-in support "
+ "for such a feature.");
+}
+
+void FilterOptions::load()
+{
+ load( false );
+}
+
+void FilterOptions::load( bool useDefaults )
+{
+ // Clear state first.
+ m_dlg->lvSearchProviders->clear();
+
+ KConfig config( KURISearchFilterEngine::self()->name() + "rc", false, false );
+
+ config.setReadDefaults( useDefaults );
+
+ config.setGroup("General");
+
+ QString defaultSearchEngine = config.readEntry("DefaultSearchEngine");
+
+ m_favoriteEngines.clear();
+ m_favoriteEngines << "google" << "google_groups" << "google_news" << "webster" << "dmoz" << "wikipedia";
+ m_favoriteEngines = config.readListEntry("FavoriteSearchEngines", m_favoriteEngines);
+
+ const KTrader::OfferList services = KTrader::self()->query("SearchProvider");
+
+ for (KTrader::OfferList::ConstIterator it = services.begin();
+ it != services.end(); ++it)
+ {
+ displaySearchProvider(new SearchProvider(*it),
+ ((*it)->desktopEntryName() == defaultSearchEngine));
+ }
+
+ bool webShortcutsEnabled = config.readBoolEntry("EnableWebShortcuts", true);
+ m_dlg->cbEnableShortcuts->setChecked( webShortcutsEnabled );
+
+ setDelimiter (config.readNumEntry ("KeywordDelimiter", ':'));
+
+ // Update the GUI to reflect the config options read above...
+ setWebShortcutState();
+
+ if (m_dlg->lvSearchProviders->childCount())
+ m_dlg->lvSearchProviders->setSelected(m_dlg->lvSearchProviders->firstChild(), true);
+
+ // Connect all the signals/slots...
+ connect(m_dlg->cbEnableShortcuts, SIGNAL(clicked()), this,
+ SLOT(setWebShortcutState()));
+ connect(m_dlg->cbEnableShortcuts, SIGNAL(clicked()), this,
+ SLOT(configChanged()));
+
+ connect(m_dlg->lvSearchProviders, SIGNAL(selectionChanged(QListViewItem *)),
+ this, SLOT(updateSearchProvider()));
+ connect(m_dlg->lvSearchProviders, SIGNAL(doubleClicked(QListViewItem *)),
+ this, SLOT(changeSearchProvider()));
+ connect(m_dlg->lvSearchProviders, SIGNAL(returnPressed(QListViewItem *)),
+ this, SLOT(changeSearchProvider()));
+ connect(m_dlg->lvSearchProviders, SIGNAL(executed(QListViewItem *)),
+ this, SLOT(checkFavoritesChanged()));
+ connect(m_dlg->lvSearchProviders, SIGNAL(spacePressed(QListViewItem *)),
+ this, SLOT(checkFavoritesChanged()));
+ connect(m_dlg->lvSearchProviders, SIGNAL(pressed(QListViewItem *)),
+ this, SLOT(checkFavoritesChanged()));
+
+ connect(m_dlg->cmbDefaultEngine, SIGNAL(activated(const QString &)), this,
+ SLOT(configChanged()));
+ connect(m_dlg->cmbDelimiter, SIGNAL(activated(const QString &)), this,
+ SLOT(configChanged()));
+
+ connect(m_dlg->pbNew, SIGNAL(clicked()), this, SLOT(addSearchProvider()));
+ connect(m_dlg->pbChange, SIGNAL(clicked()), this, SLOT(changeSearchProvider()));
+ connect(m_dlg->pbDelete, SIGNAL(clicked()), this, SLOT(deleteSearchProvider()));
+
+ emit changed( useDefaults );
+}
+
+char FilterOptions::delimiter ()
+{
+ switch (m_dlg->cmbDelimiter->currentItem())
+ {
+ case 1:
+ return ' ';
+ case 0:
+ default:
+ return ':';
+ };
+}
+
+void FilterOptions::setDelimiter (char sep)
+{
+ switch (sep)
+ {
+ case ' ':
+ m_dlg->cmbDelimiter->setCurrentItem (1);
+ break;
+ case ':':
+ default:
+ m_dlg->cmbDelimiter->setCurrentItem (0);
+ };
+}
+
+void FilterOptions::save()
+{
+ KConfig config( KURISearchFilterEngine::self()->name() + "rc", false, false );
+
+ config.setGroup("General");
+ config.writeEntry("EnableWebShortcuts", m_dlg->cbEnableShortcuts->isChecked());
+ config.writeEntry("KeywordDelimiter", delimiter() );
+
+ QString engine;
+
+ if (m_dlg->cmbDefaultEngine->currentItem() != 0)
+ engine = m_dlg->cmbDefaultEngine->currentText();
+
+ config.writeEntry("DefaultSearchEngine", m_defaultEngineMap[engine]);
+
+ // kdDebug () << "Engine: " << m_defaultEngineMap[engine] << endl;
+
+ int changedProviderCount = 0;
+ QString path = kapp->dirs()->saveLocation("services", "searchproviders/");
+
+ m_favoriteEngines.clear();
+
+ for (QListViewItemIterator it(m_dlg->lvSearchProviders); it.current(); ++it)
+ {
+ SearchProviderItem *item = dynamic_cast<SearchProviderItem *>(it.current());
+
+ Q_ASSERT(item);
+
+ SearchProvider *provider = item->provider();
+
+ QString name = provider->desktopEntryName();
+
+ if (item->isOn())
+ m_favoriteEngines << name;
+
+ if (provider->isDirty())
+ {
+ changedProviderCount++;
+
+ if (name.isEmpty())
+ {
+ // New provider
+ // 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 (QStringList::ConstIterator it = provider->keys().begin(); it != provider->keys().end(); ++it)
+ {
+ if ((*it).length() > name.length())
+ name = (*it).lower();
+ }
+ for (int suffix = 0; ; ++suffix)
+ {
+ QString located, check = name;
+ if (suffix)
+ check += QString().setNum(suffix);
+ if ((located = locate("services", "searchproviders/" + check + ".desktop")).isEmpty())
+ {
+ name = check;
+ break;
+ }
+ else if (located.left(path.length()) == path)
+ {
+ // If it's a deleted (hidden) entry, overwrite it
+ if (KService(located).isDeleted())
+ break;
+ }
+ }
+ }
+
+ KSimpleConfig service(path + name + ".desktop");
+ service.setGroup("Desktop Entry");
+ service.writeEntry("Type", "Service");
+ service.writeEntry("ServiceTypes", "SearchProvider");
+ service.writeEntry("Name", provider->name());
+ service.writeEntry("Query", provider->query(), true, false, true);
+ service.writeEntry("Keys", provider->keys());
+ service.writeEntry("Charset", provider->charset());
+
+ // we might be overwriting a hidden entry
+ service.writeEntry("Hidden", false);
+ }
+ }
+
+ for (QStringList::ConstIterator it = m_deletedProviders.begin();
+ it != m_deletedProviders.end(); ++it)
+ {
+ QStringList matches = kapp->dirs()->findAllResources("services", "searchproviders/" + *it + ".desktop");
+
+ // Shouldn't happen
+ if (!matches.count())
+ continue;
+
+ if (matches.count() == 1 && matches[0].left(path.length()) == path)
+ {
+ // If only the local copy existed, unlink it
+ // TODO: error handling
+ QFile::remove(matches[0]);
+ continue;
+ }
+ KSimpleConfig service(path + *it + ".desktop");
+ service.setGroup("Desktop Entry");
+ service.writeEntry("Type", "Service");
+ service.writeEntry("ServiceTypes", "SearchProvider");
+ service.writeEntry("Hidden", true);
+ }
+
+ config.writeEntry("FavoriteSearchEngines", m_favoriteEngines);
+ config.sync();
+
+ emit changed(false);
+
+ // Update filters in running applications...
+ (void) DCOPRef("*", "KURIIKWSFilterIface").send("configure");
+ (void) DCOPRef("*", "KURISearchFilterIface").send("configure");
+
+ // If the providers changed, tell sycoca to rebuild its database...
+ if (changedProviderCount)
+ KService::rebuildKSycoca(this);
+}
+
+void FilterOptions::defaults()
+{
+ load( true );
+}
+
+void FilterOptions::configChanged()
+{
+ // kdDebug () << "FilterOptions::configChanged: TRUE" << endl;
+ emit changed(true);
+}
+
+void FilterOptions::checkFavoritesChanged()
+{
+ QStringList currentFavoriteEngines;
+ for (QListViewItemIterator it(m_dlg->lvSearchProviders); it.current(); ++it)
+ {
+ SearchProviderItem *item = dynamic_cast<SearchProviderItem *>(it.current());
+
+ Q_ASSERT(item);
+
+ if (item->isOn())
+ currentFavoriteEngines << item->provider()->desktopEntryName();
+ }
+
+ if (!(currentFavoriteEngines==m_favoriteEngines)) {
+ m_favoriteEngines=currentFavoriteEngines;
+ configChanged();
+ }
+}
+
+void FilterOptions::setWebShortcutState()
+{
+ bool use_keywords = m_dlg->cbEnableShortcuts->isChecked();
+ m_dlg->lvSearchProviders->setEnabled(use_keywords);
+ m_dlg->pbNew->setEnabled(use_keywords);
+ m_dlg->pbChange->setEnabled(use_keywords);
+ m_dlg->pbDelete->setEnabled(use_keywords);
+ m_dlg->lbDelimiter->setEnabled (use_keywords);
+ m_dlg->cmbDelimiter->setEnabled (use_keywords);
+ m_dlg->lbDefaultEngine->setEnabled (use_keywords);
+ m_dlg->cmbDefaultEngine->setEnabled (use_keywords);
+}
+
+void FilterOptions::addSearchProvider()
+{
+ SearchProviderDialog dlg(0, this);
+ if (dlg.exec())
+ {
+ m_dlg->lvSearchProviders->setSelected(displaySearchProvider(dlg.provider()), true);
+ configChanged();
+ }
+}
+
+void FilterOptions::changeSearchProvider()
+{
+ SearchProviderItem *item = dynamic_cast<SearchProviderItem *>(m_dlg->lvSearchProviders->currentItem());
+ Q_ASSERT(item);
+
+ SearchProviderDialog dlg(item->provider(), this);
+
+ if (dlg.exec())
+ {
+ m_dlg->lvSearchProviders->setSelected(displaySearchProvider(dlg.provider()), true);
+ configChanged();
+ }
+}
+
+void FilterOptions::deleteSearchProvider()
+{
+ SearchProviderItem *item = dynamic_cast<SearchProviderItem *>(m_dlg->lvSearchProviders->currentItem());
+ Q_ASSERT(item);
+
+ // Update the combo box to go to None if the fallback was deleted.
+ int current = m_dlg->cmbDefaultEngine->currentItem();
+ for (int i = 1, count = m_dlg->cmbDefaultEngine->count(); i < count; ++i)
+ {
+ if (m_dlg->cmbDefaultEngine->text(i) == item->provider()->name())
+ {
+ m_dlg->cmbDefaultEngine->removeItem(i);
+ if (i == current)
+ m_dlg->cmbDefaultEngine->setCurrentItem(0);
+ else if (current > i)
+ m_dlg->cmbDefaultEngine->setCurrentItem(current - 1);
+
+ break;
+ }
+ }
+
+ if (item->nextSibling())
+ m_dlg->lvSearchProviders->setSelected(item->nextSibling(), true);
+ else if (item->itemAbove())
+ m_dlg->lvSearchProviders->setSelected(item->itemAbove(), true);
+
+ if (!item->provider()->desktopEntryName().isEmpty())
+ m_deletedProviders.append(item->provider()->desktopEntryName());
+
+ delete item;
+ updateSearchProvider();
+ configChanged();
+}
+
+void FilterOptions::updateSearchProvider()
+{
+ m_dlg->pbChange->setEnabled(m_dlg->lvSearchProviders->currentItem());
+ m_dlg->pbDelete->setEnabled(m_dlg->lvSearchProviders->currentItem());
+}
+
+SearchProviderItem *FilterOptions::displaySearchProvider(SearchProvider *p, bool fallback)
+{
+ // Show the provider in the list.
+ SearchProviderItem *item = 0L;
+
+ QListViewItemIterator it(m_dlg->lvSearchProviders);
+
+ for (; it.current(); ++it)
+ {
+ if (it.current()->text(0) == p->name())
+ {
+ item = dynamic_cast<SearchProviderItem *>(it.current());
+ Q_ASSERT(item);
+ break;
+ }
+ }
+
+ if (item)
+ item->update ();
+ else
+ {
+ // Put the name in the default search engine combo box.
+ int itemCount;
+ int totalCount = m_dlg->cmbDefaultEngine->count();
+
+ item = new SearchProviderItem(m_dlg->lvSearchProviders, p);
+
+ if (m_favoriteEngines.find(p->desktopEntryName())!=m_favoriteEngines.end())
+ item->setOn(true);
+
+ for (itemCount = 1; itemCount < totalCount; itemCount++)
+ {
+ if (m_dlg->cmbDefaultEngine->text(itemCount) > p->name())
+ {
+ int currentItem = m_dlg->cmbDefaultEngine->currentItem();
+ m_dlg->cmbDefaultEngine->insertItem(p->name(), itemCount);
+ m_defaultEngineMap[p->name ()] = p->desktopEntryName ();
+ if (currentItem >= itemCount)
+ m_dlg->cmbDefaultEngine->setCurrentItem(currentItem+1);
+ break;
+ }
+ }
+
+ // Append it to the end of the list...
+ if (itemCount == totalCount)
+ {
+ m_dlg->cmbDefaultEngine->insertItem(p->name(), itemCount);
+ m_defaultEngineMap[p->name ()] = p->desktopEntryName ();
+ }
+
+ if (fallback)
+ m_dlg->cmbDefaultEngine->setCurrentItem(itemCount);
+ }
+
+ if (!it.current())
+ m_dlg->lvSearchProviders->sort();
+
+ return item;
+}
+
+#include "ikwsopts.moc"