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; | 
