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.
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
37 SearchProviderItem(QTreeWidget
*parent
, SearchProvider
*provider
)
38 :QTreeWidgetItem(parent
, QStringList() << provider
->name()), m_provider(provider
)
40 setFlags(Qt::ItemIsSelectable
| Qt::ItemIsUserCheckable
| Qt::ItemIsEnabled
);
44 virtual ~SearchProviderItem()
51 setText(0, m_provider
->name());
52 setText(1, m_provider
->keys().join(","));
55 SearchProvider
*provider() const { return m_provider
; }
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())
157 void FilterOptions::setDelimiter (char sep
)
162 m_dlg
->cmbDelimiter
->setCurrentIndex (1);
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() ) );
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
);
194 SearchProviderItem
*item
= dynamic_cast<SearchProviderItem
*>(*it
);
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
++;
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
;
224 check
+= QString().setNum(suffix
);
225 if ((located
= KStandardDirs::locate("services", "searchproviders/" + check
+ ".desktop")).isEmpty())
230 else if (located
.left(path
.length()) == path
)
232 // If it's a deleted (hidden) entry, overwrite it
233 if (KService(located
).isDeleted())
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);
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");
260 if (!matches
.count())
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]);
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
);
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()
294 m_dlg
->cmbDefaultEngine
->setCurrentIndex (0);
295 m_dlg
->cbEnableShortcuts
->setChecked( true );
298 void FilterOptions::configChanged()
300 // kDebug () << "FilterOptions::configChanged: TRUE";
304 void FilterOptions::checkFavoritesChanged()
306 QStringList currentFavoriteEngines
;
307 QTreeWidgetItemIterator
it(m_dlg
->lvSearchProviders
);
309 SearchProviderItem
*item
= dynamic_cast<SearchProviderItem
*>(*it
);
313 if (item
->checkState(0) == Qt::Checked
)
314 currentFavoriteEngines
<< item
->provider()->desktopEntryName();
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
;
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);
348 m_dlg
->lvSearchProviders
->setCurrentItem(displaySearchProvider(dlg
.provider()));
353 void FilterOptions::changeSearchProvider()
355 SearchProviderItem
*item
= dynamic_cast<SearchProviderItem
*>(m_dlg
->lvSearchProviders
->currentItem());
358 SearchProviderDialog
dlg(item
->provider(), this);
362 m_dlg
->lvSearchProviders
->setCurrentItem(displaySearchProvider(dlg
.provider()));
367 void FilterOptions::deleteSearchProvider()
369 SearchProviderItem
*item
= dynamic_cast<SearchProviderItem
*>(m_dlg
->lvSearchProviders
->currentItem());
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
);
380 m_dlg
->cmbDefaultEngine
->setCurrentIndex(0);
381 else if (current
> i
)
382 m_dlg
->cmbDefaultEngine
->setCurrentIndex(current
- 1);
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());
397 updateSearchProvider();
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
);
415 if ((*it
)->text(0) == p
->name())
417 item
= dynamic_cast<SearchProviderItem
*>(*it
);
428 // Put the name in the default search engine combo box.
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
);
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);
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 ();
460 m_dlg
->cmbDefaultEngine
->setCurrentIndex(itemCount
);
463 m_dlg
->lvSearchProviders
->sortItems(0, Qt::AscendingOrder
);
469 #include "ikwsopts.moc"