From 03db6da1a967a83683ad6bd8acdbe41a302586f6 Mon Sep 17 00:00:00 2001 From: nowrep Date: Thu, 8 Mar 2012 13:05:57 +0100 Subject: [PATCH] Added option to create search engine from element on page. - accessible in context menu on input - added translations for plugins into resources so they can be loaded - in access keys navigation plugin: lower case chars are choose first --- src/lib/data/icons/menu/search-icon.png | Bin 840 -> 935 bytes src/lib/navigation/websearchbar.cpp | 9 +- src/lib/navigation/websearchbar.h | 4 +- src/lib/network/qupzillaschemehandler.cpp | 2 +- src/lib/opensearch/editsearchengine.cpp | 2 + src/lib/opensearch/opensearchreader.cpp | 3 +- src/lib/opensearch/searchenginesdialog.cpp | 3 +- src/lib/opensearch/searchenginesmanager.cpp | 81 ++++++++++++++++-- src/lib/opensearch/searchenginesmanager.h | 8 +- src/lib/webview/webview.cpp | 56 +++++++++--- src/lib/webview/webview.h | 5 +- .../AccessKeysNavigation.pro | 5 +- .../AccessKeysNavigation/akn_handler.cpp | 2 +- src/plugins/AccessKeysNavigation/akn_res.qrc | 2 + src/plugins/MouseGestures/MouseGestures.pro | 6 +- src/plugins/MouseGestures/mousegestures.qrc | 3 + 16 files changed, 159 insertions(+), 32 deletions(-) diff --git a/src/lib/data/icons/menu/search-icon.png b/src/lib/data/icons/menu/search-icon.png index c4830676b0b48a7c0e7d0ca15280c3b19cb627d6..c0fb527faca9af979a7f92f87395b0d825eaebab 100644 GIT binary patch delta 913 zcmV;C18)4t2B!y*B!2{FK}|sb0I$e51&Zka000?uMObuGZ)S9NVRB^vL1b@YWgtmy zVP|DhWnpA_ami&o0009yNklT})e59RHoud)r=U=?AQ=lmQ~R57!O4EyFoP zr->$$7?hDcqGmc-$R=?y__hbe!@e+);I;>6+=C$|B+M*ZFn=0x2&}S1&_uRT9b?); zZC6Tr`*H6*JNI_UUVQUB+?(^y|NQ>Hk8=oP4F6{l{UdZtK^bl`3LD;=!Tk&0mtcRO zWBt0~2FXn6pOMsU1jD1-4{izldUk?$bwO&o0eNIE2Wb5fxYELl{n+2vj@f&w!|hGp z15de~$YdCFf`5{gU?r8p=&iqJIKXT0`=Xe81GH_tz@V`DZ5$x^a=j1Nf@v0C(?BVR z-k@q=l9}L@fJE-661X_@%O1=vP6FKpfU>uLMq`aDx7k@K&Me6Ax=nbqSwc-YMd%+D zBR4XL#8nRXWZw9|*KQ6Fr;qn%{GLj2YF=j59s!qoU4PjAw1DY(1-mwx@l~%AWey7M zvElk}$MKdilz+h)?ED6;Z2=Yw+xY~B6P+c{G~lE235X^juK=eHJK(fYd@vA4k(EME z&gsr!ba2e8Gk8|Z74bY6<64c$m#(K#%#D*Q1ok3=kqH?M^#aTyMQl~W{Gy6KLS~@3 zs+C$dxqs@EyZ|oG5EzMR2=L~V%%GQ&X@vkQ4Vh^kOjhSelPsa>iU>=vrX zS!P@bf%Ccios7PBOCV=~iQjVAxzU1SZ`tt9sfSScL9@VNc{aLCFyu&a=eNGC&TUIY zRMI67eR9(l5$C!b5P9>Otii_RB>A0aJhXyDihmg%Xq>XW^7a9PcA)1@bY-ceG%4#* z0ofemW)XNCCMTkg-0?0{3K~y-)m6Od*6JZ#I&o|R{ z%Fuzf1PaB0R?4q}Z43(|!3%I9i39h;_%aKTmQ_-k0DMN-49uw>zw4lwrN3-=H?>L&-F)?(X0KfVMh8UQ-RjG&7ZQxvOxZ9Nu<9`^Q=Ldc5zVPtSpuMPOky8s$lnjhQ9<5G7?u=izY1s_35M6k=v%T{cfPQZ1 z>+3^TS66U$_VLd8`X{O=d3t!9qWcGNdhjDjwPK0JVlg^3HAMk@C4}5RjS>K06-9w4 ziq&{L{#nzsCPm3y^)?AaXyCw-8dg`{XmiizM;zXO%Q}}x7&TqZns~u+igNNn|+l`CKHE;M-Kqpo1UH~(P%Uc;1Ph8y1R}startingEngineName(); @@ -142,12 +144,13 @@ void WebSearchBar::setupEngines() } } - searchChanged(m_boxSearchType->currentItem(), false); + searchChanged(m_boxSearchType->currentItem()); connect(m_searchManager, SIGNAL(enginesChanged()), this, SLOT(setupEngines())); + m_reloadingEngines = false; } -void WebSearchBar::searchChanged(const ButtonWithMenu::Item &item, bool reload) +void WebSearchBar::searchChanged(const ButtonWithMenu::Item &item) { setPlaceholderText(item.text); m_completerModel->setStringList(QStringList()); @@ -159,7 +162,7 @@ void WebSearchBar::searchChanged(const ButtonWithMenu::Item &item, bool reload) m_searchManager->setActiveEngine(m_activeEngine); - if (reload && !text().isEmpty()) { + if (!m_reloadingEngines && !text().isEmpty()) { search(); } } diff --git a/src/lib/navigation/websearchbar.h b/src/lib/navigation/websearchbar.h index 22452cec2..15696ac77 100644 --- a/src/lib/navigation/websearchbar.h +++ b/src/lib/navigation/websearchbar.h @@ -55,7 +55,7 @@ public: explicit WebSearchBar(QupZilla* mainClass, QWidget* parent = 0); private slots: - void searchChanged(const ButtonWithMenu::Item &item, bool reload = true); + void searchChanged(const ButtonWithMenu::Item &item); void setupEngines(); void search(); @@ -94,6 +94,8 @@ private: QMenu* m_menu; QAction* m_pasteAndGoAction; QAction* m_clearAction; + + bool m_reloadingEngines; }; #endif // WEBSEARCHBAR_H diff --git a/src/lib/network/qupzillaschemehandler.cpp b/src/lib/network/qupzillaschemehandler.cpp index 2d6a4e5a5..06a8602a4 100644 --- a/src/lib/network/qupzillaschemehandler.cpp +++ b/src/lib/network/qupzillaschemehandler.cpp @@ -354,7 +354,7 @@ QString QupZillaSchemeReply::configPage() QString allGroupsString; QSettings* settings = Settings::globalSettings(); foreach(const QString & group, settings->childGroups()) { - QString groupString = QString("%1").arg(group); + QString groupString = QString("[%1]").arg(group); settings->beginGroup(group); foreach(const QString & key, settings->childKeys()) { diff --git a/src/lib/opensearch/editsearchengine.cpp b/src/lib/opensearch/editsearchengine.cpp index 655188a74..f4d5b82bc 100644 --- a/src/lib/opensearch/editsearchengine.cpp +++ b/src/lib/opensearch/editsearchengine.cpp @@ -28,6 +28,8 @@ EditSearchEngine::EditSearchEngine(const QString &title, QWidget* parent) ui->setupUi(this); connect(ui->iconFromFile, SIGNAL(clicked()), this, SLOT(chooseIcon())); + + ui->buttonBox->setFocus(); } QString EditSearchEngine::name() diff --git a/src/lib/opensearch/opensearchreader.cpp b/src/lib/opensearch/opensearchreader.cpp index 8d5fe9480..e2b3bdfcf 100644 --- a/src/lib/opensearch/opensearchreader.cpp +++ b/src/lib/opensearch/opensearchreader.cpp @@ -103,7 +103,8 @@ OpenSearchEngine* OpenSearchReader::read() readNext(); } - if (!m_searchXml.contains(QLatin1String("http://a9.com/-/spec/opensearch/1.1/"))) { + if (!m_searchXml.contains(QLatin1String("http://a9.com/-/spec/opensearch/1.1/")) && + !m_searchXml.contains(QLatin1String("http://www.mozilla.org/2006/browser/search/"))) { raiseError(QObject::tr("The file is not an OpenSearch 1.1 file.")); return engine; } diff --git a/src/lib/opensearch/searchenginesdialog.cpp b/src/lib/opensearch/searchenginesdialog.cpp index 50e9e4793..9251046ce 100644 --- a/src/lib/opensearch/searchenginesdialog.cpp +++ b/src/lib/opensearch/searchenginesdialog.cpp @@ -24,12 +24,11 @@ SearchEnginesDialog::SearchEnginesDialog(QWidget* parent) : QDialog(parent) , ui(new Ui::SearchEnginesDialog) + , m_manager(mApp->searchEnginesManager()) { setAttribute(Qt::WA_DeleteOnClose); ui->setupUi(this); - m_manager = mApp->searchEnginesManager(); - connect(ui->add, SIGNAL(clicked()), this, SLOT(addEngine())); connect(ui->remove, SIGNAL(clicked()), this, SLOT(removeEngine())); connect(ui->edit, SIGNAL(clicked()), this, SLOT(editEngine())); diff --git a/src/lib/opensearch/searchenginesmanager.cpp b/src/lib/opensearch/searchenginesmanager.cpp index b815d0788..e9a8f05f5 100644 --- a/src/lib/opensearch/searchenginesmanager.cpp +++ b/src/lib/opensearch/searchenginesmanager.cpp @@ -16,6 +16,8 @@ * along with this program. If not, see . * ============================================================ */ #include "searchenginesmanager.h" +#include "searchenginesdialog.h" +#include "editsearchengine.h" #include "iconprovider.h" #include "mainapplication.h" #include "networkmanager.h" @@ -23,9 +25,11 @@ #include "opensearchengine.h" #include "databasewriter.h" #include "settings.h" +#include "webview.h" #include #include +#include #define ENSURE_LOADED if (!m_settingsLoaded) loadSettings(); @@ -140,10 +144,10 @@ void SearchEnginesManager::restoreDefaults() duck.url = "https://duckduckgo.com/?q=%s&t=qupzilla"; duck.shortcut = "d"; - addEngine(google, false); - addEngine(wiki, false); - addEngine(yt, false); - addEngine(duck, false); + addEngine(google); + addEngine(wiki); + addEngine(yt); + addEngine(duck); emit enginesChanged(); } @@ -179,7 +183,7 @@ void SearchEnginesManager::editEngine(const Engine &before, const Engine &after) addEngine(after); } -void SearchEnginesManager::addEngine(const Engine &engine, bool emitSignal) +void SearchEnginesManager::addEngine(const Engine &engine) { ENSURE_LOADED; @@ -189,9 +193,72 @@ void SearchEnginesManager::addEngine(const Engine &engine, bool emitSignal) m_allEngines.append(engine); - if (emitSignal) { - emit enginesChanged(); + emit enginesChanged(); +} + +void SearchEnginesManager::addEngineFromForm(const QWebElement &element, WebView* view) +{ + QWebElement formElement = element.parent(); + + while (!formElement.isNull()) { + if (formElement.tagName().toLower() == "form") { + break; + } + + formElement = formElement.parent(); } + + if (formElement.isNull()) { + return; + } + + QUrl actionUrl = QUrl::fromEncoded(formElement.attribute("action").toUtf8()); + if (actionUrl.isRelative()) { + actionUrl = view->url().resolved(actionUrl); + } + + actionUrl.addQueryItem(element.attribute("name"), "%s"); + + QList > queryItems; + QWebElementCollection allInputs = formElement.findAll("input"); + foreach (QWebElement e, allInputs) { + if (element == e || !e.hasAttribute("name")) { + continue; + } + + QPair item; + item.first = QUrl::toPercentEncoding(e.attribute("name").toUtf8()); + item.second = QUrl::toPercentEncoding(e.evaluateJavaScript("this.value").toByteArray()); + + queryItems.append(item); + } + + actionUrl.setEncodedQueryItems(queryItems + actionUrl.encodedQueryItems()); + + SearchEngine engine; + engine.name = view->title(); + engine.icon = view->icon(); + engine.url = actionUrl.toString(); + + EditSearchEngine dialog(SearchEnginesDialog::tr("Add Search Engine"), view); + dialog.setName(engine.name); + dialog.setIcon(engine.icon); + dialog.setUrl(engine.url); + + if (dialog.exec() != QDialog::Accepted) { + return; + } + + engine.name = dialog.name(); + engine.icon = dialog.icon(); + engine.url = dialog.url(); + engine.shortcut = dialog.shortcut(); + + if (engine.name.isEmpty() || engine.url.isEmpty()) { + return; + } + + addEngine(engine); } void SearchEnginesManager::addEngine(OpenSearchEngine* engine) diff --git a/src/lib/opensearch/searchenginesmanager.h b/src/lib/opensearch/searchenginesmanager.h index 6e23c5a0f..d7b68bf6c 100644 --- a/src/lib/opensearch/searchenginesmanager.h +++ b/src/lib/opensearch/searchenginesmanager.h @@ -26,6 +26,10 @@ #include "qz_namespace.h" #include "opensearchengine.h" +class QWebElement; + +class WebView; + class QT_QUPZILLA_EXPORT SearchEnginesManager : public QObject { Q_OBJECT @@ -55,7 +59,9 @@ public: void addEngine(const QUrl &url); void addEngine(OpenSearchEngine* engine); - void addEngine(const Engine &engine, bool emitSignal = true); + void addEngine(const Engine &engine); + + void addEngineFromForm(const QWebElement &element, WebView *view); void removeEngine(const Engine &engine); diff --git a/src/lib/webview/webview.cpp b/src/lib/webview/webview.cpp index d7afe5e27..f8d5c53f6 100644 --- a/src/lib/webview/webview.cpp +++ b/src/lib/webview/webview.cpp @@ -504,6 +504,36 @@ bool WebView::isMediaElement(const QWebElement &element) return (element.tagName().toLower() == "video" || element.tagName().toLower() == "audio"); } +void WebView::checkForForm(QMenu *menu, const QWebElement &element) +{ + QWebElement parentElement = element.parent(); + + while (!parentElement.isNull()) { + if (parentElement.tagName().toLower() == "form") { + break; + } + + parentElement = parentElement.parent(); + } + + if (parentElement.isNull()) { + return; + } + + QString method = parentElement.hasAttribute("method") ? parentElement.attribute("method").toUpper() : "GET"; + + if (method == "GET") { + menu->addAction(QIcon(":icons/menu/search-icon.png"), tr("Create Search Engine"), this, SLOT(createSearchEngine())); + + m_clickedElement = element; + } +} + +void WebView::createSearchEngine() +{ + mApp->searchEnginesManager()->addEngineFromForm(m_clickedElement, this); +} + void WebView::createContextMenu(QMenu* menu, const QWebHitTestResult &hitTest, const QPoint &pos) { if (!m_actionsHaveImages) { @@ -560,6 +590,10 @@ void WebView::createContextMenu(QMenu* menu, const QWebHitTestResult &hitTest, c } } + if (hitTest.element().tagName().toLower() == "input") { + checkForForm(menu, hitTest.element()); + } + if (!selectedText().isEmpty()) { createSelectedTextContextMenu(menu, hitTest); } @@ -735,15 +769,15 @@ void WebView::createSelectedTextContextMenu(QMenu* menu, const QWebHitTestResult void WebView::createMediaContextMenu(QMenu* menu, const QWebHitTestResult &hitTest) { - m_mediaElement = hitTest.element(); + m_clickedElement = hitTest.element(); - if (m_mediaElement.isNull()) { + if (m_clickedElement.isNull()) { return; } - bool paused = m_mediaElement.evaluateJavaScript("this.paused").toBool(); - bool muted = m_mediaElement.evaluateJavaScript("this.muted").toBool(); - QUrl videoUrl = m_mediaElement.evaluateJavaScript("this.currentSrc").toUrl(); + bool paused = m_clickedElement.evaluateJavaScript("this.paused").toBool(); + bool muted = m_clickedElement.evaluateJavaScript("this.muted").toBool(); + QUrl videoUrl = m_clickedElement.evaluateJavaScript("this.currentSrc").toUrl(); menu->addSeparator(); menu->addAction(paused ? tr("&Play") : tr("&Pause"), this, SLOT(pauseMedia()))->setIcon(QIcon::fromTheme(paused ? "media-playback-start" : "media-playback-pause")); @@ -756,25 +790,25 @@ void WebView::createMediaContextMenu(QMenu* menu, const QWebHitTestResult &hitTe void WebView::pauseMedia() { - bool paused = m_mediaElement.evaluateJavaScript("this.paused").toBool(); + bool paused = m_clickedElement.evaluateJavaScript("this.paused").toBool(); if (paused) { - m_mediaElement.evaluateJavaScript("this.play()"); + m_clickedElement.evaluateJavaScript("this.play()"); } else { - m_mediaElement.evaluateJavaScript("this.pause()"); + m_clickedElement.evaluateJavaScript("this.pause()"); } } void WebView::muteMedia() { - bool muted = m_mediaElement.evaluateJavaScript("this.muted").toBool(); + bool muted = m_clickedElement.evaluateJavaScript("this.muted").toBool(); if (muted) { - m_mediaElement.evaluateJavaScript("this.muted = false"); + m_clickedElement.evaluateJavaScript("this.muted = false"); } else { - m_mediaElement.evaluateJavaScript("this.muted = true"); + m_clickedElement.evaluateJavaScript("this.muted = true"); } } diff --git a/src/lib/webview/webview.h b/src/lib/webview/webview.h index 042c09557..55835c6e8 100644 --- a/src/lib/webview/webview.h +++ b/src/lib/webview/webview.h @@ -92,6 +92,8 @@ protected slots: void openUrlInSelectedTab(); void openUrlInBackgroundTab(); + void createSearchEngine(); + // Clicked frame actions void loadClickedFrame(); @@ -117,6 +119,7 @@ protected: QUrl lastUrl(); bool isMediaElement(const QWebElement &element); + void checkForForm(QMenu* menu, const QWebElement &element); void createContextMenu(QMenu* menu, const QWebHitTestResult &hitTest, const QPoint &pos); void createPageContextMenu(QMenu* menu, const QPoint &pos); @@ -141,7 +144,7 @@ private: QUrl m_aboutToLoadUrl; QUrl m_lastUrl; - QWebElement m_mediaElement; + QWebElement m_clickedElement; QWebFrame* m_clickedFrame; QUrl m_clickedUrl; bool m_actionsHaveImages; diff --git a/src/plugins/AccessKeysNavigation/AccessKeysNavigation.pro b/src/plugins/AccessKeysNavigation/AccessKeysNavigation.pro index 665bfbb27..8431ad615 100644 --- a/src/plugins/AccessKeysNavigation/AccessKeysNavigation.pro +++ b/src/plugins/AccessKeysNavigation/AccessKeysNavigation.pro @@ -16,8 +16,11 @@ FORMS += \ RESOURCES = akn_res.qrc -TRANSLATIONS = translations/cs_CZ.ts \ +TRANSLATIONS = \ + translations/cs_CZ.ts \ translations/sr_BA.ts \ translations/sr_RS.ts \ + translations/de_DE.ts \ + translations/zh_TW.ts \ include(../../plugins.pri) diff --git a/src/plugins/AccessKeysNavigation/akn_handler.cpp b/src/plugins/AccessKeysNavigation/akn_handler.cpp index d721c1564..bcb96f3af 100644 --- a/src/plugins/AccessKeysNavigation/akn_handler.cpp +++ b/src/plugins/AccessKeysNavigation/akn_handler.cpp @@ -276,7 +276,7 @@ void AKN_Handler::showAccessKeys() continue; } QChar accessKey; - QString text = element.toPlainText().toUpper(); + QString text = element.toPlainText().toLower(); for (int i = 0; i < text.count(); ++i) { const QChar &c = text.at(i); if (unusedKeys.contains(c)) { diff --git a/src/plugins/AccessKeysNavigation/akn_res.qrc b/src/plugins/AccessKeysNavigation/akn_res.qrc index 9943456ea..efde52034 100644 --- a/src/plugins/AccessKeysNavigation/akn_res.qrc +++ b/src/plugins/AccessKeysNavigation/akn_res.qrc @@ -5,5 +5,7 @@ locale/cs_CZ.qm locale/sr_BA.qm locale/sr_RS.qm + locale/de_DE.qm + locale/zh_TW.qm diff --git a/src/plugins/MouseGestures/MouseGestures.pro b/src/plugins/MouseGestures/MouseGestures.pro index fee92a9df..1e4560f40 100644 --- a/src/plugins/MouseGestures/MouseGestures.pro +++ b/src/plugins/MouseGestures/MouseGestures.pro @@ -24,10 +24,12 @@ FORMS += \ RESOURCES = mousegestures.qrc -TRANSLATIONS = translations/cs_CZ.ts \ +TRANSLATIONS = \ + translations/cs_CZ.ts \ + translations/de_DE.ts \ + translations/sk_SK.ts \ translations/sr_BA.ts \ translations/sr_RS.ts \ - translations/de_DE.ts \ translations/zh_TW.ts \ include(../../plugins.pri) diff --git a/src/plugins/MouseGestures/mousegestures.qrc b/src/plugins/MouseGestures/mousegestures.qrc index 293dc3a45..d45692a50 100644 --- a/src/plugins/MouseGestures/mousegestures.qrc +++ b/src/plugins/MouseGestures/mousegestures.qrc @@ -13,7 +13,10 @@ data/up-right.gif data/copyright locale/cs_CZ.qm + locale/de_DE.qm + locale/sk_SK.qm locale/sr_BA.qm locale/sr_RS.qm + locale/zh_TW.qm