diff --git a/src/lib/data/icons/menu/search-icon.png b/src/lib/data/icons/menu/search-icon.png
index c4830676b..c0fb527fa 100644
Binary files a/src/lib/data/icons/menu/search-icon.png and b/src/lib/data/icons/menu/search-icon.png differ
diff --git a/src/lib/navigation/websearchbar.cpp b/src/lib/navigation/websearchbar.cpp
index 33072a62d..a4e6bcd01 100644
--- a/src/lib/navigation/websearchbar.cpp
+++ b/src/lib/navigation/websearchbar.cpp
@@ -53,6 +53,7 @@ WebSearchBar::WebSearchBar(QupZilla* mainClass, QWidget* parent)
, m_menu(new QMenu(this))
, m_pasteAndGoAction(0)
, m_clearAction(0)
+ , m_reloadingEngines(false)
{
setObjectName("websearchbar");
@@ -118,6 +119,7 @@ void WebSearchBar::openSearchEnginesDialog()
void WebSearchBar::setupEngines()
{
disconnect(m_searchManager, SIGNAL(enginesChanged()), this, SLOT(setupEngines()));
+ m_reloadingEngines = true;
QString activeEngine = m_searchManager->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