diff options
32 files changed, 727 insertions, 102 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f0310b4d..6cf26517 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -70,6 +70,7 @@ SET( rekonq_KDEINIT_SRCS urlbar/listitem.cpp urlbar/rsswidget.cpp urlbar/bookmarkwidget.cpp + urlbar/webshortcutwidget.cpp #---------------------------------------- analyzer/analyzerpanel.cpp analyzer/networkanalyzer.cpp diff --git a/src/application.cpp b/src/application.cpp index 95aa9cf0..a7575b94 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -503,7 +503,7 @@ void Application::updateConfiguration() // Enabling WebKit "Page Cache" feature: http://webkit.org/blog/427/webkit-page-cache-i-the-basics/ defaultSettings->setMaximumPagesInCache(3); - + // ===== HTML 5 features WebKit support ====== defaultSettings->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, ReKonfig::offlineStorageDatabaseEnabled()); defaultSettings->setAttribute(QWebSettings::OfflineWebApplicationCacheEnabled, ReKonfig::offlineWebApplicationCacheEnabled()); @@ -600,20 +600,20 @@ void Application::setPrivateBrowsingMode(bool b) bool isJustEnabled = settings->testAttribute(QWebSettings::PrivateBrowsingEnabled); if(isJustEnabled == b) return; // uhm... something goes wrong... - + if (b) { QString caption = i18n("Are you sure you want to turn on private browsing?"); QString text = i18n("<b>%1</b>" "<p>rekonq will save your current tabs for when you'll stop private browsing the net..</p>", caption); - + int button = KMessageBox::warningContinueCancel(mainWindow(), text, caption, KStandardGuiItem::cont(), KStandardGuiItem::cancel(), i18n("don't ask again") ); if (button != KMessageBox::Continue) return; - + settings->setAttribute(QWebSettings::PrivateBrowsingEnabled, true); _privateBrowsingAction->setChecked(true); - + Q_FOREACH(const QWeakPointer<MainWindow> &w, m_mainWindows) { w.data()->close(); @@ -629,7 +629,7 @@ void Application::setPrivateBrowsingMode(bool b) settings->setAttribute(QWebSettings::PrivateBrowsingEnabled, false); _privateBrowsingAction->setChecked(false); - + loadUrl( KUrl("about:blank"), Rekonq::NewWindow); if(!sessionManager()->restoreSession()) loadUrl( KUrl("about:home"), Rekonq::NewWindow); diff --git a/src/data/CMakeLists.txt b/src/data/CMakeLists.txt index 5f499941..f34936b4 100644 --- a/src/data/CMakeLists.txt +++ b/src/data/CMakeLists.txt @@ -31,7 +31,19 @@ INSTALL( # opensearch engines INSTALL( FILES + beolingus.xml + de2en.xml + dictfr.xml + facebook.xml google.xml + kde_techbase.xml + kde_userbase.xml + youtube.xml + voila.xml + wikia.xml wikipedia.xml + wiktionary.xml + wr_english.xml + db_opensearch.json DESTINATION ${DATA_INSTALL_DIR}/rekonq/opensearch ) diff --git a/src/data/beolingus.xml b/src/data/beolingus.xml new file mode 100644 index 00000000..60901163 --- /dev/null +++ b/src/data/beolingus.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> + <ShortName>De-En Beolingus</ShortName> + <Description>Beolingus: German-English Dictionary</Description> + <Url method="get" template="http://dict.tu-chemnitz.de/?query={searchTerms}"/> + <Url method="get" type="application/x-suggestions+json" template="http://dict.tu-chemnitz.de/sugg.php?json=1;s={searchTerms}"/> + <Image>http://dict.tu-chemnitz.de/pics/beo-de.png</Image> +</OpenSearchDescription> diff --git a/src/data/db_opensearch.json b/src/data/db_opensearch.json new file mode 100644 index 00000000..16fc3f89 --- /dev/null +++ b/src/data/db_opensearch.json @@ -0,0 +1,67 @@ +[["http://www.7digital.com/osd.xml","7digital"], +["http://dict.tu-chemnitz.de/de-en/opensearch.xml","beolingus"], +["http://www.blip.tv/opensearch.xml","blip"], +["http://b.static.ak.fbcdn.net/rsrc.php/zJ/r/H2SSvhJMJA-.xml","facebook"], +["http://www.flickr.com/opensearch.xml","flickr"], +["https://github.com/opensearch.xml","github"], +["https://bugs.kde.org/search_plugin.cgi","bugft"], +["http://st.pimg.net/tucs/opensearch.xml","cpan"], + +["http://citeseerx.ist.psu.edu/search_plugins/citeseerx_general.xml","citeseerx"], +["http://citeseerx.ist.psu.edu/search_plugins/citeseerx_authorl.xml","citeseerx"], +["http://citeseerx.ist.psu.edu/search_plugins/citeseerx_title.xml","citeseerx"], + +["http://identi.ca/opensearch/people","identica_people"], +["http://identi.ca/opensearch/notice","identica_notices"], + +["http://www.cnrtl.fr/portail/opensearch.xml","dictfr"], + +["http://www.youtube.com/opensearch?locale=en_GB","youtube"], +["http://static1.urbandictionary.com/osd.xml?1292027099","urbandictionary"], + +["http://www.wordreference.com/tools/OpenSearch/enes.xml","en2es"], +["http://www.wordreference.com/tools/OpenSearch/esen.xml","es2en"], +["http://www.wordreference.com/tools/OpenSearch/enfr.xml","en2fr"], +["http://www.wordreference.com/tools/OpenSearch/fren.xml","fr2en"], +["http://www.wordreference.com/tools/OpenSearch/enit.xml","en2it"], +["http://www.wordreference.com/tools/OpenSearch/iten.xml","it2en"], +["http://www.wordreference.com/tools/OpenSearch/definition.xml","wordref"], +["http://dict.tu-chemnitz.de/de-en/opensearch.xml","de2en"], +["http://www.dict.cc/opensearch.xml","en2de"], +["http://dict.leo.org/plugins/Shared/Searches/leo_frde_de.xml","fr2de"], +["http://dict.leo.org/plugins/Shared/Searches/leo_ende_de.xml","leo"], + +["http://opensearch.search.ke.voila.fr/voila.xml","voila"], +["http://www.wikia.com/opensearch_desc.php","wikia"], + +["http://techbase.kde.org/opensearch_desc.php","kde_techbase"], +["http://userbase.kde.org/opensearch_desc.php","kde_userbase"], + +["http://duckduckgo.com/opensearch.xml","duckduckgo"], + +["http://ecosia.org/_files/searchplugin.xml","ecosia"], + +["http://fr.wikipedia.org/w/opensearch_desc.php","wikipedia"], +["http://en.wikipedia.org/w/opensearch_desc.php","wikipedia"], +["http://it.wikipedia.org/w/opensearch_desc.php","wikipedia"], +["http://de.wikipedia.org/w/opensearch_desc.php","wikipedia"], +["http://es.wikipedia.org/w/opensearch_desc.php","wikipedia"], +["http://nl.wikipedia.org/w/opensearch_desc.php","wikipedia"], +["http://pl.wikipedia.org/w/opensearch_desc.php","wikipedia"], +["http://ja.wikipedia.org/w/opensearch_desc.php","wikipedia"], +["http://ru.wikipedia.org/w/opensearch_desc.php","wikipedia"], +["http://pt.wikipedia.org/w/opensearch_desc.php","wikipedia"], + +["http://fr.wiktionary.org/w/opensearch_desc.php","wiktionary"], +["http://en.wiktionary.org/w/opensearch_desc.php","wiktionary"], +["http://it.wiktionary.org/w/opensearch_desc.php","wiktionary"], +["http://de.wiktionary.org/w/opensearch_desc.php","wiktionary"], +["http://es.wiktionary.org/w/opensearch_desc.php","wiktionary"], +["http://nl.wiktionary.org/w/opensearch_desc.php","wiktionary"], +["http://pl.wiktionary.org/w/opensearch_desc.php","wiktionary"], +["http://ja.wiktionary.org/w/opensearch_desc.php","wiktionary"], +["http://ru.wiktionary.org/w/opensearch_desc.php","wiktionary"], +["http://pt.wiktionary.org/w/opensearch_desc.php","wiktionary"], + +["http://search.yippy.com/search?v:project=opensearch-desc&v:frame=form&","yippy"], +["http://www.wolframalpha.com/searchDescription.xml","wolfram_alpha"]]
\ No newline at end of file diff --git a/src/data/de2en.xml b/src/data/de2en.xml new file mode 100644 index 00000000..60901163 --- /dev/null +++ b/src/data/de2en.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> + <ShortName>De-En Beolingus</ShortName> + <Description>Beolingus: German-English Dictionary</Description> + <Url method="get" template="http://dict.tu-chemnitz.de/?query={searchTerms}"/> + <Url method="get" type="application/x-suggestions+json" template="http://dict.tu-chemnitz.de/sugg.php?json=1;s={searchTerms}"/> + <Image>http://dict.tu-chemnitz.de/pics/beo-de.png</Image> +</OpenSearchDescription> diff --git a/src/data/dictfr.xml b/src/data/dictfr.xml new file mode 100644 index 00000000..64e90ea3 --- /dev/null +++ b/src/data/dictfr.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> + <ShortName>Portail Lexical - CNRTL</ShortName> + <Description>Cherche dans le TLF sur le portail lexical du CNRTL</Description> + <Url method="get" template="http://www.cnrtl.fr/definition/{searchTerms}"/> + <Url method="get" type="application/x-suggestions+json" template="http://www.cnrtl.fr/utilities/OPEN?query={searchTerms}"/> + <Image>http://www.cnrtl.fr/favicon.ico</Image> +</OpenSearchDescription> diff --git a/src/data/facebook.xml b/src/data/facebook.xml new file mode 100644 index 00000000..612e7cd0 --- /dev/null +++ b/src/data/facebook.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> + <ShortName>Facebook</ShortName> + <Description>Search Facebook</Description> + <Url method="get" template="http://www.facebook.com/search/?src=os&q={searchTerms}"/> + <Url method="get" type="application/x-suggestions+xml" template="http://www.facebook.com/search/opensearch_typeahead.php?format=xml&q={searchTerms}"/> + <Image>http://www.facebook.com/favicon.ico</Image> +</OpenSearchDescription> diff --git a/src/data/kde_techbase.xml b/src/data/kde_techbase.xml new file mode 100644 index 00000000..25fc6e4c --- /dev/null +++ b/src/data/kde_techbase.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> + <ShortName>KDE TechBase (en)</ShortName> + <Description>KDE TechBase (en)</Description> + <Url method="get" template="http://techbase.kde.org/index.php?title=Special:Search&search={searchTerms}"/> + <Url method="get" type="application/x-suggestions+xml" template="http://techbase.kde.org/api.php?action=opensearch&format=xml&search={searchTerms}&namespace=0"/> + <Image>http://techbase.kde.org/favicon.ico</Image> +</OpenSearchDescription> diff --git a/src/data/kde_userbase.xml b/src/data/kde_userbase.xml new file mode 100644 index 00000000..64877019 --- /dev/null +++ b/src/data/kde_userbase.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> + <ShortName>KDE UserBase (en)</ShortName> + <Description>KDE UserBase (en)</Description> + <Url method="get" template="http://userbase.kde.org/index.php?title=Special:Search&search={searchTerms}"/> + <Url method="get" type="application/x-suggestions+xml" template="http://userbase.kde.org/api.php?action=opensearch&format=xml&search={searchTerms}&namespace=0"/> + <Image>http://userbase.kde.org/favicon.png</Image> +</OpenSearchDescription> diff --git a/src/data/voila.xml b/src/data/voila.xml new file mode 100644 index 00000000..55780275 --- /dev/null +++ b/src/data/voila.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> + <ShortName>Voila</ShortName> + <Description>Moteur de recherche Voila</Description> + <Url method="get" template="http://rws.search.ke.voila.fr/RW/S/opensearch_voila?rdata={searchTerms}"/> + <Url method="get" type="application/x-suggestions+json" template="http://search.ke.voila.fr/fr/cmplopensearch/xml/fullxml?rdata={searchTerms}&amp;id=1&amp;dtd=2.0"/> + <Image>http://www.voila.fr/favicon.ico</Image> +</OpenSearchDescription> diff --git a/src/data/wikia.xml b/src/data/wikia.xml new file mode 100644 index 00000000..0a1eac69 --- /dev/null +++ b/src/data/wikia.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> + <ShortName>Wikia (en)</ShortName> + <Description>Wikia (en)</Description> + <Url method="get" template="http://www.wikia.com/index.php?title=Special:Search&search={searchTerms}"/> + <Url method="get" type="application/x-suggestions+json" template="http://www.wikia.com/api.php?action=opensearch&search={searchTerms}&namespace=1"/> + <Image>http://images.wikia.com/wikiaglobal/images/6/64/Favicon.ico</Image> +</OpenSearchDescription> diff --git a/src/data/wikipedia.xml b/src/data/wikipedia.xml index 4e152087..9f9bdda4 100644 --- a/src/data/wikipedia.xml +++ b/src/data/wikipedia.xml @@ -2,7 +2,7 @@ <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> <ShortName>Wikipedia</ShortName> <Description>Wikipedia</Description> - <Url method="get" template="http://en.wikipedia.org/w/index.php?title=Sp%C3%A9cial:Recherche&search={searchTerms}"/> - <Url method="get" type="application/x-suggestions+xml" template="http://en.wikipedia.org/w/api.php?action=opensearch&format=xml&search={searchTerms}&namespace=0"/> + <Url method="get" template="http://{country}.wikipedia.org/w/index.php?title=Sp%C3%A9cial:Recherche&search={searchTerms}"/> + <Url method="get" type="application/x-suggestions+xml" template="http://{country}.wikipedia.org/w/api.php?action=opensearch&format=xml&search={searchTerms}&namespace=0"/> <Image>http://en.wikipedia.org/favicon.ico</Image> </OpenSearchDescription> diff --git a/src/data/wiktionary.xml b/src/data/wiktionary.xml new file mode 100644 index 00000000..033f5b9e --- /dev/null +++ b/src/data/wiktionary.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> + <ShortName>Wiktionary</ShortName> + <Description>Wiktionary</Description> + <Url method="get" template="http://{country}.wiktionary.org/w/index.php?title=Special:Search&search={searchTerms}"/> + <Url method="get" type="application/x-suggestions+xml" template="http://{country}.wiktionary.org/w/api.php?action=opensearch&format=xml&search={searchTerms}&namespace=0"/> + <Image>http://en.wiktionary.org/favicon.ico</Image> +</OpenSearchDescription> diff --git a/src/data/wr_english.xml b/src/data/wr_english.xml new file mode 100644 index 00000000..30c9339b --- /dev/null +++ b/src/data/wr_english.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> + <ShortName>WR English</ShortName> + <Description>WordReference monolingual English dictionary search</Description> + <Url method="get" template="http://www.wordreference.com/definition/{searchTerms}"/> +</OpenSearchDescription> diff --git a/src/data/youtube.xml b/src/data/youtube.xml new file mode 100644 index 00000000..1fa8338a --- /dev/null +++ b/src/data/youtube.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> + <ShortName>Recherche de vidéos YouTube</ShortName> + <Description>Recherche de vidéos sur YouTube</Description> + <Url method="get" template="http://www.youtube.com/results?search_query={searchTerms}&page={startPage?}&utm_source=opensearch"/> + <Image>http://www.youtube.com/favicon.ico</Image> +</OpenSearchDescription> diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 4159d451..938e6985 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -737,12 +737,12 @@ void MainWindow::printRequested(QWebFrame *frame) connect(this, SIGNAL(triggerPartPrint()), ext, actionSlotMap->value("print")); emit triggerPartPrint(); - + return; } } } - + QWebFrame *printFrame = 0; if (frame == 0) { @@ -800,7 +800,7 @@ void MainWindow::findNext() return; } } - + if (m_findBar->isHidden()) { QPoint previous_position = currentTab()->view()->page()->currentFrame()->scrollPosition(); @@ -1385,7 +1385,7 @@ bool MainWindow::queryClose() // smooth private browsing mode if(QWebSettings::globalSettings()->testAttribute(QWebSettings::PrivateBrowsingEnabled)) return true; - + if (m_view->count() > 1) { int answer = KMessageBox::questionYesNoCancel( diff --git a/src/opensearch/opensearchengine.cpp b/src/opensearch/opensearchengine.cpp index 9d5e866f..37685fb5 100644 --- a/src/opensearch/opensearchengine.cpp +++ b/src/opensearch/opensearchengine.cpp @@ -57,12 +57,18 @@ QString OpenSearchEngine::parseTemplate(const QString &searchTerm, const QString QString language = QLocale().name(); // Simple conversion to RFC 3066. language = language.replace(QL1C('_'), QL1C('-')); + QString country = language; + country = (country.replace(0, country.indexOf("-")+1, "")).toLower(); + const int firstDashPosition = country.indexOf(QL1C('-')); + if (firstDashPosition >= 0) + country = country.mid(firstDashPosition+1); QString result = searchTemplate; result.replace(QL1S("{count}"), QL1S("20")); result.replace(QL1S("{startIndex}"), QL1S("0")); result.replace(QL1S("{startPage}"), QL1S("0")); result.replace(QL1S("{language}"), language); + result.replace(QL1S("{country}"), country.toLower()); result.replace(QL1S("{inputEncoding}"), QL1S("UTF-8")); result.replace(QL1S("{outputEncoding}"), QL1S("UTF-8")); result.replace(QL1S("{searchTerms}"), searchTerm); diff --git a/src/opensearch/opensearchmanager.cpp b/src/opensearch/opensearchmanager.cpp index e5afc144..4ee1de33 100644 --- a/src/opensearch/opensearchmanager.cpp +++ b/src/opensearch/opensearchmanager.cpp @@ -34,6 +34,7 @@ #include "opensearchengine.h" #include "opensearchreader.h" #include "opensearchwriter.h" +#include "application.h" // KDE Includes #include <KDebug> @@ -41,10 +42,17 @@ #include <KStandardDirs> #include <KUrl> #include <kio/scheduler.h> +#include <KService> +#include <KStandardDirs> +#include <KDE/KMessageBox> +#include <KUriFilterData> +#include <KConfigGroup> // Qt Includes #include <QtCore/QFile> - +#include <QtCore/QFileInfo> +#include <QDBusMessage> +#include <QDBusConnection> OpenSearchManager::OpenSearchManager(QObject *parent) : QObject(parent) @@ -52,13 +60,15 @@ OpenSearchManager::OpenSearchManager(QObject *parent) , m_currentJob(0) { m_state = IDLE; + loadEngines(); } OpenSearchManager::~OpenSearchManager() { - qDeleteAll(m_enginesMap.values()); - m_enginesMap.clear(); + qDeleteAll(m_engineCache.values()); + m_engineCache.clear(); + m_engines.clear(); } @@ -66,10 +76,10 @@ void OpenSearchManager::setSearchProvider(const QString &searchProvider) { m_activeEngine = 0; - if (!m_enginesMap.contains(searchProvider)) + if (!m_engineCache.contains(searchProvider)) { - const QString fileName = KGlobal::dirs()->findResource("data", "rekonq/opensearch/" + searchProvider + ".xml"); - kDebug() << searchProvider << " file name path: " << fileName; + const QString fileName = KGlobal::dirs()->findResource("data", "rekonq/opensearch/" + trimmedEngineName(searchProvider) + ".xml"); + kDebug() << searchProvider << " trimmed name: " << trimmedEngineName(searchProvider) << " file name path: " << fileName; if (fileName.isEmpty()) { kDebug() << "OpenSearch file name empty"; @@ -88,7 +98,7 @@ void OpenSearchManager::setSearchProvider(const QString &searchProvider) if (engine) { - m_enginesMap.insert(searchProvider, engine); + m_engineCache.insert(searchProvider, engine); } else { @@ -96,7 +106,7 @@ void OpenSearchManager::setSearchProvider(const QString &searchProvider) } } - m_activeEngine = m_enginesMap.value(searchProvider); + m_activeEngine = m_engineCache.value(searchProvider); } @@ -106,22 +116,24 @@ bool OpenSearchManager::isSuggestionAvailable() } -void OpenSearchManager::addOpenSearchEngine(const KUrl &url, const QString &title) +void OpenSearchManager::addOpenSearchEngine(const KUrl &url, const QString &title, const QString &shortcut) { Q_UNUSED(title); + m_shortcut = shortcut; + if (m_state != IDLE) { idleJob(); } m_currentJob = KIO::get(url, KIO::NoReload, KIO::HideProgressInfo); + m_jobUrl = url; m_state = REQ_DESCRIPTION; connect(m_currentJob, SIGNAL(data(KIO::Job *, const QByteArray &)), this, SLOT(dataReceived(KIO::Job *, const QByteArray &))); connect(m_currentJob, SIGNAL(result(KJob *)), this, SLOT(jobFinished(KJob *))); } - void OpenSearchManager::requestSuggestion(const QString &searchText) { if (!m_activeEngine) @@ -135,7 +147,7 @@ void OpenSearchManager::requestSuggestion(const QString &searchText) // if we want in any case lets it finish its previous job we can just return here. idleJob(); } - + _typedText = searchText; KUrl url = m_activeEngine->suggestionsUrl(searchText); @@ -163,7 +175,7 @@ void OpenSearchManager::jobFinished(KJob *job) m_state = IDLE; return; // just silently return } - + if (m_state == REQ_SUGGESTION) { const ResponseList suggestionsList = m_activeEngine->parseSuggestion(m_jobData); @@ -184,40 +196,144 @@ void OpenSearchManager::jobFinished(KJob *job) OpenSearchEngine *engine = reader.read(m_jobData); if (engine) { - m_enginesMap.insert(engine->name(), engine); - QString path = KGlobal::dirs()->findResource("data", "rekonq/opensearch/"); - QString fileName = trimmedEngineName(engine->name()); - QFile file(path + fileName + ".xml"); - OpenSearchWriter writer; - writer.write(&file, engine); + m_engineCache.insert(engine->name(), engine); + m_engines.insert(m_jobUrl, trimmedEngineName(engine->name())); + saveEngines(); + + QString path; + if (engine->providesSuggestions()) //save opensearch description only if it provides suggestions + { + OpenSearchWriter writer; + path = KGlobal::dirs()->findResource("data", "rekonq/opensearch/"); + QFile file(path + trimmedEngineName(engine->name()) + ".xml"); + writer.write(&file, engine); + } QString searchUrl = OpenSearchEngine::parseTemplate("\\{@}", engine->searchUrlTemplate()); m_currentJob = NULL; - emit openSearchEngineAdded(engine->name(), searchUrl, fileName); + + path = KGlobal::mainComponent().dirs()->saveLocation("services", "searchproviders/"); + KConfig _service(path + trimmedEngineName(engine->name()) + ".desktop", KConfig::SimpleConfig); + KConfigGroup service(&_service, "Desktop Entry"); + service.writeEntry("Type", "Service"); + service.writeEntry("ServiceTypes", "SearchProvider"); + service.writeEntry("Name", engine->name()); + service.writeEntry("Query", searchUrl); + service.writeEntry("Keys", m_shortcut); + // TODO charset + service.writeEntry("Charset", "" /* provider->charset() */); + // we might be overwriting a hidden entry + service.writeEntry("Hidden", false); + service.sync(); + + // Update filters in running applications... + QDBusMessage msg = QDBusMessage::createSignal("/", "org.kde.KUriFilterPlugin", "configure"); + QDBusConnection::sessionBus().send(msg); + + emit openSearchEngineAdded(engine->name(), searchUrl, m_shortcut); } else { kFatal() << "Error while adding new open search engine"; } - + idleJob(); } } +void OpenSearchManager::loadEngines() +{ + QFile file(KStandardDirs::locate("appdata", "opensearch/db_opensearch.json")); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + { + kDebug() << "opensearch db cannot be read"; + return; + } + + QString fileContent = QString::fromUtf8(file.readAll()); + QScriptEngine reader; + if (!reader.canEvaluate(fileContent)) + { + kDebug() << "opensearch db cannot be read"; + return; + } + + QScriptValue responseParts = reader.evaluate(fileContent); + QVariantList list; + qScriptValueToSequence(responseParts, list); + QStringList l; + Q_FOREACH(const QVariant &e, list) + { + l=e.toStringList(); + m_engines.insert(KUrl(l.first()),l.last()); + } + file.close(); +} + + +void OpenSearchManager::saveEngines() +{ + QFile file(KStandardDirs::locate("appdata", "opensearch/db_opensearch.json")); + if (!file.open(QIODevice::WriteOnly)) + { + kDebug() << "opensearch db cannot be writen"; + return; + } + QTextStream out(&file); + out << "["; + int i=0; + QList<KUrl> urls = m_engines.keys(); + Q_FOREACH(const KUrl &url, urls) + { + out << "[\"" << url.url() << "\",\"" << m_engines.value(url) << "\"]"; + i++; + if (i != urls.size()) + { + out << ",\n"; + } + } + out << "]\n"; + file.close(); +} + + +void OpenSearchManager::removeDeletedEngines() +{ + KService::Ptr service; + Q_FOREACH(const KUrl &url, m_engines.keys()) + { + service = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(m_engines.value(url))); + if (!service) + { + QString path = KStandardDirs::locate("appdata", "opensearch/" + trimmedEngineName(m_engines.value(url)) + ".xml"); + QFile::remove(path + trimmedEngineName(m_engines.value(url)) + ".xml"); + m_engines.remove(url); + } + } + saveEngines(); +} + + +bool OpenSearchManager::engineExists(const KUrl &url) +{ + return m_engines.contains(url); +} + + QString OpenSearchManager::trimmedEngineName(const QString &engineName) const { QString trimmed; QString::ConstIterator constIter = engineName.constBegin(); - while (constIter != engineName.constEnd()) + while (constIter != engineName.constEnd()) { - if (constIter->isSpace()) + if (constIter->isSpace()) { - trimmed.append('-'); + trimmed.append('_'); } - else + else { - if (*constIter != '.') + if (*constIter != '.') { trimmed.append(constIter->toLower()); } diff --git a/src/opensearch/opensearchmanager.h b/src/opensearch/opensearchmanager.h index 4f42b4a8..df8e5367 100644 --- a/src/opensearch/opensearchmanager.h +++ b/src/opensearch/opensearchmanager.h @@ -39,6 +39,7 @@ // Qt Includes #include <QtCore/QObject> +#include <QFile> // Forward Declarations class OpenSearchEngine; @@ -59,7 +60,7 @@ class OpenSearchManager : public QObject REQ_DESCRIPTION, IDLE }; - + public: /** * Constructor @@ -76,7 +77,7 @@ public: */ bool isSuggestionAvailable(); - void addOpenSearchEngine(const KUrl &url, const QString &title); + bool engineExists(const KUrl &url); public Q_SLOTS: /** @@ -85,6 +86,8 @@ public Q_SLOTS: * @param searchText the text to be queried to the suggestion service */ void requestSuggestion(const QString &searchText); + void addOpenSearchEngine(const KUrl &url, const QString &title, const QString &shortcut); + void removeDeletedEngines(); private Q_SLOTS: void dataReceived(KIO::Job *job, const QByteArray &data); @@ -96,18 +99,23 @@ Q_SIGNALS: private: QString trimmedEngineName(const QString &engineName) const; - + void loadEngines(); + void saveEngines(); void idleJob(); - + // QString substitutueSearchText(const QString &searchText, const QString &requestURL) const; QByteArray m_jobData; - QMap<QString, OpenSearchEngine*> m_enginesMap; + QMap<QString, OpenSearchEngine*> m_engineCache; + QMap<KUrl, QString> m_engines; + OpenSearchEngine *m_activeEngine; STATE m_state; - + KIO::TransferJob *m_currentJob; + KUrl m_jobUrl; QString _typedText; + QString m_shortcut; }; #endif // OPENSEARCHMANAGER_H diff --git a/src/opensearch/suggestionparser.cpp b/src/opensearch/suggestionparser.cpp index 4ed13e16..b2ecd009 100644 --- a/src/opensearch/suggestionparser.cpp +++ b/src/opensearch/suggestionparser.cpp @@ -35,7 +35,7 @@ ResponseList SuggestionParser::parse(const QByteArray &) { - return ResponseList(); + return ResponseList(); } @@ -47,7 +47,7 @@ SuggestionParser::~SuggestionParser() ResponseList XMLParser::parse(const QByteArray &resp) { ResponseList rlist; - + m_reader.clear(); m_reader.addData(resp); @@ -73,16 +73,19 @@ ResponseList XMLParser::parse(const QByteArray &resp) { if(m_reader.isStartElement()) { + if (m_reader.name() == QL1S("Text")) title = m_reader.readElementText(); if (m_reader.name() == QL1S("Url")) url = m_reader.readElementText(); + if (m_reader.name() == QL1S("Image")) { image = m_reader.attributes().value("source").toString(); image_width = m_reader.attributes().value("width").toString().toInt(); image_height = m_reader.attributes().value("height").toString().toInt(); } + if (m_reader.name() == QL1S("Description")) description = m_reader.readElementText(); } @@ -94,7 +97,7 @@ ResponseList XMLParser::parse(const QByteArray &resp) m_reader.readNext(); } - + return rlist; } @@ -103,23 +106,23 @@ ResponseList JSONParser::parse(const QByteArray &resp) { QString response = QString::fromLocal8Bit(resp); response = response.trimmed(); - - if (response.isEmpty()) + + if (response.isEmpty()) { kDebug() << "RESPONSE IS EMPTY"; return ResponseList(); } - - if (!response.startsWith(QL1C('[')) + + if (!response.startsWith(QL1C('[')) || !response.endsWith(QL1C(']')) - ) + ) { kDebug() << "RESPONSE is NOT well FORMED"; return ResponseList(); } // Evaluate the JSON response using QtScript. - if (!m_reader.canEvaluate(response)) + if (!m_reader.canEvaluate(response)) { kDebug() << "m_reader cannot evaluate the response"; return ResponseList(); @@ -127,7 +130,7 @@ ResponseList JSONParser::parse(const QByteArray &resp) QScriptValue responseParts = m_reader.evaluate(response); - if (!responseParts.property(1).isArray()) + if (!responseParts.property(1).isArray()) { kDebug() << "RESPONSE is not an array"; return ResponseList(); @@ -141,6 +144,6 @@ ResponseList JSONParser::parse(const QByteArray &resp) { rlist << Response(s); } - + return rlist; } diff --git a/src/settings/generalwidget.cpp b/src/settings/generalwidget.cpp index 642813ae..0128830c 100644 --- a/src/settings/generalwidget.cpp +++ b/src/settings/generalwidget.cpp @@ -48,9 +48,9 @@ GeneralWidget::GeneralWidget(QWidget *parent) connect(setHomeToCurrentPageButton, SIGNAL(clicked()), this, SLOT(setHomeToCurrentPage())); disableHomeSettings(ReKonfig::useNewTabPage()); - + connect(kcfg_useNewTabPage, SIGNAL(toggled(bool)), this, SLOT(disableHomeSettings(bool))); - + checkKGetPresence(); } diff --git a/src/settings/settingsdialog.cpp b/src/settings/settingsdialog.cpp index a3b4f976..4a8776ad 100644 --- a/src/settings/settingsdialog.cpp +++ b/src/settings/settingsdialog.cpp @@ -37,6 +37,7 @@ #include "mainwindow.h" #include "webtab.h" #include "searchengine.h" +#include "opensearchmanager.h" // Widget Includes #include "adblockwidget.h" @@ -70,7 +71,7 @@ private: WebKitWidget *webkitWidg; NetworkWidget *networkWidg; AdBlockWidget *adBlockWidg; - + KCModuleProxy *ebrowsingModule; KShortcutsEditor *shortcutsEditor; @@ -94,13 +95,13 @@ Private::Private(SettingsDialog *parent) tabsWidg->layout()->setMargin(0); pageItem = parent->addPage(tabsWidg, i18n("Tabs")); pageItem->setIcon(KIcon("tab-duplicate")); - + // -- 3 appearanceWidg = new AppearanceWidget(parent); appearanceWidg->layout()->setMargin(0); pageItem = parent->addPage(appearanceWidg, i18n("Appearance")); pageItem->setIcon(KIcon("preferences-desktop-font")); - + // -- 4 webkitWidg = new WebKitWidget(parent); webkitWidg->layout()->setMargin(0); @@ -108,7 +109,7 @@ Private::Private(SettingsDialog *parent) QString webkitIconPath = KStandardDirs::locate("appdata", "pics/webkit-icon.png"); KIcon webkitIcon = KIcon(QIcon(webkitIconPath)); pageItem->setIcon(webkitIcon); - + // -- 5 networkWidg = new NetworkWidget(parent); networkWidg->layout()->setMargin(0); @@ -151,7 +152,7 @@ SettingsDialog::SettingsDialog(QWidget *parent) setModal(true); readConfig(); - + // update buttons connect(d->generalWidg, SIGNAL(changed(bool)), this, SLOT(updateButtons())); connect(d->tabsWidg, SIGNAL(changed(bool)), this, SLOT(updateButtons())); @@ -187,7 +188,7 @@ void SettingsDialog::saveSettings() return; ReKonfig::self()->writeConfig(); - + d->generalWidg->save(); d->tabsWidg->save(); d->appearanceWidg->save(); @@ -196,8 +197,9 @@ void SettingsDialog::saveSettings() d->adBlockWidg->save(); d->shortcutsEditor->save(); d->ebrowsingModule->save(); - + SearchEngine::reload(); + Application::opensearchManager()->removeDeletedEngines(); updateButtons(); emit settingsChanged("ReKonfig"); diff --git a/src/urlbar/listitem.cpp b/src/urlbar/listitem.cpp index f29a0e98..d82613f1 100644 --- a/src/urlbar/listitem.cpp +++ b/src/urlbar/listitem.cpp @@ -63,9 +63,9 @@ ListItem::ListItem(const UrlSearchItem &item, QWidget *parent) : QWidget(parent) , m_option() , m_url(item.url) -{ +{ m_option.initFrom(this); - m_option.direction = Qt::LeftToRight; + m_option.direction = Qt::LeftToRight; // use the same application palette (hence, the same colors) // Qt docs says that using this cctor is possible & fast (qt:qpalette) @@ -98,7 +98,7 @@ void ListItem::deactivate() void ListItem::paintEvent(QPaintEvent *event) { - Q_UNUSED(event); + Q_UNUSED(event); QWidget::paintEvent(event); QPainter painter(this); @@ -473,7 +473,7 @@ KAction *EngineBar::newEngineAction(KService::Ptr engine, KService::Ptr selected { QUrl u = engine->property("Query").toUrl(); KUrl url = KUrl( u.toString( QUrl::RemovePath | QUrl::RemoveQuery ) ); - + kDebug() << "Engine NAME: " << engine->name() << " URL: " << url; KAction *a = new KAction(Application::iconManager()->iconForUrl(url), engine->name(), this); a->setCheckable(true); @@ -562,7 +562,7 @@ VisualSuggestionListItem::VisualSuggestionListItem(const UrlSearchItem &item, co new IconLabel(item.url, previewLabelIcon); } - hLayout->addWidget(previewLabelIcon); + hLayout->addWidget(previewLabelIcon); QVBoxLayout *vLayout = new QVBoxLayout; vLayout->setMargin(0); vLayout->addItem(new QSpacerItem(0,0,QSizePolicy::Expanding,QSizePolicy::MinimumExpanding)); @@ -608,31 +608,31 @@ BrowseListItem::BrowseListItem(const UrlSearchItem &item, const QString &text, Q ListItem *ListItemFactory::create(const UrlSearchItem &item, const QString &text, QWidget *parent) -{ +{ if (item.type & UrlSearchItem::Search) { kDebug() << "Search"; return new SearchListItem(item, text, parent); } - + if (item.type & UrlSearchItem::Browse) { kDebug() << "Browse"; return new BrowseListItem(item, text, parent); } - + if (item.type & UrlSearchItem::History) { kDebug() << "History"; return new PreviewListItem(item, text, parent); } - + if (item.type & UrlSearchItem::Bookmark) { kDebug() << "Bookmark"; return new PreviewListItem(item, text, parent); } - + if (item.type & UrlSearchItem::Suggestion) { kDebug() << "ITEM URL: " << item.url; @@ -641,11 +641,11 @@ ListItem *ListItemFactory::create(const UrlSearchItem &item, const QString &text kDebug() << "Suggestion"; return new SuggestionListItem(item, text, parent); } - + kDebug() << "Visual Suggestion"; return new VisualSuggestionListItem(item, text, parent); } - + kDebug() << "Undefined"; return new PreviewListItem(item, text, parent); } diff --git a/src/urlbar/listitem.h b/src/urlbar/listitem.h index f5f11532..0d66a12c 100644 --- a/src/urlbar/listitem.h +++ b/src/urlbar/listitem.h @@ -63,7 +63,7 @@ public: KUrl url(); virtual QString text(); - + public slots: virtual void nextItemSubChoice(); diff --git a/src/urlbar/urlbar.cpp b/src/urlbar/urlbar.cpp index d93aeb75..f963be07 100644 --- a/src/urlbar/urlbar.cpp +++ b/src/urlbar/urlbar.cpp @@ -110,7 +110,10 @@ UrlBar::UrlBar(QWidget *parent) connect(_tab->view(), SIGNAL(iconChanged()), this, SLOT(refreshFavicon())); // bookmark icon - connect(Application::bookmarkProvider()->bookmarkManager(), SIGNAL(changed(const QString &, const QString &)), this, SLOT(onBookmarksChanged())); + connect(Application::bookmarkProvider()->bookmarkManager(), SIGNAL(changed(const QString &, const QString &)), this, SLOT(updateRightIcons())); + + // search icon + connect(Application::opensearchManager(), SIGNAL(openSearchEngineAdded(const QString &, const QString &, const QString &)), this, SLOT(updateRightIcons())); _suggestionTimer->setSingleShot(true); connect(_suggestionTimer, SIGNAL(timeout()), this, SLOT(suggest())); @@ -335,6 +338,13 @@ void UrlBar::loadFinished() connect(bt, SIGNAL(clicked(QPoint)), _tab->page(), SLOT(showSSLInfo(QPoint))); } + // show add search engine + if (_tab->hasNewSearchEngine()) + { + IconButton *bt = addRightIcon(UrlBar::SearchEngine); + connect(bt, SIGNAL(clicked(QPoint)), _tab, SLOT(showSearchEngine(QPoint))); + } + // we need to update urlbar after the right icon settings // removing this code (where setStyleSheet automatically calls update) needs adding again // an update call @@ -367,7 +377,7 @@ void UrlBar::showBookmarkInfo(const QPoint &pos) } -void UrlBar::onBookmarksChanged() +void UrlBar::updateRightIcons() { if (!_tab->isPageLoading()) { @@ -442,6 +452,10 @@ IconButton *UrlBar::addRightIcon(UrlBar::icon ic) rightIcon->setToolTip(i18n("Edit this bookmark")); } break; + case UrlBar::SearchEngine: + rightIcon->setIcon(KIcon("preferences-web-browser-shortcuts")); + rightIcon->setToolTip(i18n("Add search engine")); + break; default: kDebug() << "ERROR.. default non extant case!!"; break; diff --git a/src/urlbar/urlbar.h b/src/urlbar/urlbar.h index 67a693c0..964534cb 100644 --- a/src/urlbar/urlbar.h +++ b/src/urlbar/urlbar.h @@ -79,10 +79,11 @@ public: enum icon { - KGet = 0x00000001, - RSS = 0x00000010, - SSL = 0x00000100, - BK = 0x00001000 + KGet = 0x00000001, + RSS = 0x00000010, + SSL = 0x00000100, + BK = 0x00001000, + SearchEngine = 0x00010000 }; explicit UrlBar(QWidget *parent = 0); @@ -100,15 +101,15 @@ private slots: void loadTyped(const QString &); void clearRightIcons(); - + void updateRightIcons(); + void detectTypedString(const QString &); void suggest(); void showBookmarkInfo(const QPoint &pos); - void onBookmarksChanged(); void refreshFavicon(); - + protected: void paintEvent(QPaintEvent *event); void keyPressEvent(QKeyEvent *event); diff --git a/src/urlbar/urlresolver.cpp b/src/urlbar/urlresolver.cpp index 57d6ca64..864eca04 100644 --- a/src/urlbar/urlresolver.cpp +++ b/src/urlbar/urlresolver.cpp @@ -412,16 +412,12 @@ void UrlResolver::suggestionsReceived(const QString &text, const ResponseList &s Q_FOREACH(const Response &i, suggestions) { - QString urlString = i.url; - if(urlString.isEmpty()) + QString url = i.url; + if (url.isEmpty()) { - QStringList list; - list << QL1S("kuriikwsfilter"); - urlString = KUriFilter::self()->filteredUri(i.title, list); + url = SearchEngine::buildQuery(searchEngine(), i.title); } - kDebug() << "RESPONSE URL: " << i.url; - - UrlSearchItem gItem(UrlSearchItem::Suggestion, urlString, i.title, i.description, i.image, i.image_width, i.image_height); + UrlSearchItem gItem(UrlSearchItem::Suggestion, url, i.title, i.description, i.image, i.image_width, i.image_height); sugList << gItem; } emit suggestionsReady(sugList, _typedString); diff --git a/src/urlbar/webshortcutwidget.cpp b/src/urlbar/webshortcutwidget.cpp new file mode 100644 index 00000000..843d528b --- /dev/null +++ b/src/urlbar/webshortcutwidget.cpp @@ -0,0 +1,184 @@ +/* This file is part of the KDE project + * Copyright (C) 2009 Fredy Yanardi <fyanardi@gmail.com> + * Copyright (C) 2010 Lionel Chauvin <megabigbug@yahoo.fr> + * + * This library 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 library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "webshortcutwidget.h" + +#include <QtCore/QTimer> +#include <QtCore/QSet> +#include <QtGui/QBoxLayout> +#include <QtGui/QLabel> +#include <QtGui/QLineEdit> +#include <QtGui/QPushButton> +#include <QtGui/QFormLayout> + + +#include <KGlobalSettings> +#include <KIcon> +#include <KLocale> +#include <KServiceTypeTrader> + +WebShortcutWidget::WebShortcutWidget(QWidget *parent) + : QDialog(parent) +{ + QVBoxLayout *mainLayout = new QVBoxLayout(); + QHBoxLayout *titleLayout = new QHBoxLayout(); + mainLayout->addLayout(titleLayout); + QLabel *iconLabel = new QLabel(this); + KIcon wsIcon("preferences-web-browser-shortcuts"); + iconLabel->setPixmap(wsIcon.pixmap(22, 22)); + titleLayout->addWidget(iconLabel); + m_searchTitleLabel = new QLabel(i18n("Add Search Engine"), this); + QFont boldFont = KGlobalSettings::generalFont(); + boldFont.setBold(true); + m_searchTitleLabel->setFont(boldFont); + titleLayout->addWidget(m_searchTitleLabel); + titleLayout->addStretch(); + + QFormLayout *formLayout = new QFormLayout(); + mainLayout->addLayout(formLayout); + + QFont smallFont = KGlobalSettings::smallestReadableFont(); + m_nameLineEdit = new QLineEdit(this); + m_nameLineEdit->setEnabled(false); + m_nameLineEdit->setFont(smallFont); + QLabel *nameLabel = new QLabel(i18n("Name:"), this); + nameLabel->setFont(smallFont); + formLayout->addRow(nameLabel, m_nameLineEdit); + + QLabel *shortcutsLabel = new QLabel(i18n("Shortcuts:"), this); + shortcutsLabel->setFont(smallFont); + m_wsLineEdit = new QLineEdit(this); + m_wsLineEdit->setMinimumWidth(100); + m_wsLineEdit->setFont(smallFont); + formLayout->addRow(shortcutsLabel, m_wsLineEdit); + connect(m_wsLineEdit, SIGNAL(textChanged(QString)), SLOT(shortcutsChanged(const QString&))); + + m_noteLabel = new QLabel(this); + m_noteLabel->setFont(boldFont); + m_noteLabel->setWordWrap(true); + formLayout->addRow(m_noteLabel); + m_noteLabel->setVisible(false); + + mainLayout->addStretch(); + + QHBoxLayout *buttonLayout = new QHBoxLayout(); + mainLayout->addLayout(buttonLayout); + buttonLayout->addStretch(); + m_okButton = new QPushButton(i18n("Ok"), this); + m_okButton->setDefault(true); + buttonLayout->addWidget(m_okButton); + connect(m_okButton, SIGNAL(clicked()), this, SLOT(okClicked())); + + QPushButton *cancelButton = new QPushButton(i18n("Cancel"), this); + buttonLayout->addWidget(cancelButton); + connect(cancelButton, SIGNAL(clicked()), this, SLOT(cancelClicked())); + + setLayout(mainLayout); + + setMinimumWidth (250); + + m_providers = KServiceTypeTrader::self()->query("SearchProvider"); + + QTimer::singleShot(0, m_wsLineEdit, SLOT(setFocus())); +} + + +void WebShortcutWidget::showAt(const QPoint &pos) +{ + adjustSize(); + + QPoint p; + p.setX(pos.x() - width()); + p.setY(pos.y() + 10); + + move(p); + QDialog::show(); +} + + +void WebShortcutWidget::show(const KUrl &url, const QString &openSearchName, const QPoint &pos) +{ + m_wsLineEdit->clear(); + m_nameLineEdit->setText(openSearchName); + m_url = url; + showAt(pos); +} + + +void WebShortcutWidget::okClicked() +{ + hide(); + emit webShortcutSet(m_url, m_nameLineEdit->text(), m_wsLineEdit->text()); +} + + +void WebShortcutWidget::cancelClicked() +{ + hide(); +} + + +void WebShortcutWidget::shortcutsChanged(const QString& newShorthands) +{ + int savedCursorPosition = m_wsLineEdit->cursorPosition(); + QString normalizedShorthands = QString(newShorthands).replace(" ", ","); + m_wsLineEdit->setText(normalizedShorthands); + m_wsLineEdit->setCursorPosition(savedCursorPosition); + + QSet<QString> shorthands = normalizedShorthands.split(",").toSet(); + QString contenderName = ""; + QString contenderWS = ""; + + Q_FOREACH (const QString &shorthand, shorthands) + { + Q_FOREACH (KService::Ptr provider, m_providers) + { + if(provider->property("Keys").toStringList().contains(shorthand)) + { + contenderName = provider->property("Name").toString(); + contenderWS = shorthand; + break; + } + } + } + + if (!contenderName.isEmpty()) + { + m_okButton->setEnabled(false); + m_noteLabel->setText(i18n("The shortcut \"%1\" is already assigned to \"%2\".", contenderWS, contenderName)); + m_noteLabel->setVisible(true); + resize(minimumSize().width(), minimumSizeHint().height()+15); + } + else + { + m_okButton->setEnabled(true); + m_noteLabel->clear(); + bool noteIsVisible = m_noteLabel->isVisible(); + m_noteLabel->setVisible(false); + if (noteIsVisible) + { + resize(minimumSize()); + } + } +} + +#include "webshortcutwidget.moc" + + diff --git a/src/urlbar/webshortcutwidget.h b/src/urlbar/webshortcutwidget.h new file mode 100644 index 00000000..02ddaf17 --- /dev/null +++ b/src/urlbar/webshortcutwidget.h @@ -0,0 +1,61 @@ +/* This file is part of the KDE project + * Copyright (C) 2009 Fredy Yanardi <fyanardi@gmail.com> + * Copyright (C) 2010 Lionel Chauvin <megabigbug@yahoo.fr> + * + * This library 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 library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef WEBSHORTCUTWIDGET_H +#define WEBSHORTCUTWIDGET_H + +#include <QtGui/QDialog> +#include <KUrl> +#include <KService> + +class QLabel; +class QLineEdit; + +class WebShortcutWidget : public QDialog +{ + Q_OBJECT +public: + explicit WebShortcutWidget(QWidget *parent = 0); + + void show(const KUrl &url, const QString &openSearchName, const QPoint &pos); + +private slots: + void okClicked(); + void cancelClicked(); + void shortcutsChanged(const QString& newShorthands); + +signals: + void webShortcutSet(const KUrl &url, const QString &openSearchName, const QString &webShortcut); + +private: + QLabel *m_searchTitleLabel; + QLineEdit *m_wsLineEdit; + QLineEdit *m_nameLineEdit; + QLabel *m_noteLabel; + QPushButton *m_okButton; + + KService::List m_providers; + KUrl m_url; + + void showAt(const QPoint &pos); +}; + +#endif // WEBSHORTCUTWIDGET_H + diff --git a/src/webtab.cpp b/src/webtab.cpp index bac73fec..2641f9c9 100644 --- a/src/webtab.cpp +++ b/src/webtab.cpp @@ -28,7 +28,6 @@ // Self Includes #include "webtab.h" #include "webtab.moc" - // Auto Includes #include "rekonq.h" @@ -38,14 +37,22 @@ #include "rsswidget.h" #include "walletbar.h" #include "webpage.h" +#include "webshortcutwidget.h" +#include "application.h" +#include "opensearchmanager.h" // KDE Includes #include <KWebWallet> +#include <KStandardShortcut> +#include <KMenu> +#include <KActionMenu> +#include <KWebView> +#include <KDebug> +#include <KBuildSycocaProgressDialog> // Qt Includes #include <QtGui/QVBoxLayout> - WebTab::WebTab(QWidget *parent) : QWidget(parent) , m_webView(new WebView(this)) @@ -95,7 +102,7 @@ KUrl WebTab::url() kDebug() << "REKONQ PAGE. URL = " << page()->loadingUrl(); return page()->loadingUrl(); } - + return view()->url(); } @@ -178,7 +185,7 @@ bool WebTab::hasRSSInfo() } -void WebTab::showRSSInfo(QPoint pos) +void WebTab::showRSSInfo(const QPoint &pos) { QWebElementCollection col = page()->mainFrame()->findAllElements("link[type=\"application/rss+xml\"]"); col.append(page()->mainFrame()->findAllElements("link[type=\"application/atom+xml\"]")); @@ -228,10 +235,64 @@ void WebTab::setPart(KParts::ReadOnlyPart *p, const KUrl &u) if(!m_part) return; - + // Part NO more exists. Let's clean up from webtab m_webView->show(); qobject_cast<QVBoxLayout *>(layout())->removeWidget(m_part->widget()); delete m_part; m_part = 0; } + + +KUrl WebTab::extractOpensearchUrl(QWebElement e) +{ + QString href = e.attribute(QLatin1String("href")); + KUrl url = KUrl(href); + if (!href.contains(":")) + { + KUrl docUrl = m_webView->url(); + QString host = docUrl.scheme() + "://" + docUrl.host(); + if (docUrl.port() != -1) + { + host += ":" + QString::number(docUrl.port()); + } + url = KUrl(docUrl, href); + } + return url; +} + + +bool WebTab::hasNewSearchEngine() +{ + QWebElement e = page()->mainFrame()->findFirstElement(QLatin1String("head >link[rel=\"search\"][ type=\"application/opensearchdescription+xml\"]")); + return !e.isNull() && !Application::opensearchManager()->engineExists(extractOpensearchUrl(e)); +} + + +void WebTab::showSearchEngine(const QPoint &pos) +{ + QWebElement e = page()->mainFrame()->findFirstElement(QLatin1String("head >link[rel=\"search\"][ type=\"application/opensearchdescription+xml\"]")); + QString title = e.attribute(QLatin1String("title")); + if (!title.isEmpty()) + { + WebShortcutWidget *widget = new WebShortcutWidget(window()); + widget->setWindowFlags(Qt::Popup); + + connect(widget, SIGNAL(webShortcutSet(const KUrl &, const QString &, const QString &)), + Application::opensearchManager(), SLOT(addOpenSearchEngine(const KUrl &, const QString &, const QString &))); + connect(Application::opensearchManager(), SIGNAL(openSearchEngineAdded(const QString &, const QString &, const QString &)), + this, SLOT(openSearchEngineAdded())); + + widget->show(extractOpensearchUrl(e), title, pos); + } +} + + +void WebTab::openSearchEngineAdded() +{ + // If the providers changed, tell sycoca to rebuild its database... + KBuildSycocaProgressDialog::rebuildKSycoca(this); + + disconnect(Application::opensearchManager(), SIGNAL(openSearchEngineAdded(const QString &, const QString &, const QString &)), + this, SLOT(openSearchEngineAdded())); +} diff --git a/src/webtab.h b/src/webtab.h index 12f528d9..7b7c3c7a 100644 --- a/src/webtab.h +++ b/src/webtab.h @@ -33,6 +33,7 @@ #include "rekonq_defines.h" // Local Includes +#include "webpage.h" #include "webview.h" // KDE Includes @@ -46,6 +47,7 @@ class UrlBar; class PreviewSelectorBar; class WalletBar; class NotificationBar; +class QPoint; class REKONQ_TESTS_EXPORT WebTab : public QWidget @@ -66,26 +68,32 @@ public: void insertBar(NotificationBar* bar); bool hasRSSInfo(); + bool isPageLoading(); + bool hasNewSearchEngine(); KParts::ReadOnlyPart *part() { return m_part; } void setPart(KParts::ReadOnlyPart *p, const KUrl &u); - + private Q_SLOTS: void updateProgress(int progress); void loadFinished(bool); void createWalletBar(const QString &, const QUrl &); - void showRSSInfo(QPoint pos); + void showRSSInfo(const QPoint &pos); + void showSearchEngine(const QPoint &pos); + void openSearchEngineAdded(); Q_SIGNALS: void loadProgressing(); void titleChanged(const QString &); - + private: + KUrl extractOpensearchUrl(QWebElement e); + WebView *const m_webView; UrlBar *const m_urlBar; - + int m_progress; QWeakPointer<WalletBar> m_walletBar; |