add more spacing
[personal-kdebase.git] / runtime / kurifilter-plugins / ikws / ikwsopts.cpp
blob525eafd61def785a6e7cb52df1758bf7094cb3ab
1 /*
2 * Copyright (c) 2000 Yves Arrouye <yves@realnames.com>
3 * Copyright (c) 2001, 2002 Dawit Alemayehu <adawit@kde.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include "ikwsopts.h"
22 #include <QFile>
24 #include <QtDBus/QtDBus>
26 #include <kbuildsycocaprogressdialog.h>
27 #include <kstandarddirs.h>
28 #include <kservicetypetrader.h>
30 #include "kuriikwsfiltereng.h"
31 #include "searchprovider.h"
32 #include "searchproviderdlg.h"
34 class SearchProviderItem : public QTreeWidgetItem
36 public:
37 SearchProviderItem(QTreeWidget *parent, SearchProvider *provider)
38 :QTreeWidgetItem(parent, QStringList() << provider->name()), m_provider(provider)
40 setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
41 update();
44 virtual ~SearchProviderItem()
46 delete m_provider;
49 void update()
51 setText(0, m_provider->name());
52 setText(1, m_provider->keys().join(","));
55 SearchProvider *provider() const { return m_provider; }
57 private:
58 SearchProvider *m_provider;
61 FilterOptions::FilterOptions(const KComponentData &componentData, QWidget *parent)
62 :KCModule(componentData, parent)
64 QVBoxLayout *mainLayout = new QVBoxLayout( this );
66 m_dlg = new FilterOptionsUI (this);
67 mainLayout->addWidget(m_dlg);
69 m_dlg->lvSearchProviders->setColumnWidth(0, 200);
71 // Connect all the signals/slots...
72 connect(m_dlg->cbEnableShortcuts, SIGNAL(toggled(bool)), this,
73 SLOT(setWebShortcutState()));
74 connect(m_dlg->cbEnableShortcuts, SIGNAL(toggled(bool)), this,
75 SLOT(configChanged()));
77 connect(m_dlg->lvSearchProviders, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
78 this, SLOT(updateSearchProvider()));
79 connect(m_dlg->lvSearchProviders, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),
80 this, SLOT(changeSearchProvider()));
81 connect(m_dlg->lvSearchProviders, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
82 this, SLOT(checkFavoritesChanged()));
84 connect(m_dlg->cmbDefaultEngine, SIGNAL(currentIndexChanged(int)), this,
85 SLOT(configChanged()));
86 connect(m_dlg->cmbDelimiter, SIGNAL(currentIndexChanged(int)), this,
87 SLOT(configChanged()));
89 connect(m_dlg->pbNew, SIGNAL(clicked()), this, SLOT(addSearchProvider()));
90 connect(m_dlg->pbChange, SIGNAL(clicked()), this, SLOT(changeSearchProvider()));
91 connect(m_dlg->pbDelete, SIGNAL(clicked()), this, SLOT(deleteSearchProvider()));
94 QString FilterOptions::quickHelp() const
96 return i18n("<p>In this module you can configure the web shortcuts feature. "
97 "Web shortcuts allow you to quickly search or lookup words on "
98 "the Internet. For example, to search for information about the "
99 "KDE project using the Google engine, you simply type <b>gg:KDE</b> "
100 "or <b>google:KDE</b>.</p>"
101 "<p>If you select a default search engine, normal words or phrases "
102 "will be looked up at the specified search engine by simply typing "
103 "them into applications, such as Konqueror, that have built-in support "
104 "for such a feature.</p>");
107 void FilterOptions::load()
109 // Clear state first.
110 m_dlg->lvSearchProviders->clear();
112 KConfig config( KURISearchFilterEngine::self()->name() + "rc", KConfig::NoGlobals );
113 KConfigGroup group = config.group("General");
115 QString defaultSearchEngine = group.readEntry("DefaultSearchEngine");
117 m_favoriteEngines.clear();
118 m_favoriteEngines << "google" << "google_groups" << "google_news" << "webster" << "dmoz" << "wikipedia";
119 m_favoriteEngines = group.readEntry("FavoriteSearchEngines", m_favoriteEngines );
121 const KService::List services = KServiceTypeTrader::self()->query("SearchProvider");
123 m_dlg->lvSearchProviders->blockSignals(true); // do not emit itemChanged signals
124 for (KService::List::ConstIterator it = services.begin();
125 it != services.end(); ++it)
127 displaySearchProvider(new SearchProvider(*it),
128 ((*it)->desktopEntryName() == defaultSearchEngine));
130 m_dlg->lvSearchProviders->blockSignals(false);
132 bool webShortcutsEnabled = group.readEntry("EnableWebShortcuts", true);
133 m_dlg->cbEnableShortcuts->setChecked( webShortcutsEnabled );
135 QString delimiter = group.readEntry ("KeywordDelimiter", ":");
136 setDelimiter( delimiter[0].toLatin1() );
138 // Update the GUI to reflect the config options read above...
139 setWebShortcutState();
141 if (m_dlg->lvSearchProviders->topLevelItemCount() > 0)
142 m_dlg->lvSearchProviders->setCurrentItem(m_dlg->lvSearchProviders->topLevelItem(0));
145 char FilterOptions::delimiter ()
147 switch (m_dlg->cmbDelimiter->currentIndex())
149 case 1:
150 return ' ';
151 case 0:
152 default:
153 return ':';
157 void FilterOptions::setDelimiter (char sep)
159 switch (sep)
161 case ' ':
162 m_dlg->cmbDelimiter->setCurrentIndex (1);
163 break;
164 case ':':
165 default:
166 m_dlg->cmbDelimiter->setCurrentIndex (0);
170 void FilterOptions::save()
172 KConfig config( KURISearchFilterEngine::self()->name() + "rc", KConfig::NoGlobals );
174 KConfigGroup group = config.group("General");
175 group.writeEntry("EnableWebShortcuts", m_dlg->cbEnableShortcuts->isChecked());
176 group.writeEntry("KeywordDelimiter", QString( delimiter() ) );
178 QString engine;
180 if (m_dlg->cmbDefaultEngine->currentIndex() != 0)
181 engine = m_dlg->cmbDefaultEngine->currentText();
183 group.writeEntry("DefaultSearchEngine", m_defaultEngineMap[engine]);
185 // kDebug () << "Engine: " << m_defaultEngineMap[engine];
187 int changedProviderCount = 0;
188 QString path = KGlobal::mainComponent().dirs()->saveLocation("services", "searchproviders/");
190 m_favoriteEngines.clear();
192 QTreeWidgetItemIterator it(m_dlg->lvSearchProviders);
193 while (*it) {
194 SearchProviderItem *item = dynamic_cast<SearchProviderItem *>(*it);
196 Q_ASSERT(item);
198 SearchProvider *provider = item->provider();
200 QString name = provider->desktopEntryName();
202 if (item->checkState(0) == Qt::Checked)
203 m_favoriteEngines << name;
205 if (provider->isDirty())
207 changedProviderCount++;
209 if (name.isEmpty())
211 // New provider
212 // Take the longest search shortcut as filename,
213 // if such a file already exists, append a number and increase it
214 // until the name is unique
215 for (QStringList::ConstIterator it = provider->keys().begin(); it != provider->keys().end(); ++it)
217 if ((*it).length() > name.length())
218 name = (*it).toLower();
220 for (int suffix = 0; ; ++suffix)
222 QString located, check = name;
223 if (suffix)
224 check += QString().setNum(suffix);
225 if ((located = KStandardDirs::locate("services", "searchproviders/" + check + ".desktop")).isEmpty())
227 name = check;
228 break;
230 else if (located.left(path.length()) == path)
232 // If it's a deleted (hidden) entry, overwrite it
233 if (KService(located).isDeleted())
234 break;
239 KConfig _service( path + name + ".desktop", KConfig::SimpleConfig );
240 KConfigGroup service(&_service, "Desktop Entry");
241 service.writeEntry("Type", "Service");
242 service.writeEntry("ServiceTypes", "SearchProvider");
243 service.writeEntry("Name", provider->name());
244 service.writeEntry("Query", provider->query());
245 service.writeEntry("Keys", provider->keys());
246 service.writeEntry("Charset", provider->charset());
248 // we might be overwriting a hidden entry
249 service.writeEntry("Hidden", false);
251 ++it;
254 for (QStringList::ConstIterator it = m_deletedProviders.constBegin();
255 it != m_deletedProviders.constEnd(); ++it)
257 QStringList matches = KGlobal::mainComponent().dirs()->findAllResources("services", "searchproviders/" + *it + ".desktop");
259 // Shouldn't happen
260 if (!matches.count())
261 continue;
263 if (matches.count() == 1 && matches[0].left(path.length()) == path)
265 // If only the local copy existed, unlink it
266 // TODO: error handling
267 QFile::remove(matches[0]);
268 continue;
270 KConfig _service( path + *it + ".desktop", KConfig::SimpleConfig );
271 KConfigGroup service(&_service, "Desktop Entry");
272 service.writeEntry("Type", "Service");
273 service.writeEntry("ServiceTypes", "SearchProvider");
274 service.writeEntry("Hidden", true);
277 group.writeEntry("FavoriteSearchEngines", m_favoriteEngines);
278 config.sync();
280 emit changed(false);
282 // Update filters in running applications...
283 QDBusMessage msg = QDBusMessage::createSignal("/", "org.kde.KUriFilterPlugin", "configure");
284 QDBusConnection::sessionBus().send(msg);
286 // If the providers changed, tell sycoca to rebuild its database...
287 if (changedProviderCount)
288 KBuildSycocaProgressDialog::rebuildKSycoca(this);
291 void FilterOptions::defaults()
293 setDelimiter (':');
294 m_dlg->cmbDefaultEngine->setCurrentIndex (0);
295 m_dlg->cbEnableShortcuts->setChecked( true );
298 void FilterOptions::configChanged()
300 // kDebug () << "FilterOptions::configChanged: TRUE";
301 emit changed(true);
304 void FilterOptions::checkFavoritesChanged()
306 QStringList currentFavoriteEngines;
307 QTreeWidgetItemIterator it(m_dlg->lvSearchProviders);
308 while (*it) {
309 SearchProviderItem *item = dynamic_cast<SearchProviderItem *>(*it);
311 Q_ASSERT(item);
313 if (item->checkState(0) == Qt::Checked)
314 currentFavoriteEngines << item->provider()->desktopEntryName();
316 ++it;
319 currentFavoriteEngines.sort(); // make sure that both lists do have the same sorting
320 m_favoriteEngines.sort();
322 if (!(currentFavoriteEngines==m_favoriteEngines)) {
323 m_favoriteEngines=currentFavoriteEngines;
324 configChanged();
328 void FilterOptions::setWebShortcutState()
330 bool use_keywords = m_dlg->cbEnableShortcuts->isChecked();
331 m_dlg->lvSearchProviders->setEnabled(use_keywords);
332 bool itemActive = m_dlg->lvSearchProviders->currentItem() != 0;
333 m_dlg->pbNew->setEnabled(use_keywords);
334 m_dlg->pbChange->setEnabled(use_keywords && itemActive);
335 m_dlg->pbDelete->setEnabled(use_keywords && itemActive);
336 m_dlg->lbDelimiter->setEnabled (use_keywords);
337 m_dlg->cmbDelimiter->setEnabled (use_keywords);
338 m_dlg->lbDefaultEngine->setEnabled (use_keywords);
339 m_dlg->cmbDefaultEngine->setEnabled (use_keywords);
342 void FilterOptions::addSearchProvider()
344 SearchProviderDialog dlg(0, this);
346 if (dlg.exec())
348 m_dlg->lvSearchProviders->setCurrentItem(displaySearchProvider(dlg.provider()));
349 configChanged();
353 void FilterOptions::changeSearchProvider()
355 SearchProviderItem *item = dynamic_cast<SearchProviderItem *>(m_dlg->lvSearchProviders->currentItem());
356 Q_ASSERT(item);
358 SearchProviderDialog dlg(item->provider(), this);
360 if (dlg.exec())
362 m_dlg->lvSearchProviders->setCurrentItem(displaySearchProvider(dlg.provider()));
363 configChanged();
367 void FilterOptions::deleteSearchProvider()
369 SearchProviderItem *item = dynamic_cast<SearchProviderItem *>(m_dlg->lvSearchProviders->currentItem());
370 Q_ASSERT(item);
372 // Update the combo box to go to None if the fallback was deleted.
373 int current = m_dlg->cmbDefaultEngine->currentIndex();
374 for (int i = 1, count = m_dlg->cmbDefaultEngine->count(); i < count; ++i)
376 if (m_dlg->cmbDefaultEngine->itemText(i) == item->provider()->name())
378 m_dlg->cmbDefaultEngine->removeItem(i);
379 if (i == current)
380 m_dlg->cmbDefaultEngine->setCurrentIndex(0);
381 else if (current > i)
382 m_dlg->cmbDefaultEngine->setCurrentIndex(current - 1);
384 break;
388 if (m_dlg->lvSearchProviders->topLevelItem(current + 1))
389 m_dlg->lvSearchProviders->setCurrentItem(m_dlg->lvSearchProviders->topLevelItem(current + 1));
390 else if (m_dlg->lvSearchProviders->topLevelItem(current - 1))
391 m_dlg->lvSearchProviders->setCurrentItem(m_dlg->lvSearchProviders->topLevelItem(current - 1));
393 if (!item->provider()->desktopEntryName().isEmpty())
394 m_deletedProviders.append(item->provider()->desktopEntryName());
396 delete item;
397 updateSearchProvider();
398 configChanged();
401 void FilterOptions::updateSearchProvider()
403 m_dlg->pbChange->setEnabled(m_dlg->lvSearchProviders->currentItem());
404 m_dlg->pbDelete->setEnabled(m_dlg->lvSearchProviders->currentItem());
407 SearchProviderItem *FilterOptions::displaySearchProvider(SearchProvider *p, bool fallback)
409 // Show the provider in the list.
410 SearchProviderItem *item = 0L;
412 QTreeWidgetItemIterator it(m_dlg->lvSearchProviders);
413 while (*it)
415 if ((*it)->text(0) == p->name())
417 item = dynamic_cast<SearchProviderItem *>(*it);
418 Q_ASSERT(item);
419 break;
421 ++it;
424 if (item)
425 item->update ();
426 else
428 // Put the name in the default search engine combo box.
429 int itemCount;
430 int totalCount = m_dlg->cmbDefaultEngine->count();
432 item = new SearchProviderItem(m_dlg->lvSearchProviders, p);
434 if (m_favoriteEngines.contains(p->desktopEntryName()))
435 item->setCheckState(0, Qt::Checked);
436 else
437 item->setCheckState(0, Qt::Unchecked);
439 for (itemCount = 1; itemCount < totalCount; itemCount++)
441 if (m_dlg->cmbDefaultEngine->itemText(itemCount) > p->name())
443 int currentItem = m_dlg->cmbDefaultEngine->currentIndex();
444 m_dlg->cmbDefaultEngine->insertItem(itemCount, p->name());
445 m_defaultEngineMap[p->name ()] = p->desktopEntryName ();
446 if (currentItem >= itemCount)
447 m_dlg->cmbDefaultEngine->setCurrentIndex(currentItem+1);
448 break;
452 // Append it to the end of the list...
453 if (itemCount == totalCount)
455 m_dlg->cmbDefaultEngine->insertItem(itemCount, p->name());
456 m_defaultEngineMap[p->name ()] = p->desktopEntryName ();
459 if (fallback)
460 m_dlg->cmbDefaultEngine->setCurrentIndex(itemCount);
462 if (!(*it))
463 m_dlg->lvSearchProviders->sortItems(0, Qt::AscendingOrder);
466 return item;
469 #include "ikwsopts.moc"