diff options
-rw-r--r-- | libre/konqueror/PKGBUILD | 6 | ||||
-rw-r--r-- | libre/konqueror/libre.patch | 14 | ||||
-rw-r--r-- | libre/konqueror/webkit.patch | 19659 |
3 files changed, 19668 insertions, 11 deletions
diff --git a/libre/konqueror/PKGBUILD b/libre/konqueror/PKGBUILD index e9be3590a..504995ec9 100644 --- a/libre/konqueror/PKGBUILD +++ b/libre/konqueror/PKGBUILD @@ -5,12 +5,12 @@ pkgname=konqueror pkgver=16.12.3 -pkgrel=1.parabola1 +pkgrel=2.parabola1 pkgdesc="KDE File Manager & Web Browser, without Google, nonfree software recommendation and nonfree qt5-webengine support" arch=(i686 x86_64 armv7h) url="https://konqueror.org/" license=(LGPL) -depends=(dolphin keditbookmarks) +depends=(dolphin keditbookmarks mesa) makedepends=(extra-cmake-modules kdoctools python tidy kdesignerplugin kdesu) optdepends=('tidy: tidy HTML plugin' 'kdesu: shell command plugin') conflicts=(kdebase-konqueror kdebase-konq-plugins) @@ -20,7 +20,7 @@ source=("https://download.kde.org/stable/applications/$pkgver/src/$pkgname-$pkgv 'libre.patch') sha256sums=('e52654a1bb2c0be317f8ed80dba3147bc4d2126abce209ab57c6e69e64159bdf' 'SKIP' - 'af6595efd698e61b69297207918c8fc4679c42226656d5a31725d870bb436a87') + 'a7a19439e211cd96f63273c9cf5a8dbfa7385b02e4143e67a0992551c1297a73') validpgpkeys=(CA262C6C83DE4D2FB28A332A3A6A4DB839EAA6D7) # Albert Astals Cid <aacid@kde.org> prepare() { diff --git a/libre/konqueror/libre.patch b/libre/konqueror/libre.patch index 81251960d..f772c625a 100644 --- a/libre/konqueror/libre.patch +++ b/libre/konqueror/libre.patch @@ -20,28 +20,26 @@ index 0b1c8782c..8a822fcf8 100644 add_subdirectory( about ) add_subdirectory( pics ) diff --git a/about/konq_aboutpage.cpp b/about/konq_aboutpage.cpp -index 017875809..fc95efa89 100644 +index 017875809..86d8f0d4c 100644 --- a/about/konq_aboutpage.cpp +++ b/about/konq_aboutpage.cpp -@@ -219,14 +219,11 @@ QString KonqAboutPageSingleton::specs() +@@ -219,13 +219,10 @@ QString KonqAboutPageSingleton::specs() QStringLiteral("http://www.ecma-international.org/publications/standards/ECMA-262.HTM"))) .arg(i18n("JavaScript disabled (globally). Enable JavaScript <A HREF=\"%1\">here</A>.", QStringLiteral("exec:/kcmshell5 khtml_java_js"))) .arg(i18n("JavaScript enabled (globally). Configure JavaScript <A HREF=\\\"%1\\\">here</A>.", QStringLiteral("exec:/kcmshell5 khtml_java_js"))) // leave the double backslashes here, they are necessary for javascript ! - .arg(i18n("Secure <A HREF=\"%1\">Java</A><SUP>®</SUP> support", QStringLiteral("http://www.oracle.com/technetwork/java/index.html"))) - .arg(i18n("JDK 1.2.0 (Java 2) compatible VM (<A HREF=\"%1\">IBM</A> or <A HREF=\"%2\">Sun/Oracle</A>)", - QStringLiteral("http://www.ibm.com"), QStringLiteral("http://www.oracle.com/technetwork/java/index.html"))) -+ .arg(i18n("Secure Java<SUP>®</SUP> support"), -+ QStringLiteral("about:plugins")) ++ .arg(i18n("Secure Java support")) ++ .arg(i18n("JDK 1.2.0 (Java 2) compatible VM")) .arg(i18n("Enable Java (globally) <A HREF=\"%1\">here</A>.", QStringLiteral("exec:/kcmshell5 khtml_java_js"))) // TODO Maybe test if Java is enabled ? - .arg(i18n("Netscape Communicator<SUP>®</SUP> <A HREF=\"%4\">plugins</A> (for viewing <A HREF=\"%1\">Flash<SUP>®</SUP></A>, <A HREF=\"%2\">Real<SUP>®</SUP></A>Audio, <A HREF=\"%3\">Real<SUP>®</SUP></A>Video, etc.)", - QStringLiteral("http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash"), - QStringLiteral("http://www.real.com"), QStringLiteral("http://www.real.com"), -- QStringLiteral("about:plugins"))) -+ .arg(i18n("Netscape Communicator<SUP>®</SUP> <A HREF=\"%1\">plugins</A>"), -+ QStringLiteral("about:plugins")) ++ .arg(i18n("NPAPI<SUP>®</SUP> <A HREF=\"%1\">plugins</A>", + QStringLiteral("about:plugins"))) .arg(i18n("built-in")) .arg(i18n("Secure Sockets Layer")) - .arg(i18n("(TLS/SSL v2/3) for secure communications up to 168bit")) @@ -301,8 +298,8 @@ QString KonqAboutPageSingleton::tips() .arg(i18n("Tips")) .arg(i18n("Specifications")) diff --git a/libre/konqueror/webkit.patch b/libre/konqueror/webkit.patch new file mode 100644 index 000000000..5bf669235 --- /dev/null +++ b/libre/konqueror/webkit.patch @@ -0,0 +1,19659 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 0b1c8782c..8f1da02d1 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -20,7 +20,7 @@ include(ECMSetupVersion) + set(KONQUEROR_LIB_VERSION "5.0.97") + set(KONQUEROR_VERSION "${KONQUEROR_LIB_VERSION}") + +-find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core Widgets WebEngineWidgets) ++find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core Widgets WebKitWidgets) + find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS Parts KCMUtils KHtml KDELibs4Support Archive Crash) + + find_package(KF5 ${KF5_MIN_VERSION} COMPONENTS Activities DocTools) # Optional +@@ -52,7 +52,7 @@ add_subdirectory( libkonq ) + add_subdirectory( src ) + add_subdirectory( client ) + add_subdirectory( autotests ) +-add_subdirectory( webenginepart ) ++add_subdirectory( webkitpart ) + + add_subdirectory( about ) + add_subdirectory( pics ) +diff --git a/about/konq_aboutpage.cpp b/about/konq_aboutpage.cpp +index 017875809..edfab3b64 100644 +--- a/about/konq_aboutpage.cpp ++++ b/about/konq_aboutpage.cpp +@@ -219,13 +219,10 @@ QString KonqAboutPageSingleton::specs() + QStringLiteral("http://www.ecma-international.org/publications/standards/ECMA-262.HTM"))) + .arg(i18n("JavaScript disabled (globally). Enable JavaScript <A HREF=\"%1\">here</A>.", QStringLiteral("exec:/kcmshell5 khtml_java_js"))) + .arg(i18n("JavaScript enabled (globally). Configure JavaScript <A HREF=\\\"%1\\\">here</A>.", QStringLiteral("exec:/kcmshell5 khtml_java_js"))) // leave the double backslashes here, they are necessary for javascript ! +- .arg(i18n("Secure <A HREF=\"%1\">Java</A><SUP>®</SUP> support", QStringLiteral("http://www.oracle.com/technetwork/java/index.html"))) +- .arg(i18n("JDK 1.2.0 (Java 2) compatible VM (<A HREF=\"%1\">IBM</A> or <A HREF=\"%2\">Sun/Oracle</A>)", +- QStringLiteral("http://www.ibm.com"), QStringLiteral("http://www.oracle.com/technetwork/java/index.html"))) ++ .arg(i18n("Secure <A HREF=\"%1\">Java</A><SUP>®</SUP> support")) ++ .arg(i18n("JDK 1.2.0 (Java 2) compatible VM")) + .arg(i18n("Enable Java (globally) <A HREF=\"%1\">here</A>.", QStringLiteral("exec:/kcmshell5 khtml_java_js"))) // TODO Maybe test if Java is enabled ? +- .arg(i18n("Netscape Communicator<SUP>®</SUP> <A HREF=\"%4\">plugins</A> (for viewing <A HREF=\"%1\">Flash<SUP>®</SUP></A>, <A HREF=\"%2\">Real<SUP>®</SUP></A>Audio, <A HREF=\"%3\">Real<SUP>®</SUP></A>Video, etc.)", +- QStringLiteral("http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash"), +- QStringLiteral("http://www.real.com"), QStringLiteral("http://www.real.com"), ++ .arg(i18n("NPAPI<SUP>®</SUP> <A HREF=\"%4\">plugins</A>", + QStringLiteral("about:plugins"))) + .arg(i18n("built-in")) + .arg(i18n("Secure Sockets Layer")) +@@ -301,8 +298,8 @@ QString KonqAboutPageSingleton::tips() + .arg(i18n("Tips")) + .arg(i18n("Specifications")) + .arg(i18n("Tips & Tricks")) +- .arg(i18n("Use Web-Shortcuts: by typing \"gg: KDE\" one can search the Internet, " +- "using Google, for the search phrase \"KDE\". There are a lot of " ++ .arg(i18n("Use Web-Shortcuts: by typing \"dd: KDE\" one can search the Internet, " ++ "using DuckDuckGo HTML, for the search phrase \"KDE\". There are a lot of " + "Web-Shortcuts predefined to make searching for software or looking " + "up certain words in an encyclopedia a breeze. You can even " + "<a href=\"%1\">create your own</a> Web-Shortcuts.", QStringLiteral("exec:/kcmshell5 webshortcuts"))) +diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt +index 09c1a28e9..590aea85d 100644 +--- a/autotests/CMakeLists.txt ++++ b/autotests/CMakeLists.txt +@@ -12,7 +12,7 @@ add_test(konqviewmgrtest konqviewmgrtest) + ecm_mark_as_test(konqviewmgrtest) + target_link_libraries(konqviewmgrtest kdeinit_konqueror Qt5::Core Qt5::Gui + # KF5::KHtml +- kwebenginepartlib Qt5::WebEngineWidgets Qt5::Test) ++ kwebkitpartlib Qt5::WebKitWidgets Qt5::Test) + + ########### historymanagertest ############### + +@@ -33,7 +33,7 @@ target_link_libraries(undomanagertest kdeinit_konqueror Qt5::Core Qt5::Test) + add_executable(konqhtmltest konqhtmltest.cpp) + add_test(konqhtmltest konqhtmltest) + ecm_mark_as_test(konqhtmltest) +-target_link_libraries(konqhtmltest kdeinit_konqueror kwebenginepartlib Qt5::Core Qt5::Test) ++target_link_libraries(konqhtmltest kdeinit_konqueror kwebkitpartlib Qt5::Core Qt5::Test) + + ########### konqviewtest ############### + +diff --git a/autotests/konqhtmltest.cpp b/autotests/konqhtmltest.cpp +index b893e704e..e43b735d2 100644 +--- a/autotests/konqhtmltest.cpp ++++ b/autotests/konqhtmltest.cpp +@@ -23,8 +23,8 @@ + #include <konqview.h> + #include <konqsessionmanager.h> + +-#include <webenginepart.h> +-#include <webengineview.h> ++#include <webkitpart.h> ++#include <webkitview.h> + + #include <KSharedConfig> + #include <kstandarddirs.h> +@@ -50,14 +50,14 @@ private Q_SLOTS: + KonqSessionManager::self()->disableAutosave(); + //qRegisterMetaType<KonqView *>("KonqView*"); + +- // Ensure the tests use webenginepart, not KHTML or kwebkitpart ++ // Ensure the tests use webkitpart, not KHTML or kwebkitpart + // This code is inspired by settings/konqhtml/generalopts.cpp + bool needsUpdate = false; + KSharedConfig::Ptr profile = KSharedConfig::openConfig(QStringLiteral("mimeapps.list"), KConfig::NoGlobals, QStandardPaths::ApplicationsLocation); + KConfigGroup addedServices(profile, "Added KDE Service Associations"); + Q_FOREACH (const QString &mimeType, QStringList() << "text/html" << "application/xhtml+xml" << "application/xml") { + QStringList services = addedServices.readXdgListEntry(mimeType); +- const QString wanted = QStringLiteral("webenginepart.desktop"); ++ const QString wanted = QStringLiteral("webkitpart.desktop"); + if (services.isEmpty() || services.at(0) != wanted) { + services.removeAll(wanted); + services.prepend(wanted); // make it the preferred one +@@ -87,7 +87,7 @@ private Q_SLOTS: + QSignalSpy spyCompleted(view, SIGNAL(viewCompleted(KonqView*))); + QVERIFY(spyCompleted.wait(20000)); + QCOMPARE(view->serviceType(), QString("text/html")); +- WebEnginePart* part = qobject_cast<WebEnginePart *>(view->part()); ++ WebKitPart* part = qobject_cast<WebKitPart *>(view->part()); + QVERIFY(part); + } + +@@ -105,7 +105,7 @@ private Q_SLOTS: + QVERIFY(spyCompleted.wait(20000)); // which then opens the right part + QCOMPARE(view->serviceType(), QString("inode/directory")); + } else { +- // WebEngine can actually list directories, no error. ++ // WebKit can actually list directories, no error. + // To test this: konqueror --mimetype text/html $HOME + QCOMPARE(view->url().adjusted(QUrl::StripTrailingSlash), url); + } +@@ -181,9 +181,9 @@ private Q_SLOTS: + KonqFrame *frame = newWindow->currentView()->frame(); + QVERIFY(frame); + QVERIFY(!frame->childView()->isLoading()); +- WebEnginePart *part = qobject_cast<WebEnginePart *>(frame->part()); ++ WebKitPart *part = qobject_cast<WebKitPart *>(frame->part()); + QVERIFY(part); +- QTRY_VERIFY(!part->view()->url().isEmpty()); // hack to wait for webengine to load the page ++ QTRY_VERIFY(!part->view()->url().isEmpty()); // hack to wait for webkit to load the page + QTRY_COMPARE(part->view()->title(), QString("Opener=[object Window]")); + deleteAllMainWindows(); + } +@@ -210,14 +210,14 @@ private: + static QWidget *partWidget(KonqView *view) + { + QWidget *widget = view->part()->widget(); +- WebEnginePart *htmlPart = qobject_cast<WebEnginePart *>(view->part()); ++ WebKitPart *htmlPart = qobject_cast<WebKitPart *>(view->part()); + if (htmlPart) { + widget = htmlPart->view(); // khtmlview != widget() nowadays, due to find bar + } + if (QScrollArea *scrollArea = qobject_cast<QScrollArea *>(widget)) { + widget = scrollArea->widget(); + } +- if (widget && widget->focusProxy()) { // for WebEngine's RenderWidgetHostViewQtDelegateWidget ++ if (widget && widget->focusProxy()) { // for WebKit's RenderWidgetHostViewQtDelegateWidget + return widget->focusProxy(); + } + return widget; +diff --git a/autotests/konqviewmgrtest.cpp b/autotests/konqviewmgrtest.cpp +index c1ac0fc05..b68c21190 100644 +--- a/autotests/konqviewmgrtest.cpp ++++ b/autotests/konqviewmgrtest.cpp +@@ -45,9 +45,9 @@ + #include <khtml_part.h> + #include <khtmlview.h> + #else +-#include <webenginepart.h> +-#include <webengineview.h> +-#include "../webenginepart/autotests/webengine_testutils.h" ++#include <webkitpart.h> ++#include <webkitview.h> ++#include "../webkitpart/autotests/webkit_testutils.h" + #endif + + #include <QStandardPaths> +@@ -81,7 +81,7 @@ static QWidget *partWidget(KonqView *view) + #ifdef TEST_KHTML + KHTMLPart *htmlPart = qobject_cast<KHTMLPart *>(view->part()); + #else +- WebEnginePart *htmlPart = qobject_cast<WebEnginePart *>(view->part()); ++ WebKitPart *htmlPart = qobject_cast<WebKitPart *>(view->part()); + #endif + if (htmlPart) { + widget = htmlPart->view(); // khtmlview != widget() nowadays, due to find bar +@@ -89,7 +89,7 @@ static QWidget *partWidget(KonqView *view) + if (QScrollArea *scrollArea = qobject_cast<QScrollArea *>(widget)) { + widget = scrollArea->widget(); + } +- if (widget && widget->focusProxy()) { // for WebEngine's RenderWidgetHostViewQtDelegateWidget ++ if (widget && widget->focusProxy()) { // for WebKit's RenderWidgetHostViewQtDelegateWidget + return widget->focusProxy(); + } + return widget; +@@ -192,7 +192,7 @@ void ViewMgrTest::initTestCase() + QCOMPARE(KonqSettings::mmbOpensTab(), true); + QCOMPARE(KonqSettings::popupsWithinTabs(), false); + +- // Ensure the tests use webenginepart (not khtml or webkit) ++ // Ensure the tests use webkitpart (not khtml or webkit) + // This code is inspired by settings/konqhtml/generalopts.cpp + KSharedConfig::Ptr profile = KSharedConfig::openConfig(QStringLiteral("mimeapps.list"), KConfig::NoGlobals, QStandardPaths::ApplicationsLocation); + KConfigGroup addedServices(profile, "Added KDE Service Associations"); +@@ -202,7 +202,7 @@ void ViewMgrTest::initTestCase() + #ifdef TEST_KHTML + const QString wanted = "khtml.desktop"; + #else +- const QString wanted = QStringLiteral("webenginepart.desktop"); ++ const QString wanted = QStringLiteral("webkitpart.desktop"); + #endif + if (services.isEmpty() || services.at(0) != wanted) { + services.removeAll(wanted); +@@ -434,7 +434,7 @@ void ViewMgrTest::testLinkedViews() + MyKonqMainWindow mainWindow; + openHtmlWithLink(mainWindow); + KonqView *view = mainWindow.currentView(); +- WebEnginePart *part = qobject_cast<WebEnginePart *>(view->part()); ++ WebKitPart *part = qobject_cast<WebKitPart *>(view->part()); + QVERIFY(part); + // Split it + qDebug() << "SPLITTING"; +diff --git a/doc/konqueror/index.docbook b/doc/konqueror/index.docbook +index 05bed1fc0..4f9313758 100644 +--- a/doc/konqueror/index.docbook ++++ b/doc/konqueror/index.docbook +@@ -2244,7 +2244,7 @@ playground/utils + Extensions...</guimenuitem></menuchoice> to open a dialog with all installed plugins and select + the ones you need. All plugins are accessible in the <guimenu>Tools</guimenu> menu.</para> + +-<para>Only plugins appropriate for the current mode (file manager or browser in KHTML/WebEngine view) ++<para>Only plugins appropriate for the current mode (file manager or browser in KHTML/WebKit view) + are listed in the dialog.</para> + + <variablelist> +@@ -2254,7 +2254,7 @@ FIXME 16.12 + KHTML: Auto Refresh, HTML Settings, Minitools-Bookmarklets, Translate (disabled), DOM Tree Viewer, Document Relations, Web Archiver, Website Validators, Search Bar + kwebkitpart for kf5 in extragear/base in branch frameworks + WebKit only HTML Settings and Translate (disabled) +-WebEngine -> no extensions ++WebKit -> no extensions + --> + <varlistentry> <!-- disabled here, why?--> + <term>Web Page Translation</term> +@@ -3406,7 +3406,7 @@ in the text or &HTML; page.</para></listitem> + <guisubmenu>View Mode</guisubmenu> + </menuchoice></term> + <listitem><para>In browser mode this submenu holds items to select embedded +-views like <guimenuitem>KHTML</guimenuitem>, <guimenuitem>WebEngine</guimenuitem>, <guimenuitem>Embedded Advanced ++views like <guimenuitem>KHTML</guimenuitem>, <guimenuitem>WebKit</guimenuitem>, <guimenuitem>Embedded Advanced + Text Editor</guimenuitem> and more embedded views.</para> + <para>In file manager mode this submenu holds items to select <guimenuitem>Icon</guimenuitem>, + <guimenuitem>Details</guimenuitem>, <guimenuitem>Compact</guimenuitem>, +@@ -3495,7 +3495,7 @@ page.</para> + <guimenu>View</guimenu> + <guimenuitem>Zoom In</guimenuitem> <guimenuitem>Zoom Out</guimenuitem> + <guimenuitem>Actual Size</guimenuitem> <guimenuitem>Zoom Text Only</guimenuitem> +-<guimenuitem>Zoom To DPI</guimenuitem></menuchoice> (Browser mode - WebEngine view)</term> ++<guimenuitem>Zoom To DPI</guimenuitem></menuchoice> (Browser mode - WebKit view)</term> + <listitem><para>These menuitems offer different actions to modify the size of the items + in the page.</para> + </listitem> +diff --git a/settings/konqhtml/generalopts.cpp b/settings/konqhtml/generalopts.cpp +index 36cb14388..3298adc3d 100644 +--- a/settings/konqhtml/generalopts.cpp ++++ b/settings/konqhtml/generalopts.cpp +@@ -126,12 +126,12 @@ void KKonqGeneralOptions::addHomeUrlWidgets(QVBoxLayout *lay) + + QLabel *webLabel = new QLabel(i18n("Default web browser engine:"), this); + +- m_webEngineCombo = new QComboBox(this); +- m_webEngineCombo->setEditable(false); +- m_webEngineCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents); +- formLayout->addRow(webLabel, m_webEngineCombo); +- webLabel->setBuddy(m_webEngineCombo); +- connect(m_webEngineCombo, SIGNAL(currentIndexChanged(int)), SLOT(slotChanged())); ++ m_webCombo = new QComboBox(this); ++ m_webCombo->setEditable(false); ++ m_webCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents); ++ formLayout->addRow(webLabel, m_webCombo); ++ webLabel->setBuddy(m_webCombo); ++ connect(m_webCombo, SIGNAL(currentIndexChanged(int)), SLOT(slotChanged())); + } + + KKonqGeneralOptions::~KKonqGeneralOptions() +@@ -180,7 +180,7 @@ void KKonqGeneralOptions::load() + Q_ASSERT(startComboIndex != -1); + m_startCombo->setCurrentIndex(startComboIndex); + +- m_webEngineCombo->clear(); ++ m_webCombo->clear(); + // ## Well, the problem with using the trader to find the available parts, is that if a user + // removed a part in keditfiletype text/html, it won't be in the list anymore. Oh well. + const KService::List partOfferList = KMimeTypeTrader::self()->query(QStringLiteral("text/html"), QStringLiteral("KParts/ReadOnlyPart"), QStringLiteral("not ('KParts/ReadWritePart' in ServiceTypes)")); +@@ -189,7 +189,7 @@ void KKonqGeneralOptions::load() + // We want only the HTML-capable parts, not any text/plain part (via inheritance) + // This is a small "private inheritance" hack, pending a more general solution + if (!partService->hasMimeType(QStringLiteral("text/plain"))) { +- m_webEngineCombo->addItem(QIcon::fromTheme(partService->icon()), partService->name(), ++ m_webCombo->addItem(QIcon::fromTheme(partService->icon()), partService->name(), + QVariant(partService->storageId())); + } + } +@@ -234,17 +234,17 @@ void KKonqGeneralOptions::save() + userSettings.writeEntry("StartURL", startUrl); + userSettings.writeEntry("HomeURL", homeURL->text()); + +- if (m_webEngineCombo->currentIndex() > 0) { ++ if (m_webCombo->currentIndex() > 0) { + // The user changed the preferred web engine, save into mimeapps.list. +- const QString preferredWebEngine = m_webEngineCombo->itemData(m_webEngineCombo->currentIndex()).toString(); +- //qDebug() << "preferredWebEngine=" << preferredWebEngine; ++ const QString preferredWebKit = m_webCombo->itemData(m_webCombo->currentIndex()).toString(); ++ //qDebug() << "preferredWebKit=" << preferredWebKit; + + KSharedConfig::Ptr profile = KSharedConfig::openConfig("mimeapps.list", KConfig::NoGlobals, QStandardPaths::ConfigLocation); + KConfigGroup addedServices(profile, "Added KDE Service Associations"); + Q_FOREACH (const QString &mimeType, QStringList() << "text/html" << "application/xhtml+xml" << "application/xml") { + QStringList services = addedServices.readXdgListEntry(mimeType); +- services.removeAll(preferredWebEngine); +- services.prepend(preferredWebEngine); // make it the preferred one ++ services.removeAll(preferredWebKit); ++ services.prepend(preferredWebKit); // make it the preferred one + addedServices.writeXdgListEntry(mimeType, services); + } + profile->sync(); +diff --git a/settings/konqhtml/generalopts.h b/settings/konqhtml/generalopts.h +index 066d02c81..838483c54 100644 +--- a/settings/konqhtml/generalopts.h ++++ b/settings/konqhtml/generalopts.h +@@ -41,7 +41,7 @@ private: + QComboBox *m_startCombo; + QLineEdit *homeURL; + QLineEdit *startURL; +- QComboBox *m_webEngineCombo; ++ QComboBox *m_webCombo; + Ui_advancedTabOptions *tabOptions; + }; + +diff --git a/src/konqmain.cpp b/src/konqmain.cpp +index 73c6a2f88..413bf5061 100644 +--- a/src/konqmain.cpp ++++ b/src/konqmain.cpp +@@ -58,7 +58,7 @@ static KonqPreloadingHandler s_preloadingHandler; + + extern "C" Q_DECL_EXPORT int kdemain(int argc, char **argv) + { +- QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts); // says QtWebEngine ++ QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts); // says QtWebKit + KonquerorApplication app(argc, argv); + KLocalizedString::setApplicationDomain("konqueror"); + +diff --git a/webenginepart/CMakeLists.txt a/webenginepart/CMakeLists.txt +deleted file mode 100644 +index b62735e8b..000000000 +--- a/webenginepart/CMakeLists.txt ++++ /dev/null +@@ -1,4 +0,0 @@ +-add_subdirectory(icons) +-add_subdirectory(src) +-add_subdirectory(tests) +-add_subdirectory(autotests) +diff --git a/webenginepart/COPYING.LIB a/webenginepart/COPYING.LIB +deleted file mode 100644 +index 01148ab6f..000000000 +--- a/webenginepart/COPYING.LIB ++++ /dev/null +@@ -1,486 +0,0 @@ +-NOTE! The LGPL below is copyrighted by the Free Software Foundation, but +-the instance of code that it refers to (the kde libraries) are copyrighted +-by the authors who actually wrote it. +- +---------------------------------------------------------------------------- +- GNU LIBRARY GENERAL PUBLIC LICENSE +- Version 2, June 1991 +- +- Copyright (C) 1991 Free Software Foundation, Inc. +- 51 Franklin Street, Fifth Floor +- Boston, MA 02110-1301, USA. +- Everyone is permitted to copy and distribute verbatim copies +- of this license document, but changing it is not allowed. +- +-[This is the first released version of the library GPL. It is +- numbered 2 because it goes with version 2 of the ordinary GPL.] +- +- Preamble +- +- The licenses for most software are designed to take away your +-freedom to share and change it. By contrast, the GNU General Public +-Licenses are intended to guarantee your freedom to share and change +-free software--to make sure the software is free for all its users. +- +- This license, the Library General Public License, applies to some +-specially designated Free Software Foundation software, and to any +-other libraries whose authors decide to use it. You can use it for +-your libraries, too. +- +- When we speak of free software, we are referring to freedom, not +-price. Our General Public Licenses are designed to make sure that you +-have the freedom to distribute copies of free software (and charge for +-this service if you wish), that you receive source code or can get it +-if you want it, that you can change the software or use pieces of it +-in new free programs; and that you know you can do these things. +- +- To protect your rights, we need to make restrictions that forbid +-anyone to deny you these rights or to ask you to surrender the rights. +-These restrictions translate to certain responsibilities for you if +-you distribute copies of the library, or if you modify it. +- +- For example, if you distribute copies of the library, whether gratis +-or for a fee, you must give the recipients all the rights that we gave +-you. You must make sure that they, too, receive or can get the source +-code. If you link a program with the library, you must provide +-complete object files to the recipients so that they can relink them +-with the library, after making changes to the library and recompiling +-it. And you must show them these terms so they know their rights. +- +- Our method of protecting your rights has two steps: (1) copyright +-the library, and (2) offer you this license which gives you legal +-permission to copy, distribute and/or modify the library. +- +- Also, for each distributor's protection, we want to make certain +-that everyone understands that there is no warranty for this free +-library. If the library is modified by someone else and passed on, we +-want its recipients to know that what they have is not the original +-version, so that any problems introduced by others will not reflect on +-the original authors' reputations. +- +- Finally, any free program is threatened constantly by software +-patents. We wish to avoid the danger that companies distributing free +-software will individually obtain patent licenses, thus in effect +-transforming the program into proprietary software. To prevent this, +-we have made it clear that any patent must be licensed for everyone's +-free use or not licensed at all. +- +- Most GNU software, including some libraries, is covered by the ordinary +-GNU General Public License, which was designed for utility programs. This +-license, the GNU Library General Public License, applies to certain +-designated libraries. This license is quite different from the ordinary +-one; be sure to read it in full, and don't assume that anything in it is +-the same as in the ordinary license. +- +- The reason we have a separate public license for some libraries is that +-they blur the distinction we usually make between modifying or adding to a +-program and simply using it. Linking a program with a library, without +-changing the library, is in some sense simply using the library, and is +-analogous to running a utility program or application program. However, in +-a textual and legal sense, the linked executable is a combined work, a +-derivative of the original library, and the ordinary General Public License +-treats it as such. +- +- Because of this blurred distinction, using the ordinary General +-Public License for libraries did not effectively promote software +-sharing, because most developers did not use the libraries. We +-concluded that weaker conditions might promote sharing better. +- +- However, unrestricted linking of non-free programs would deprive the +-users of those programs of all benefit from the free status of the +-libraries themselves. This Library General Public License is intended to +-permit developers of non-free programs to use free libraries, while +-preserving your freedom as a user of such programs to change the free +-libraries that are incorporated in them. (We have not seen how to achieve +-this as regards changes in header files, but we have achieved it as regards +-changes in the actual functions of the Library.) The hope is that this +-will lead to faster development of free libraries. +- +- The precise terms and conditions for copying, distribution and +-modification follow. Pay close attention to the difference between a +-"work based on the library" and a "work that uses the library". The +-former contains code derived from the library, while the latter only +-works together with the library. +- +- Note that it is possible for a library to be covered by the ordinary +-General Public License rather than by this special one. +- +- GNU LIBRARY GENERAL PUBLIC LICENSE +- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION +- +- 0. This License Agreement applies to any software library which +-contains a notice placed by the copyright holder or other authorized +-party saying it may be distributed under the terms of this Library +-General Public License (also called "this License"). Each licensee is +-addressed as "you". +- +- A "library" means a collection of software functions and/or data +-prepared so as to be conveniently linked with application programs +-(which use some of those functions and data) to form executables. +- +- The "Library", below, refers to any such software library or work +-which has been distributed under these terms. A "work based on the +-Library" means either the Library or any derivative work under +-copyright law: that is to say, a work containing the Library or a +-portion of it, either verbatim or with modifications and/or translated +-straightforwardly into another language. (Hereinafter, translation is +-included without limitation in the term "modification".) +- +- "Source code" for a work means the preferred form of the work for +-making modifications to it. For a library, complete source code means +-all the source code for all modules it contains, plus any associated +-interface definition files, plus the scripts used to control compilation +-and installation of the library. +- +- Activities other than copying, distribution and modification are not +-covered by this License; they are outside its scope. The act of +-running a program using the Library is not restricted, and output from +-such a program is covered only if its contents constitute a work based +-on the Library (independent of the use of the Library in a tool for +-writing it). Whether that is true depends on what the Library does +-and what the program that uses the Library does. +- +- 1. You may copy and distribute verbatim copies of the Library's +-complete source code as you receive it, in any medium, provided that +-you conspicuously and appropriately publish on each copy an +-appropriate copyright notice and disclaimer of warranty; keep intact +-all the notices that refer to this License and to the absence of any +-warranty; and distribute a copy of this License along with the +-Library. +- +- You may charge a fee for the physical act of transferring a copy, +-and you may at your option offer warranty protection in exchange for a +-fee. +- +- 2. You may modify your copy or copies of the Library or any portion +-of it, thus forming a work based on the Library, and copy and +-distribute such modifications or work under the terms of Section 1 +-above, provided that you also meet all of these conditions: +- +- a) The modified work must itself be a software library. +- +- b) You must cause the files modified to carry prominent notices +- stating that you changed the files and the date of any change. +- +- c) You must cause the whole of the work to be licensed at no +- charge to all third parties under the terms of this License. +- +- d) If a facility in the modified Library refers to a function or a +- table of data to be supplied by an application program that uses +- the facility, other than as an argument passed when the facility +- is invoked, then you must make a good faith effort to ensure that, +- in the event an application does not supply such function or +- table, the facility still operates, and performs whatever part of +- its purpose remains meaningful. +- +- (For example, a function in a library to compute square roots has +- a purpose that is entirely well-defined independent of the +- application. Therefore, Subsection 2d requires that any +- application-supplied function or table used by this function must +- be optional: if the application does not supply it, the square +- root function must still compute square roots.) +- +-These requirements apply to the modified work as a whole. If +-identifiable sections of that work are not derived from the Library, +-and can be reasonably considered independent and separate works in +-themselves, then this License, and its terms, do not apply to those +-sections when you distribute them as separate works. But when you +-distribute the same sections as part of a whole which is a work based +-on the Library, the distribution of the whole must be on the terms of +-this License, whose permissions for other licensees extend to the +-entire whole, and thus to each and every part regardless of who wrote +-it. +- +-Thus, it is not the intent of this section to claim rights or contest +-your rights to work written entirely by you; rather, the intent is to +-exercise the right to control the distribution of derivative or +-collective works based on the Library. +- +-In addition, mere aggregation of another work not based on the Library +-with the Library (or with a work based on the Library) on a volume of +-a storage or distribution medium does not bring the other work under +-the scope of this License. +- +- 3. You may opt to apply the terms of the ordinary GNU General Public +-License instead of this License to a given copy of the Library. To do +-this, you must alter all the notices that refer to this License, so +-that they refer to the ordinary GNU General Public License, version 2, +-instead of to this License. (If a newer version than version 2 of the +-ordinary GNU General Public License has appeared, then you can specify +-that version instead if you wish.) Do not make any other change in +-these notices. +- +- Once this change is made in a given copy, it is irreversible for +-that copy, so the ordinary GNU General Public License applies to all +-subsequent copies and derivative works made from that copy. +- +- This option is useful when you wish to copy part of the code of +-the Library into a program that is not a library. +- +- 4. You may copy and distribute the Library (or a portion or +-derivative of it, under Section 2) in object code or executable form +-under the terms of Sections 1 and 2 above provided that you accompany +-it with the complete corresponding machine-readable source code, which +-must be distributed under the terms of Sections 1 and 2 above on a +-medium customarily used for software interchange. +- +- If distribution of object code is made by offering access to copy +-from a designated place, then offering equivalent access to copy the +-source code from the same place satisfies the requirement to +-distribute the source code, even though third parties are not +-compelled to copy the source along with the object code. +- +- 5. A program that contains no derivative of any portion of the +-Library, but is designed to work with the Library by being compiled or +-linked with it, is called a "work that uses the Library". Such a +-work, in isolation, is not a derivative work of the Library, and +-therefore falls outside the scope of this License. +- +- However, linking a "work that uses the Library" with the Library +-creates an executable that is a derivative of the Library (because it +-contains portions of the Library), rather than a "work that uses the +-library". The executable is therefore covered by this License. +-Section 6 states terms for distribution of such executables. +- +- When a "work that uses the Library" uses material from a header file +-that is part of the Library, the object code for the work may be a +-derivative work of the Library even though the source code is not. +-Whether this is true is especially significant if the work can be +-linked without the Library, or if the work is itself a library. The +-threshold for this to be true is not precisely defined by law. +- +- If such an object file uses only numerical parameters, data +-structure layouts and accessors, and small macros and small inline +-functions (ten lines or less in length), then the use of the object +-file is unrestricted, regardless of whether it is legally a derivative +-work. (Executables containing this object code plus portions of the +-Library will still fall under Section 6.) +- +- Otherwise, if the work is a derivative of the Library, you may +-distribute the object code for the work under the terms of Section 6. +-Any executables containing that work also fall under Section 6, +-whether or not they are linked directly with the Library itself. +- +- 6. As an exception to the Sections above, you may also compile or +-link a "work that uses the Library" with the Library to produce a +-work containing portions of the Library, and distribute that work +-under terms of your choice, provided that the terms permit +-modification of the work for the customer's own use and reverse +-engineering for debugging such modifications. +- +- You must give prominent notice with each copy of the work that the +-Library is used in it and that the Library and its use are covered by +-this License. You must supply a copy of this License. If the work +-during execution displays copyright notices, you must include the +-copyright notice for the Library among them, as well as a reference +-directing the user to the copy of this License. Also, you must do one +-of these things: +- +- a) Accompany the work with the complete corresponding +- machine-readable source code for the Library including whatever +- changes were used in the work (which must be distributed under +- Sections 1 and 2 above); and, if the work is an executable linked +- with the Library, with the complete machine-readable "work that +- uses the Library", as object code and/or source code, so that the +- user can modify the Library and then relink to produce a modified +- executable containing the modified Library. (It is understood +- that the user who changes the contents of definitions files in the +- Library will not necessarily be able to recompile the application +- to use the modified definitions.) +- +- b) Accompany the work with a written offer, valid for at +- least three years, to give the same user the materials +- specified in Subsection 6a, above, for a charge no more +- than the cost of performing this distribution. +- +- c) If distribution of the work is made by offering access to copy +- from a designated place, offer equivalent access to copy the above +- specified materials from the same place. +- +- d) Verify that the user has already received a copy of these +- materials or that you have already sent this user a copy. +- +- For an executable, the required form of the "work that uses the +-Library" must include any data and utility programs needed for +-reproducing the executable from it. However, as a special exception, +-the source code distributed need not include anything that is normally +-distributed (in either source or binary form) with the major +-components (compiler, kernel, and so on) of the operating system on +-which the executable runs, unless that component itself accompanies +-the executable. +- +- It may happen that this requirement contradicts the license +-restrictions of other proprietary libraries that do not normally +-accompany the operating system. Such a contradiction means you cannot +-use both them and the Library together in an executable that you +-distribute. +- +- 7. You may place library facilities that are a work based on the +-Library side-by-side in a single library together with other library +-facilities not covered by this License, and distribute such a combined +-library, provided that the separate distribution of the work based on +-the Library and of the other library facilities is otherwise +-permitted, and provided that you do these two things: +- +- a) Accompany the combined library with a copy of the same work +- based on the Library, uncombined with any other library +- facilities. This must be distributed under the terms of the +- Sections above. +- +- b) Give prominent notice with the combined library of the fact +- that part of it is a work based on the Library, and explaining +- where to find the accompanying uncombined form of the same work. +- +- 8. You may not copy, modify, sublicense, link with, or distribute +-the Library except as expressly provided under this License. Any +-attempt otherwise to copy, modify, sublicense, link with, or +-distribute the Library is void, and will automatically terminate your +-rights under this License. However, parties who have received copies, +-or rights, from you under this License will not have their licenses +-terminated so long as such parties remain in full compliance. +- +- 9. You are not required to accept this License, since you have not +-signed it. However, nothing else grants you permission to modify or +-distribute the Library or its derivative works. These actions are +-prohibited by law if you do not accept this License. Therefore, by +-modifying or distributing the Library (or any work based on the +-Library), you indicate your acceptance of this License to do so, and +-all its terms and conditions for copying, distributing or modifying +-the Library or works based on it. +- +- 10. Each time you redistribute the Library (or any work based on the +-Library), the recipient automatically receives a license from the +-original licensor to copy, distribute, link with or modify the Library +-subject to these terms and conditions. You may not impose any further +-restrictions on the recipients' exercise of the rights granted herein. +-You are not responsible for enforcing compliance by third parties to +-this License. +- +- 11. If, as a consequence of a court judgment or allegation of patent +-infringement or for any other reason (not limited to patent issues), +-conditions are imposed on you (whether by court order, agreement or +-otherwise) that contradict the conditions of this License, they do not +-excuse you from the conditions of this License. If you cannot +-distribute so as to satisfy simultaneously your obligations under this +-License and any other pertinent obligations, then as a consequence you +-may not distribute the Library at all. For example, if a patent +-license would not permit royalty-free redistribution of the Library by +-all those who receive copies directly or indirectly through you, then +-the only way you could satisfy both it and this License would be to +-refrain entirely from distribution of the Library. +- +-If any portion of this section is held invalid or unenforceable under any +-particular circumstance, the balance of the section is intended to apply, +-and the section as a whole is intended to apply in other circumstances. +- +-It is not the purpose of this section to induce you to infringe any +-patents or other property right claims or to contest validity of any +-such claims; this section has the sole purpose of protecting the +-integrity of the free software distribution system which is +-implemented by public license practices. Many people have made +-generous contributions to the wide range of software distributed +-through that system in reliance on consistent application of that +-system; it is up to the author/donor to decide if he or she is willing +-to distribute software through any other system and a licensee cannot +-impose that choice. +- +-This section is intended to make thoroughly clear what is believed to +-be a consequence of the rest of this License. +- +- 12. If the distribution and/or use of the Library is restricted in +-certain countries either by patents or by copyrighted interfaces, the +-original copyright holder who places the Library under this License may add +-an explicit geographical distribution limitation excluding those countries, +-so that distribution is permitted only in or among countries not thus +-excluded. In such case, this License incorporates the limitation as if +-written in the body of this License. +- +- 13. The Free Software Foundation may publish revised and/or new +-versions of the Library General Public License from time to time. +-Such new versions will be similar in spirit to the present version, +-but may differ in detail to address new problems or concerns. +- +-Each version is given a distinguishing version number. If the Library +-specifies a version number of this License which applies to it and +-"any later version", you have the option of following the terms and +-conditions either of that version or of any later version published by +-the Free Software Foundation. If the Library does not specify a +-license version number, you may choose any version ever published by +-the Free Software Foundation. +- +- 14. If you wish to incorporate parts of the Library into other free +-programs whose distribution conditions are incompatible with these, +-write to the author to ask for permission. For software which is +-copyrighted by the Free Software Foundation, write to the Free +-Software Foundation; we sometimes make exceptions for this. Our +-decision will be guided by the two goals of preserving the free status +-of all derivatives of our free software and of promoting the sharing +-and reuse of software generally. +- +- NO WARRANTY +- +- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. +- +- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +-DAMAGES. +- +- END OF TERMS AND CONDITIONS +- How to Apply These Terms to Your New Libraries +- +- If you develop a new library, and you want it to be of the greatest +-possible use to the public, we recommend making it free software that +-everyone can redistribute and change. You can do so by permitting +-redistribution under these terms (or, alternatively, under the terms of the +-ordinary General Public License). +- +- To apply these terms, attach the following notices to the library. It is +-safest to attach them to the start of each source file to most effectively +-convey the exclusion of warranty; and each file should have at least the +-"copyright" line and a pointer to where the full notice is found. +- +- <one line to give the library's name and a brief idea of what it does.> +- Copyright (C) <year> <name of author> +- +- This library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser 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 +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with this library; if not, write to the Free Software +- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +- +-Also add information on how to contact you by electronic and paper mail. +- +-You should also get your employer (if you work as a programmer) or your +-school, if any, to sign a "copyright disclaimer" for the library, if +-necessary. Here is a sample; alter the names: +- +- Yoyodyne, Inc., hereby disclaims all copyright interest in the +- library `Frob' (a library for tweaking knobs) written by James Random Hacker. +- +- <signature of Ty Coon>, 1 April 1990 +- Ty Coon, President of Vice +- +-That's all there is to it! +diff --git a/webenginepart/Mainpage.dox a/webenginepart/Mainpage.dox +deleted file mode 100644 +index 832196aef..000000000 +--- a/webenginepart/Mainpage.dox ++++ /dev/null +@@ -1,4 +0,0 @@ +-/** @mainpage +-* +-* Main Doxygen page for KWebKitPart. +-*/ +diff --git a/webenginepart/Messages.sh a/webenginepart/Messages.sh +deleted file mode 100644 +index 1fea7c2bb..000000000 +--- a/webenginepart/Messages.sh ++++ /dev/null +@@ -1,4 +0,0 @@ +-#! /usr/bin/env bash +-$EXTRACTRC `find . -name '*.rc' -or -name '*.ui'` >> rc.cpp || exit 11 +-$XGETTEXT `find . -name '*.cpp' | grep -v '/tests/'` -o $podir/webenginepart.pot +-rm -f rc.cpp +diff --git a/webenginepart/README a/webenginepart/README +deleted file mode 100644 +index f73bfc864..000000000 +--- a/webenginepart/README ++++ /dev/null +@@ -1,40 +0,0 @@ +-KWebKitPart +-=========== +- +-KWebKitPart is a KDE component (KPart) wrapper for QtWebKit. It is intended to +-allow KPart based KDE applications such as Konqueror to use it in place of other +-browser engine, such as KHTML, to browse the web in Konqueror. +- +-Known limitations and unimplemented features are listed in the following +-documents: +- +-* https://projects.kde.org/projects/kde/kdelibs/repository/revisions/master/entry/kdewebkit/ISSUES +-* https://projects.kde.org/projects/extragear/base/kwebkitpart/repository/revisions/master/entry/TODO +- +-Please report any issues to: https://bugs.kde.org +-IMPORTANT NOTE: Do not select "konqueror" as product, but "kwebkitpart"! +- +-There is also a public mailing list available for support: +- +- webkit-devel @ kde.org +- +-How to use KWebKitPart in Konqueror +-=================================== +- +-You can switch between the different rendering engines: +-View -> View Mode -> {KHTML, WebKit} (website needs to be open) +-If WebKit does not show up in Konqueror, run 'kbuildsycoca4' and +-restart Konqueror. Note that this change does not persist. If you +-press the reload button or open a new website, it will fall back +-to the default rendering engine. +- +-If you want to set KWebKitPart as default for any website, run: +-'keditfiletype text/html' +-and move "WebKit (kwebkitpart)" in the "Embedding" tab to the top. +- +-In KDE 4.6 and higher you can choose the default rendering engine +-in Konqueror's configuration dialog under the "General" section. +- +-For more information about this project please see also: +-http://techbase.kde.org/Projects/WebKit +- +diff --git a/webenginepart/TODO a/webenginepart/TODO +deleted file mode 100644 +index f6ba03459..000000000 +--- a/webenginepart/TODO ++++ /dev/null +@@ -1,23 +0,0 @@ +-* Proper support for KWebKitPart in the following Konqueror plugins: +- - adblock This plugin's GUI needs to be changed to use the KPart plugin +- extensions so that it is not khtml specific. Other than that +- kwebkitpart supports the ad filtering functionalities supported +- by khtml. +- +-* Add KPartStatusBarExtension support for the following plugins/features: +- - Popup blocker (non-plugin) +- +-* Implement some means of showing information about the webkit rendering engine: +- - KWebKitPart's version # +- - QtWebKit's version # +- - UserAgent string ??? +- +-* Look through all of Konqueror's web configuration options and make sure we +- honor all those we possibly can. Here is a non-complete list of features +- that are either partially implemented or not implemented at all: +- - Change cursor over links (TODO, QtWebKit ???). +- - Smooth scrolling support (TODO, QtWebKit ???). +- - Underline links support (Partial, does not work as intended). +- - Enable access key navigation with Ctrl key (TODO, QtWebKit ???). +- - Animations (TODO, QtWebKit ???). +- - Draw frames around not completely loaded images (TODO, QtWebKit ???). +diff --git a/webenginepart/autotests/CMakeLists.txt a/webenginepart/autotests/CMakeLists.txt +deleted file mode 100644 +index 6c9f3b14f..000000000 +--- a/webenginepart/autotests/CMakeLists.txt ++++ /dev/null +@@ -1,14 +0,0 @@ +-include(ECMAddTests) +- +-find_package(Qt5Test ${QT_MIN_VERSION} CONFIG REQUIRED) +- +-macro(webenginepart_unit_tests) +- foreach(_testname ${ARGN}) +- ecm_add_test(${_testname}.cpp TEST_NAME ${_testname} +- LINK_LIBRARIES kwebenginepartlib Qt5::Test) +- endforeach() +-endmacro(webenginepart_unit_tests) +- +-webenginepart_unit_tests( +- webengine_partapi_test +-) +diff --git a/webenginepart/autotests/data/hello.html a/webenginepart/autotests/data/hello.html +deleted file mode 100644 +index e965047ad..000000000 +--- a/webenginepart/autotests/data/hello.html ++++ /dev/null +@@ -1 +0,0 @@ +-Hello +diff --git a/webenginepart/autotests/data/page-with-link.html a/webenginepart/autotests/data/page-with-link.html +deleted file mode 100644 +index df85219d6..000000000 +--- a/webenginepart/autotests/data/page-with-link.html ++++ /dev/null +@@ -1 +0,0 @@ +-<a href="hello.html" id="linkid">click me</a> +diff --git a/webenginepart/autotests/webengine_partapi_test.cpp a/webenginepart/autotests/webengine_partapi_test.cpp +deleted file mode 100644 +index c246536bf..000000000 +--- a/webenginepart/autotests/webengine_partapi_test.cpp ++++ /dev/null +@@ -1,133 +0,0 @@ +-/* +- Copyright (c) 2016 David Faure <faure@kde.org> +- +- This library is free software; you can redistribute it and/or modify +- it under the terms of the GNU Lesser General Public License as published by +- the Free Software Foundation; either version 2 of the License or ( at +- your option ) version 3 or, at the discretion of KDE e.V. ( which shall +- act as a proxy as in section 14 of the GPLv3 ), 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 Lesser 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 <webenginepart.h> +-#include "webengine_testutils.h" +- +-#include <KIO/Job> +-#include <KParts/BrowserExtension> +- +-#include <QTest> +-#include <QObject> +-#include <QSignalSpy> +-#include <QWebEngineView> +- +-class WebEnginePartApiTest : public QObject +-{ +- Q_OBJECT +-private Q_SLOTS: +- void initTestCase(); +- void shouldHaveBrowserExtension(); +- void shouldEmitStartedAndCompleted(); +- void shouldEmitSetWindowCaption(); +- void shouldEmitOpenUrlNotifyOnClick(); +- +-}; +- +-void WebEnginePartApiTest::initTestCase() +-{ +- qRegisterMetaType<KIO::Job *>(); // for the KParts started signal +-} +- +-void WebEnginePartApiTest::shouldHaveBrowserExtension() +-{ +- // GIVEN +- WebEnginePart part; +- +- // WHEN +- KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject(&part); +- +- // THEN +- QVERIFY(ext); +-} +- +-void WebEnginePartApiTest::shouldEmitStartedAndCompleted() +-{ +- // GIVEN +- WebEnginePart part; +- QSignalSpy spyStarted(&part, &KParts::ReadOnlyPart::started); +- QSignalSpy spyCompleted(&part, SIGNAL(completed(bool))); +- QSignalSpy spySetWindowCaption(&part, &KParts::ReadOnlyPart::setWindowCaption); +- KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject(&part); +- QSignalSpy spyOpenUrlNotify(ext, &KParts::BrowserExtension::openUrlNotify); +- const QUrl url(QStringLiteral("data:text/html, <p>Hello World</p>")); +- +- // WHEN +- part.openUrl(url); +- +- // THEN +- QVERIFY(spyStarted.wait()); +- QVERIFY(spySetWindowCaption.wait()); +- QCOMPARE(spySetWindowCaption.at(0).at(0).toUrl().toString(), url.toString()); +- QVERIFY(spyCompleted.wait()); +- QVERIFY(!spyCompleted.at(0).at(0).toBool()); +- QVERIFY(spyOpenUrlNotify.isEmpty()); +-} +- +-void WebEnginePartApiTest::shouldEmitSetWindowCaption() +-{ +- // GIVEN +- WebEnginePart part; +- QSignalSpy spyStarted(&part, &KParts::ReadOnlyPart::started); +- QSignalSpy spyCompleted(&part, SIGNAL(completed(bool))); +- QSignalSpy spySetWindowCaption(&part, &KParts::ReadOnlyPart::setWindowCaption); +- +- // WHEN opening a URL with a title tag +- part.openUrl(QUrl(QStringLiteral("data:text/html, <title>Custom Title</title><p>Hello World</p>"))); +- +- // THEN +- QVERIFY(spyStarted.wait()); +- QVERIFY(spyCompleted.wait()); +- QVERIFY(!spyCompleted.at(0).at(0).toBool()); +- QCOMPARE(spySetWindowCaption.count(), 2); +- QCOMPARE(spySetWindowCaption.at(1).at(0).toUrl().toString(), QStringLiteral("Custom Title")); +-} +- +-void WebEnginePartApiTest::shouldEmitOpenUrlNotifyOnClick() +-{ +- // GIVEN +- WebEnginePart part; +- QSignalSpy spyStarted(&part, &KParts::ReadOnlyPart::started); +- QSignalSpy spyCompleted(&part, SIGNAL(completed(bool))); +- QSignalSpy spySetWindowCaption(&part, &KParts::ReadOnlyPart::setWindowCaption); +- KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject(&part); +- QSignalSpy spyOpenUrlNotify(ext, &KParts::BrowserExtension::openUrlNotify); +- const QString file = QFINDTESTDATA("data/page-with-link.html"); +- QVERIFY(!file.isEmpty()); +- const QUrl url = QUrl::fromLocalFile(file); +- part.openUrl(url); +- QVERIFY(spyCompleted.wait()); +- QVERIFY(spyOpenUrlNotify.isEmpty()); +- QWebEnginePage *page = part.view()->page(); +- const QPoint pos = elementCenter(page, QStringLiteral("linkid")); // doesn't seem fully correct... +- part.widget()->show(); +- spyCompleted.clear(); +- +- // WHEN clicking on the link +- QTest::mouseClick(part.view()->focusProxy(), Qt::LeftButton, Qt::KeyboardModifiers(), pos); +- +- // THEN +- QVERIFY(spyCompleted.wait()); +- QCOMPARE(spyOpenUrlNotify.count(), 1); +- QCOMPARE(part.url().fileName(), QStringLiteral("hello.html")); +-} +- +-QTEST_MAIN(WebEnginePartApiTest) +-#include "webengine_partapi_test.moc" +diff --git a/webenginepart/autotests/webengine_testutils.h a/webenginepart/autotests/webengine_testutils.h +deleted file mode 100644 +index 37489847b..000000000 +--- a/webenginepart/autotests/webengine_testutils.h ++++ /dev/null +@@ -1,108 +0,0 @@ +-/**************************************************************************** +- ** +- ** Copyright (C) 2016 The Qt Company Ltd. +- ** Contact: https://www.qt.io/licensing/ +- ** +- ** This file is part of the QtWebEngine module of the Qt Toolkit. +- ** +- ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +- ** Commercial License Usage +- ** Licensees holding valid commercial Qt licenses may use this file in +- ** accordance with the commercial license agreement provided with the +- ** Software or, alternatively, in accordance with the terms contained in +- ** a written agreement between you and The Qt Company. For licensing terms +- ** and conditions see https://www.qt.io/terms-conditions. For further +- ** information use the contact form at https://www.qt.io/contact-us. +- ** +- ** GNU General Public License Usage +- ** Alternatively, this file may be used under the terms of the GNU +- ** General Public License version 3 as published by the Free Software +- ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +- ** included in the packaging of this file. Please review the following +- ** information to ensure the GNU General Public License requirements will +- ** be met: https://www.gnu.org/licenses/gpl-3.0.html. +- ** +- ** $QT_END_LICENSE$ +- ** +- ****************************************************************************/ +- +-#include <QEventLoop> +-#include <QTimer> +-#include <QWebEnginePage> +- +-template<typename T, typename R> +-struct RefWrapper { +- R &ref; +- void operator()(const T& result) { +- ref(result); +- } +-}; +- +-template<typename T> +-class CallbackSpy { +-public: +- CallbackSpy() : called(false) { +- timeoutTimer.setSingleShot(true); +- QObject::connect(&timeoutTimer, SIGNAL(timeout()), &eventLoop, SLOT(quit())); +- } +- +- T waitForResult() { +- if (!called) { +- timeoutTimer.start(10000); +- eventLoop.exec(); +- } +- return result; +- } +- +- bool wasCalled() const { +- return called; +- } +- +- void operator()(const T &result) { +- this->result = result; +- called = true; +- eventLoop.quit(); +- } +- +- // Cheap rip-off of boost/std::ref +- RefWrapper<T, CallbackSpy<T> > ref() +- { +- RefWrapper<T, CallbackSpy<T> > wrapper = {*this}; +- return wrapper; +- } +- +-private: +- Q_DISABLE_COPY(CallbackSpy) +- bool called; +- QTimer timeoutTimer; +- QEventLoop eventLoop; +- T result; +-}; +- +-// taken from the qwebengine unittests +-static inline QVariant evaluateJavaScriptSync(QWebEnginePage *page, const QString &script) +-{ +- CallbackSpy<QVariant> spy; +- page->runJavaScript(script, spy.ref()); +- return spy.waitForResult(); +-} +- +-// Taken from QtWebEngine's tst_qwebenginepage.cpp +-static QPoint elementCenter(QWebEnginePage *page, const QString &id) +-{ +- QVariantList rectList = evaluateJavaScriptSync(page, +- "(function(){" +- "var elem = document.getElementById('" + id + "');" +- "var rect = elem.getBoundingClientRect();" +- "return [rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top];" +- "})()").toList(); +- +- if (rectList.count() != 4) { +- qWarning("elementCenter failed."); +- return QPoint(); +- } +- const QRect rect(rectList.at(0).toInt(), rectList.at(1).toInt(), +- rectList.at(2).toInt(), rectList.at(3).toInt()); +- return rect.center(); +-} +- +diff --git a/webenginepart/icons/CMakeLists.txt a/webenginepart/icons/CMakeLists.txt +deleted file mode 100644 +index 4b820aeb3..000000000 +--- a/webenginepart/icons/CMakeLists.txt ++++ /dev/null +@@ -1,2 +0,0 @@ +-include(ECMInstallIcons) +-ecm_install_icons(${ICON_INSTALL_DIR}) +diff --git a/webenginepart/icons/webengine.svg a/webenginepart/icons/webengine.svg +deleted file mode 100644 +index 148d955f9..000000000 +--- a/webenginepart/icons/webengine.svg ++++ /dev/null +@@ -1,104 +0,0 @@ +-<?xml version="1.0" encoding="UTF-8" standalone="no"?> +-<!-- Created with Inkscape (http://www.inkscape.org/) --> +- +-<svg +- xmlns:dc="http://purl.org/dc/elements/1.1/" +- xmlns:cc="http://creativecommons.org/ns#" +- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" +- xmlns:svg="http://www.w3.org/2000/svg" +- xmlns="http://www.w3.org/2000/svg" +- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" +- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" +- width="64" +- height="64" +- id="svg3360" +- version="1.1" +- inkscape:version="0.91 r13725" +- viewBox="0 0 64 64" +- sodipodi:docname="webengine.svg" +- inkscape:export-filename="/home/sune/git/kwebkitpart/icons/hi128-app-webengine.png" +- inkscape:export-xdpi="180" +- inkscape:export-ydpi="180"> +- <defs +- id="defs3362" /> +- <sodipodi:namedview +- id="base" +- pagecolor="#ffffff" +- bordercolor="#666666" +- borderopacity="1.0" +- inkscape:pageopacity="0.0" +- inkscape:pageshadow="2" +- inkscape:zoom="5.5" +- inkscape:cx="-5.0909091" +- inkscape:cy="24.727273" +- inkscape:current-layer="layer1" +- showgrid="true" +- inkscape:document-units="px" +- inkscape:grid-bbox="true" +- inkscape:window-width="3200" +- inkscape:window-height="1685" +- inkscape:window-x="0" +- inkscape:window-y="0" +- inkscape:window-maximized="1" /> +- <metadata +- id="metadata3365"> +- <rdf:RDF> +- <cc:Work +- rdf:about=""> +- <dc:format>image/svg+xml</dc:format> +- <dc:type +- rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> +- <dc:title></dc:title> +- </cc:Work> +- </rdf:RDF> +- </metadata> +- <g +- id="layer1" +- inkscape:label="Layer 1" +- inkscape:groupmode="layer"> +- <text +- xml:space="preserve" +- style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#0079b1;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" +- x="1.6363635" +- y="32.545456" +- id="text3368" +- sodipodi:linespacing="125%"><tspan +- sodipodi:role="line" +- id="tspan3370" +- x="1.6363635" +- y="32.545456">W</tspan></text> +- <text +- xml:space="preserve" +- style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b0009d;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" +- x="14.545453" +- y="46" +- id="text4172" +- sodipodi:linespacing="125%"><tspan +- sodipodi:role="line" +- id="tspan4174" +- x="14.545453" +- y="46">E</tspan></text> +- <text +- xml:space="preserve" +- style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b0009d;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" +- x="39.40696" +- y="32.398262" +- id="text4172-3" +- sodipodi:linespacing="125%"><tspan +- sodipodi:role="line" +- id="tspan4174-6" +- x="39.40696" +- y="32.398262">E</tspan></text> +- <text +- xml:space="preserve" +- style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#848400;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" +- x="28" +- y="59.818184" +- id="text4194" +- sodipodi:linespacing="125%"><tspan +- sodipodi:role="line" +- id="tspan4196" +- x="28" +- y="59.818184">B</tspan></text> +- </g> +-</svg> +diff --git a/webenginepart/scripts/codingstyle.sh a/webenginepart/scripts/codingstyle.sh +deleted file mode 100755 +index 1761942d6..000000000 +--- a/webenginepart/scripts/codingstyle.sh ++++ /dev/null +@@ -1,19 +0,0 @@ +-#!/bin/sh +-# +-# Kdelibs coding style is defined in http://techbase.kde.org/Policies/Kdelibs_Coding_Style +-# +- +-PWD=$(pwd) +-cd $PWD +- +-echo "Applying astyle rules..." +-astyle -v --indent=spaces=4 \ +- --brackets=linux \ +- --indent-labels \ +- --pad=oper --unpad=paren \ +- --one-line=keep-statements \ +- --convert-tabs --indent-preprocessor \ +- `find -type f -name '*.cpp' -or -name '*.h' -or -name '*.cc' | grep -Ev "\./.+/settings/"` +- +-echo "Done!" +- +diff --git a/webenginepart/scripts/create_release_package.sh a/webenginepart/scripts/create_release_package.sh +deleted file mode 100755 +index a8694c897..000000000 +--- a/webenginepart/scripts/create_release_package.sh ++++ /dev/null +@@ -1,16 +0,0 @@ +-#!/bin/sh +- +-VERSION=${1} +-GITREPO=${2} +-OUTPUTDIR=${3} +- +-if [ -z ${VERSION} ] || [ -z {GITREPO} ]; then +- echo "Usage: `basename ${0}` <VERSION> <GITREPO> [<OUTPUTDIR>]" +- exit 1 +-fi +- +-if [ -z $OUTPUTDIR ] || [ ! -d $OUTPUTDIR ]; then +- OUTPUTDIR="${PWD}" +-fi +- +-git archive --format=tar --prefix=kwebkitpart-${VERSION}/ ${GITREPO} | bzip2 -9 > ${OUTPUTDIR}/kwebkitpart-${VERSION}.tar.bz2 +diff --git a/webenginepart/src/CMakeLists.txt a/webenginepart/src/CMakeLists.txt +deleted file mode 100644 +index 1672c6038..000000000 +--- a/webenginepart/src/CMakeLists.txt ++++ /dev/null +@@ -1,41 +0,0 @@ +-include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_BINARY_DIR}) +- +-set(kwebenginepartlib_LIB_SRCS +- webenginepart.cpp +- webenginepart_ext.cpp +- webengineview.cpp +- webenginepage.cpp +- websslinfo.cpp +- webhistoryinterface.cpp +- settings/webenginesettings.cpp +- settings/webengine_filter.cpp +- ui/searchbar.cpp +- ui/passwordbar.cpp +- ui/featurepermissionbar.cpp +-) +- +-qt5_wrap_ui(kwebenginepartlib_LIB_SRCS +- ui/searchbar.ui +-) +- +-add_library(kwebenginepartlib ${kwebenginepartlib_LIB_SRCS}) +- +-generate_export_header(kwebenginepartlib) +- +-target_link_libraries(kwebenginepartlib Qt5::Core Qt5::DBus Qt5::Gui Qt5::Widgets Qt5::WebEngineWidgets Qt5::PrintSupport KF5::Parts KF5::SonnetCore) +- +-target_include_directories(kwebenginepartlib PUBLIC +- "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/>" +-) +- +-install(TARGETS kwebenginepartlib ${KF5_INSTALL_TARGETS_DEFAULT_ARGS}) +- +-add_library(webenginepart MODULE webenginepartfactory.cpp) +- +-target_link_libraries(webenginepart kwebenginepartlib) +- +-install(TARGETS webenginepart DESTINATION ${KDE_INSTALL_PLUGINDIR}/kf5/parts) +- +-install(FILES webenginepart.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}) +- +-install(FILES webenginepart.rc DESTINATION ${KDE_INSTALL_KXMLGUI5DIR}/webenginepart) +diff --git a/webenginepart/src/settings/webengine_filter.cpp a/webenginepart/src/settings/webengine_filter.cpp +deleted file mode 100644 +index 98f505d60..000000000 +--- a/webenginepart/src/settings/webengine_filter.cpp ++++ /dev/null +@@ -1,344 +0,0 @@ +-/* This file is part of the KDE project +- +- Copyright (C) 2005 Ivor Hewitt <ivor@kde.org> +- Copyright (C) 2008 Maksim Orlovich <maksim@kde.org> +- Copyright (C) 2008 Vyacheslav Tokarev <tsjoker@gmail.com> +- +- This library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Library 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 "webengine_filter.h" +- +-#include <QHash> +-#include <QBitArray> +- +-// rolling hash parameters +-#define HASH_P (1997) +-#define HASH_Q (17509) +-// HASH_MOD = (HASH_P^7) % HASH_Q +-#define HASH_MOD (523) +- +- +-using namespace KDEPrivate; +- +-// Updateable Multi-String Matcher based on Rabin-Karp's algorithm +-class StringsMatcher { +-public: +- // add filter to matching set +- void addString(const QString& pattern) +- { +- if (pattern.length() < 8) { +- // handle short string differently +- shortStringFilters.append(pattern); +- } else { +- // use modified Rabin-Karp's algorithm with 8-length string hash +- // i.e. store hash of first 8 chars in the HashMap for fast look-up +- stringFilters.append(pattern); +- int ind = stringFilters.size() - 1; +- int current = 0; +- +- // compute hash using rolling hash +- // hash for string: x0,x1,x2...xn-1 will be: +- // (p^(n-1)*x0 + p^(n-2)*x1 + ... + p * xn-2 + xn-1) % q +- // where p and q some wisely-chosen integers +- /*for (int k = 0; k < 8; ++k)*/ +- int len = pattern.length(); +- for (int k = len - 8; k < len; ++k) +- current = (current * HASH_P + pattern[k].unicode()) % HASH_Q; +- +- // insert computed hash value into HashMap +- QHash<int, QVector<int> >::iterator it = stringFiltersHash.find(current + 1); +- if (it == stringFiltersHash.end()) { +- QVector<int> list; +- list.append(ind); +- stringFiltersHash.insert(current + 1, list); +- fastLookUp.setBit(current); +- } else { +- it->append(ind); +- } +- } +- } +- +- +- // check if string match at least one string from matching set +- bool isMatched(const QString& str, QString *by = 0) const +- { +- // check short strings first +- for (int i = 0; i < shortStringFilters.size(); ++i) { +- if (str.contains(shortStringFilters[i])) +- { +- if (by != 0) *by = shortStringFilters[i]; +- return true; +- } +- } +- +- int len = str.length(); +- int k; +- +- int current = 0; +- int next = 0; +- // compute hash for first 8 characters +- for (k = 0; k < 8 && k < len; ++k) +- current = (current * HASH_P + str[k].unicode()) % HASH_Q; +- +- QHash<int, QVector<int> >::const_iterator hashEnd = stringFiltersHash.end(); +- // main Rabin-Karp's algorithm loop +- for (k = 7; k < len; ++k, current = next) { +- // roll the hash if not at the end +- // (calculate hash for the next iteration) +- if (k + 1 < len) +- next = (HASH_P * ((current + HASH_Q - ((HASH_MOD * str[k - 7].unicode()) % HASH_Q)) % HASH_Q) + str[k + 1].unicode()) % HASH_Q; +- +- if (!fastLookUp.testBit(current)) +- continue; +- +- // look-up the hash in the HashMap and check all strings +- QHash<int, QVector<int> >::const_iterator it = stringFiltersHash.find(current + 1); +- +- // check possible strings +- if (it != hashEnd) { +- for (int j = 0; j < it->size(); ++j) { +- int index = it->value(j); +- // check if we got simple string or REs prefix +- if (index >= 0) { +- int flen = stringFilters[index].length(); +- if (k - flen + 1 >= 0 && stringFilters[index] == str.midRef(k - flen + 1 , flen)) +- { +- if (by != 0) *by = stringFilters[index]; +- return true; +- } +- } else { +- index = -index - 1; +- int flen = rePrefixes[index].length(); +- if (k - 8 + flen < len && rePrefixes[index] == str.midRef(k - 7, flen)) +- { +- int remStart = k - 7 + flen; +- QString remainder = QString::fromRawData(str.unicode() + remStart, +- str.length() - remStart); +- if (reFilters[index].exactMatch(remainder)) { +- if (by != 0) *by = rePrefixes[index]+reFilters[index].pattern(); +- return true; +- } +- } +- } +- } +- } +- } +- +- return false; +- } +- +- // add filter to matching set with wildcards (*,?) in it +- void addWildedString(const QString& prefix, const QRegExp& rx) +- { +- rePrefixes.append(prefix); +- reFilters.append(rx); +- int index = -rePrefixes.size(); +- +- int current = 0; +- for (int k = 0; k < 8; ++k) +- current = (current * HASH_P + prefix[k].unicode()) % HASH_Q; +- +- // insert computed hash value into HashMap +- QHash<int, QVector<int> >::iterator it = stringFiltersHash.find(current + 1); +- if (it == stringFiltersHash.end()) { +- QVector<int> list; +- list.append(index); +- stringFiltersHash.insert(current + 1, list); +- fastLookUp.setBit(current); +- } else { +- it->append(index); +- } +- } +- +- void clear() +- { +- stringFilters.clear(); +- shortStringFilters.clear(); +- reFilters.clear(); +- rePrefixes.clear(); +- stringFiltersHash.clear(); +- fastLookUp.resize(HASH_Q); +- fastLookUp.fill(0, 0, HASH_Q); +- } +- +-private: +- QVector<QString> stringFilters; +- QVector<QString> shortStringFilters; +- QVector<QRegExp> reFilters; +- QVector<QString> rePrefixes; +- QBitArray fastLookUp; +- +- QHash<int, QVector<int> > stringFiltersHash; +-}; +- +- +-// We only want a subset of features of wildcards -- just the +-// star, so we escape the rest before passing to QRegExp. +-// The \ is escaped due to a QRegExp bug. +-// ### we really should rather parse it ourselves, in order to +-// handle adblock-special things like | and ^ properly. +-static QRegExp fromAdBlockWildcard(const QString& wcStr) { +- QRegExp rx; +- rx.setPatternSyntax(QRegExp::Wildcard); +- +- QString out; +- for (int p = 0; p < wcStr.length(); ++p) { +- QChar c = wcStr[p]; +- if (c == QLatin1Char('?')) +- out += QLatin1String("[?]"); +- else if (c == QLatin1Char('[')) +- out += QLatin1String("[[]"); +- else if (c == QLatin1Char('\\')) +- out += QLatin1String("[\\]"); +- else +- out += c; +- } +- +- rx.setPattern(out); +- return rx; +-} +- +-FilterSet::FilterSet() +- :stringFiltersMatcher(new StringsMatcher) +-{ +-} +- +-FilterSet::~FilterSet() +-{ +- delete stringFiltersMatcher; +-} +- +-void FilterSet::addFilter(const QString& filterStr) +-{ +- QString filter = filterStr; +- +- /** ignore special lines starting with "[", "!", "&", or "#" or contain "#" (comments or features are not supported by KHTML's AdBlock */ +- QChar firstChar = filter.at(0); +- if (firstChar == QLatin1Char('[') || firstChar == QLatin1Char('!') || firstChar == QLatin1Char('&') || firstChar == QLatin1Char('#') || filter.contains(QLatin1Char('#'))) +- return; +- +- // Strip leading @@ +- int first = 0; +- int last = filter.length() - 1; +- if (filter.startsWith(QLatin1String("@@"))) +- first = 2; +- +- // Strip options, we ignore them for now. +- // TODO: Add support for filters with options. See #310230. +- int dollar = filter.lastIndexOf(QLatin1Char('$')); +- if (dollar != -1) { +- return; +- } +- +- // Perhaps nothing left? +- if (first > last) +- return; +- +- filter = filter.mid(first, last - first + 1); +- +- // Is it a regexp filter? +- if (filter.length()>2 && filter.startsWith(QLatin1Char('/')) && filter.endsWith(QLatin1Char('/'))) +- { +- QString inside = filter.mid(1, filter.length()-2); +- QRegExp rx(inside); +- reFilters.append(rx); +-// qDebug() << "R:" << inside; +- } +- else +- { +- // Nope, a wildcard one. +- // Note: For these, we also need to handle |. +- +- // Strip wildcards at the ends +- first = 0; +- last = filter.length() - 1; +- +- while (first < filter.length() && filter[first] == QLatin1Char('*')) +- ++first; +- +- while (last >= 0 && filter[last] == QLatin1Char('*')) +- --last; +- +- if (first > last) +- filter = QStringLiteral("*"); // erm... Well, they asked for it. +- else +- filter = filter.mid(first, last - first + 1); +- +- // Now, do we still have any wildcard stuff left? +- if (filter.contains(QLatin1String("*"))) +- { +- // check if we can use RK first (and then check full RE for the rest) for better performance +- int aPos = filter.indexOf('*'); +- if (aPos < 0) +- aPos = filter.length(); +- if (aPos > 7) { +- QRegExp rx = fromAdBlockWildcard(filter.mid(aPos) + QLatin1Char('*')); +- // We pad the final r.e. with * so we can check for an exact match +- stringFiltersMatcher->addWildedString(filter.mid(0, aPos), rx); +- } else { +- QRegExp rx = fromAdBlockWildcard(filter); +- reFilters.append(rx); +- } +- } +- else +- { +- // Fast path +- stringFiltersMatcher->addString(filter); +- } +- } +-} +- +-bool FilterSet::isUrlMatched(const QString& url) +-{ +- if (stringFiltersMatcher->isMatched(url)) +- return true; +- +- for (int c = 0; c < reFilters.size(); ++c) +- { +- if (url.contains(reFilters[c])) +- return true; +- } +- +- return false; +-} +- +-QString FilterSet::urlMatchedBy(const QString& url) +-{ +- QString by; +- +- if (stringFiltersMatcher->isMatched(url, &by)) +- return by; +- +- for (int c = 0; c < reFilters.size(); ++c) +- { +- if (url.contains(reFilters[c])) +- { +- by = reFilters[c].pattern(); +- break; +- } +- } +- +- return by; +-} +- +-void FilterSet::clear() +-{ +- reFilters.clear(); +- stringFiltersMatcher->clear(); +-} +- +-// kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on; +diff --git a/webenginepart/src/settings/webengine_filter.h a/webenginepart/src/settings/webengine_filter.h +deleted file mode 100644 +index 2c908a478..000000000 +--- a/webenginepart/src/settings/webengine_filter.h ++++ /dev/null +@@ -1,60 +0,0 @@ +-/* This file is part of the KDE project +- +- Copyright (C) 2005 Ivor Hewitt <ivor@kde.org> +- Copyright (C) 2008 Maksim Orlovich <maksim@kde.org> +- Copyright (C) 2008 Vyacheslav Tokarev <tsjoker@gmail.com> +- +- This library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Library 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 WEBENGNINE_FILTER_P_H +-#define WEBENGNINE_FILTER_P_H +- +-#include <QString> +-#include <QRegExp> +-#include <QVector> +-#include <webenginepart.h> +- +-class StringsMatcher; +- +-namespace KDEPrivate +-{ +-// This represents a set of filters that may match URLs. +-// Currently it supports a subset of AddBlock Plus functionality. +-class FilterSet { +-public: +- FilterSet(); +- ~FilterSet(); +- +- // Parses and registers a filter. This will also strip @@ for exclusion rules, skip comments, etc. +- // The user does have to split black and white lists into separate sets, however +- void addFilter(const QString& filter); +- +- bool isUrlMatched(const QString& url); +- QString urlMatchedBy(const QString& url); +- +- void clear(); +- +-private: +- QVector<QRegExp> reFilters; +- StringsMatcher* stringFiltersMatcher; +-}; +- +-} +- +-#endif // WEBENGINE_FILTER_P_H +- +-// kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on; +diff --git a/webenginepart/src/settings/webenginesettings.cpp a/webenginepart/src/settings/webenginesettings.cpp +deleted file mode 100644 +index d159d29c0..000000000 +--- a/webenginepart/src/settings/webenginesettings.cpp ++++ /dev/null +@@ -1,1276 +0,0 @@ +-/* This file is part of the KDE project +- Copyright (C) 1999 David Faure <faure@kde.org> +- +- This library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Library 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 "webenginesettings.h" +- +-#include "webengine_filter.h" +- +-#include <KConfig> +-#include <KSharedConfig> +-#include <KLocalizedString> +-#include <KConfigGroup> +-#include <KJob> +-#include <KIO/Job> +-#include <KMessageBox> +- +-#include <QtWebEngineWidgets/QWebEngineSettings> +-#include <QFontDatabase> +-#include <QFileInfo> +- +-// browser window color defaults -- Bernd +-#define HTML_DEFAULT_LNK_COLOR Qt::blue +-#define HTML_DEFAULT_TXT_COLOR Qt::black +-#define HTML_DEFAULT_VLNK_COLOR Qt::magenta +-#define HTML_DEFAULT_BASE_COLOR Qt::white +- +-#define HTML_DEFAULT_VIEW_FONT "Sans Serif" +-#define HTML_DEFAULT_VIEW_FIXED_FONT "Monospace" +-#define HTML_DEFAULT_VIEW_SERIF_FONT "Serif" +-#define HTML_DEFAULT_VIEW_SANSSERIF_FONT "Sans Serif" +-#define HTML_DEFAULT_VIEW_CURSIVE_FONT "Sans Serif" +-#define HTML_DEFAULT_VIEW_FANTASY_FONT "Sans Serif" +-#define HTML_DEFAULT_MIN_FONT_SIZE 7 // everything smaller is usually unreadable. +- +-/** +- * @internal +- * Contains all settings which are both available globally and per-domain +- */ +-struct KPerDomainSettings { +- bool m_bEnableJava : 1; +- bool m_bEnableJavaScript : 1; +- bool m_bEnablePlugins : 1; +- // don't forget to maintain the bitfields as the enums grow +- KParts::HtmlSettingsInterface::JSWindowOpenPolicy m_windowOpenPolicy : 2; +- KParts::HtmlSettingsInterface::JSWindowStatusPolicy m_windowStatusPolicy : 1; +- KParts::HtmlSettingsInterface::JSWindowFocusPolicy m_windowFocusPolicy : 1; +- KParts::HtmlSettingsInterface::JSWindowMovePolicy m_windowMovePolicy : 1; +- KParts::HtmlSettingsInterface::JSWindowResizePolicy m_windowResizePolicy : 1; +- +-#ifdef DEBUG_SETTINGS +- void dump(const QString &infix = QString()) const { +- kDebug() << "KPerDomainSettings " << infix << " @" << this << ":"; +- kDebug() << " m_bEnableJava: " << m_bEnableJava; +- kDebug() << " m_bEnableJavaScript: " << m_bEnableJavaScript; +- kDebug() << " m_bEnablePlugins: " << m_bEnablePlugins; +- kDebug() << " m_windowOpenPolicy: " << m_windowOpenPolicy; +- kDebug() << " m_windowStatusPolicy: " << m_windowStatusPolicy; +- kDebug() << " m_windowFocusPolicy: " << m_windowFocusPolicy; +- kDebug() << " m_windowMovePolicy: " << m_windowMovePolicy; +- kDebug() << " m_windowResizePolicy: " << m_windowResizePolicy; +- } +-#endif +-}; +- +-typedef QMap<QString,KPerDomainSettings> PolicyMap; +- +-class WebEngineSettingsData +-{ +-public: +- bool m_bChangeCursor : 1; +- bool m_bOpenMiddleClick : 1; +- bool m_underlineLink : 1; +- bool m_hoverLink : 1; +- bool m_bEnableJavaScriptDebug : 1; +- bool m_bEnableJavaScriptErrorReporting : 1; +- bool enforceCharset : 1; +- bool m_bAutoLoadImages : 1; +- bool m_bUnfinishedImageFrame : 1; +- bool m_formCompletionEnabled : 1; +- bool m_autoDelayedActionsEnabled : 1; +- bool m_jsErrorsEnabled : 1; +- bool m_follow_system_colors : 1; +- bool m_allowTabulation : 1; +- bool m_autoSpellCheck : 1; +- bool m_adFilterEnabled : 1; +- bool m_hideAdsEnabled : 1; +- bool m_jsPopupBlockerPassivePopup : 1; +- bool m_accessKeysEnabled : 1; +- bool m_zoomTextOnly : 1; +- bool m_useCookieJar : 1; +- bool m_bAutoRefreshPage: 1; +- bool m_bEnableFavicon:1; +- bool m_disableInternalPluginHandling:1; +- bool m_offerToSaveWebSitePassword:1; +- bool m_loadPluginsOnDemand:1; +- bool m_enableLocalStorage:1; +- bool m_enableOfflineStorageDb:1; +- bool m_enableOfflineWebAppCache:1; +- bool m_enableWebGL:1; +- bool m_zoomToDPI:1; +- bool m_allowActiveMixedContent:1; +- bool m_allowMixedContentDisplay:1; +- +- // the virtual global "domain" +- KPerDomainSettings global; +- +- int m_fontSize; +- int m_minFontSize; +- int m_maxFormCompletionItems; +- WebEngineSettings::KAnimationAdvice m_showAnimations; +- WebEngineSettings::KSmoothScrollingMode m_smoothScrolling; +- +- QString m_encoding; +- QString m_userSheet; +- +- QColor m_textColor; +- QColor m_baseColor; +- QColor m_linkColor; +- QColor m_vLinkColor; +- +- PolicyMap domainPolicy; +- QStringList fonts; +- QStringList defaultFonts; +- +- KDEPrivate::FilterSet adBlackList; +- KDEPrivate::FilterSet adWhiteList; +- QList< QPair< QString, QChar > > m_fallbackAccessKeysAssignments; +- +- KSharedConfig::Ptr nonPasswordStorableSites; +-}; +- +-class WebEngineSettingsPrivate : public QObject, public WebEngineSettingsData +-{ +- Q_OBJECT +-public: +- void adblockFilterLoadList(const QString& filename) +- { +- /** load list file and process each line */ +- QFile file(filename); +- if (file.open(QIODevice::ReadOnly)) { +- QTextStream ts(&file); +- QString line = ts.readLine(); +- while (!line.isEmpty()) { +- //kDebug() << "Adding filter:" << line; +- /** white list lines start with "@@" */ +- if (line.startsWith(QLatin1String("@@"))) +- adWhiteList.addFilter(line); +- else +- adBlackList.addFilter(line); +- line = ts.readLine(); +- } +- file.close(); +- } +- } +- +-public Q_SLOTS: +- void adblockFilterResult(KJob *job) +- { +- KIO::StoredTransferJob *tJob = qobject_cast<KIO::StoredTransferJob*>(job); +- Q_ASSERT(tJob); +- +- if ( job->error() == KJob::NoError ) +- { +- const QByteArray byteArray = tJob->data(); +- const QString localFileName = tJob->property( "webenginesettings_adBlock_filename" ).toString(); +- +- QFile file(localFileName); +- if ( file.open(QFile::WriteOnly) ) +- { +- const bool success = (file.write(byteArray) == byteArray.size()); +- if ( success ) +- adblockFilterLoadList(localFileName); +- else +- qWarning() << "Could not write" << byteArray.size() << "to file" << localFileName; +- file.close(); +- } +- else +- qDebug() << "Cannot open file" << localFileName << "for filter list"; +- } +- else +- qDebug() << "Downloading" << tJob->url() << "failed with message:" << job->errorText(); +- } +-}; +- +- +-/** Returns a writeable per-domains settings instance for the given domain +- * or a deep copy of the global settings if not existent. +- */ +-static KPerDomainSettings &setup_per_domain_policy(WebEngineSettingsPrivate* const d, const QString &domain) +-{ +- if (domain.isEmpty()) +- qWarning() << "setup_per_domain_policy: domain is empty"; +- +- const QString ldomain = domain.toLower(); +- PolicyMap::iterator it = d->domainPolicy.find(ldomain); +- if (it == d->domainPolicy.end()) { +- // simply copy global domain settings (they should have been initialized +- // by this time) +- it = d->domainPolicy.insert(ldomain,d->global); +- } +- return *it; +-} +- +-template<typename T> +-static T readEntry(const KConfigGroup& config, const QString& key, int defaultValue) +-{ +- return static_cast<T>(config.readEntry(key, defaultValue)); +-} +- +-void WebEngineSettings::readDomainSettings(const KConfigGroup &config, bool reset, +- bool global, KPerDomainSettings &pd_settings) +-{ +- const QString javaPrefix ((global ? QString() : QStringLiteral("java."))); +- const QString jsPrefix ((global ? QString() : QStringLiteral("javascript."))); +- const QString pluginsPrefix (global ? QString() : QStringLiteral("plugins.")); +- +- // The setting for Java +- QString key = javaPrefix + QLatin1String("EnableJava"); +- if ( (global && reset) || config.hasKey( key ) ) +- pd_settings.m_bEnableJava = config.readEntry( key, false ); +- else if ( !global ) +- pd_settings.m_bEnableJava = d->global.m_bEnableJava; +- +- // The setting for Plugins +- key = pluginsPrefix + QLatin1String("EnablePlugins"); +- if ( (global && reset) || config.hasKey( key ) ) +- pd_settings.m_bEnablePlugins = config.readEntry( key, true ); +- else if ( !global ) +- pd_settings.m_bEnablePlugins = d->global.m_bEnablePlugins; +- +- // The setting for JavaScript +- key = jsPrefix + QLatin1String("EnableJavaScript"); +- if ( (global && reset) || config.hasKey( key ) ) +- pd_settings.m_bEnableJavaScript = config.readEntry( key, true ); +- else if ( !global ) +- pd_settings.m_bEnableJavaScript = d->global.m_bEnableJavaScript; +- +- // window property policies +- key = jsPrefix + QLatin1String("WindowOpenPolicy"); +- if ( (global && reset) || config.hasKey( key ) ) +- pd_settings.m_windowOpenPolicy = readEntry<KParts::HtmlSettingsInterface::JSWindowOpenPolicy>(config, key, KParts::HtmlSettingsInterface::JSWindowOpenSmart); +- else if ( !global ) +- pd_settings.m_windowOpenPolicy = d->global.m_windowOpenPolicy; +- +- key = jsPrefix + QLatin1String("WindowMovePolicy"); +- if ( (global && reset) || config.hasKey( key ) ) +- pd_settings.m_windowMovePolicy = readEntry<KParts::HtmlSettingsInterface::JSWindowMovePolicy>(config, key, KParts::HtmlSettingsInterface::JSWindowMoveAllow); +- else if ( !global ) +- pd_settings.m_windowMovePolicy = d->global.m_windowMovePolicy; +- +- key = jsPrefix + QLatin1String("WindowResizePolicy"); +- if ( (global && reset) || config.hasKey( key ) ) +- pd_settings.m_windowResizePolicy = readEntry<KParts::HtmlSettingsInterface::JSWindowResizePolicy>(config, key, KParts::HtmlSettingsInterface::JSWindowResizeAllow); +- else if ( !global ) +- pd_settings.m_windowResizePolicy = d->global.m_windowResizePolicy; +- +- key = jsPrefix + QLatin1String("WindowStatusPolicy"); +- if ( (global && reset) || config.hasKey( key ) ) +- pd_settings.m_windowStatusPolicy = readEntry<KParts::HtmlSettingsInterface::JSWindowStatusPolicy>(config, key, KParts::HtmlSettingsInterface::JSWindowStatusAllow); +- else if ( !global ) +- pd_settings.m_windowStatusPolicy = d->global.m_windowStatusPolicy; +- +- key = jsPrefix + QLatin1String("WindowFocusPolicy"); +- if ( (global && reset) || config.hasKey( key ) ) +- pd_settings.m_windowFocusPolicy = readEntry<KParts::HtmlSettingsInterface::JSWindowFocusPolicy>(config, key, KParts::HtmlSettingsInterface::JSWindowFocusAllow); +- else if ( !global ) +- pd_settings.m_windowFocusPolicy = d->global.m_windowFocusPolicy; +-} +- +- +-WebEngineSettings::WebEngineSettings() +- :d (new WebEngineSettingsPrivate) +-{ +- init(); +-} +- +-WebEngineSettings::~WebEngineSettings() +-{ +- delete d; +-} +- +-bool WebEngineSettings::changeCursor() const +-{ +- return d->m_bChangeCursor; +-} +- +-bool WebEngineSettings::underlineLink() const +-{ +- return d->m_underlineLink; +-} +- +-bool WebEngineSettings::hoverLink() const +-{ +- return d->m_hoverLink; +-} +- +-void WebEngineSettings::init() +-{ +- initWebEngineSettings(); +- +- KConfig global( QStringLiteral("khtmlrc"), KConfig::NoGlobals ); +- init( &global, true ); +- +- KSharedConfig::Ptr local = KSharedConfig::openConfig(); +- if ( local ) { +- init( local.data(), false ); +- } +- +- initNSPluginSettings(); +- initCookieJarSettings(); +-} +- +-void WebEngineSettings::init( KConfig * config, bool reset ) +-{ +- KConfigGroup cg( config, "MainView Settings" ); +- if (reset || cg.exists() ) +- { +- if ( reset || cg.hasKey( "OpenMiddleClick" ) ) +- d->m_bOpenMiddleClick = cg.readEntry( "OpenMiddleClick", true ); +- } +- +- KConfigGroup cgAccess(config,"Access Keys" ); +- if (reset || cgAccess.exists() ) { +- d->m_accessKeysEnabled = cgAccess.readEntry( "Enabled", true ); +- } +- +- KConfigGroup cgFilter( config, "Filter Settings" ); +- +- if ((reset || cgFilter.exists()) && (d->m_adFilterEnabled = cgFilter.readEntry("Enabled", false))) +- { +- d->m_hideAdsEnabled = cgFilter.readEntry("Shrink", false); +- +- d->adBlackList.clear(); +- d->adWhiteList.clear(); +- +- /** read maximum age for filter list files, minimum is one day */ +- int htmlFilterListMaxAgeDays = cgFilter.readEntry(QStringLiteral("HTMLFilterListMaxAgeDays")).toInt(); +- if (htmlFilterListMaxAgeDays < 1) +- htmlFilterListMaxAgeDays = 1; +- +- QMapIterator<QString,QString> it (cgFilter.entryMap()); +- while (it.hasNext()) +- { +- it.next(); +- int id = -1; +- const QString name = it.key(); +- const QString url = it.value(); +- +- if (name.startsWith(QLatin1String("Filter"))) +- { +- if (url.startsWith(QLatin1String("@@"))) +- d->adWhiteList.addFilter(url); +- else +- d->adBlackList.addFilter(url); +- } +- else if (name.startsWith(QLatin1String("HTMLFilterListName-")) && (id = name.midRef(19).toInt()) > 0) +- { +- /** check if entry is enabled */ +- bool filterEnabled = cgFilter.readEntry(QStringLiteral("HTMLFilterListEnabled-").append(QString::number(id))) != QLatin1String("false"); +- +- /** get url for HTMLFilterList */ +- QUrl url(cgFilter.readEntry(QStringLiteral("HTMLFilterListURL-").append(QString::number(id)))); +- +- if (filterEnabled && url.isValid()) { +- /** determine where to cache HTMLFilterList file */ +- QString localFile = cgFilter.readEntry(QStringLiteral("HTMLFilterListLocalFilename-").append(QString::number(id))); +- localFile = QStandardPaths::locate(QStandardPaths::ConfigLocation, "khtml/" + localFile); +- +- /** determine existence and age of cache file */ +- QFileInfo fileInfo(localFile); +- +- /** load cached file if it exists, irrespective of age */ +- if (fileInfo.exists()) +- d->adblockFilterLoadList( localFile ); +- +- /** if no cache list file exists or if it is too old ... */ +- if (!fileInfo.exists() || fileInfo.lastModified().daysTo(QDateTime::currentDateTime()) > htmlFilterListMaxAgeDays) +- { +- /** ... in this case, refetch list asynchronously */ +- // kDebug() << "Fetching filter list from" << url << "to" << localFile; +- KIO::StoredTransferJob *job = KIO::storedGet( url, KIO::Reload, KIO::HideProgressInfo ); +- QObject::connect( job, SIGNAL(result(KJob*)), d, SLOT(adblockFilterResult(KJob*)) ); +- /** for later reference, store name of cache file */ +- job->setProperty("webenginesettings_adBlock_filename", localFile); +- } +- } +- } +- } +- } +- +- KConfigGroup cgHtml( config, "HTML Settings" ); +- if (reset || cgHtml.exists() ) +- { +- // Fonts and colors +- if( reset ) { +- d->defaultFonts = QStringList(); +- d->defaultFonts.append( cgHtml.readEntry( "StandardFont", QFontDatabase::systemFont(QFontDatabase::GeneralFont).family() ) ); +- d->defaultFonts.append( cgHtml.readEntry( "FixedFont", QFontDatabase::systemFont(QFontDatabase::FixedFont).family() )); +- d->defaultFonts.append( cgHtml.readEntry( "SerifFont", HTML_DEFAULT_VIEW_SERIF_FONT ) ); +- d->defaultFonts.append( cgHtml.readEntry( "SansSerifFont", HTML_DEFAULT_VIEW_SANSSERIF_FONT ) ); +- d->defaultFonts.append( cgHtml.readEntry( "CursiveFont", HTML_DEFAULT_VIEW_CURSIVE_FONT ) ); +- d->defaultFonts.append( cgHtml.readEntry( "FantasyFont", HTML_DEFAULT_VIEW_FANTASY_FONT ) ); +- d->defaultFonts.append( QStringLiteral( "0" ) ); // font size adjustment +- } +- +- if ( reset || cgHtml.hasKey( "MinimumFontSize" ) ) +- d->m_minFontSize = cgHtml.readEntry( "MinimumFontSize", HTML_DEFAULT_MIN_FONT_SIZE ); +- +- if ( reset || cgHtml.hasKey( "MediumFontSize" ) ) +- d->m_fontSize = cgHtml.readEntry( "MediumFontSize", 12 ); +- +- d->fonts = cgHtml.readEntry( "Fonts", QStringList() ); +- +- if ( reset || cgHtml.hasKey( "DefaultEncoding" ) ) +- d->m_encoding = cgHtml.readEntry( "DefaultEncoding", "" ); +- +- if ( reset || cgHtml.hasKey( "EnforceDefaultCharset" ) ) +- d->enforceCharset = cgHtml.readEntry( "EnforceDefaultCharset", false ); +- +- // Behavior +- +- if ( reset || cgHtml.hasKey("UnderlineLinks") ) +- d->m_underlineLink = cgHtml.readEntry( "UnderlineLinks", true ); +- +- if ( reset || cgHtml.hasKey( "HoverLinks" ) ) +- { +- if ( (d->m_hoverLink = cgHtml.readEntry( "HoverLinks", false ))) +- d->m_underlineLink = false; +- } +- +- if ( reset || cgHtml.hasKey( "AllowTabulation" ) ) +- d->m_allowTabulation = cgHtml.readEntry( "AllowTabulation", false ); +- +- if ( reset || cgHtml.hasKey( "AutoSpellCheck" ) ) +- d->m_autoSpellCheck = cgHtml.readEntry( "AutoSpellCheck", true ); +- +- // Other +- if ( reset || cgHtml.hasKey( "AutoLoadImages" ) ) +- d->m_bAutoLoadImages = cgHtml.readEntry( "AutoLoadImages", true ); +- +- if ( reset || cgHtml.hasKey( "AutoDelayedActions" ) ) +- d->m_bAutoRefreshPage = cgHtml.readEntry( "AutoDelayedActions", true ); +- +- if ( reset || cgHtml.hasKey( "UnfinishedImageFrame" ) ) +- d->m_bUnfinishedImageFrame = cgHtml.readEntry( "UnfinishedImageFrame", true ); +- +- if ( reset || cgHtml.hasKey( "ShowAnimations" ) ) +- { +- QString value = cgHtml.readEntry( "ShowAnimations").toLower(); +- if (value == QLatin1String("disabled")) +- d->m_showAnimations = KAnimationDisabled; +- else if (value == QLatin1String("looponce")) +- d->m_showAnimations = KAnimationLoopOnce; +- else +- d->m_showAnimations = KAnimationEnabled; +- } +- +- if ( reset || cgHtml.hasKey( "SmoothScrolling" ) ) +- { +- QString value = cgHtml.readEntry( "SmoothScrolling", "whenefficient" ).toLower(); +- if (value == QLatin1String("disabled")) +- d->m_smoothScrolling = KSmoothScrollingDisabled; +- else if (value == QLatin1String("whenefficient")) +- d->m_smoothScrolling = KSmoothScrollingWhenEfficient; +- else +- d->m_smoothScrolling = KSmoothScrollingEnabled; +- } +- +- if ( reset || cgHtml.hasKey( "ZoomTextOnly" ) ) { +- d->m_zoomTextOnly = cgHtml.readEntry( "ZoomTextOnly", false ); +- } +- +- if ( reset || cgHtml.hasKey( "ZoomToDPI" ) ) { +- d->m_zoomToDPI = cgHtml.readEntry( "ZoomToDPI", false ); +- } +- +- if (cgHtml.readEntry("UserStyleSheetEnabled", false)) { +- if (reset || cgHtml.hasKey("UserStyleSheet")) +- d->m_userSheet = cgHtml.readEntry("UserStyleSheet", QString()); +- } else { +- d->m_userSheet.clear(); +- } +- +- d->m_formCompletionEnabled = cgHtml.readEntry("FormCompletion", true); +- d->m_maxFormCompletionItems = cgHtml.readEntry("MaxFormCompletionItems", 10); +- d->m_autoDelayedActionsEnabled = cgHtml.readEntry ("AutoDelayedActions", true); +- d->m_jsErrorsEnabled = cgHtml.readEntry("ReportJSErrors", true); +- const QStringList accesskeys = cgHtml.readEntry("FallbackAccessKeysAssignments", QStringList()); +- d->m_fallbackAccessKeysAssignments.clear(); +- for( QStringList::ConstIterator it = accesskeys.begin(); it != accesskeys.end(); ++it ) +- if( (*it).length() > 2 && (*it)[ 1 ] == ':' ) +- d->m_fallbackAccessKeysAssignments.append( qMakePair( (*it).mid( 2 ), (*it)[ 0 ] )); +- +- d->m_bEnableFavicon = cgHtml.readEntry("EnableFavicon", true); +- d->m_offerToSaveWebSitePassword = cgHtml.readEntry("OfferToSaveWebsitePassword", true); +- } +- +- // Colors +- //In which group ????? +- if ( reset || cg.hasKey( "FollowSystemColors" ) ) +- d->m_follow_system_colors = cg.readEntry( "FollowSystemColors", false ); +- +- KConfigGroup cgGeneral( config, "General" ); +- if ( reset || cgGeneral.exists( ) ) +- { +- if ( reset || cgGeneral.hasKey( "foreground" ) ) { +- QColor def(HTML_DEFAULT_TXT_COLOR); +- d->m_textColor = cgGeneral.readEntry( "foreground", def ); +- } +- +- if ( reset || cgGeneral.hasKey( "linkColor" ) ) { +- QColor def(HTML_DEFAULT_LNK_COLOR); +- d->m_linkColor = cgGeneral.readEntry( "linkColor", def ); +- } +- +- if ( reset || cgGeneral.hasKey( "visitedLinkColor" ) ) { +- QColor def(HTML_DEFAULT_VLNK_COLOR); +- d->m_vLinkColor = cgGeneral.readEntry( "visitedLinkColor", def); +- } +- +- if ( reset || cgGeneral.hasKey( "background" ) ) { +- QColor def(HTML_DEFAULT_BASE_COLOR); +- d->m_baseColor = cgGeneral.readEntry( "background", def); +- } +- } +- +- KConfigGroup cgJava( config, "Java/JavaScript Settings" ); +- if( reset || cgJava.exists() ) +- { +- // The global setting for JavaScript debugging +- // This is currently always enabled by default +- if ( reset || cgJava.hasKey( "EnableJavaScriptDebug" ) ) +- d->m_bEnableJavaScriptDebug = cgJava.readEntry( "EnableJavaScriptDebug", false ); +- +- // The global setting for JavaScript error reporting +- if ( reset || cgJava.hasKey( "ReportJavaScriptErrors" ) ) +- d->m_bEnableJavaScriptErrorReporting = cgJava.readEntry( "ReportJavaScriptErrors", false ); +- +- // The global setting for popup block passive popup +- if ( reset || cgJava.hasKey( "PopupBlockerPassivePopup" ) ) +- d->m_jsPopupBlockerPassivePopup = cgJava.readEntry("PopupBlockerPassivePopup", true ); +- +- // Read options from the global "domain" +- readDomainSettings(cgJava,reset,true,d->global); +-#ifdef DEBUG_SETTINGS +- d->global.dump("init global"); +-#endif +- +- // The domain-specific settings. +- +- static const char *const domain_keys[] = { // always keep order of keys +- "ECMADomains", "JavaDomains", "PluginDomains" +- }; +- bool check_old_ecma_settings = true; +- bool check_old_java_settings = true; +- // merge all domains into one list +- QSet<QString> domainList; +- for (unsigned i = 0; i < sizeof domain_keys/sizeof domain_keys[0]; ++i) { +- if (reset || cgJava.hasKey(domain_keys[i])) { +- if (i == 0) check_old_ecma_settings = false; +- else if (i == 1) check_old_java_settings = false; +- const QStringList dl = cgJava.readEntry( domain_keys[i], QStringList() ); +- const QSet<QString>::Iterator notfound = domainList.end(); +- QStringList::ConstIterator it = dl.begin(); +- const QStringList::ConstIterator itEnd = dl.end(); +- for (; it != itEnd; ++it) { +- const QString domain = (*it).toLower(); +- QSet<QString>::Iterator pos = domainList.find(domain); +- if (pos == notfound) domainList.insert(domain); +- }/*next it*/ +- } +- }/*next i*/ +- +- if (reset) +- d->domainPolicy.clear(); +- +- { +- QSet<QString>::ConstIterator it = domainList.constBegin(); +- const QSet<QString>::ConstIterator itEnd = domainList.constEnd(); +- for ( ; it != itEnd; ++it) +- { +- const QString domain = *it; +- KConfigGroup cg( config, domain ); +- readDomainSettings(cg,reset,false,d->domainPolicy[domain]); +-#ifdef DEBUG_SETTINGS +- d->domainPolicy[domain].dump("init "+domain); +-#endif +- } +- } +- +- bool check_old_java = true; +- if( (reset || cgJava.hasKey("JavaDomainSettings")) && check_old_java_settings) +- { +- check_old_java = false; +- const QStringList domainList = cgJava.readEntry( "JavaDomainSettings", QStringList() ); +- QStringList::ConstIterator it = domainList.constBegin(); +- const QStringList::ConstIterator itEnd = domainList.constEnd(); +- for ( ; it != itEnd; ++it) +- { +- QString domain; +- KParts::HtmlSettingsInterface::JavaScriptAdvice javaAdvice; +- KParts::HtmlSettingsInterface::JavaScriptAdvice javaScriptAdvice; +- KParts::HtmlSettingsInterface::splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice); +- setup_per_domain_policy(d,domain).m_bEnableJava = javaAdvice == KParts::HtmlSettingsInterface::JavaScriptAccept; +-#ifdef DEBUG_SETTINGS +- setup_per_domain_policy(d,domain).dump("JavaDomainSettings 4 "+domain); +-#endif +- } +- } +- +- bool check_old_ecma = true; +- if( ( reset || cgJava.hasKey( "ECMADomainSettings" ) ) && check_old_ecma_settings ) +- { +- check_old_ecma = false; +- const QStringList domainList = cgJava.readEntry( "ECMADomainSettings", QStringList() ); +- QStringList::ConstIterator it = domainList.constBegin(); +- const QStringList::ConstIterator itEnd = domainList.constEnd(); +- for ( ; it != itEnd; ++it) +- { +- QString domain; +- KParts::HtmlSettingsInterface::JavaScriptAdvice javaAdvice; +- KParts::HtmlSettingsInterface::JavaScriptAdvice javaScriptAdvice; +- KParts::HtmlSettingsInterface::splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice); +- setup_per_domain_policy(d,domain).m_bEnableJavaScript = javaScriptAdvice == KParts::HtmlSettingsInterface::JavaScriptAccept; +-#ifdef DEBUG_SETTINGS +- setup_per_domain_policy(d,domain).dump("ECMADomainSettings 4 "+domain); +-#endif +- } +- } +- +- if( ( reset || cgJava.hasKey( "JavaScriptDomainAdvice" ) ) +- && ( check_old_java || check_old_ecma ) +- && ( check_old_ecma_settings || check_old_java_settings ) ) +- { +- const QStringList domainList = cgJava.readEntry( "JavaScriptDomainAdvice", QStringList() ); +- QStringList::ConstIterator it = domainList.constBegin(); +- const QStringList::ConstIterator itEnd = domainList.constEnd(); +- for ( ; it != itEnd; ++it) +- { +- QString domain; +- KParts::HtmlSettingsInterface::JavaScriptAdvice javaAdvice; +- KParts::HtmlSettingsInterface::JavaScriptAdvice javaScriptAdvice; +- KParts::HtmlSettingsInterface::splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice); +- if( check_old_java ) +- setup_per_domain_policy(d,domain).m_bEnableJava = javaAdvice == KParts::HtmlSettingsInterface::JavaScriptAccept; +- if( check_old_ecma ) +- setup_per_domain_policy(d,domain).m_bEnableJavaScript = javaScriptAdvice == KParts::HtmlSettingsInterface::JavaScriptAccept; +-#ifdef DEBUG_SETTINGS +- setup_per_domain_policy(d,domain).dump("JavaScriptDomainAdvice 4 "+domain); +-#endif +- } +- } +- } +- +-#if 0 +- // DNS Prefect support... +- if ( reset || cgHtml.hasKey( "DNSPrefetch" ) ) +- { +- // Enabled, Disabled, OnlyWWWAndSLD +- QString value = cgHtml.readEntry( "DNSPrefetch", "Enabled" ).toLower(); +- +- if (value == "enabled") +- QWebEngineSettings::globalSettings()->setAttribute(QWebEngineSettings::DnsPrefetchEnabled, true); +- else +- QWebEngineSettings::globalSettings()->setAttribute(QWebEngineSettings::DnsPrefetchEnabled, false); +- } +- +- // Sync with QWebEngineSettings. +- if (!d->m_encoding.isEmpty()) +- QWebEngineSettings::globalSettings()->setDefaultTextEncoding(d->m_encoding); +- QWebEngineSettings::globalSettings()->setUserStyleSheetUrl(QUrl::fromUserInput(userStyleSheet())); +-#endif +- +- QWebEngineSettings::globalSettings()->setAttribute(QWebEngineSettings::AutoLoadImages, autoLoadImages()); +- QWebEngineSettings::globalSettings()->setAttribute(QWebEngineSettings::JavascriptEnabled, isJavaScriptEnabled()); +- // QWebEngineSettings::globalSettings()->setAttribute(QWebEngineSettings::JavaEnabled, isJavaEnabled()); +- QWebEngineSettings::globalSettings()->setAttribute(QWebEngineSettings::PluginsEnabled, isPluginsEnabled()); +- +- // By default disable JS window.open when policy is deny or smart. +- const KParts::HtmlSettingsInterface::JSWindowOpenPolicy policy = windowOpenPolicy(); +- if (policy == KParts::HtmlSettingsInterface::JSWindowOpenDeny || policy == KParts::HtmlSettingsInterface::JSWindowOpenSmart) +- QWebEngineSettings::globalSettings()->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, false); +- else +- QWebEngineSettings::globalSettings()->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, true); +- +-// QWebEngineSettings::globalSettings()->setAttribute(QWebEngineSettings::ZoomTextOnly, zoomTextOnly()); +-// QWebEngineSettings::globalSettings()->setAttribute(QWebEngineSettings::DeveloperExtrasEnabled, isJavaScriptDebugEnabled()); +- QWebEngineSettings::globalSettings()->setFontFamily(QWebEngineSettings::StandardFont, stdFontName()); +- QWebEngineSettings::globalSettings()->setFontFamily(QWebEngineSettings::FixedFont, fixedFontName()); +- QWebEngineSettings::globalSettings()->setFontFamily(QWebEngineSettings::SerifFont, serifFontName()); +- QWebEngineSettings::globalSettings()->setFontFamily(QWebEngineSettings::SansSerifFont, sansSerifFontName()); +- QWebEngineSettings::globalSettings()->setFontFamily(QWebEngineSettings::CursiveFont, cursiveFontName()); +- QWebEngineSettings::globalSettings()->setFontFamily(QWebEngineSettings::FantasyFont, fantasyFontName()); +- +- // TODO: Create a webengine config module that gets embeded into Konqueror's kcm. +- // Turn on WebGL support +-// QWebEngineSettings::globalSettings()->setAttribute(QWebEngineSettings::WebGLEnabled, d->m_enableWebGL); +- // Turn on HTML 5 local and offline storage capabilities... +-// QWebEngineSettings::globalSettings()->setAttribute(QWebEngineSettings::OfflineStorageDatabaseEnabled, d->m_enableOfflineStorageDb); +-// QWebEngineSettings::globalSettings()->setAttribute(QWebEngineSettings::OfflineWebApplicationCacheEnabled, d->m_enableOfflineWebAppCache); +- QWebEngineSettings::globalSettings()->setAttribute(QWebEngineSettings::LocalStorageEnabled, d->m_enableLocalStorage); +- +- QWebEngineSettings::globalSettings()->setAttribute(QWebEngineSettings::ScrollAnimatorEnabled, smoothScrolling() != KSmoothScrollingDisabled); +- +- // These numbers should be calculated from real "logical" DPI/72, using a default dpi of 96 for now +- computeFontSizes(96); +-} +- +- +-void WebEngineSettings::computeFontSizes( int logicalDpi ) +-{ +- if (zoomToDPI()) +- logicalDpi = 96; +- +- float toPix = logicalDpi/72.0; +- +- if (toPix < 96.0/72.0) +- toPix = 96.0/72.0; +- +- QWebEngineSettings::globalSettings()->setFontSize(QWebEngineSettings::MinimumFontSize, qRound(minFontSize() * toPix)); +- QWebEngineSettings::globalSettings()->setFontSize(QWebEngineSettings::DefaultFontSize, qRound(mediumFontSize() * toPix)); +-} +- +-bool WebEngineSettings::zoomToDPI() const +-{ +- return d->m_zoomToDPI; +-} +- +-void WebEngineSettings::setZoomToDPI(bool enabled) +-{ +- d->m_zoomToDPI = enabled; +- // save it +- KConfigGroup cg( KSharedConfig::openConfig(), "HTML Settings"); +- cg.writeEntry("ZoomToDPI", enabled); +- cg.sync(); +-} +- +-/** Local helper for retrieving per-domain settings. +- * +- * In case of doubt, the global domain is returned. +- */ +-static const KPerDomainSettings& lookup_hostname_policy(const WebEngineSettingsPrivate* const d, +- const QString& hostname) +-{ +-#ifdef DEBUG_SETTINGS +- kDebug() << "lookup_hostname_policy(" << hostname << ")"; +-#endif +- if (hostname.isEmpty()) { +-#ifdef DEBUG_SETTINGS +- d->global.dump("global"); +-#endif +- return d->global; +- } +- +- const PolicyMap::const_iterator notfound = d->domainPolicy.constEnd(); +- +- // First check whether there is a perfect match. +- PolicyMap::const_iterator it = d->domainPolicy.find(hostname); +- if( it != notfound ) { +-#ifdef DEBUG_SETTINGS +- kDebug() << "perfect match"; +- (*it).dump(hostname); +-#endif +- // yes, use it (unless dunno) +- return *it; +- } +- +- // Now, check for partial match. Chop host from the left until +- // there's no dots left. +- QString host_part = hostname; +- int dot_idx = -1; +- while( (dot_idx = host_part.indexOf(QChar('.'))) >= 0 ) { +- host_part.remove(0,dot_idx); +- it = d->domainPolicy.find(host_part); +- Q_ASSERT(notfound == d->domainPolicy.end()); +- if( it != notfound ) { +-#ifdef DEBUG_SETTINGS +- kDebug() << "partial match"; +- (*it).dump(host_part); +-#endif +- return *it; +- } +- // assert(host_part[0] == QChar('.')); +- host_part.remove(0,1); // Chop off the dot. +- } +- +- // No domain-specific entry: use global domain +-#ifdef DEBUG_SETTINGS +- kDebug() << "no match"; +- d->global.dump("global"); +-#endif +- return d->global; +-} +- +-bool WebEngineSettings::isOpenMiddleClickEnabled() +-{ +- return d->m_bOpenMiddleClick; +-} +- +-bool WebEngineSettings::accessKeysEnabled() const +-{ +- return d->m_accessKeysEnabled; +-} +- +-bool WebEngineSettings::favIconsEnabled() const +-{ +- return d->m_bEnableFavicon; +-} +- +-bool WebEngineSettings::isAdFilterEnabled() const +-{ +- return d->m_adFilterEnabled; +-} +- +-bool WebEngineSettings::isHideAdsEnabled() const +-{ +- return d->m_hideAdsEnabled; +-} +- +-bool WebEngineSettings::isAdFiltered( const QString &url ) const +-{ +- if (!d->m_adFilterEnabled) +- return false; +- +- if (url.startsWith(QLatin1String("data:"))) +- return false; +- +- return d->adBlackList.isUrlMatched(url) && !d->adWhiteList.isUrlMatched(url); +-} +- +-QString WebEngineSettings::adFilteredBy( const QString &url, bool *isWhiteListed ) const +-{ +- QString m = d->adWhiteList.urlMatchedBy(url); +- +- if (!m.isEmpty()) { +- if (isWhiteListed != 0) +- *isWhiteListed = true; +- return m; +- } +- +- m = d->adBlackList.urlMatchedBy(url); +- if (m.isEmpty()) +- return QString(); +- +- if (isWhiteListed != 0) +- *isWhiteListed = false; +- return m; +-} +- +-void WebEngineSettings::addAdFilter( const QString &url ) +-{ +- KConfigGroup config = KSharedConfig::openConfig( QStringLiteral("khtmlrc"), KConfig::NoGlobals )->group( "Filter Settings" ); +- +- QRegExp rx; +- +- // Try compiling to avoid invalid stuff. Only support the basic syntax here... +- // ### refactor somewhat +- if (url.length()>2 && url[0]=='/' && url[url.length()-1] == '/') +- { +- const QString inside = url.mid(1, url.length()-2); +- rx.setPattern(inside); +- } +- else +- { +- rx.setPatternSyntax(QRegExp::Wildcard); +- rx.setPattern(url); +- } +- +- if (rx.isValid()) +- { +- int last=config.readEntry("Count", 0); +- const QString key = "Filter-" + QString::number(last); +- config.writeEntry(key, url); +- config.writeEntry("Count",last+1); +- config.sync(); +- +- if (url.startsWith(QLatin1String("@@"))) +- d->adWhiteList.addFilter(url); +- else +- d->adBlackList.addFilter(url); +- } +- else +- { +- KMessageBox::error(0, +- rx.errorString(), +- i18n("Filter error")); +- } +-} +- +-bool WebEngineSettings::isJavaEnabled( const QString& hostname ) const +-{ +- return lookup_hostname_policy(d,hostname.toLower()).m_bEnableJava; +-} +- +-bool WebEngineSettings::isJavaScriptEnabled( const QString& hostname ) const +-{ +- return lookup_hostname_policy(d,hostname.toLower()).m_bEnableJavaScript; +-} +- +-bool WebEngineSettings::isJavaScriptDebugEnabled( const QString& /*hostname*/ ) const +-{ +- // debug setting is global for now, but could change in the future +- return d->m_bEnableJavaScriptDebug; +-} +- +-bool WebEngineSettings::isJavaScriptErrorReportingEnabled( const QString& /*hostname*/ ) const +-{ +- // error reporting setting is global for now, but could change in the future +- return d->m_bEnableJavaScriptErrorReporting; +-} +- +-bool WebEngineSettings::isPluginsEnabled( const QString& hostname ) const +-{ +- return lookup_hostname_policy(d,hostname.toLower()).m_bEnablePlugins; +-} +- +-KParts::HtmlSettingsInterface::JSWindowOpenPolicy WebEngineSettings::windowOpenPolicy(const QString& hostname) const { +- return lookup_hostname_policy(d,hostname.toLower()).m_windowOpenPolicy; +-} +- +-KParts::HtmlSettingsInterface::JSWindowMovePolicy WebEngineSettings::windowMovePolicy(const QString& hostname) const { +- return lookup_hostname_policy(d,hostname.toLower()).m_windowMovePolicy; +-} +- +-KParts::HtmlSettingsInterface::JSWindowResizePolicy WebEngineSettings::windowResizePolicy(const QString& hostname) const { +- return lookup_hostname_policy(d,hostname.toLower()).m_windowResizePolicy; +-} +- +-KParts::HtmlSettingsInterface::JSWindowStatusPolicy WebEngineSettings::windowStatusPolicy(const QString& hostname) const { +- return lookup_hostname_policy(d,hostname.toLower()).m_windowStatusPolicy; +-} +- +-KParts::HtmlSettingsInterface::JSWindowFocusPolicy WebEngineSettings::windowFocusPolicy(const QString& hostname) const { +- return lookup_hostname_policy(d,hostname.toLower()).m_windowFocusPolicy; +-} +- +-int WebEngineSettings::mediumFontSize() const +-{ +- return d->m_fontSize; +-} +- +-int WebEngineSettings::minFontSize() const +-{ +- return d->m_minFontSize; +-} +- +-QString WebEngineSettings::settingsToCSS() const +-{ +- // lets start with the link properties +- QString str = QStringLiteral("a:link {\ncolor: "); +- str += d->m_linkColor.name(); +- str += ';'; +- if(d->m_underlineLink) +- str += QLatin1String("\ntext-decoration: underline;"); +- +- if( d->m_bChangeCursor ) +- { +- str += QLatin1String("\ncursor: pointer;"); +- str += QLatin1String("\n}\ninput[type=image] { cursor: pointer;"); +- } +- str += QLatin1String("\n}\n"); +- str += QLatin1String("a:visited {\ncolor: "); +- str += d->m_vLinkColor.name(); +- str += ';'; +- if(d->m_underlineLink) +- str += QLatin1String("\ntext-decoration: underline;"); +- +- if( d->m_bChangeCursor ) +- str += QLatin1String("\ncursor: pointer;"); +- str += QLatin1String("\n}\n"); +- +- if(d->m_hoverLink) +- str += QLatin1String("a:link:hover, a:visited:hover { text-decoration: underline; }\n"); +- +- return str; +-} +- +-QString WebEngineSettings::lookupFont(int i) const +-{ +- if (d->fonts.count() > i) { +- return d->fonts.at(i); +- } +- +- if (d->defaultFonts.count() > i) { +- return d->defaultFonts.at(i); +- } +- +- return QString(); +-} +- +-QString WebEngineSettings::stdFontName() const +-{ +- return lookupFont(0); +-} +- +-QString WebEngineSettings::fixedFontName() const +-{ +- return lookupFont(1); +-} +- +-QString WebEngineSettings::serifFontName() const +-{ +- return lookupFont(2); +-} +- +-QString WebEngineSettings::sansSerifFontName() const +-{ +- return lookupFont(3); +-} +- +-QString WebEngineSettings::cursiveFontName() const +-{ +- return lookupFont(4); +-} +- +-QString WebEngineSettings::fantasyFontName() const +-{ +- return lookupFont(5); +-} +- +-void WebEngineSettings::setStdFontName(const QString &n) +-{ +- while(d->fonts.count() <= 0) +- d->fonts.append(QString()); +- d->fonts[0] = n; +-} +- +-void WebEngineSettings::setFixedFontName(const QString &n) +-{ +- while(d->fonts.count() <= 1) +- d->fonts.append(QString()); +- d->fonts[1] = n; +-} +- +-QString WebEngineSettings::userStyleSheet() const +-{ +- return d->m_userSheet; +-} +- +-bool WebEngineSettings::isFormCompletionEnabled() const +-{ +- return d->m_formCompletionEnabled; +-} +- +-int WebEngineSettings::maxFormCompletionItems() const +-{ +- return d->m_maxFormCompletionItems; +-} +- +-const QString &WebEngineSettings::encoding() const +-{ +- return d->m_encoding; +-} +- +-bool WebEngineSettings::followSystemColors() const +-{ +- return d->m_follow_system_colors; +-} +- +-const QColor& WebEngineSettings::textColor() const +-{ +- return d->m_textColor; +-} +- +-const QColor& WebEngineSettings::baseColor() const +-{ +- return d->m_baseColor; +-} +- +-const QColor& WebEngineSettings::linkColor() const +-{ +- return d->m_linkColor; +-} +- +-const QColor& WebEngineSettings::vLinkColor() const +-{ +- return d->m_vLinkColor; +-} +- +-bool WebEngineSettings::autoPageRefresh() const +-{ +- return d->m_bAutoRefreshPage; +-} +- +-bool WebEngineSettings::autoLoadImages() const +-{ +- return d->m_bAutoLoadImages; +-} +- +-bool WebEngineSettings::unfinishedImageFrame() const +-{ +- return d->m_bUnfinishedImageFrame; +-} +- +-WebEngineSettings::KAnimationAdvice WebEngineSettings::showAnimations() const +-{ +- return d->m_showAnimations; +-} +- +-WebEngineSettings::KSmoothScrollingMode WebEngineSettings::smoothScrolling() const +-{ +- return d->m_smoothScrolling; +-} +- +-bool WebEngineSettings::zoomTextOnly() const +-{ +- return d->m_zoomTextOnly; +-} +- +-bool WebEngineSettings::isAutoDelayedActionsEnabled() const +-{ +- return d->m_autoDelayedActionsEnabled; +-} +- +-bool WebEngineSettings::jsErrorsEnabled() const +-{ +- return d->m_jsErrorsEnabled; +-} +- +-void WebEngineSettings::setJSErrorsEnabled(bool enabled) +-{ +- d->m_jsErrorsEnabled = enabled; +- // save it +- KConfigGroup cg( KSharedConfig::openConfig(), "HTML Settings"); +- cg.writeEntry("ReportJSErrors", enabled); +- cg.sync(); +-} +- +-bool WebEngineSettings::allowTabulation() const +-{ +- return d->m_allowTabulation; +-} +- +-bool WebEngineSettings::autoSpellCheck() const +-{ +- return d->m_autoSpellCheck; +-} +- +-QList< QPair< QString, QChar > > WebEngineSettings::fallbackAccessKeysAssignments() const +-{ +- return d->m_fallbackAccessKeysAssignments; +-} +- +-void WebEngineSettings::setJSPopupBlockerPassivePopup(bool enabled) +-{ +- d->m_jsPopupBlockerPassivePopup = enabled; +- // save it +- KConfigGroup cg( KSharedConfig::openConfig(), "Java/JavaScript Settings"); +- cg.writeEntry("PopupBlockerPassivePopup", enabled); +- cg.sync(); +-} +- +-bool WebEngineSettings::jsPopupBlockerPassivePopup() const +-{ +- return d->m_jsPopupBlockerPassivePopup; +-} +- +-bool WebEngineSettings::isCookieJarEnabled() const +-{ +- return d->m_useCookieJar; +-} +- +-// Password storage... +-static KConfigGroup nonPasswordStorableSitesCg(KSharedConfig::Ptr& configPtr) +-{ +- if (!configPtr) { +- configPtr = KSharedConfig::openConfig(QStandardPaths::locate(QStandardPaths::DataLocation, QStringLiteral("khtml/formcompletions")), KConfig::NoGlobals); +- } +- +- return KConfigGroup(configPtr, "NonPasswordStorableSites"); +-} +- +-bool WebEngineSettings::isNonPasswordStorableSite(const QString &host) const +-{ +- KConfigGroup cg = nonPasswordStorableSitesCg(d->nonPasswordStorableSites); +- const QStringList sites = cg.readEntry("Sites", QStringList()); +- return sites.contains(host); +-} +- +-void WebEngineSettings::addNonPasswordStorableSite(const QString &host) +-{ +- KConfigGroup cg = nonPasswordStorableSitesCg(d->nonPasswordStorableSites); +- QStringList sites = cg.readEntry("Sites", QStringList()); +- sites.append(host); +- cg.writeEntry("Sites", sites); +- cg.sync(); +-} +- +-void WebEngineSettings::removeNonPasswordStorableSite(const QString &host) +-{ +- KConfigGroup cg = nonPasswordStorableSitesCg(d->nonPasswordStorableSites); +- QStringList sites = cg.readEntry("Sites", QStringList()); +- sites.removeOne(host); +- cg.writeEntry("Sites", sites); +- cg.sync(); +-} +- +-bool WebEngineSettings::askToSaveSitePassword() const +-{ +- return d->m_offerToSaveWebSitePassword; +-} +- +-bool WebEngineSettings::isInternalPluginHandlingDisabled() const +-{ +- return d->m_disableInternalPluginHandling; +-} +- +-bool WebEngineSettings::isLoadPluginsOnDemandEnabled() const +-{ +- return d->m_loadPluginsOnDemand; +-} +- +-bool WebEngineSettings::allowMixedContentDisplay() const +-{ +- return d->m_allowMixedContentDisplay; +-} +- +-bool WebEngineSettings::alowActiveMixedContent() const +-{ +- return d->m_allowActiveMixedContent; +-} +- +- +-void WebEngineSettings::initWebEngineSettings() +-{ +- KConfig cfg (QStringLiteral("webenginepartrc"), KConfig::NoGlobals); +- KConfigGroup generalCfg (&cfg, "General"); +- d->m_disableInternalPluginHandling = generalCfg.readEntry("DisableInternalPluginHandling", false); +- d->m_enableLocalStorage = generalCfg.readEntry("EnableLocalStorage", true); +- d->m_enableOfflineStorageDb = generalCfg.readEntry("EnableOfflineStorageDatabase", true); +- d->m_enableOfflineWebAppCache = generalCfg.readEntry("EnableOfflineWebApplicationCache", true); +- d->m_enableWebGL = generalCfg.readEntry("EnableWebGL", true); +- d->m_allowActiveMixedContent = generalCfg.readEntry("AllowActiveMixedContent", false); +- d->m_allowMixedContentDisplay = generalCfg.readEntry("AllowMixedContentDisplay", true); +- +- // Force the reloading of the non password storable sites settings. +- d->nonPasswordStorableSites.reset(); +-} +- +-void WebEngineSettings::initCookieJarSettings() +-{ +- KSharedConfig::Ptr cookieCfgPtr = KSharedConfig::openConfig(QStringLiteral("kcookiejarrc"), KConfig::NoGlobals); +- KConfigGroup cookieCfg ( cookieCfgPtr, "Cookie Policy"); +- d->m_useCookieJar = cookieCfg.readEntry("Cookies", false); +-} +- +-void WebEngineSettings::initNSPluginSettings() +-{ +- KSharedConfig::Ptr cookieCfgPtr = KSharedConfig::openConfig(QStringLiteral("kcmnspluginrc"), KConfig::NoGlobals); +- KConfigGroup cookieCfg ( cookieCfgPtr, "Misc"); +- d->m_loadPluginsOnDemand = cookieCfg.readEntry("demandLoad", false); +-} +- +- +-WebEngineSettings* WebEngineSettings::self() +-{ +- static WebEngineSettings s_webEngineSettings; +- return &s_webEngineSettings; +-} +- +-#include "webenginesettings.moc" +diff --git a/webenginepart/src/settings/webenginesettings.h a/webenginepart/src/settings/webenginesettings.h +deleted file mode 100644 +index 6b2baa101..000000000 +--- a/webenginepart/src/settings/webenginesettings.h ++++ /dev/null +@@ -1,213 +0,0 @@ +-/* This file is part of the KDE project +- Copyright (C) 1999 David Faure <faure@kde.org> +- +- This library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Library 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 WEBENGINESETTINGS_H +-#define WEBENGINESETTINGS_H +- +-class KConfig; +-class KConfigGroup; +- +-#include <QColor> +-#include <QStringList> +-#include <QPair> +- +-#include <KParts/HtmlExtension> +-#include <KParts/HtmlSettingsInterface> +- +-struct KPerDomainSettings; +-class WebEngineSettingsPrivate; +- +-/** +- * Settings for the HTML view. +- */ +-class WebEngineSettings +-{ +-public: +- +- enum KAnimationAdvice { +- KAnimationDisabled=0, +- KAnimationLoopOnce, +- KAnimationEnabled +- }; +- +- enum KSmoothScrollingMode { +- KSmoothScrollingDisabled=0, +- KSmoothScrollingWhenEfficient, +- KSmoothScrollingEnabled +- }; +- +- /** +- * Called by constructor and reparseConfiguration +- */ +- void init(); +- +- /** +- * Destructor. Don't delete any instance by yourself. +- */ +- virtual ~WebEngineSettings(); +- +- void computeFontSizes(int logicalDpi); +- bool zoomToDPI() const; +- void setZoomToDPI(bool b); +- +- // Automatic page reload/refresh... +- bool autoPageRefresh() const; +- +- bool isOpenMiddleClickEnabled(); +- +- // Java and JavaScript +- bool isJavaEnabled( const QString& hostname = QString() ) const; +- bool isJavaScriptEnabled( const QString& hostname = QString() ) const; +- bool isJavaScriptDebugEnabled( const QString& hostname = QString() ) const; +- bool isJavaScriptErrorReportingEnabled( const QString& hostname = QString() ) const; +- bool isPluginsEnabled( const QString& hostname = QString() ) const; +- bool isLoadPluginsOnDemandEnabled() const; +- bool isInternalPluginHandlingDisabled() const; +- +- // AdBlocK Filtering +- bool isAdFiltered( const QString &url ) const; +- bool isAdFilterEnabled() const; +- bool isHideAdsEnabled() const; +- void addAdFilter( const QString &url ); +- QString adFilteredBy( const QString &url, bool *isWhiteListed = 0 ) const; +- +- // Access Keys +- bool accessKeysEnabled() const; +- +- // Favicons +- bool favIconsEnabled() const; +- +- KParts::HtmlSettingsInterface::JSWindowOpenPolicy windowOpenPolicy( const QString& hostname = QString() ) const; +- KParts::HtmlSettingsInterface::JSWindowMovePolicy windowMovePolicy( const QString& hostname = QString() ) const; +- KParts::HtmlSettingsInterface::JSWindowResizePolicy windowResizePolicy( const QString& hostname = QString() ) const; +- KParts::HtmlSettingsInterface::JSWindowStatusPolicy windowStatusPolicy( const QString& hostname = QString() ) const; +- KParts::HtmlSettingsInterface::JSWindowFocusPolicy windowFocusPolicy( const QString& hostname = QString() ) const; +- +- QString settingsToCSS() const; +- QString userStyleSheet() const; +- +- // Form completion +- bool isFormCompletionEnabled() const; +- int maxFormCompletionItems() const; +- +- // Meta refresh/redirect (http-equiv) +- bool isAutoDelayedActionsEnabled () const; +- +- // CookieJar... +- bool isCookieJarEnabled() const; +- +- // Password storage... +- bool isNonPasswordStorableSite(const QString &host) const; +- void addNonPasswordStorableSite(const QString &host); +- void removeNonPasswordStorableSite(const QString &host); +- bool askToSaveSitePassword() const; +- +- // Mixed content +- bool alowActiveMixedContent() const; +- bool allowMixedContentDisplay() const; +- +- // Global config object stuff. +- static WebEngineSettings* self(); +- +-private: +- /** +- * Read settings from @p config. +- * @param config is a pointer to KConfig object. +- * @param reset if true, settings are always set; if false, +- * settings are only set if the config file has a corresponding key. +- */ +- void init( KConfig * config, bool reset = true ); +- +- // Behavior settings +- bool changeCursor() const; +- bool underlineLink() const; +- bool hoverLink() const; +- bool allowTabulation() const; +- bool autoSpellCheck() const; +- KAnimationAdvice showAnimations() const; +- KSmoothScrollingMode smoothScrolling() const; +- bool zoomTextOnly() const; +- +- // Font settings +- QString stdFontName() const; +- QString fixedFontName() const; +- QString serifFontName() const; +- QString sansSerifFontName() const; +- QString cursiveFontName() const; +- QString fantasyFontName() const; +- +- // these two can be set. Mainly for historical reasons (the method in KHTMLPart exists...) +- void setStdFontName(const QString &n); +- void setFixedFontName(const QString &n); +- +- int minFontSize() const; +- int mediumFontSize() const; +- +- bool jsErrorsEnabled() const; +- void setJSErrorsEnabled(bool enabled); +- +- const QString &encoding() const; +- +- bool followSystemColors() const; +- +- // Color settings +- const QColor& textColor() const; +- const QColor& baseColor() const; +- const QColor& linkColor() const; +- const QColor& vLinkColor() const; +- +- // Autoload images +- bool autoLoadImages() const; +- bool unfinishedImageFrame() const; +- +- /** +- * reads from @p config's current group, forcing initialization +- * if @p reset is true. +- * @param config is a pointer to KConfig object. +- * @param reset true if initialization is to be forced. +- * @param global true if the global domain is to be read. +- * @param pd_settings will be initialised with the computed (inherited) +- * settings. +- */ +- void readDomainSettings(const KConfigGroup &config, bool reset, +- bool global, KPerDomainSettings &pd_settings); +- +- +- QList< QPair< QString, QChar > > fallbackAccessKeysAssignments() const; +- +- // Whether to show passive popup when windows are blocked +- void setJSPopupBlockerPassivePopup(bool enabled); +- bool jsPopupBlockerPassivePopup() const; +- +- +- QString lookupFont(int i) const; +- +- void initWebEngineSettings(); +- void initCookieJarSettings(); +- void initNSPluginSettings(); +- +- /** +- * @internal Constructor +- */ +- WebEngineSettings(); +- +- WebEngineSettingsPrivate* const d; +-}; +- +-#endif +diff --git a/webenginepart/src/ui/featurepermissionbar.cpp a/webenginepart/src/ui/featurepermissionbar.cpp +deleted file mode 100644 +index e13351a16..000000000 +--- a/webenginepart/src/ui/featurepermissionbar.cpp ++++ /dev/null +@@ -1,75 +0,0 @@ +-/* +- * This file is part of the KDE project. +- * +- * Copyright (C) 2009 Dawit Alemayehu <adawit @ kde.org> +- * Copyright (C) 2013 Allan Sandfeld Jensen <sandfeld@kde.org> +- * +- * This library is free software; you can redistribute it and/or +- * modify it under the terms of the GNU Library 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 "featurepermissionbar.h" +- +-#include <KLocalizedString> +- +-#include <QAction> +- +- +-FeaturePermissionBar::FeaturePermissionBar(QWidget *parent) +- :KMessageWidget(parent) +-{ +- setCloseButtonVisible(false); +- setMessageType(KMessageWidget::Information); +- +- QAction* action = new QAction(i18nc("@action:deny access", "&Deny access"), this); +- connect(action, SIGNAL(triggered()), this, SLOT(onDeniedButtonClicked())); +- addAction(action); +- +- action = new QAction(i18nc("@action:grant access", "&Grant access"), this); +- connect(action, SIGNAL(triggered()), this, SLOT(onGrantedButtonClicked())); +- addAction(action); +- +- // FIXME: Add option to allow and remember for this site. +-} +- +-FeaturePermissionBar::~FeaturePermissionBar() +-{ +-} +- +-QWebEnginePage::Feature FeaturePermissionBar::feature() const +-{ +- return m_feature; +-} +- +-void FeaturePermissionBar::setFeature (QWebEnginePage::Feature feature) +-{ +- m_feature = feature; +-} +- +-void FeaturePermissionBar::onDeniedButtonClicked() +-{ +- animatedHide(); +- emit permissionDenied(m_feature); +- emit done(); +-} +- +-void FeaturePermissionBar::onGrantedButtonClicked() +-{ +- animatedHide(); +- emit permissionGranted(m_feature); +- emit done(); +-} +- +-#include "featurepermissionbar.moc" +diff --git a/webenginepart/src/ui/featurepermissionbar.h a/webenginepart/src/ui/featurepermissionbar.h +deleted file mode 100644 +index d988ad36f..000000000 +--- a/webenginepart/src/ui/featurepermissionbar.h ++++ /dev/null +@@ -1,54 +0,0 @@ +-/* +- * This file is part of the KDE project. +- * +- * Copyright (C) 2013 Allan Sandfeld Jensen <sandfeld @ kde.org> +- * +- * This library is free software; you can redistribute it and/or +- * modify it under the terms of the GNU Library General Public +- * License as published by the Free Software Foundation; either +- * version 2.1 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 FEATUREPERMISSIONBAR_H +-#define FEATUREPERMISSIONBAR_H +- +-#include <KMessageWidget> +- +-#include <QtWebEngineWidgets/QWebEnginePage> +- +- +-class FeaturePermissionBar : public KMessageWidget +-{ +- Q_OBJECT +-public: +- explicit FeaturePermissionBar(QWidget *parent = Q_NULLPTR); +- ~FeaturePermissionBar(); +- +- QWebEnginePage::Feature feature() const; +- +- void setFeature(QWebEnginePage::Feature); +- +-Q_SIGNALS: +- void permissionGranted(QWebEnginePage::Feature); +- void permissionDenied(QWebEnginePage::Feature); +- void done(); +- +-private Q_SLOTS: +- void onDeniedButtonClicked(); +- void onGrantedButtonClicked(); +- +-private: +- QWebEnginePage::Feature m_feature; +-}; +- +-#endif // FEATUREPERMISSIONBAR_H +diff --git a/webenginepart/src/ui/passwordbar.cpp a/webenginepart/src/ui/passwordbar.cpp +deleted file mode 100644 +index 328d5d4b2..000000000 +--- a/webenginepart/src/ui/passwordbar.cpp ++++ /dev/null +@@ -1,105 +0,0 @@ +-/* +- * This file is part of the KDE project. +- * +- * Copyright (C) 2009 Dawit Alemayehu <adawit @ kde.org> +- * +- * This library is free software; you can redistribute it and/or +- * modify it under the terms of the GNU Library 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 "passwordbar.h" +- +-#include "settings/webenginesettings.h" +- +-#include <KColorScheme> +-#include <KLocalizedString> +- +-#include <QCoreApplication> +-#include <QAction> +-#include <QPalette> +- +- +-PasswordBar::PasswordBar(QWidget *parent) +- :KMessageWidget(parent) +-{ +- setCloseButtonVisible(false); +- setMessageType(KMessageWidget::Information); +- +- QAction* action = new QAction(i18nc("@action:remember password", "&Remember"), this); +- connect(action, SIGNAL(triggered()), this, SLOT(onRememberButtonClicked())); +- addAction(action); +- +- action = new QAction(i18nc("@action:never for this site", "Ne&ver for this site"), this); +- connect(action, SIGNAL(triggered()), this, SLOT(onNeverButtonClicked())); +- addAction(action); +- +- action = new QAction(i18nc("@action:not now", "N&ot now"), this); +- connect(action, SIGNAL(triggered()), this, SLOT(onNotNowButtonClicked())); +- addAction(action); +-} +- +-PasswordBar::~PasswordBar() +-{ +-} +- +-QUrl PasswordBar::url() const +-{ +- return m_url; +-} +- +-QString PasswordBar::requestKey() const +-{ +- return m_requestKey; +-} +- +-void PasswordBar::setUrl (const QUrl& url) +-{ +- m_url = url; +-} +- +-void PasswordBar::setRequestKey (const QString& key) +-{ +- m_requestKey = key; +-} +- +-void PasswordBar::onNotNowButtonClicked() +-{ +- animatedHide(); +- emit saveFormDataRejected (m_requestKey); +- emit done(); +- clear(); +-} +- +-void PasswordBar::onNeverButtonClicked() +-{ +- WebEngineSettings::self()->addNonPasswordStorableSite(m_url.host()); +- onNotNowButtonClicked(); +-} +- +-void PasswordBar::onRememberButtonClicked() +-{ +- animatedHide(); +- emit saveFormDataAccepted(m_requestKey); +- emit done(); +- clear(); +-} +- +-void PasswordBar::clear() +-{ +- m_requestKey.clear(); +- m_url.clear(); +-} +- +-#include "passwordbar.moc" +diff --git a/webenginepart/src/ui/passwordbar.h a/webenginepart/src/ui/passwordbar.h +deleted file mode 100644 +index 9f641a625..000000000 +--- a/webenginepart/src/ui/passwordbar.h ++++ /dev/null +@@ -1,60 +0,0 @@ +-/* +- * This file is part of the KDE project. +- * +- * Copyright (C) 2009 Dawit Alemayehu <adawit @ kde.org> +- * +- * This library is free software; you can redistribute it and/or +- * modify it under the terms of the GNU Library 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 PASSWORDBAR_H +-#define PASSWORDBAR_H +- +-#include <KMessageWidget> +- +-#include <QUrl> +- +- +-class PasswordBar : public KMessageWidget +-{ +- Q_OBJECT +-public: +- explicit PasswordBar(QWidget *parent = Q_NULLPTR); +- ~PasswordBar(); +- +- QUrl url() const; +- QString requestKey() const; +- +- void setUrl(const QUrl&); +- void setRequestKey(const QString&); +- +-Q_SIGNALS: +- void saveFormDataRejected(const QString &key); +- void saveFormDataAccepted(const QString &key); +- void done(); +- +-private Q_SLOTS: +- void onNotNowButtonClicked(); +- void onNeverButtonClicked(); +- void onRememberButtonClicked(); +- +-private: +- void clear(); +- +- QUrl m_url; +- QString m_requestKey; +-}; +- +-#endif // PASSWORDBAR_H +diff --git a/webenginepart/src/ui/searchbar.cpp a/webenginepart/src/ui/searchbar.cpp +deleted file mode 100644 +index aca133ff6..000000000 +--- a/webenginepart/src/ui/searchbar.cpp ++++ /dev/null +@@ -1,194 +0,0 @@ +-/* +- * This file is part of the KDE project. +- * +- * Copyright (C) 2008 Laurent Montel <montel@kde.org> +- * Copyright (C) 2008 Benjamin C. Meyer <ben@meyerhome.net> +- * Copyright (C) 2008 Urs Wolfer <uwolfer @ kde.org> +- * Copyright (C) 2009 Dawit Alemayehu <adawit @ kde.org> +- * +- * This library is free software; you can redistribute it and/or +- * modify it under the terms of the GNU Library 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 "searchbar.h" +- +-#include <KLineEdit> +-#include <KColorScheme> +-#include <QIcon> +-#include <KLocalizedString> +- +-#include <QResizeEvent> +- +- +-SearchBar::SearchBar(QWidget *parent) +- :QWidget(parent) +-{ +- +- // Get the widget that currently has the focus so we can properly +- // restore it when the filter bar is closed. +- QWidget* widgetWindow = (parent ? parent->window() : 0); +- m_focusWidget = (widgetWindow ? widgetWindow->focusWidget() : 0); +- +- // Initialize the user interface... +- m_ui.setupUi(this); +- m_ui.optionsButton->addAction(m_ui.actionMatchCase); +- m_ui.optionsButton->addAction(m_ui.actionHighlightMatch); +- m_ui.optionsButton->addAction(m_ui.actionSearchAutomatically); +- m_ui.closeButton->setIcon(QIcon::fromTheme(QStringLiteral("dialog-close"))); +- m_ui.previousButton->setIcon(QIcon::fromTheme(QStringLiteral("go-up-search"))); +- m_ui.nextButton->setIcon(QIcon::fromTheme(QStringLiteral("go-down-search"))); +- m_ui.previousButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); +- m_ui.nextButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); +- m_ui.searchInfo->setText(i18nc("label for input line to find text", "&Find:")); +- +- setFocusProxy(m_ui.searchComboBox); +- +- connect(m_ui.nextButton, SIGNAL(clicked()), +- this, SLOT(findNext())); +- connect(m_ui.previousButton, SIGNAL(clicked()), +- this, SLOT(findPrevious())); +- connect(m_ui.searchComboBox, SIGNAL(returnPressed()), +- this, SLOT(findNext())); +- connect(m_ui.searchComboBox, SIGNAL(editTextChanged(QString)), +- this, SLOT(textChanged(QString))); +- +- // Start off hidden by default... +- setVisible(false); +-} +- +-SearchBar::~SearchBar() +-{ +- // NOTE: For some reason, if we do not clear the focus from the line edit +- // widget before we delete this object, it seems to cause a crash!! +- m_ui.searchComboBox->clearFocus(); +-} +- +-void SearchBar::clear() +-{ +- m_ui.searchComboBox->clear(); +-} +- +-void SearchBar::setVisible (bool visible) +-{ +- if (visible) { +- m_ui.searchComboBox->setFocus(Qt::ActiveWindowFocusReason); +- m_ui.searchComboBox->lineEdit()->selectAll(); +- } else { +- m_ui.searchComboBox->setPalette(QPalette()); +- emit searchTextChanged(QString()); +- } +- +- QWidget::setVisible(visible); +-} +- +-QString SearchBar::searchText() const +-{ +- return m_ui.searchComboBox->currentText(); +-} +- +-bool SearchBar::caseSensitive() const +-{ +- return m_ui.actionMatchCase->isChecked(); +-} +- +-bool SearchBar::highlightMatches() const +-{ +- return m_ui.actionHighlightMatch->isChecked(); +-} +- +-void SearchBar::setSearchText(const QString& text) +-{ +- show(); +- m_ui.searchComboBox->setEditText(text); +-} +- +-void SearchBar::setFoundMatch(bool match) +-{ +- //kDebug() << match; +- if (m_ui.searchComboBox->currentText().isEmpty()) { +- m_ui.searchComboBox->setPalette(QPalette()); +- return; +- } +- +- KColorScheme::BackgroundRole role = (match ? KColorScheme::PositiveBackground : KColorScheme::NegativeBackground); +- QPalette newPal(m_ui.searchComboBox->palette()); +- KColorScheme::adjustBackground(newPal, role); +- m_ui.searchComboBox->setPalette(newPal); +-} +- +-void SearchBar::findNext() +-{ +- if (!isVisible()) +- return; +- +- const QString text (m_ui.searchComboBox->currentText()); +- if (m_ui.searchComboBox->findText(text) == -1) { +- m_ui.searchComboBox->addItem(text); +- } +- +- emit searchTextChanged(text); +-} +- +-void SearchBar::findPrevious() +-{ +- if (!isVisible()) +- return; +- +- const QString text (m_ui.searchComboBox->currentText()); +- if (m_ui.searchComboBox->findText(text) == -1) { +- m_ui.searchComboBox->addItem(text); +- } +- +- emit searchTextChanged(m_ui.searchComboBox->currentText(), true); +-} +- +-void SearchBar::textChanged(const QString &text) +-{ +- if (text.isEmpty()) { +- m_ui.searchComboBox->setPalette(QPalette()); +- m_ui.nextButton->setEnabled(false); +- m_ui.previousButton->setEnabled(false); +- } else { +- m_ui.nextButton->setEnabled(true); +- m_ui.previousButton->setEnabled(true); +- } +- +- if (m_ui.actionSearchAutomatically->isChecked()) { +- emit searchTextChanged(m_ui.searchComboBox->currentText()); +- } +-} +- +-bool SearchBar::event(QEvent* e) +-{ +- // Close the bar when Escape is pressed. Note we cannot +- // assign Escape as a shortcut key because it would cause +- // a conflict with the Stop button. +- if (e->type() == QEvent::ShortcutOverride) { +- QKeyEvent* kev = static_cast<QKeyEvent*>(e); +- if (kev->key() == Qt::Key_Escape) { +- e->accept(); +- close(); +- if (m_focusWidget) { +- m_focusWidget->setFocus(); +- m_focusWidget = 0; +- } +- return true; +- } +- } +- return QWidget::event(e); +-} +- +-#include "searchbar.moc" +diff --git a/webenginepart/src/ui/searchbar.h a/webenginepart/src/ui/searchbar.h +deleted file mode 100644 +index 598fe69ff..000000000 +--- a/webenginepart/src/ui/searchbar.h ++++ /dev/null +@@ -1,68 +0,0 @@ +-/* +- * This file is part of the KDE project. +- * +- * Copyright (C) 2008 Laurent Montel <montel@kde.org> +- * Copyright 2008 Benjamin C. Meyer <ben@meyerhome.net> +- * Copyright (C) 2008 Urs Wolfer <uwolfer @ kde.org> +- * Copyright (C) 2009 Dawit Alemayehu <adawit @ kde.org> +- * +- * This library is free software; you can redistribute it and/or +- * modify it under the terms of the GNU Library 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 SEARCHBAR_P_H +-#define SEARCHBAR_P_H +- +-#include <QWidget> +- +-#include "ui_searchbar.h" +- +-class QEvent; +- +-/** +- * This is the widget that shows up when the search is initiated. +- */ +-class SearchBar : public QWidget +-{ +- Q_OBJECT +- +-public: +- SearchBar(QWidget *parent = Q_NULLPTR); +- ~SearchBar(); +- +- QString searchText() const; +- bool caseSensitive() const; +- bool highlightMatches() const; +- void setFoundMatch(bool match); +- void setSearchText(const QString&); +- +- bool event(QEvent* e) Q_DECL_OVERRIDE; +- +-public Q_SLOTS: +- void setVisible(bool visible) Q_DECL_OVERRIDE; +- void clear(); +- void findNext(); +- void findPrevious(); +- void textChanged(const QString&); +- +-Q_SIGNALS: +- void searchTextChanged(const QString& text, bool backward = false); +- +-private: +- Ui::SearchBar m_ui; +- QPointer<QWidget> m_focusWidget; +-}; +- +-#endif // SEARCHBAR_P_H +diff --git a/webenginepart/src/ui/searchbar.ui a/webenginepart/src/ui/searchbar.ui +deleted file mode 100644 +index 0ed50bdda..000000000 +--- a/webenginepart/src/ui/searchbar.ui ++++ /dev/null +@@ -1,168 +0,0 @@ +-<?xml version="1.0" encoding="UTF-8"?> +-<ui version="4.0"> +- <class>SearchBar</class> +- <widget class="QWidget" name="SearchBar"> +- <property name="geometry"> +- <rect> +- <x>0</x> +- <y>0</y> +- <width>564</width> +- <height>34</height> +- </rect> +- </property> +- <property name="sizePolicy"> +- <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> +- <horstretch>0</horstretch> +- <verstretch>0</verstretch> +- </sizepolicy> +- </property> +- <layout class="QHBoxLayout" name="horizontalLayout"> +- <item> +- <widget class="QToolButton" name="closeButton"> +- <property name="toolTip"> +- <string>Close the search bar</string> +- </property> +- <property name="autoRaise"> +- <bool>true</bool> +- </property> +- </widget> +- </item> +- <item> +- <widget class="QLabel" name="searchInfo"> +- <property name="text"> +- <string>&Find:</string> +- </property> +- <property name="buddy"> +- <cstring>searchComboBox</cstring> +- </property> +- </widget> +- </item> +- <item> +- <widget class="KHistoryComboBox" name="searchComboBox"> +- <property name="sizePolicy"> +- <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> +- <horstretch>0</horstretch> +- <verstretch>0</verstretch> +- </sizepolicy> +- </property> +- </widget> +- </item> +- <item> +- <widget class="QToolButton" name="nextButton"> +- <property name="enabled"> +- <bool>false</bool> +- </property> +- <property name="toolTip"> +- <string>Find the next match for the current search phrase</string> +- </property> +- <property name="text"> +- <string>&Next</string> +- </property> +- </widget> +- </item> +- <item> +- <widget class="QToolButton" name="previousButton"> +- <property name="enabled"> +- <bool>false</bool> +- </property> +- <property name="toolTip"> +- <string>Find the previous match for the current search phrase</string> +- </property> +- <property name="text"> +- <string>&Previous</string> +- </property> +- </widget> +- </item> +- <item> +- <widget class="QToolButton" name="optionsButton"> +- <property name="toolTip"> +- <string>Find the previous match for the current search phrase</string> +- </property> +- <property name="text"> +- <string>&Options</string> +- </property> +- <property name="popupMode"> +- <enum>QToolButton::InstantPopup</enum> +- </property> +- </widget> +- </item> +- <item> +- <spacer name="horizontalSpacer"> +- <property name="orientation"> +- <enum>Qt::Horizontal</enum> +- </property> +- <property name="sizeType"> +- <enum>QSizePolicy::MinimumExpanding</enum> +- </property> +- <property name="sizeHint" stdset="0"> +- <size> +- <width>20</width> +- <height>20</height> +- </size> +- </property> +- </spacer> +- </item> +- </layout> +- <action name="actionMatchCase"> +- <property name="checkable"> +- <bool>true</bool> +- </property> +- <property name="text"> +- <string>&Match Case</string> +- </property> +- </action> +- <action name="actionSearchAutomatically"> +- <property name="checkable"> +- <bool>true</bool> +- </property> +- <property name="checked"> +- <bool>true</bool> +- </property> +- <property name="text"> +- <string>&Search As You Type</string> +- </property> +- </action> +- <action name="actionHighlightMatch"> +- <property name="checkable"> +- <bool>true</bool> +- </property> +- <property name="text"> +- <string>&Highlight All Matches</string> +- </property> +- <property name="toolTip"> +- <string>Highlight Matches</string> +- </property> +- </action> +- </widget> +- <customwidgets> +- <customwidget> +- <class>KComboBox</class> +- <extends>QComboBox</extends> +- <header>kcombobox.h</header> +- </customwidget> +- <customwidget> +- <class>KHistoryComboBox</class> +- <extends>KComboBox</extends> +- <header>khistorycombobox.h</header> +- </customwidget> +- </customwidgets> +- <resources/> +- <connections> +- <connection> +- <sender>closeButton</sender> +- <signal>clicked()</signal> +- <receiver>SearchBar</receiver> +- <slot>close()</slot> +- <hints> +- <hint type="sourcelabel"> +- <x>16</x> +- <y>16</y> +- </hint> +- <hint type="destinationlabel"> +- <x>290</x> +- <y>16</y> +- </hint> +- </hints> +- </connection> +- </connections> +-</ui> +diff --git a/webenginepart/src/utils.h a/webenginepart/src/utils.h +deleted file mode 100644 +index c3b33267c..000000000 +--- a/webenginepart/src/utils.h ++++ /dev/null +@@ -1,16 +0,0 @@ +-#ifndef WEBENGINEPART_UTILS_H +-#define WEBENGINEPART_UTILS_H +- +-namespace Utils +-{ +- +-#define QL1S(x) QLatin1String(x) +-#define QL1C(x) QLatin1Char(x) +- +-inline bool isBlankUrl(const QUrl& url) +-{ +- return (url.isEmpty() || url.url() == QL1S("about:blank")); +-} +- +-} +-#endif // WEBENGINEPART_UTILS_H +diff --git a/webenginepart/src/webenginepage.cpp a/webenginepart/src/webenginepage.cpp +deleted file mode 100644 +index cde853641..000000000 +--- a/webenginepart/src/webenginepage.cpp ++++ /dev/null +@@ -1,888 +0,0 @@ +-/* +- * This file is part of the KDE project. +- * +- * Copyright (C) 2008 Dirk Mueller <mueller@kde.org> +- * Copyright (C) 2008 - 2010 Urs Wolfer <uwolfer @ kde.org> +- * Copyright (C) 2009 Dawit Alemayehu <adawit@kde.org> +- * +- * This library is free software; you can redistribute it and/or modify it +- * under the terms of the GNU Lesser General Public License as published by the +- * Free Software Foundation; either version 2.1 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 Lesser General Public License for more +- * details. +- * +- * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- */ +- +-#include "webenginepage.h" +- +-#include "webenginepart.h" +-#include "websslinfo.h" +-#include "webengineview.h" +-#include "settings/webenginesettings.h" +-#include <QWebEngineSettings> +-#include <QWebEngineProfile> +- +-#include <KMessageBox> +-#include <KRun> +-#include <KLocalizedString> +-#include <KShell> +-#include <KAuthorized> +-#include <KStringHandler> +-#include <KUrlAuthorized> +-#include <KSharedConfig> +-#include <KIO/Job> +-#include <KIO/AccessManager> +-#include <KIO/Scheduler> +-#include <KParts/HtmlExtension> +-#include <QStandardPaths> +-#include <QDesktopWidget> +- +-#include <QFile> +-#include <QApplication> +-#include <QTextDocument> // Qt::escape +-#include <QNetworkReply> +-#include <QWebEngineHistory> +-#include <QWebEngineHistoryItem> +-#include <QWebEngineDownloadItem> +-#include <QUrlQuery> +-#include <KConfigGroup> +-//#include <QWebSecurityOrigin> +-#include "utils.h" +- +- +-WebEnginePage::WebEnginePage(WebEnginePart *part, QWidget *parent) +- : QWebEnginePage(parent), +- m_kioErrorCode(0), +- m_ignoreError(false), +- m_part(part) +-{ +- if (view()) +- WebEngineSettings::self()->computeFontSizes(view()->logicalDpiY()); +- +- //setForwardUnsupportedContent(true); +- +- connect(this, &QWebEnginePage::geometryChangeRequested, +- this, &WebEnginePage::slotGeometryChangeRequested); +-// connect(this, SIGNAL(unsupportedContent(QNetworkReply*)), +-// this, SLOT(slotUnsupportedContent(QNetworkReply*))); +- connect(this, &QWebEnginePage::featurePermissionRequested, +- this, &WebEnginePage::slotFeaturePermissionRequested); +- connect(this, &QWebEnginePage::loadFinished, +- this, &WebEnginePage::slotLoadFinished); +- connect(this->profile(), &QWebEngineProfile::downloadRequested, this, &WebEnginePage::downloadRequest); +- if(!this->profile()->httpUserAgent().contains(QLatin1String("Konqueror"))) +- { +- this->profile()->setHttpUserAgent(this->profile()->httpUserAgent() + " Konqueror (WebEnginePart)"); +- } +-} +- +-WebEnginePage::~WebEnginePage() +-{ +- //kDebug() << this; +-} +- +-const WebSslInfo& WebEnginePage::sslInfo() const +-{ +- return m_sslInfo; +-} +- +-void WebEnginePage::setSslInfo (const WebSslInfo& info) +-{ +- m_sslInfo = info; +-} +- +-static void checkForDownloadManager(QWidget* widget, QString& cmd) +-{ +- cmd.clear(); +- KConfigGroup cfg (KSharedConfig::openConfig(QStringLiteral("konquerorrc"), KConfig::NoGlobals), "HTML Settings"); +- const QString fileName (cfg.readPathEntry("DownloadManager", QString())); +- if (fileName.isEmpty()) +- return; +- +- const QString exeName = QStandardPaths::findExecutable(fileName); +- if (exeName.isEmpty()) { +- KMessageBox::detailedSorry(widget, +- i18n("The download manager (%1) could not be found in your installation.", fileName), +- i18n("Try to reinstall it and make sure that it is available in $PATH. \n\nThe integration will be disabled.")); +- cfg.writePathEntry("DownloadManager", QString()); +- cfg.sync(); +- return; +- } +- +- cmd = exeName; +-} +- +-void WebEnginePage::downloadRequest(QWebEngineDownloadItem* request) +-{ +- const QUrl url(request->url()); +- +- // Integration with a download manager... +- if (!url.isLocalFile()) { +- QString managerExe; +- checkForDownloadManager(view(), managerExe); +- if (!managerExe.isEmpty()) { +- //kDebug() << "Calling command" << cmd; +- KRun::runCommand((managerExe + QLatin1Char(' ') + KShell::quoteArg(url.url())), view()); +- return; +- } +- } +- request->accept(); +- +-} +- +-QWebEnginePage *WebEnginePage::createWindow(WebWindowType type) +-{ +- //qDebug() << "window type:" << type; +- // Crete an instance of NewWindowPage class to capture all the +- // information we need to create a new window. See documentation of +- // the class for more information... +- NewWindowPage* page = new NewWindowPage(type, part()); +- return page; +-} +- +-// Returns true if the scheme and domain of the two urls match... +-static bool domainSchemeMatch(const QUrl& u1, const QUrl& u2) +-{ +- if (u1.scheme() != u2.scheme()) +- return false; +- +- QStringList u1List = u1.host().split(QL1C('.'), QString::SkipEmptyParts); +- QStringList u2List = u2.host().split(QL1C('.'), QString::SkipEmptyParts); +- +- if (qMin(u1List.count(), u2List.count()) < 2) +- return false; // better safe than sorry... +- +- while (u1List.count() > 2) +- u1List.removeFirst(); +- +- while (u2List.count() > 2) +- u2List.removeFirst(); +- +- return (u1List == u2List); +-} +- +-bool WebEnginePage::acceptNavigationRequest(const QUrl& url, NavigationType type, bool isMainFrame) +-{ +- qDebug() << url << "type=" << type; +- QUrl reqUrl(url); +- +- // Handle "mailto:" url here... +- if (handleMailToUrl(reqUrl, type)) +- return false; +- +- const bool isTypedUrl = property("NavigationTypeUrlEntered").toBool(); +- +- /* +- NOTE: We use a dynamic QObject property called "NavigationTypeUrlEntered" +- to distinguish between requests generated by user entering a url vs those +- that were generated programatically through javascript (AJAX requests). +- */ +- if (isMainFrame && isTypedUrl) +- setProperty("NavigationTypeUrlEntered", QVariant()); +- +- // inPage requests are those generarted within the current page through +- // link clicks, javascript queries, and button clicks (form submission). +- bool inPageRequest = true; +- switch (type) { +- case QWebEnginePage::NavigationTypeFormSubmitted: +- //if (!checkFormData(request)) +- // return false; +- break; +-#if 0 +- case QWebEnginePage::NavigationTypeFormResubmitted: +- if (!checkFormData(request)) +- return false; +- if (KMessageBox::warningContinueCancel(view(), +- i18n("<qt><p>To display the requested web page again, " +- "the browser needs to resend information you have " +- "previously submitted.</p>" +- "<p>If you were shopping online and made a purchase, " +- "click the Cancel button to prevent a duplicate purchase." +- "Otherwise, click the Continue button to display the web" +- "page again.</p>"), +- i18n("Resubmit Information")) == KMessageBox::Cancel) { +- return false; +- } +- break; +-#endif +- case QWebEnginePage::NavigationTypeBackForward: +- // If history navigation is locked, ignore all such requests... +- if (property("HistoryNavigationLocked").toBool()) { +- setProperty("HistoryNavigationLocked", QVariant()); +- qDebug() << "Rejected history navigation because 'HistoryNavigationLocked' property is set!"; +- return false; +- } +- //kDebug() << "Navigating to item (" << history()->currentItemIndex() +- // << "of" << history()->count() << "):" << history()->currentItem().url(); +- inPageRequest = false; +- break; +- case QWebEnginePage::NavigationTypeReload: +-// setRequestMetaData(QL1S("cache"), QL1S("reload")); +- inPageRequest = false; +- break; +- case QWebEnginePage::NavigationTypeOther: // triggered by javascript +- qDebug() << "Triggered by javascript"; +- inPageRequest = !isTypedUrl; +- break; +- default: +- break; +- } +- +- if (inPageRequest) { +- // if (!checkLinkSecurity(request, type)) +- // return false; +- +- // if (m_sslInfo.isValid()) +- // setRequestMetaData(QL1S("ssl_was_in_use"), QL1S("TRUE")); +- } +- +- +- // Honor the enabling/disabling of plugins per host. +- settings()->setAttribute(QWebEngineSettings::PluginsEnabled, WebEngineSettings::self()->isPluginsEnabled(reqUrl.host())); +- // Insert the request into the queue... +- return QWebEnginePage::acceptNavigationRequest(url, type, isMainFrame); +-} +- +-#if 0 +-static int errorCodeFromReply(QNetworkReply* reply) +-{ +- // First check if there is a KIO error code sent back and use that, +- // if not attempt to convert QNetworkReply's NetworkError to KIO::Error. +- QVariant attr = reply->attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::KioError)); +- if (attr.isValid() && attr.type() == QVariant::Int) +- return attr.toInt(); +- +- switch (reply->error()) { +- case QNetworkReply::ConnectionRefusedError: +- return KIO::ERR_COULD_NOT_CONNECT; +- case QNetworkReply::HostNotFoundError: +- return KIO::ERR_UNKNOWN_HOST; +- case QNetworkReply::TimeoutError: +- return KIO::ERR_SERVER_TIMEOUT; +- case QNetworkReply::OperationCanceledError: +- return KIO::ERR_USER_CANCELED; +- case QNetworkReply::ProxyNotFoundError: +- return KIO::ERR_UNKNOWN_PROXY_HOST; +- case QNetworkReply::ContentAccessDenied: +- return KIO::ERR_ACCESS_DENIED; +- case QNetworkReply::ContentOperationNotPermittedError: +- return KIO::ERR_WRITE_ACCESS_DENIED; +- case QNetworkReply::ContentNotFoundError: +- return KIO::ERR_NO_CONTENT; +- case QNetworkReply::AuthenticationRequiredError: +- return KIO::ERR_COULD_NOT_AUTHENTICATE; +- case QNetworkReply::ProtocolUnknownError: +- return KIO::ERR_UNSUPPORTED_PROTOCOL; +- case QNetworkReply::ProtocolInvalidOperationError: +- return KIO::ERR_UNSUPPORTED_ACTION; +- case QNetworkReply::UnknownNetworkError: +- return KIO::ERR_UNKNOWN; +- case QNetworkReply::NoError: +- default: +- break; +- } +- +- return 0; +-} +-#endif +- +-WebEnginePart* WebEnginePage::part() const +-{ +- return m_part.data(); +-} +- +-void WebEnginePage::setPart(WebEnginePart* part) +-{ +- m_part = part; +-} +- +-void WebEnginePage::slotLoadFinished(bool ok) +-{ +- QUrl requestUrl = url(); +- requestUrl.setUserInfo(QString()); +- const bool shouldResetSslInfo = (m_sslInfo.isValid() && !domainSchemeMatch(requestUrl, m_sslInfo.url())); +-#if 0 +- QWebFrame* frame = qobject_cast<QWebFrame *>(reply->request().originatingObject()); +- if (!frame) +- return; +- const bool isMainFrameRequest = (frame == mainFrame()); +-#else +- // PORTING_TODO +- const bool isMainFrameRequest = true; +-#endif +- +-#if 0 +- // Only deal with non-redirect responses... +- const QVariant redirectVar = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); +- +- if (isMainFrameRequest && redirectVar.isValid()) { +- m_sslInfo.restoreFrom(reply->attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::MetaData)), +- reply->url(), shouldResetSslInfo); +- return; +- } +- +- const int errCode = errorCodeFromReply(reply); +- kDebug() << frame << "is main frame request?" << isMainFrameRequest << requestUrl; +-#endif +- +- if (ok) { +- if (isMainFrameRequest) { +-#if 0 +- m_sslInfo.restoreFrom(reply->attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::MetaData)), +- reply->url(), shouldResetSslInfo); +-#endif +- setPageJScriptPolicy(url()); +- } +- } else { +- // Handle any error... +-#if 0 +- switch (errCode) { +- case 0: +- case KIO::ERR_NO_CONTENT: +- break; +- case KIO::ERR_ABORTED: +- case KIO::ERR_USER_CANCELED: // Do nothing if request is cancelled/aborted +- //kDebug() << "User aborted request!"; +- m_ignoreError = true; +- emit loadAborted(QUrl()); +- return; +- // Handle the user clicking on a link that refers to a directory +- // Since KIO cannot automatically convert a GET request to a LISTDIR one. +- case KIO::ERR_IS_DIRECTORY: +- m_ignoreError = true; +- emit loadAborted(reply->url()); +- return; +- default: +- // Make sure the saveFrameStateRequested signal is emitted so +- // the page can restored properly. +- if (isMainFrameRequest) +- emit saveFrameStateRequested(frame, 0); +- +- m_ignoreError = (reply->attribute(QNetworkRequest::User).toInt() == QNetworkReply::ContentAccessDenied); +- m_kioErrorCode = errCode; +- break; +-#endif +- } +- +- if (isMainFrameRequest) { +- const WebEnginePageSecurity security = (m_sslInfo.isValid() ? PageEncrypted : PageUnencrypted); +- emit m_part->browserExtension()->setPageSecurity(security); +- } +-} +- +-void WebEnginePage::slotUnsupportedContent(QNetworkReply* reply) +-{ +-#if 0 +- //kDebug() << reply->url(); +- QString mimeType; +- KIO::MetaData metaData; +- +- KIO::AccessManager::putReplyOnHold(reply); +- QString downloadCmd; +- checkForDownloadManager(view(), downloadCmd); +- if (!downloadCmd.isEmpty()) { +- reply->setProperty("DownloadManagerExe", downloadCmd); +- } +- +- if (QWePage::handleReply(reply, &mimeType, &metaData)) { +- reply->deleteLater(); +- if (qobject_cast<NewWindowPage*>(this) && isBlankUrl(m_part->url())) { +- m_part->closeUrl(); +- if (m_part->arguments().metaData().contains(QL1S("new-window"))) { +- m_part->widget()->topLevelWidget()->close(); +- } else { +- delete m_part; +- } +- } +- return; +- } +- +- //kDebug() << "mimetype=" << mimeType << "metadata:" << metaData; +- +- if (reply->request().originatingObject() == this->mainFrame()) { +- KParts::OpenUrlArguments args; +- args.setMimeType(mimeType); +- args.metaData() = metaData; +- emit m_part->browserExtension()->openUrlRequest(reply->url(), args, KParts::BrowserArguments()); +- return; +- } +-#endif +- reply->deleteLater(); +- +-} +-void WebEnginePage::slotFeaturePermissionRequested(const QUrl& url, QWebEnginePage::Feature feature) +-{ +- if (url == this->url()) { +- part()->slotShowFeaturePermissionBar(feature); +- return; +- } +- switch(feature) { +- case QWebEnginePage::Notifications: +- // FIXME: We should have a setting to tell if this is enabled, but so far it is always enabled. +- setFeaturePermission(url, feature, QWebEnginePage::PermissionGrantedByUser); +- break; +- case QWebEnginePage::Geolocation: +- if (KMessageBox::warningContinueCancel(0, i18n("This site is attempting to " +- "access information about your " +- "physical location.\n" +- "Do you want to allow it access?"), +- i18n("Network Transmission"), +- KGuiItem(i18n("Allow access")), +- KStandardGuiItem::cancel(), +- QStringLiteral("WarnGeolocation")) == KMessageBox::Cancel) { +- setFeaturePermission(url, feature, QWebEnginePage::PermissionDeniedByUser); +- } else { +- setFeaturePermission(url, feature, QWebEnginePage::PermissionGrantedByUser); +- } +- break; +- default: +- setFeaturePermission(url, feature, QWebEnginePage::PermissionUnknown); +- break; +- } +-} +- +-void WebEnginePage::slotGeometryChangeRequested(const QRect & rect) +-{ +- const QString host = url().host(); +- +- // NOTE: If a new window was created from another window which is in +- // maximized mode and its width and/or height were not specified at the +- // time of its creation, which is always the case in QWebEnginePage::createWindow, +- // then any move operation will seem not to work. That is because the new +- // window will be in maximized mode where moving it will not be possible... +- if (WebEngineSettings::self()->windowMovePolicy(host) == KParts::HtmlSettingsInterface::JSWindowMoveAllow && +- (view()->x() != rect.x() || view()->y() != rect.y())) +- emit m_part->browserExtension()->moveTopLevelWidget(rect.x(), rect.y()); +- +- const int height = rect.height(); +- const int width = rect.width(); +- +- // parts of following code are based on kjs_window.cpp +- // Security check: within desktop limits and bigger than 100x100 (per spec) +- if (width < 100 || height < 100) { +- qWarning() << "Window resize refused, window would be too small (" << width << "," << height << ")"; +- return; +- } +- +- QRect sg = QApplication::desktop()->screenGeometry(view()); +- +- if (width > sg.width() || height > sg.height()) { +- qWarning() << "Window resize refused, window would be too big (" << width << "," << height << ")"; +- return; +- } +- +- if (WebEngineSettings::self()->windowResizePolicy(host) == KParts::HtmlSettingsInterface::JSWindowResizeAllow) { +- //kDebug() << "resizing to " << width << "x" << height; +- emit m_part->browserExtension()->resizeTopLevelWidget(width, height); +- } +- +- // If the window is out of the desktop, move it up/left +- // (maybe we should use workarea instead of sg, otherwise the window ends up below kicker) +- const int right = view()->x() + view()->frameGeometry().width(); +- const int bottom = view()->y() + view()->frameGeometry().height(); +- int moveByX = 0, moveByY = 0; +- if (right > sg.right()) +- moveByX = - right + sg.right(); // always <0 +- if (bottom > sg.bottom()) +- moveByY = - bottom + sg.bottom(); // always <0 +- +- if ((moveByX || moveByY) && WebEngineSettings::self()->windowMovePolicy(host) == KParts::HtmlSettingsInterface::JSWindowMoveAllow) +- emit m_part->browserExtension()->moveTopLevelWidget(view()->x() + moveByX, view()->y() + moveByY); +-} +- +-bool WebEnginePage::checkLinkSecurity(const QNetworkRequest &req, NavigationType type) const +-{ +- // Check whether the request is authorized or not... +- if (!KUrlAuthorized::authorizeUrlAction(QStringLiteral("redirect"), url(), req.url())) { +- +- //kDebug() << "*** Failed security check: base-url=" << mainFrame()->url() << ", dest-url=" << req.url(); +- QString buttonText, title, message; +- +- int response = KMessageBox::Cancel; +- QUrl linkUrl (req.url()); +- +- if (type == QWebEnginePage::NavigationTypeLinkClicked) { +- message = i18n("<qt>This untrusted page links to<br/><b>%1</b>." +- "<br/>Do you want to follow the link?</qt>", linkUrl.url()); +- title = i18n("Security Warning"); +- buttonText = i18nc("follow link despite of security warning", "Follow"); +- } else { +- title = i18n("Security Alert"); +- message = i18n("<qt>Access by untrusted page to<br/><b>%1</b><br/> denied.</qt>", +- linkUrl.toDisplayString().toHtmlEscaped()); +- } +- +- if (buttonText.isEmpty()) { +- KMessageBox::error( 0, message, title); +- } else { +- // Dangerous flag makes the Cancel button the default +- response = KMessageBox::warningContinueCancel(0, message, title, +- KGuiItem(buttonText), +- KStandardGuiItem::cancel(), +- QString(), // no don't ask again info +- KMessageBox::Notify | KMessageBox::Dangerous); +- } +- +- return (response == KMessageBox::Continue); +- } +- +- return true; +-} +- +-bool WebEnginePage::checkFormData(const QNetworkRequest &req) const +-{ +- const QString scheme (req.url().scheme()); +- +- if (m_sslInfo.isValid() && +- !scheme.compare(QL1S("https")) && !scheme.compare(QL1S("mailto")) && +- (KMessageBox::warningContinueCancel(0, +- i18n("Warning: This is a secure form " +- "but it is attempting to send " +- "your data back unencrypted.\n" +- "A third party may be able to " +- "intercept and view this " +- "information.\nAre you sure you " +- "want to send the data unencrypted?"), +- i18n("Network Transmission"), +- KGuiItem(i18n("&Send Unencrypted"))) == KMessageBox::Cancel)) { +- +- return false; +- } +- +- +- if (scheme.compare(QL1S("mailto")) == 0 && +- (KMessageBox::warningContinueCancel(0, i18n("This site is attempting to " +- "submit form data via email.\n" +- "Do you want to continue?"), +- i18n("Network Transmission"), +- KGuiItem(i18n("&Send Email")), +- KStandardGuiItem::cancel(), +- QStringLiteral("WarnTriedEmailSubmit")) == KMessageBox::Cancel)) { +- return false; +- } +- +- return true; +-} +- +-// Sanitizes the "mailto:" url, e.g. strips out any "attach" parameters. +-static QUrl sanitizeMailToUrl(const QUrl &url, QStringList& files) { +- QUrl sanitizedUrl; +- +- // NOTE: This is necessary to ensure we can properly use QUrl's query +- // related APIs to process 'mailto:' urls of form 'mailto:foo@bar.com'. +- if (url.hasQuery()) +- sanitizedUrl = url; +- else +- sanitizedUrl = QUrl(url.scheme() + QL1S(":?") + url.path()); +- +- QUrlQuery query(sanitizedUrl); +- const QList<QPair<QString, QString> > items (query.queryItems()); +- +- QUrlQuery sanitizedQuery; +- for(auto queryItem : items) { +- if (queryItem.first.contains(QL1C('@')) && queryItem.second.isEmpty()) { +- // ### DF: this hack breaks mailto:faure@kde.org, kmail doesn't expect mailto:?to=faure@kde.org +- queryItem.second = queryItem.first; +- queryItem.first = QStringLiteral("to"); +- } else if (QString::compare(queryItem.first, QL1S("attach"), Qt::CaseInsensitive) == 0) { +- files << queryItem.second; +- continue; +- } +- sanitizedQuery.addQueryItem(queryItem.first, queryItem.second); +- } +- +- sanitizedUrl.setQuery(sanitizedQuery); +- return sanitizedUrl; +-} +- +-bool WebEnginePage::handleMailToUrl (const QUrl &url, NavigationType type) const +-{ +- if (QString::compare(url.scheme(), QL1S("mailto"), Qt::CaseInsensitive) == 0) { +- QStringList files; +- QUrl mailtoUrl (sanitizeMailToUrl(url, files)); +- +- switch (type) { +- case QWebEnginePage::NavigationTypeLinkClicked: +- if (!files.isEmpty() && KMessageBox::warningContinueCancelList(0, +- i18n("<qt>Do you want to allow this site to attach " +- "the following files to the email message?</qt>"), +- files, i18n("Email Attachment Confirmation"), +- KGuiItem(i18n("&Allow attachments")), +- KGuiItem(i18n("&Ignore attachments")), QL1S("WarnEmailAttachment")) == KMessageBox::Continue) { +- +- // Re-add the attachments... +- QStringListIterator filesIt (files); +- QUrlQuery query(mailtoUrl); +- while (filesIt.hasNext()) { +- query.addQueryItem(QL1S("attach"), filesIt.next()); +- } +- mailtoUrl.setQuery(query); +- } +- break; +- case QWebEnginePage::NavigationTypeFormSubmitted: +- //case QWebEnginePage::NavigationTypeFormResubmitted: +- if (!files.isEmpty()) { +- KMessageBox::information(0, i18n("This site attempted to attach a file from your " +- "computer in the form submission. The attachment " +- "was removed for your protection."), +- i18n("Attachment Removed"), QStringLiteral("InfoTriedAttach")); +- } +- break; +- default: +- break; +- } +- +- //kDebug() << "Emitting openUrlRequest with " << mailtoUrl; +- emit m_part->browserExtension()->openUrlRequest(mailtoUrl); +- return true; +- } +- +- return false; +-} +- +-void WebEnginePage::setPageJScriptPolicy(const QUrl &url) +-{ +- const QString hostname (url.host()); +- settings()->setAttribute(QWebEngineSettings::JavascriptEnabled, +- WebEngineSettings::self()->isJavaScriptEnabled(hostname)); +- +- const KParts::HtmlSettingsInterface::JSWindowOpenPolicy policy = WebEngineSettings::self()->windowOpenPolicy(hostname); +- settings()->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, +- (policy != KParts::HtmlSettingsInterface::JSWindowOpenDeny && +- policy != KParts::HtmlSettingsInterface::JSWindowOpenSmart)); +-} +- +- +- +- +- +-/************************************* Begin NewWindowPage ******************************************/ +- +-NewWindowPage::NewWindowPage(WebWindowType type, WebEnginePart* part, QWidget* parent) +- :WebEnginePage(part, parent) , m_type(type) , m_createNewWindow(true) +-{ +- Q_ASSERT_X (part, "NewWindowPage", "Must specify a valid KPart"); +- +- connect(this, SIGNAL(menuBarVisibilityChangeRequested(bool)), +- this, SLOT(slotMenuBarVisibilityChangeRequested(bool))); +- connect(this, SIGNAL(toolBarVisibilityChangeRequested(bool)), +- this, SLOT(slotToolBarVisibilityChangeRequested(bool))); +- connect(this, SIGNAL(statusBarVisibilityChangeRequested(bool)), +- this, SLOT(slotStatusBarVisibilityChangeRequested(bool))); +- connect(this, SIGNAL(loadFinished(bool)), this, SLOT(slotLoadFinished(bool))); +-#if QTWEBENGINE_VERSION >= QT_VERSION_CHECK(5, 7, 0) +- if (m_type == WebBrowserBackgroundTab) { +- m_windowArgs.setLowerWindow(true); +- } +-#endif +-} +- +-NewWindowPage::~NewWindowPage() +-{ +-} +- +-static KParts::BrowserArguments browserArgs(WebEnginePage::WebWindowType type) +-{ +- KParts::BrowserArguments bargs; +- switch (type) { +- case WebEnginePage::WebDialog: +- case WebEnginePage::WebBrowserWindow: +- bargs.setForcesNewWindow(true); +- break; +- case WebEnginePage::WebBrowserTab: +-#if QTWEBENGINE_VERSION >= QT_VERSION_CHECK(5, 7, 0) +- case WebEnginePage::WebBrowserBackgroundTab: +-#endif +- // let konq decide, based on user configuration +- //bargs.setNewTab(true); +- break; +- } +- return bargs; +-} +- +-bool NewWindowPage::acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame) +-{ +- //qDebug() << "url:" << url << ", type:" << type << ", isMainFrame:" << isMainFrame << "m_createNewWindow=" << m_createNewWindow; +- if (m_createNewWindow) { +- const QUrl reqUrl (url); +- +- const bool actionRequestedByUser = type != QWebEnginePage::NavigationTypeOther; +- +- if (actionRequestedByUser) { +- if (!part() && !isMainFrame) { +- return false; +- } +- const KParts::HtmlSettingsInterface::JSWindowOpenPolicy policy = WebEngineSettings::self()->windowOpenPolicy(reqUrl.host()); +- switch (policy) { +- case KParts::HtmlSettingsInterface::JSWindowOpenDeny: +- // TODO: Implement support for dealing with blocked pop up windows. +- this->deleteLater(); +- return false; +- case KParts::HtmlSettingsInterface::JSWindowOpenAsk: { +- const QString message = (reqUrl.isEmpty() ? +- i18n("This site is requesting to open a new popup window.\n" +- "Do you want to allow this?") : +- i18n("<qt>This site is requesting to open a popup window to" +- "<p>%1</p><br/>Do you want to allow this?</qt>", +- KStringHandler::rsqueeze(reqUrl.toDisplayString().toHtmlEscaped(), 100))); +- if (KMessageBox::questionYesNo(view(), message, +- i18n("Javascript Popup Confirmation"), +- KGuiItem(i18n("Allow")), +- KGuiItem(i18n("Do Not Allow"))) == KMessageBox::No) { +- // TODO: Implement support for dealing with blocked pop up windows. +- this->deleteLater(); +- return false; +- } +- break; +- } +- default: +- break; +- } +- } +- +- // Browser args... +- KParts::BrowserArguments bargs = browserArgs(m_type); +- +- // OpenUrl args... +- KParts::OpenUrlArguments uargs; +- uargs.setMimeType(QL1S("text/html")); +- uargs.setActionRequestedByUser(actionRequestedByUser); +- +- // Window args... +- KParts::WindowArgs wargs (m_windowArgs); +- +- KParts::ReadOnlyPart* newWindowPart =0; +- part()->browserExtension()->createNewWindow(QUrl(), uargs, bargs, wargs, &newWindowPart); +- qDebug() << "Created new window" << newWindowPart; +- +- if (!newWindowPart) { +- return false; +- } else if (newWindowPart->widget()->topLevelWidget() != part()->widget()->topLevelWidget()) { +- KParts::OpenUrlArguments args; +- args.metaData().insert(QL1S("new-window"), QL1S("true")); +- newWindowPart->setArguments(args); +- } +- +- // Get the webview... +- WebEnginePart* webenginePart = qobject_cast<WebEnginePart*>(newWindowPart); +- WebEngineView* webView = webenginePart ? qobject_cast<WebEngineView*>(webenginePart->view()) : 0; +- +- // If the newly created window is NOT a webenginepart... +- if (!webView) { +- qDebug() << "Opening URL on" << newWindowPart; +- newWindowPart->openUrl(reqUrl); +- this->deleteLater(); +- return false; +- } +- // Reparent this page to the new webview to prevent memory leaks. +- setParent(webView); +- // Replace the webpage of the new webview with this one. Nice trick... +- webView->setPage(this); +- // Set the new part as the one this page will use going forward. +- setPart(webenginePart); +- // Connect all the signals from this page to the slots in the new part. +- webenginePart->connectWebEnginePageSignals(this); +- //Set the create new window flag to false... +- m_createNewWindow = false; +- } +- +- return WebEnginePage::acceptNavigationRequest(url, type, isMainFrame); +-} +- +-void NewWindowPage::slotGeometryChangeRequested(const QRect & rect) +-{ +- if (!rect.isValid()) +- return; +- +- if (!m_createNewWindow) { +- WebEnginePage::slotGeometryChangeRequested(rect); +- return; +- } +- +- m_windowArgs.setX(rect.x()); +- m_windowArgs.setY(rect.y()); +- m_windowArgs.setWidth(qMax(rect.width(), 100)); +- m_windowArgs.setHeight(qMax(rect.height(), 100)); +-} +- +-void NewWindowPage::slotMenuBarVisibilityChangeRequested(bool visible) +-{ +- //kDebug() << visible; +- m_windowArgs.setMenuBarVisible(visible); +-} +- +-void NewWindowPage::slotStatusBarVisibilityChangeRequested(bool visible) +-{ +- //kDebug() << visible; +- m_windowArgs.setStatusBarVisible(visible); +-} +- +-void NewWindowPage::slotToolBarVisibilityChangeRequested(bool visible) +-{ +- //kDebug() << visible; +- m_windowArgs.setToolBarsVisible(visible); +-} +- +-// When is this called? (and acceptNavigationRequest is not called?) +-// The only case I found is Ctrl+click on link to data URL (like in konqviewmgrtest), that's quite specific... +-// Everything else seems to work with this method being commented out... +-void NewWindowPage::slotLoadFinished(bool ok) +-{ +- Q_UNUSED(ok) +- qDebug() << ok; +- if (!m_createNewWindow) +- return; +- +- const bool actionRequestedByUser = true; // ### we don't have the information here, unlike in acceptNavigationRequest +- +- // Browser args... +- KParts::BrowserArguments bargs = browserArgs(m_type); +- //bargs.frameName = mainFrame()->frameName(); +- +- // OpenUrl args... +- KParts::OpenUrlArguments uargs; +- uargs.setMimeType(QL1S("text/html")); +- uargs.setActionRequestedByUser(actionRequestedByUser); +- +- // Window args... +- KParts::WindowArgs wargs (m_windowArgs); +- +- KParts::ReadOnlyPart* newWindowPart =0; +- part()->browserExtension()->createNewWindow(QUrl(), uargs, bargs, wargs, &newWindowPart); +- +- qDebug() << "Created new window or tab" << newWindowPart; +- +- // Get the webview... +- WebEnginePart* webenginePart = newWindowPart ? qobject_cast<WebEnginePart*>(newWindowPart) : 0; +- WebEngineView* webView = webenginePart ? qobject_cast<WebEngineView*>(webenginePart->view()) : 0; +- +- if (webView) { +- // if a new window is created, set a new window meta-data flag. +- if (newWindowPart->widget()->topLevelWidget() != part()->widget()->topLevelWidget()) { +- KParts::OpenUrlArguments args; +- args.metaData().insert(QL1S("new-window"), QL1S("true")); +- newWindowPart->setArguments(args); +- } +- // Reparent this page to the new webview to prevent memory leaks. +- setParent(webView); +- // Replace the webpage of the new webview with this one. Nice trick... +- webView->setPage(this); +- // Set the new part as the one this page will use going forward. +- setPart(webenginePart); +- // Connect all the signals from this page to the slots in the new part. +- webenginePart->connectWebEnginePageSignals(this); +- } +- +- //Set the create new window flag to false... +- m_createNewWindow = false; +-} +- +-/****************************** End NewWindowPage *************************************************/ +- +diff --git a/webenginepart/src/webenginepage.h a/webenginepart/src/webenginepage.h +deleted file mode 100644 +index 0cd74ac1b..000000000 +--- a/webenginepart/src/webenginepage.h ++++ /dev/null +@@ -1,162 +0,0 @@ +-/* +- * This file is part of the KDE project. +- * +- * Copyright (C) 2008 Dirk Mueller <mueller@kde.org> +- * Copyright (C) 2008 Urs Wolfer <uwolfer @ kde.org> +- * Copyright (C) 2009 Dawit Alemayehu <adawit@kde.org> +- * +- * This library is free software; you can redistribute it and/or modify it +- * under the terms of the GNU Lesser General Public License as published by the +- * Free Software Foundation; either version 2.1 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 Lesser General Public License for more +- * details. +- * +- * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- */ +- +-#ifndef WEBENGINEPAGE_H +-#define WEBENGINEPAGE_H +- +-#include "websslinfo.h" +- +-#include <KParts/BrowserExtension> +-#include <QtWebEngineWidgets/QWebEnginePage> +- +-#include <QUrl> +-#include <QDebug> +-#include <QMultiHash> +-#include <QPointer> +- +-class QUrl; +-class WebSslInfo; +-class WebEnginePart; +-class QWebEngineDownloadItem; +- +- +-class WebEnginePage : public QWebEnginePage +-{ +- Q_OBJECT +-public: +- explicit WebEnginePage(WebEnginePart *wpart, QWidget *parent = Q_NULLPTR); +- ~WebEnginePage(); +- +- /** +- * Returns the SSL information for the current page. +- * +- * @see WebSslInfo. +- */ +- const WebSslInfo& sslInfo() const; +- +- /** +- * Sets the page's SSL information to @p other. +- * +- * @see WebSslInfo +- */ +- void setSslInfo (const WebSslInfo &other); +- +- /** +- * Reimplemented for internal reasons. The API is not affected. +- * +- * @internal +- * @see KWebEnginePage::downloadRequest. +- */ +- void downloadRequest(QWebEngineDownloadItem* request); +- +-Q_SIGNALS: +- /** +- * This signal is emitted whenever a user cancels/aborts a load resource +- * request. +- */ +- void loadAborted(const QUrl &url); +- +-protected: +- /** +- * Returns the webengine part in use by this object. +- * @internal +- */ +- WebEnginePart* part() const; +- +- /** +- * Sets the webengine part to be used by this object. +- * @internal +- */ +- void setPart(WebEnginePart*); +- +- /** +- * Reimplemented for internal reasons, the API is not affected. +- * @internal +- */ +- QWebEnginePage* createWindow(WebWindowType type) Q_DECL_OVERRIDE; +- +- /** +- * Reimplemented for internal reasons, the API is not affected. +- * @internal +- */ +- bool acceptNavigationRequest(const QUrl& request, NavigationType type, bool isMainFrame) Q_DECL_OVERRIDE; +- +-protected Q_SLOTS: +- void slotLoadFinished(bool ok); +- void slotUnsupportedContent(QNetworkReply* reply); +- virtual void slotGeometryChangeRequested(const QRect& rect); +- void slotFeaturePermissionRequested(const QUrl& url, QWebEnginePage::Feature feature); +- +-private: +- bool checkLinkSecurity(const QNetworkRequest& req, NavigationType type) const; +- bool checkFormData(const QNetworkRequest& req) const; +- bool handleMailToUrl (const QUrl& , NavigationType type) const; +- void setPageJScriptPolicy(const QUrl& url); +- +-private: +- enum WebEnginePageSecurity { PageUnencrypted, PageEncrypted, PageMixed }; +- +- int m_kioErrorCode; +- bool m_ignoreError; +- +- WebSslInfo m_sslInfo; +- QPointer<WebEnginePart> m_part; +-}; +- +- +-/** +- * This is a fake implementation of WebEnginePage to workaround the ugly API used +- * to request for the creation of a new window from javascript in QtWebEngine. PORTING_TODO +- * +- * The KPart API for creating new windows requires all the information about the +- * new window up front. Unfortunately QWebEnginePage::createWindow function does not +- * provide any of these necessary information except for the window type. All +- * the other necessary information is emitted as signals instead! Hence, the +- * need for this class to collect all of the necessary information, such as +- * window name, size and position, before calling KPart's createNewWindow +- * function. +- */ +-class NewWindowPage : public WebEnginePage +-{ +- Q_OBJECT +-public: +- NewWindowPage(WebWindowType windowType, WebEnginePart* part, +- QWidget* parent = Q_NULLPTR); +- virtual ~NewWindowPage(); +- +-protected: +- bool acceptNavigationRequest(const QUrl& request, NavigationType type, bool isMainFrame) Q_DECL_OVERRIDE; +- +-private Q_SLOTS: +- void slotGeometryChangeRequested(const QRect& rect) override; +- void slotMenuBarVisibilityChangeRequested(bool visible); +- void slotStatusBarVisibilityChangeRequested(bool visible); +- void slotToolBarVisibilityChangeRequested(bool visible); +- void slotLoadFinished(bool); +- +-private: +- KParts::WindowArgs m_windowArgs; +- WebWindowType m_type; +- bool m_createNewWindow; +-}; +- +-#endif // WEBENGINEPAGE_H +diff --git a/webenginepart/src/webenginepart.cpp a/webenginepart/src/webenginepart.cpp +deleted file mode 100644 +index 10bbffc15..000000000 +--- a/webenginepart/src/webenginepart.cpp ++++ /dev/null +@@ -1,926 +0,0 @@ +-/* +- * This file is part of the KDE project. +- * +- * Copyright (C) 2007 Trolltech ASA +- * Copyright (C) 2008 - 2010 Urs Wolfer <uwolfer @ kde.org> +- * Copyright (C) 2008 Laurent Montel <montel@kde.org> +- * Copyright (C) 2009 Dawit Alemayehu <adawit@kde.org> +- * Copyright (C) 2013 Allan Sandfeld Jensen <sandfeld@kde.org> +- * +- * This library is free software; you can redistribute it and/or modify it +- * under the terms of the GNU Lesser General Public License as published by the +- * Free Software Foundation; either version 2.1 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 Lesser General Public License for more +- * details. +- * +- * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- */ +- +-#include "webenginepart.h" +- +-//#include <QWebHistoryItem> +-#include <QWebEngineSettings> +-#include <QWebEngineProfile> +-#include <QUrlQuery> +- +-#include "webenginepart_ext.h" +-#include "webengineview.h" +-#include "webenginepage.h" +-#include "websslinfo.h" +-#include "webhistoryinterface.h" +- +-#include "ui/searchbar.h" +-#include "ui/passwordbar.h" +-#include "ui/featurepermissionbar.h" +-#include "settings/webenginesettings.h" +- +-#include <kcodecaction.h> +-#include <kio/global.h> +- +-#include <KActionCollection> +-#include <KAboutData> +-#include <KUrlLabel> +-#include <KMessageBox> +-#include <KStringHandler> +-#include <KToolInvocation> +-#include <KAcceleratorManager> +-#include <KFileItem> +-#include <KMessageWidget> +-#include <KProtocolInfo> +-#include <KToggleAction> +-#include <KParts/StatusBarExtension> +-#include <KParts/GUIActivateEvent> +-#include <KLocalizedString> +-#include <KConfigGroup> +-#include <KSharedConfig> +-#include <KSslInfoDialog> +- +-#include <QUrl> +-#include <QFile> +-#include <QTextCodec> +-#include <QCoreApplication> +-#include <QVBoxLayout> +-#include <QDBusInterface> +-#include <QMenu> +-#include <QStatusBar> +-#include "utils.h" +- +-WebEnginePart::WebEnginePart(QWidget *parentWidget, QObject *parent, +- const QByteArray& cachedHistory, const QStringList& /*args*/) +- :KParts::ReadOnlyPart(parent), +- m_emitOpenUrlNotify(true), +- m_hasCachedFormData(false), +- m_doLoadFinishedActions(false), +- m_statusBarWalletLabel(0), +- m_searchBar(0), +- m_passwordBar(0), +- m_featurePermissionBar(0) +-{ +- KAboutData about = KAboutData(QStringLiteral("webenginepart"), +- i18nc("Program Name", "WebEnginePart"), +- /*version*/ QStringLiteral("1.3.0"), +- i18nc("Short Description", "QtWebEngine Browser Engine Component"), +- KAboutLicense::LGPL, +- i18n("(C) 2009-2010 Dawit Alemayehu\n" +- "(C) 2008-2010 Urs Wolfer\n" +- "(C) 2007 Trolltech ASA")); +- +- about.addAuthor(i18n("Sune Vuorela"), i18n("Maintainer, Developer"), QStringLiteral("sune@kde.org")); +- about.addAuthor(i18n("Dawit Alemayehu"), i18n("Developer"), QStringLiteral("adawit@kde.org")); +- about.addAuthor(i18n("Urs Wolfer"), i18n("Maintainer, Developer"), QStringLiteral("uwolfer@kde.org")); +- about.addAuthor(i18n("Michael Howell"), i18n("Developer"), QStringLiteral("mhowell123@gmail.com")); +- about.addAuthor(i18n("Laurent Montel"), i18n("Developer"), QStringLiteral("montel@kde.org")); +- about.addAuthor(i18n("Dirk Mueller"), i18n("Developer"), QStringLiteral("mueller@kde.org")); +- about.setProductName("webenginepart/general"); +-// KComponentData componentData(&about); +- setComponentData(about, false /*don't load plugins yet*/); +- +-#if 0 +- // NOTE: If the application does not set its version number, we automatically +- // set it to KDE's version number so that the default user-agent string contains +- // proper application version number information. See QWebEnginePage::userAgentForUrl... +- if (QCoreApplication::applicationVersion().isEmpty()) +- QCoreApplication::setApplicationVersion(QString("%1.%2.%3") +- .arg(KDE::versionMajor()) +- .arg(KDE::versionMinor()) +- .arg(KDE::versionRelease())); +-#endif +- setXMLFile(QL1S("webenginepart.rc")); +- +- // Create this KPart's widget +- QWidget *mainWidget = new QWidget (parentWidget); +- mainWidget->setObjectName(QStringLiteral("webenginepart")); +- +- // Create the WebEngineView... +- m_webView = new WebEngineView (this, parentWidget); +- +- // Create the browser extension. +- m_browserExtension = new WebEngineBrowserExtension(this, cachedHistory); +- +- // Add status bar extension... +- m_statusBarExtension = new KParts::StatusBarExtension(this); +- +- // Add a web history interface for storing visited links. +-// if (!QWebEngineHistoryInterface::defaultInterface()) +-// QWebHistoryInterface::setDefaultInterface(new WebHistoryInterface(this)); +- +- // Add text and html extensions... +- new WebEngineTextExtension(this); +- new WebEngineHtmlExtension(this); +- new WebEngineScriptableExtension(this); +- +- +- // Layout the GUI... +- QVBoxLayout* l = new QVBoxLayout(mainWidget); +- l->setContentsMargins(0, 0, 0, 0); +- l->setSpacing(0); +- l->addWidget(m_webView); +- +- // Set the part's widget +- setWidget(mainWidget); +- +- // Set the web view as the the focus object +- mainWidget->setFocusProxy(m_webView); +- +- // Connect the signals from the webview +- connect(m_webView, &QWebEngineView::titleChanged, +- this, &Part::setWindowCaption); +- connect(m_webView, &QWebEngineView::urlChanged, +- this, &WebEnginePart::slotUrlChanged); +-// connect(m_webView, SIGNAL(linkMiddleOrCtrlClicked(QUrl)), +-// this, SLOT(slotLinkMiddleOrCtrlClicked(QUrl))); +-// connect(m_webView, SIGNAL(selectionClipboardUrlPasted(QUrl,QString)), +-// this, SLOT(slotSelectionClipboardUrlPasted(QUrl,QString))); +- connect(m_webView, &QWebEngineView::loadFinished, +- this, &WebEnginePart::slotLoadFinished); +- +- // Connect the signals from the page... +- connectWebEnginePageSignals(page()); +- +- // Init the QAction we are going to use... +- initActions(); +- +- // Load plugins once we are fully ready +- loadPlugins(); +-} +- +-WebEnginePart::~WebEnginePart() +-{ +-} +- +-WebEnginePage* WebEnginePart::page() +-{ +- if (m_webView) +- return qobject_cast<WebEnginePage*>(m_webView->page()); +- return Q_NULLPTR; +-} +- +-const WebEnginePage* WebEnginePart::page() const +-{ +- if (m_webView) +- return qobject_cast<const WebEnginePage*>(m_webView->page()); +- return Q_NULLPTR; +-} +- +-void WebEnginePart::initActions() +-{ +- actionCollection()->addAction(KStandardAction::SaveAs, QStringLiteral("saveDocument"), +- m_browserExtension, SLOT(slotSaveDocument())); +- +- QAction* action = new QAction(i18n("Save &Frame As..."), this); +- actionCollection()->addAction(QStringLiteral("saveFrame"), action); +- connect(action, &QAction::triggered, m_browserExtension, &WebEngineBrowserExtension::slotSaveFrame); +- +- action = new QAction(QIcon::fromTheme(QStringLiteral("document-print-preview")), i18n("Print Preview"), this); +- actionCollection()->addAction(QStringLiteral("printPreview"), action); +- connect(action, &QAction::triggered, m_browserExtension, &WebEngineBrowserExtension::slotPrintPreview); +- +- action = new QAction(QIcon::fromTheme(QStringLiteral("zoom-in")), i18nc("zoom in action", "Zoom In"), this); +- actionCollection()->addAction(QStringLiteral("zoomIn"), action); +- actionCollection()->setDefaultShortcuts(action, QList<QKeySequence> () << QKeySequence(QStringLiteral("CTRL++")) << QKeySequence(QStringLiteral("CTRL+="))); +- connect(action, &QAction::triggered, m_browserExtension, &WebEngineBrowserExtension::zoomIn); +- +- action = new QAction(QIcon::fromTheme(QStringLiteral("zoom-out")), i18nc("zoom out action", "Zoom Out"), this); +- actionCollection()->addAction(QStringLiteral("zoomOut"), action); +- actionCollection()->setDefaultShortcuts(action, QList<QKeySequence> () << QKeySequence(QStringLiteral("CTRL+-")) << QKeySequence(QStringLiteral("CTRL+_"))); +- connect(action, &QAction::triggered, m_browserExtension, &WebEngineBrowserExtension::zoomOut); +- +- action = new QAction(QIcon::fromTheme(QStringLiteral("zoom-original")), i18nc("reset zoom action", "Actual Size"), this); +- actionCollection()->addAction(QStringLiteral("zoomNormal"), action); +- actionCollection()->setDefaultShortcut(action, QKeySequence(QStringLiteral("CTRL+0"))); +- connect(action, &QAction::triggered, m_browserExtension, &WebEngineBrowserExtension::zoomNormal); +- +- action = new QAction(i18n("Zoom Text Only"), this); +- action->setCheckable(true); +- KConfigGroup cgHtml(KSharedConfig::openConfig(), "HTML Settings"); +- bool zoomTextOnly = cgHtml.readEntry("ZoomTextOnly", false); +- action->setChecked(zoomTextOnly); +- actionCollection()->addAction(QStringLiteral("zoomTextOnly"), action); +- connect(action, &QAction::triggered, m_browserExtension, &WebEngineBrowserExtension::toogleZoomTextOnly); +- +- action = new QAction(i18n("Zoom To DPI"), this); +- action->setCheckable(true); +- bool zoomToDPI = cgHtml.readEntry("ZoomToDPI", false); +- action->setChecked(zoomToDPI); +- actionCollection()->addAction(QStringLiteral("zoomToDPI"), action); +- connect(action, &QAction::triggered, m_browserExtension, &WebEngineBrowserExtension::toogleZoomToDPI); +- +- action = actionCollection()->addAction(KStandardAction::SelectAll, QStringLiteral("selectAll"), +- m_browserExtension, SLOT(slotSelectAll())); +- action->setShortcutContext(Qt::WidgetShortcut); +- m_webView->addAction(action); +- +- KCodecAction *codecAction = new KCodecAction( QIcon::fromTheme(QStringLiteral("character-set")), i18n( "Set &Encoding" ), this, true ); +- actionCollection()->addAction( QStringLiteral("setEncoding"), codecAction ); +- connect(codecAction, SIGNAL(triggered(QTextCodec*)), SLOT(slotSetTextEncoding(QTextCodec*))); +- +- action = new QAction(i18n("View Do&cument Source"), this); +- actionCollection()->addAction(QStringLiteral("viewDocumentSource"), action); +- actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_U)); +- connect(action, &QAction::triggered, m_browserExtension, &WebEngineBrowserExtension::slotViewDocumentSource); +- +- action = new QAction(i18nc("Secure Sockets Layer", "SSL"), this); +- actionCollection()->addAction(QStringLiteral("security"), action); +- connect(action, &QAction::triggered, this, &WebEnginePart::slotShowSecurity); +- +- action = actionCollection()->addAction(KStandardAction::Find, QStringLiteral("find"), this, SLOT(slotShowSearchBar())); +- action->setWhatsThis(i18nc("find action \"whats this\" text", "<h3>Find text</h3>" +- "Shows a dialog that allows you to find text on the displayed page.")); +-} +- +-void WebEnginePart::updateActions() +-{ +- m_browserExtension->updateActions(); +- +- QAction* action = actionCollection()->action(QL1S("saveDocument")); +- if (action) { +- const QString protocol (url().scheme()); +- action->setEnabled(protocol != QL1S("about") && protocol != QL1S("error")); +- } +- +- action = actionCollection()->action(QL1S("printPreview")); +- if (action) { +- action->setEnabled(m_browserExtension->isActionEnabled("print")); +- } +- +-} +- +-void WebEnginePart::connectWebEnginePageSignals(WebEnginePage* page) +-{ +- if (!page) +- return; +- +- connect(page, SIGNAL(loadStarted()), +- this, SLOT(slotLoadStarted())); +- connect(page, SIGNAL(loadAborted(QUrl)), +- this, SLOT(slotLoadAborted(QUrl))); +- connect(page, &QWebEnginePage::linkHovered, +- this, &WebEnginePart::slotLinkHovered); +-// connect(page, SIGNAL(saveFrameStateRequested(QWebFrame*,QWebHistoryItem*)), +-// this, SLOT(slotSaveFrameState(QWebFrame*,QWebHistoryItem*))); +-// connect(page, SIGNAL(restoreFrameStateRequested(QWebFrame*)), +-// this, SLOT(slotRestoreFrameState(QWebFrame*))); +-// connect(page, SIGNAL(statusBarMessage(QString)), +-// this, SLOT(slotSetStatusBarText(QString))); +- connect(page, SIGNAL(windowCloseRequested()), +- this, SLOT(slotWindowCloseRequested())); +-// connect(page, SIGNAL(printRequested(QWebFrame*)), +-// m_browserExtension, SLOT(slotPrintRequested(QWebFrame*))); +- // connect(page, SIGNAL(frameCreated(QWebFrame*)), +- // this, SLOT(slotFrameCreated(QWebFrame*))); +- +-// connect(m_webView, SIGNAL(linkShiftClicked(QUrl)), +-// page, SLOT(downloadUrl(QUrl))); +- +- connect(page, SIGNAL(loadProgress(int)), +- m_browserExtension, SIGNAL(loadingProgress(int))); +- connect(page, SIGNAL(selectionChanged()), +- m_browserExtension, SLOT(updateEditActions())); +-// connect(m_browserExtension, SIGNAL(saveUrl(QUrl)), +-// page, SLOT(downloadUrl(QUrl))); +- +- connect(page, &QWebEnginePage::iconUrlChanged, [page, this](const QUrl& url) { +- if (WebEngineSettings::self()->favIconsEnabled() +- && !page->profile()->isOffTheRecord()){ +- m_browserExtension->setIconUrl(url); +- } +- }); +- +-#if 0 +- KWebWallet *wallet = page->wallet(); +- if (wallet) { +- connect(wallet, SIGNAL(saveFormDataRequested(QString,QUrl)), +- this, SLOT(slotSaveFormDataRequested(QString,QUrl))); +- connect(wallet, SIGNAL(fillFormRequestCompleted(bool)), +- this, SLOT(slotFillFormRequestCompleted(bool))); +- connect(wallet, SIGNAL(walletClosed()), this, SLOT(slotWalletClosed())); +- } +-#endif +-} +- +-bool WebEnginePart::openUrl(const QUrl &_u) +-{ +- QUrl u (_u); +- +- qDebug() << u; +- +- // Ignore empty requests... +- if (u.isEmpty()) +- return false; +- +- // If the URL given is a supported local protocol, e.g. "bookmark" but lacks +- // a path component, we set the path to "/" here so that the security context +- // will properly allow access to local resources. +- if (u.host().isEmpty() && u.path().isEmpty() +- && KProtocolInfo::protocolClass(u.scheme()) == QL1S(":local")) { +- u.setPath(QL1S("/")); +- } +- +- // Do not emit update history when url is typed in since the host +- // should handle that automatically itself. +- m_emitOpenUrlNotify = false; +- +- // Pointer to the page object... +- WebEnginePage* p = page(); +- Q_ASSERT(p); +- +- KParts::BrowserArguments bargs (m_browserExtension->browserArguments()); +- KParts::OpenUrlArguments args (arguments()); +- +- if (!Utils::isBlankUrl(u)) { +- // Get the SSL information sent, if any... +- if (args.metaData().contains(QL1S("ssl_in_use"))) { +- WebSslInfo sslInfo; +- sslInfo.restoreFrom(KIO::MetaData(args.metaData()).toVariant()); +- sslInfo.setUrl(u); +- p->setSslInfo(sslInfo); +- } +- } +- +- // Set URL in KParts before emitting started; konq plugins rely on that. +- setUrl(u); +- m_doLoadFinishedActions = true; +- m_webView->loadUrl(u, args, bargs); +- return true; +-} +- +-bool WebEnginePart::closeUrl() +-{ +- m_webView->triggerPageAction(QWebEnginePage::Stop); +- m_webView->stop(); +- return true; +-} +- +-QWebEngineView* WebEnginePart::view() +-{ +- return m_webView; +-} +- +-bool WebEnginePart::isModified() const +-{ +- //return m_webView->isModified(); +- return false; +-} +- +-void WebEnginePart::guiActivateEvent(KParts::GUIActivateEvent *event) +-{ +- if (event && event->activated() && m_webView) { +- emit setWindowCaption(m_webView->title()); +- } +-} +- +-bool WebEnginePart::openFile() +-{ +- // never reached +- return false; +-} +- +- +-/// slots... +- +-void WebEnginePart::slotLoadStarted() +-{ +- if(!Utils::isBlankUrl(url())) +- { +- emit started(0); +- } +- updateActions(); +- +- // If "NoEmitOpenUrlNotification" property is set to true, do not +- // emit the open url notification. Property is set by this part's +- // extension to prevent openUrl notification being sent when +- // handling history navigation requests (back/forward). +- const bool doNotEmitOpenUrl = property("NoEmitOpenUrlNotification").toBool(); +- if (doNotEmitOpenUrl) { +- setProperty("NoEmitOpenUrlNotification", QVariant()); +- } else { +- if (m_emitOpenUrlNotify) { +- emit m_browserExtension->openUrlNotify(); +- } +- } +- // Unless we go via openUrl again, the next time we are here we emit (e.g. after clicking on a link) +- m_emitOpenUrlNotify = true; +-} +- +-void WebEnginePart::slotLoadFinished (bool ok) +-{ +- if (!ok || !m_doLoadFinishedActions) +- return; +- +- slotWalletClosed(); +- m_doLoadFinishedActions = false; +- +- // If the document contains no <title> tag, then set it to the current url. +- if (m_webView->title().trimmed().isEmpty()) { +- // If the document title is empty, then set it to the current url +- const QUrl url (m_webView->url()); +- const QString caption (url.toString((QUrl::RemoveQuery|QUrl::RemoveFragment))); +- emit setWindowCaption(caption); +- +- // The urlChanged signal is emitted if and only if the main frame +- // receives the title of the page so we manually invoke the slot as a +- // work around here for pages that do not contain it, such as text +- // documents... +- slotUrlChanged(url); +- } +- if (!Utils::isBlankUrl(url())) { +- m_hasCachedFormData = false; +- +- if (WebEngineSettings::self()->isNonPasswordStorableSite(url().host())) { +- addWalletStatusBarIcon(); +- } else { +-// Attempt to fill the web form... +-// KWebWallet *webWallet = page() ? page()->wallet() : 0; +-// if (webWallet) { +-// webWallet->fillFormData(frame, false); +-// } +- } +- } +- +- bool pending = false; +- // QWebFrame* frame = (page() ? page()->currentFrame() : 0); +- // if (ok && +- // frame == page()->mainFrame() && +- // !frame->findFirstElement(QL1S("head>meta[http-equiv=refresh]")).isNull()) { +- // if (WebEngineSettings::self()->autoPageRefresh()) { +- // pending = true; +- // } else { +- // frame->page()->triggerAction(QWebEnginePage::Stop); +- // } +- // } +- emit completed ((ok && pending)); +- +- updateActions(); +-} +- +-void WebEnginePart::slotLoadAborted(const QUrl & url) +-{ +- closeUrl(); +- m_doLoadFinishedActions = false; +- if (url.isValid()) +- emit m_browserExtension->openUrlRequest(url); +- else +- setUrl(m_webView->url()); +-} +- +-void WebEnginePart::slotUrlChanged(const QUrl& url) +-{ +- // Ignore if empty +- if (url.isEmpty()) +- return; +- +- // Ignore if error url +- if (url.scheme() == QL1S("error")) +- return; +- +- const QUrl u (url); +- +- // Ignore if url has not changed! +- if (this->url() == u) +- return; +- +- m_doLoadFinishedActions = true; +- setUrl(u); +- +- // Do not update the location bar with about:blank +- if (!Utils::isBlankUrl(url)) { +- //kDebug() << "Setting location bar to" << u.prettyUrl() << "current URL:" << this->url(); +- emit m_browserExtension->setLocationBarUrl(u.toDisplayString()); +- } +-} +- +-void WebEnginePart::slotShowSecurity() +-{ +- if (!page()) +- return; +- +- const WebSslInfo& sslInfo = page()->sslInfo(); +- if (!sslInfo.isValid()) { +- KMessageBox::information(0, i18n("The SSL information for this site " +- "appears to be corrupt."), +- i18nc("Secure Sockets Layer", "SSL")); +- return; +- } +- +- KSslInfoDialog *dlg = new KSslInfoDialog (widget()); +- dlg->setSslInfo(sslInfo.certificateChain(), +- sslInfo.peerAddress().toString(), +- url().host(), +- sslInfo.protocol(), +- sslInfo.ciphers(), +- sslInfo.usedChiperBits(), +- sslInfo.supportedChiperBits(), +- KSslInfoDialog::errorsFromString(sslInfo.certificateErrors())); +- +- dlg->open(); +-} +- +-#if 0 +-void WebEnginePart::slotSaveFrameState(QWebFrame *frame, QWebHistoryItem *item) +-{ +- if (!frame || !item) { +- return; +- } +- +- // Handle actions that apply only to the mainframe... +- if (frame == view()->page()->mainFrame()) { +- } +- +- // For some reason, QtWebEngine PORTING_TODO does not restore scroll position when +- // QWebHistory is restored from persistent storage. Therefore, we +- // preserve that information and restore it as needed. See +- // slotRestoreFrameState. +- const QPoint scrollPos (frame->scrollPosition()); +- if (!scrollPos.isNull()) { +- // kDebug() << "Saving scroll position:" << scrollPos; +- item->setUserData(scrollPos); +- } +-} +-#endif +- +-#if 0 +-void WebEnginePart::slotRestoreFrameState(QWebFrame *frame) +-{ +- QWebEnginePage* page = (frame ? frame->page() : 0); +- QWebHistory* history = (page ? page->history() : 0); +- +- // No history item... +- if (!history || history->count() < 1) +- return; +- +- QWebHistoryItem currentHistoryItem (history->currentItem()); +- +- // Update the scroll position if needed. See comment in slotSaveFrameState above. +- if (frame->baseUrl().resolved(frame->url()) == currentHistoryItem.url()) { +- const QPoint currentPos (frame->scrollPosition()); +- const QPoint desiredPos (currentHistoryItem.userData().toPoint()); +- if (currentPos.isNull() && !desiredPos.isNull()) { +- frame->setScrollPosition(desiredPos); +- } +- } +-} +-#endif +- +-void WebEnginePart::slotLinkHovered(const QString& _link) +-{ +- QString message; +- +- if (_link.isEmpty()) { +- message = QL1S(""); +- emit m_browserExtension->mouseOverInfo(KFileItem()); +- } else { +- QUrl linkUrl (_link); +- const QString scheme = linkUrl.scheme(); +- +- // Protect the user against URL spoofing! +- linkUrl.setUserName(QString()); +- const QString link (linkUrl.toString()); +- +- if (QString::compare(scheme, QL1S("mailto"), Qt::CaseInsensitive) == 0) { +- message += i18nc("status bar text when hovering email links; looks like \"Email: xy@kde.org - CC: z@kde.org -BCC: x@kde.org - Subject: Hi translator\"", "Email: "); +- +- // Workaround: for QUrl's parsing deficiencies of "mailto:foo@bar.com". +- if (!linkUrl.hasQuery()) +- linkUrl = QUrl(scheme + '?' + linkUrl.path()); +- +- QMap<QString, QStringList> fields; +- QUrlQuery query(linkUrl); +- QList<QPair<QString, QString> > queryItems = query.queryItems(); +- const int count = queryItems.count(); +- +- for(int i = 0; i < count; ++i) { +- const QPair<QString, QString> queryItem (queryItems.at(i)); +- //kDebug() << "query: " << queryItem.first << queryItem.second; +- if (queryItem.first.contains(QL1C('@')) && queryItem.second.isEmpty()) +- fields[QStringLiteral("to")] << queryItem.first; +- if (QString::compare(queryItem.first, QL1S("to"), Qt::CaseInsensitive) == 0) +- fields[QStringLiteral("to")] << queryItem.second; +- if (QString::compare(queryItem.first, QL1S("cc"), Qt::CaseInsensitive) == 0) +- fields[QStringLiteral("cc")] << queryItem.second; +- if (QString::compare(queryItem.first, QL1S("bcc"), Qt::CaseInsensitive) == 0) +- fields[QStringLiteral("bcc")] << queryItem.second; +- if (QString::compare(queryItem.first, QL1S("subject"), Qt::CaseInsensitive) == 0) +- fields[QStringLiteral("subject")] << queryItem.second; +- } +- +- if (fields.contains(QL1S("to"))) +- message += fields.value(QL1S("to")).join(QL1S(", ")); +- if (fields.contains(QL1S("cc"))) +- message += i18nc("status bar text when hovering email links; looks like \"Email: xy@kde.org - CC: z@kde.org -BCC: x@kde.org - Subject: Hi translator\"", " - CC: ") + fields.value(QL1S("cc")).join(QL1S(", ")); +- if (fields.contains(QL1S("bcc"))) +- message += i18nc("status bar text when hovering email links; looks like \"Email: xy@kde.org - CC: z@kde.org -BCC: x@kde.org - Subject: Hi translator\"", " - BCC: ") + fields.value(QL1S("bcc")).join(QL1S(", ")); +- if (fields.contains(QL1S("subject"))) +- message += i18nc("status bar text when hovering email links; looks like \"Email: xy@kde.org - CC: z@kde.org -BCC: x@kde.org - Subject: Hi translator\"", " - Subject: ") + fields.value(QL1S("subject")).join(QL1S(" ")); +- } else if (scheme == QL1S("javascript")) { +- message = KStringHandler::rsqueeze(link, 150); +- if (link.startsWith(QL1S("javascript:window.open"))) +- message += i18n(" (In new window)"); +- } else { +- message = link; +-#if 0 +- QWebFrame* frame = page() ? page()->currentFrame() : 0; +- if (frame) { +- QWebHitTestResult result = frame->hitTestContent(page()->view()->mapFromGlobal(QCursor::pos())); +- QWebFrame* target = result.linkTargetFrame(); +- if (frame->parentFrame() && target == frame->parentFrame()) { +- message += i18n(" (In parent frame)"); +- } else if (!target || target != frame) { +- message += i18n(" (In new window)"); +- } +- } +-#endif +- KFileItem item (linkUrl, QString(), KFileItem::Unknown); +- emit m_browserExtension->mouseOverInfo(item); +- } +- } +- +- emit setStatusBarText(message); +-} +- +-void WebEnginePart::slotSearchForText(const QString &text, bool backward) +-{ +- QWebEnginePage::FindFlags flags; // = QWebEnginePage::FindWrapsAroundDocument; +- +- if (backward) +- flags |= QWebEnginePage::FindBackward; +- +- if (m_searchBar->caseSensitive()) +- flags |= QWebEnginePage::FindCaseSensitively; +- +- //kDebug() << "search for text:" << text << ", backward ?" << backward; +- page()->findText(text, flags, [this](bool found) { +- m_searchBar->setFoundMatch(found); +- }); +-} +- +-void WebEnginePart::slotShowSearchBar() +-{ +- if (!m_searchBar) { +- // Create the search bar... +- m_searchBar = new SearchBar(widget()); +- connect(m_searchBar, SIGNAL(searchTextChanged(QString,bool)), +- this, SLOT(slotSearchForText(QString,bool))); +- +- actionCollection()->addAction(KStandardAction::FindNext, QStringLiteral("findnext"), +- m_searchBar, SLOT(findNext())); +- actionCollection()->addAction(KStandardAction::FindPrev, QStringLiteral("findprev"), +- m_searchBar, SLOT(findPrevious())); +- +- QBoxLayout* lay = qobject_cast<QBoxLayout*>(widget()->layout()); +- if (lay) { +- lay->addWidget(m_searchBar); +- } +- } +- const QString text = m_webView->selectedText(); +- m_searchBar->setSearchText(text.left(150)); +-} +- +-void WebEnginePart::slotLinkMiddleOrCtrlClicked(const QUrl& linkUrl) +-{ +- emit m_browserExtension->createNewWindow(linkUrl); +-} +- +-void WebEnginePart::slotSelectionClipboardUrlPasted(const QUrl& selectedUrl, const QString& searchText) +-{ +- if (!WebEngineSettings::self()->isOpenMiddleClickEnabled()) +- return; +- +- if (!searchText.isEmpty() && +- KMessageBox::questionYesNo(m_webView, +- i18n("<qt>Do you want to search for <b>%1</b>?</qt>", searchText), +- i18n("Internet Search"), KGuiItem(i18n("&Search"), QStringLiteral("edit-find")), +- KStandardGuiItem::cancel(), QStringLiteral("MiddleClickSearch")) != KMessageBox::Yes) +- return; +- +- emit m_browserExtension->openUrlRequest(selectedUrl); +-} +- +-void WebEnginePart::slotWalletClosed() +-{ +- if (!m_statusBarWalletLabel) +- return; +- +- m_statusBarExtension->removeStatusBarItem(m_statusBarWalletLabel); +- delete m_statusBarWalletLabel; +- m_statusBarWalletLabel = 0; +- m_hasCachedFormData = false; +-} +- +-void WebEnginePart::slotShowWalletMenu() +-{ +- QMenu *menu = new QMenu(0); +- +- if (m_webView && WebEngineSettings::self()->isNonPasswordStorableSite(m_webView->url().host())) +- menu->addAction(i18n("&Allow password caching for this site"), this, SLOT(slotDeleteNonPasswordStorableSite())); +- +- if (m_hasCachedFormData) +- menu->addAction(i18n("Remove all cached passwords for this site"), this, SLOT(slotRemoveCachedPasswords())); +- +- menu->addSeparator(); +- menu->addAction(i18n("&Close Wallet"), this, SLOT(slotWalletClosed())); +- +- KAcceleratorManager::manage(menu); +- menu->popup(QCursor::pos()); +-} +- +-void WebEnginePart::slotLaunchWalletManager() +-{ +- QDBusInterface r(QStringLiteral("org.kde.kwalletmanager"), QStringLiteral("/kwalletmanager/MainWindow_1")); +- if (r.isValid()) +- r.call(QDBus::NoBlock, QStringLiteral("show")); +- else +- KToolInvocation::startServiceByDesktopName(QStringLiteral("kwalletmanager_show")); +-} +- +-void WebEnginePart::slotDeleteNonPasswordStorableSite() +-{ +- if (m_webView) +- WebEngineSettings::self()->removeNonPasswordStorableSite(m_webView->url().host()); +-} +- +-void WebEnginePart::slotRemoveCachedPasswords() +-{ +- if (!page()) // || !page()->wallet()) +- return; +- +-// page()->wallet()->removeFormData(page()->mainFrame(), true); +- m_hasCachedFormData = false; +-} +- +-void WebEnginePart::slotSetTextEncoding(QTextCodec * codec) +-{ +- // FIXME: The code below that sets the text encoding has been reported not to work. +- if (!page()) +- return; +- +- QWebEngineSettings *localSettings = page()->settings(); +- if (!localSettings) +- return; +- +- qDebug() << "Encoding: new=>" << localSettings->defaultTextEncoding() << ", old=>" << codec->name(); +- +- localSettings->setDefaultTextEncoding(codec->name()); +- page()->triggerAction(QWebEnginePage::Reload); +-} +- +-void WebEnginePart::slotSetStatusBarText(const QString& text) +-{ +- const QString host (page() ? page()->url().host() : QString()); +- if (WebEngineSettings::self()->windowStatusPolicy(host) == KParts::HtmlSettingsInterface::JSWindowStatusAllow) +- emit setStatusBarText(text); +-} +- +-void WebEnginePart::slotWindowCloseRequested() +-{ +- emit m_browserExtension->requestFocus(this); +-#if 0 +- if (KMessageBox::questionYesNo(m_webView, +- i18n("Close window?"), i18n("Confirmation Required"), +- KStandardGuiItem::close(), KStandardGuiItem::cancel()) +- != KMessageBox::Yes) +- return; +-#endif +- this->deleteLater(); +-} +- +-void WebEnginePart::slotShowFeaturePermissionBar(QWebEnginePage::Feature feature) +-{ +- // FIXME: Allow multiple concurrent feature permission requests. +- if (m_featurePermissionBar && m_featurePermissionBar->isVisible()) +- return; +- +- if (!m_featurePermissionBar) { +- m_featurePermissionBar = new FeaturePermissionBar(widget()); +- +- connect(m_featurePermissionBar, SIGNAL(permissionGranted(QWebEnginePage::Feature)), +- this, SLOT(slotFeaturePermissionGranted(QWebEnginePage::Feature))); +- connect(m_featurePermissionBar, SIGNAL(permissionDenied(QWebEnginePage::Feature)), +- this, SLOT(slotFeaturePermissionDenied(QWebEnginePage::Feature))); +-// connect(m_passwordBar, SIGNAL(done()), +-// this, SLOT(slotSaveFormDataDone())); +- QBoxLayout* lay = qobject_cast<QBoxLayout*>(widget()->layout()); +- if (lay) +- lay->insertWidget(0, m_featurePermissionBar); +- } +- m_featurePermissionBar->setFeature(feature); +-// m_featurePermissionBar->setText(i18n("<html>Do you want to grant the site <b>%1</b> " +-// "access to information about your current physical location?", +-// url.host())); +- m_featurePermissionBar->setText(i18n("<html>Do you want to grant the site " +- "access to information about your current physical location?")); +- m_featurePermissionBar->animatedShow(); +-} +- +-void WebEnginePart::slotFeaturePermissionGranted(QWebEnginePage::Feature feature) +-{ +- Q_ASSERT(m_featurePermissionBar && m_featurePermissionBar->feature() == feature); +- page()->setFeaturePermission(page()->url(), feature, QWebEnginePage::PermissionGrantedByUser); +-} +- +-void WebEnginePart::slotFeaturePermissionDenied(QWebEnginePage::Feature feature) +-{ +- Q_ASSERT(m_featurePermissionBar && m_featurePermissionBar->feature() == feature); +- page()->setFeaturePermission(page()->url(), feature, QWebEnginePage::PermissionDeniedByUser); +-} +- +-void WebEnginePart::slotSaveFormDataRequested (const QString& key, const QUrl& url) +-{ +- if (WebEngineSettings::self()->isNonPasswordStorableSite(url.host())) +- return; +- +- if (!WebEngineSettings::self()->askToSaveSitePassword()) +- return; +- +- if (m_passwordBar && m_passwordBar->isVisible()) +- return; +- +- if (!m_passwordBar) { +- m_passwordBar = new PasswordBar(widget()); +-#if 0 +- KWebWallet* wallet = page()->wallet(); +- if (!wallet) { +- kWarning() << "No wallet instance found! This should never happen!"; +- return; +- } +- connect(m_passwordBar, SIGNAL(saveFormDataAccepted(QString)), +- wallet, SLOT(acceptSaveFormDataRequest(QString))); +- connect(m_passwordBar, SIGNAL(saveFormDataRejected(QString)), +- wallet, SLOT(rejectSaveFormDataRequest(QString))); +- connect(m_passwordBar, SIGNAL(done()), +- this, SLOT(slotSaveFormDataDone())); +-#endif +- } +- +- Q_ASSERT(m_passwordBar); +- +- m_passwordBar->setUrl(url); +- m_passwordBar->setRequestKey(key); +- m_passwordBar->setText(i18n("<html>Do you want %1 to remember the login " +- "information for <b>%2</b>?</html>", +- QCoreApplication::applicationName(), +- url.host())); +- +- QBoxLayout* lay = qobject_cast<QBoxLayout*>(widget()->layout()); +- if (lay) +- lay->insertWidget(0, m_passwordBar); +- +- m_passwordBar->animatedShow(); +-} +- +-void WebEnginePart::slotSaveFormDataDone() +-{ +- if (!m_passwordBar) +- return; +- +- QBoxLayout* lay = qobject_cast<QBoxLayout*>(widget()->layout()); +- if (lay) +- lay->removeWidget(m_passwordBar); +-} +- +-void WebEnginePart::addWalletStatusBarIcon () +-{ +- if (m_statusBarWalletLabel) { +- m_statusBarExtension->removeStatusBarItem(m_statusBarWalletLabel); +- } else { +- m_statusBarWalletLabel = new KUrlLabel(m_statusBarExtension->statusBar()); +- m_statusBarWalletLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum)); +- m_statusBarWalletLabel->setUseCursor(false); +- m_statusBarWalletLabel->setPixmap(QIcon::fromTheme(QStringLiteral("wallet-open")).pixmap(QSize(16,16))); +- connect(m_statusBarWalletLabel, SIGNAL(leftClickedUrl()), SLOT(slotLaunchWalletManager())); +- connect(m_statusBarWalletLabel, SIGNAL(rightClickedUrl()), SLOT(slotShowWalletMenu())); +- } +- m_statusBarExtension->addStatusBarItem(m_statusBarWalletLabel, 0, false); +-} +- +-void WebEnginePart::slotFillFormRequestCompleted (bool ok) +-{ +- if ((m_hasCachedFormData = ok)) +- addWalletStatusBarIcon(); +-} +- +diff --git a/webenginepart/src/webenginepart.desktop a/webenginepart/src/webenginepart.desktop +deleted file mode 100644 +index 5d6085773..000000000 +--- a/webenginepart/src/webenginepart.desktop ++++ /dev/null +@@ -1,65 +0,0 @@ +-[Desktop Entry] +-Type=Service +-Comment=Embeddable HTML component +-Comment[ca]=Component HTML incrustable +-Comment[ca@valencia]=Component HTML incrustable +-Comment[cs]=Zapouzdřitelná HTML komponenta +-Comment[da]=HTML-komponent som kan indlejres +-Comment[de]=Einbettungsfähige HTML-Komponente +-Comment[en_GB]=Embeddable HTML component +-Comment[es]=Componente HTML empotrable +-Comment[et]=Põimitav HTML-komponent +-Comment[fi]=Upotettava HTML-osa +-Comment[it]=Componente HTML incorporabile +-Comment[ko]=끼워넣을 수 있는 HTML 구성 요소 +-Comment[nb]=Innebyggbar HTML-komponent +-Comment[nl]=In te bedden HTML-component +-Comment[nn]=Innebyggbar HTML-komponent +-Comment[pl]=Osadzalny składnik HTML +-Comment[pt]=Componente incorporada de HTML +-Comment[pt_BR]=Componete HTML embutido +-Comment[sk]=Vložiteľný HTML komponent +-Comment[sl]=Vgradljiv sestavni del HTML +-Comment[sr]=Угнездива ХТМЛ компонента +-Comment[sr@ijekavian]=Угњездива ХТМЛ компонента +-Comment[sr@ijekavianlatin]=Ugnjezdiva HTML komponenta +-Comment[sr@latin]=Ugnezdiva HTML komponenta +-Comment[sv]=Inbäddningsbar HTML-komponent +-Comment[uk]=Придатний до вбудовування компонент HTML +-Comment[x-test]=xxEmbeddable HTML componentxx +-Comment[zh_CN]=可嵌入的 HTML 组件 +-Comment[zh_TW]=可內嵌的 HTML 元件 +-Icon=webengine +-MimeType=text/html;application/xml;application/xhtml+xml; +-Name=WebEngine +-Name[ca]=WebEngine +-Name[ca@valencia]=WebEngine +-Name[cs]=WebEngine +-Name[da]=WebEngine +-Name[de]=Webengine +-Name[en_GB]=WebEngine +-Name[es]=Motor Web +-Name[et]=WebEngine +-Name[fi]=WebEngine +-Name[it]=WebEngine +-Name[ko]=WebEngine +-Name[nl]=WebEngine +-Name[nn]=Vevmotor +-Name[pl]=SilnikSieciowy +-Name[pt]=Motor Web +-Name[pt_BR]=WebEngine +-Name[sk]=WebEngine +-Name[sl]=Spletni pogon +-Name[sr]=КуТ‑вебенџин +-Name[sr@ijekavian]=КуТ‑вебенџин +-Name[sr@ijekavianlatin]=QtWebEngine +-Name[sr@latin]=QtWebEngine +-Name[sv]=Webbgränssnitt +-Name[uk]=Вебрушій +-Name[x-test]=xxWebEnginexx +-Name[zh_CN]=WebEngine +-Name[zh_TW]=WebEngine +-X-KDE-Default-UserAgent=Mozilla/5.0 (%PLATFORM%; %SECURITY%; %OSNAME% %OSVERSION% %SYSTYPE%; %LANGUAGE%) AppleWebKit/534.34 (KHTML, like Gecko) %APPVERSION% Safari/534.34 +-X-KDE-ServiceTypes=KParts/ReadOnlyPart,Browser/View +-X-KDE-Library=kf5/parts/webenginepart +-InitialPreference=12 +diff --git a/webenginepart/src/webenginepart.h a/webenginepart/src/webenginepart.h +deleted file mode 100644 +index 6889e6d7f..000000000 +--- a/webenginepart/src/webenginepart.h ++++ /dev/null +@@ -1,165 +0,0 @@ +-/* +- * This file is part of the KDE project. +- * +- * Copyright (C) 2007 Trolltech ASA +- * Copyright (C) 2008 Urs Wolfer <uwolfer @ kde.org> +- * Copyright (C) 2009 Dawit Alemayehu <adawit@kde.org> +- * +- * This library is free software; you can redistribute it and/or modify it +- * under the terms of the GNU Lesser General Public License as published by the +- * Free Software Foundation; either version 2.1 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 Lesser General Public License for more +- * details. +- * +- * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- */ +-#ifndef WEBENGINEPART_H +-#define WEBENGINEPART_H +- +-#include "kwebenginepartlib_export.h" +- +-#include <QtWebEngineWidgets/QWebEnginePage> +- +-#include <KParts/ReadOnlyPart> +-#include <QUrl> +- +-namespace KParts { +- class BrowserExtension; +- class StatusBarExtension; +-} +- +-class QWebEngineView; +-class WebEngineView; +-class WebEnginePage; +-class SearchBar; +-class PasswordBar; +-class FeaturePermissionBar; +-class KUrlLabel; +-class WebEngineBrowserExtension; +- +-/** +- * A KPart wrapper for the QtWebEngine's browser rendering engine. +- * +- * This class attempts to provide the same type of integration into KPart +- * plugin applications, such as Konqueror, in much the same way as KHTML. +- * +- * Unlink the KHTML part however, access into the internals of the rendering +- * engine are provided through existing QtWebEngine class ; @see QWebEngineView. +- * +- */ +-class KWEBENGINEPARTLIB_EXPORT WebEnginePart : public KParts::ReadOnlyPart +-{ +- Q_OBJECT +- Q_PROPERTY( bool modified READ isModified ) +-public: +- explicit WebEnginePart(QWidget* parentWidget = 0, QObject* parent = Q_NULLPTR, +- const QByteArray& cachedHistory = QByteArray(), +- const QStringList& = QStringList()); +- ~WebEnginePart(); +- +- /** +- * Re-implemented for internal reasons. API remains unaffected. +- * +- * @see KParts::ReadOnlyPart::openUrl +- */ +- bool openUrl(const QUrl &) Q_DECL_OVERRIDE; +- +- /** +- * Re-implemented for internal reasons. API remains unaffected. +- * +- * @see KParts::ReadOnlyPart::closeUrl +- */ +- bool closeUrl() Q_DECL_OVERRIDE; +- +- /** +- * Returns a pointer to the render widget used to display a web page. +- * +- * @see QWebEngineView. +- */ +- virtual QWebEngineView *view(); +- +- /** +- * Checks whether the page contains unsubmitted form changes. +- * +- * @return @p true if form changes exist. +- */ +- bool isModified() const; +- +- /** +- * Connects the appropriate signals from the given page to the slots +- * in this class. +- */ +- void connectWebEnginePageSignals(WebEnginePage* page); +- +- void slotShowFeaturePermissionBar(QWebEnginePage::Feature); +-protected: +- /** +- * Re-implemented for internal reasons. API remains unaffected. +- * +- * @see KParts::ReadOnlyPart::guiActivateEvent +- */ +- void guiActivateEvent(KParts::GUIActivateEvent *) Q_DECL_OVERRIDE; +- +- /** +- * Re-implemented for internal reasons. API remains unaffected. +- * +- * @see KParts::ReadOnlyPart::openFile +- */ +- bool openFile() Q_DECL_OVERRIDE; +- +-private Q_SLOTS: +- void slotShowSecurity(); +- void slotShowSearchBar(); +- void slotLoadStarted(); +- void slotLoadAborted(const QUrl &); +- void slotLoadFinished(bool); +- +- void slotSearchForText(const QString &text, bool backward); +- void slotLinkHovered(const QString &); +- //void slotSaveFrameState(QWebFrame *frame, QWebHistoryItem *item); +- //void slotRestoreFrameState(QWebFrame *frame); +- void slotLinkMiddleOrCtrlClicked(const QUrl&); +- void slotSelectionClipboardUrlPasted(const QUrl&, const QString&); +- +- void slotUrlChanged(const QUrl &); +- void slotWalletClosed(); +- void slotShowWalletMenu(); +- void slotLaunchWalletManager(); +- void slotDeleteNonPasswordStorableSite(); +- void slotRemoveCachedPasswords(); +- void slotSetTextEncoding(QTextCodec*); +- void slotSetStatusBarText(const QString& text); +- void slotWindowCloseRequested(); +- void slotSaveFormDataRequested(const QString &, const QUrl &); +- void slotSaveFormDataDone(); +- void slotFillFormRequestCompleted(bool); +- +- void slotFeaturePermissionGranted(QWebEnginePage::Feature); +- void slotFeaturePermissionDenied(QWebEnginePage::Feature); +- +-private: +- WebEnginePage* page(); +- const WebEnginePage* page() const; +- void initActions(); +- void updateActions(); +- void addWalletStatusBarIcon(); +- +- bool m_emitOpenUrlNotify; +- bool m_hasCachedFormData; +- bool m_doLoadFinishedActions; +- KUrlLabel* m_statusBarWalletLabel; +- SearchBar* m_searchBar; +- PasswordBar* m_passwordBar; +- FeaturePermissionBar* m_featurePermissionBar; +- WebEngineBrowserExtension* m_browserExtension; +- KParts::StatusBarExtension* m_statusBarExtension; +- WebEngineView* m_webView; +-}; +- +-#endif // WEBENGINEPART_H +diff --git a/webenginepart/src/webenginepart.rc a/webenginepart/src/webenginepart.rc +deleted file mode 100644 +index 2b564ca97..000000000 +--- a/webenginepart/src/webenginepart.rc ++++ /dev/null +@@ -1,32 +0,0 @@ +-<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +-<kpartgui name="kwebkitpart" version="8"> +-<MenuBar> +- <Menu name="file"> +- <Action name="saveDocument" /> +- <Action name="saveFrame" /> +- <Separator /> +- <Action name="printPreview" group="print" /> +- </Menu> +- <Menu name="edit"> +- <Action name="selectAll" /> +- <Separator /> +- <Action name="find" /> +- </Menu> +- <Menu name="view"> +- <Action name="zoomIn" /> +- <Action name="zoomOut" /> +- <Action name="zoomNormal" /> +- <Action name="zoomTextOnly" /> +- <Action name="zoomToDPI" /> +- <Separator /> +- <Action name="setEncoding" /> +- <Action name="viewDocumentSource" /> +- <ActionList name="debugScriptList" /> +- </Menu> +-</MenuBar> +-<ToolBar name="htmlToolBar" iconText="icononly" iconSize="22" hidden="true"><text>HTML Toolbar</text> +- <Action name="zoomIn" /> +- <Action name="zoomOut" /> +- <Action name="zoomNormal" /> +-</ToolBar> +-</kpartgui> +diff --git a/webenginepart/src/webenginepart_ext.cpp a/webenginepart/src/webenginepart_ext.cpp +deleted file mode 100644 +index b80de84ad..000000000 +--- a/webenginepart/src/webenginepart_ext.cpp ++++ /dev/null +@@ -1,1237 +0,0 @@ +-/* +- * This file is part of the KDE project. +- * +- * Copyright (C) 2009 Dawit Alemayehu <adawit@kde.org> +- * +- * This library is free software; you can redistribute it and/or modify it +- * under the terms of the GNU Lesser General Public License as published by the +- * Free Software Foundation; either version 2.1 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 Lesser General Public License for more +- * details. +- * +- * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- */ +- +-#include <QtWebEngine/QtWebEngineVersion> +-#include "webenginepart_ext.h" +- +-#include "webenginepart.h" +-#include "webengineview.h" +-#include "webenginepage.h" +-#include "settings/webenginesettings.h" +-#include <QtWebEngineWidgets/QWebEngineSettings> +- +-#include <KDesktopFile> +-#include <KConfigGroup> +-#include <KToolInvocation> +-#include <KSharedConfig> +-#include <KRun> +-#include <KProtocolInfo> +-#include <QInputDialog> +-#include <KLocalizedString> +-#include <QTemporaryFile> +-#include <KUriFilter> +-#include <Sonnet/Dialog> +-#include <sonnet/backgroundchecker.h> +- +-#include <QBuffer> +-#include <QVariant> +-#include <QClipboard> +-#include <QApplication> +-#include <QAction> +-#include <QPrinter> +-#include <QPrintDialog> +-#include <QPrintPreviewDialog> +-#include <QInputDialog> +-#include <QWebEngineHistory> +-#include <QMimeData> +-#define QL1S(x) QLatin1String(x) +-#define QL1C(x) QLatin1Char(x) +- +-template<typename Arg, typename R, typename C> +-struct InvokeWrapper { +- R *receiver; +- void (C::*memberFun)(Arg); +- void operator()(Arg result) +- { +- (receiver->*memberFun)(result); +- } +-}; +- +-template<typename Arg, typename R, typename C> +-InvokeWrapper<Arg, R, C> invoke(R *receiver, void (C::*memberFun)(Arg)) +-{ +- InvokeWrapper<Arg, R, C> wrapper = {receiver, memberFun}; +- return wrapper; +-} +- +-WebEngineBrowserExtension::WebEngineBrowserExtension(WebEnginePart *parent, const QByteArray& cachedHistoryData) +- :KParts::BrowserExtension(parent), +- m_part(parent), +- mCurrentPrinter(Q_NULLPTR) +-{ +- enableAction("cut", false); +- enableAction("copy", false); +- enableAction("paste", false); +- enableAction("print", true); +- +- if (cachedHistoryData.isEmpty()) { +- return; +- } +- +- QBuffer buffer; +- buffer.setData(cachedHistoryData); +- if (!buffer.open(QIODevice::ReadOnly)) { +- return; +- } +- +- // NOTE: When restoring history, webengine PORTING_TODO automatically navigates to +- // the previous "currentItem". Since we do not want that to happen, +- // we set a property on the WebEnginePage object that is used to allow or +- // disallow history navigation in WebEnginePage::acceptNavigationRequest. +- view()->page()->setProperty("HistoryNavigationLocked", true); +- QDataStream s (&buffer); +- s >> *(view()->history()); +-} +- +-WebEngineBrowserExtension::~WebEngineBrowserExtension() +-{ +-} +- +-WebEngineView* WebEngineBrowserExtension::view() +-{ +- if (!m_view && m_part) { +- m_view = qobject_cast<WebEngineView*>(m_part->view()); +- } +- +- return m_view; +-} +- +-int WebEngineBrowserExtension::xOffset() +-{ +-#if QTWEBENGINE_VERSION >= QT_VERSION_CHECK(5, 7, 0) +- if (view()) +- return view()->page()->scrollPosition().x(); +-#endif +- +- return KParts::BrowserExtension::xOffset(); +-} +- +-int WebEngineBrowserExtension::yOffset() +-{ +-#if QTWEBENGINE_VERSION >= QT_VERSION_CHECK(5, 7, 0) +- if (view()) +- return view()->page()->scrollPosition().y(); +-#endif +- +- return KParts::BrowserExtension::yOffset(); +-} +- +-void WebEngineBrowserExtension::saveState(QDataStream &stream) +-{ +- // TODO: Save information such as form data from the current page. +- QWebEngineHistory* history = (view() ? view()->history() : 0); +- const int historyIndex = (history ? history->currentItemIndex() : -1); +- const QUrl historyUrl = (history && historyIndex > -1) ? QUrl(history->currentItem().url()) : m_part->url(); +- +- stream << historyUrl +- << static_cast<qint32>(xOffset()) +- << static_cast<qint32>(yOffset()) +- << historyIndex +- << m_historyData; +-} +- +-void WebEngineBrowserExtension::restoreState(QDataStream &stream) +-{ +- QUrl u; +- QByteArray historyData; +- qint32 xOfs = -1, yOfs = -1, historyItemIndex = -1; +- stream >> u >> xOfs >> yOfs >> historyItemIndex >> historyData; +- +- QWebEngineHistory* history = (view() ? view()->page()->history() : 0); +- if (history) { +- bool success = false; +- if (history->count() == 0) { // Handle restoration: crash recovery, tab close undo, session restore +- if (!historyData.isEmpty()) { +- historyData = qUncompress(historyData); // uncompress the history data... +- QBuffer buffer (&historyData); +- if (buffer.open(QIODevice::ReadOnly)) { +- QDataStream stream (&buffer); +- view()->page()->setProperty("HistoryNavigationLocked", true); +- stream >> *history; +- QWebEngineHistoryItem currentItem (history->currentItem()); +- if (currentItem.isValid()) { +- if (currentItem.isValid() && (xOfs != -1 || yOfs != -1)) { +- const QPoint scrollPos (xOfs, yOfs); +-// currentItem.setUserData(scrollPos); +- } +- // NOTE 1: The following Konqueror specific workaround is necessary +- // because Konqueror only preserves information for the last visited +- // page. However, we save the entire history content in saveState and +- // and hence need to elimiate all but the current item here. +- // NOTE 2: This condition only applies when Konqueror is restored from +- // abnormal termination ; a crash and/or a session restoration. +- if (QCoreApplication::applicationName() == QLatin1String("konqueror")) { +- history->clear(); +- } +- //kDebug() << "Restoring URL:" << currentItem.url(); +- m_part->setProperty("NoEmitOpenUrlNotification", true); +- history->goToItem(currentItem); +- } +- } +- } +- success = (history->count() > 0); +- } else { // Handle navigation: back and forward button navigation. +- //kDebug() << "history count:" << history->count() << "request index:" << historyItemIndex; +- if (history->count() > historyItemIndex && historyItemIndex > -1) { +- QWebEngineHistoryItem item (history->itemAt(historyItemIndex)); +- //kDebug() << "URL:" << u << "Item URL:" << item.url(); +- if (u == item.url()) { +- if (item.isValid() && (xOfs != -1 || yOfs != -1)) { +- const QPoint scrollPos (xOfs, yOfs); +-// item.setUserData(scrollPos); +- } +- m_part->setProperty("NoEmitOpenUrlNotification", true); +- history->goToItem(item); +- success = true; +- } +- } +- } +- +- if (success) { +- return; +- } +- } +- +- // As a last resort, in case the history restoration logic above fails, +- // attempt to open the requested URL directly. +- qDebug() << "Normal history navgation logic failed! Falling back to opening url directly."; +- m_part->openUrl(u); +-} +- +- +-void WebEngineBrowserExtension::cut() +-{ +- if (view()) +- view()->triggerPageAction(QWebEnginePage::Cut); +-} +- +-void WebEngineBrowserExtension::copy() +-{ +- if (view()) +- view()->triggerPageAction(QWebEnginePage::Copy); +-} +- +-void WebEngineBrowserExtension::paste() +-{ +- if (view()) +- view()->triggerPageAction(QWebEnginePage::Paste); +-} +- +-void WebEngineBrowserExtension::slotSaveDocument() +-{ +- if (view()) +- emit saveUrl(view()->url()); +-} +- +-void WebEngineBrowserExtension::slotSaveFrame() +-{ +- if (view()) +- emit saveUrl(view()->page()->url()); // TODO lol +-} +- +-void WebEngineBrowserExtension::print() +-{ +-#if QTWEBENGINE_VERSION >= QT_VERSION_CHECK(5, 8, 0) +- if (view()) { +- mCurrentPrinter = new QPrinter(); +- QPointer<QPrintDialog> dialog = new QPrintDialog(mCurrentPrinter, Q_NULLPTR); +- dialog->setWindowTitle(i18n("Print Document")); +- if (dialog->exec() != QDialog::Accepted) { +- slotHandlePagePrinted(false); +- delete dialog; +- return; +- } +- delete dialog; +- view()->page()->print(mCurrentPrinter, invoke(this, &WebEngineBrowserExtension::slotHandlePagePrinted)); +- } +-#endif +-} +- +-void WebEngineBrowserExtension::slotHandlePagePrinted(bool result) +-{ +- Q_UNUSED(result); +- delete mCurrentPrinter; +- mCurrentPrinter = Q_NULLPTR; +-} +- +- +-void WebEngineBrowserExtension::updateEditActions() +-{ +- if (!view()) +- return; +- +- enableAction("cut", view()->pageAction(QWebEnginePage::Cut)->isEnabled()); +- enableAction("copy", view()->pageAction(QWebEnginePage::Copy)->isEnabled()); +- enableAction("paste", view()->pageAction(QWebEnginePage::Paste)->isEnabled()); +-} +- +-void WebEngineBrowserExtension::updateActions() +-{ +- const QString protocol (m_part->url().scheme()); +- const bool isValidDocument = (protocol != QL1S("about") && protocol != QL1S("error")); +- enableAction("print", isValidDocument); +-} +- +-void WebEngineBrowserExtension::searchProvider() +-{ +- if (!view()) +- return; +- +- QAction *action = qobject_cast<QAction*>(sender()); +- if (!action) +- return; +- +- QUrl url = action->data().toUrl(); +- +- if (url.host().isEmpty()) { +- KUriFilterData data; +- data.setData(action->data().toString()); +- if (KUriFilter::self()->filterSearchUri(data, KUriFilter::WebShortcutFilter)) +- url = data.uri(); +- } +- +- if (!url.isValid()) +- return; +- +- KParts::BrowserArguments bargs; +- bargs.frameName = QL1S("_blank"); +- emit openUrlRequest(url, KParts::OpenUrlArguments(), bargs); +-} +- +-void WebEngineBrowserExtension::reparseConfiguration() +-{ +- // Force the configuration stuff to reparse... +- WebEngineSettings::self()->init(); +-} +- +-void WebEngineBrowserExtension::disableScrolling() +-{ +- QWebEngineView* currentView = view(); +- QWebEnginePage* page = currentView ? currentView->page() : 0; +- +- if (!page) +- return; +- +- page->runJavaScript(QStringLiteral("document.documentElement.style.overflow = 'hidden';")); +-} +- +-void WebEngineBrowserExtension::zoomIn() +-{ +- if (view()) +- view()->setZoomFactor(view()->zoomFactor() + 0.1); +-} +- +-void WebEngineBrowserExtension::zoomOut() +-{ +- if (view()) +- view()->setZoomFactor(view()->zoomFactor() - 0.1); +-} +- +-void WebEngineBrowserExtension::zoomNormal() +-{ +- if (view()) { +- if (WebEngineSettings::self()->zoomToDPI()) +- view()->setZoomFactor(view()->logicalDpiY() / 96.0f); +- else +- view()->setZoomFactor(1); +- } +-} +- +-void WebEngineBrowserExtension::toogleZoomTextOnly() +-{ +- if (!view()) +- return; +- +- KConfigGroup cgHtml(KSharedConfig::openConfig(), "HTML Settings"); +- bool zoomTextOnly = cgHtml.readEntry( "ZoomTextOnly", false ); +- cgHtml.writeEntry("ZoomTextOnly", !zoomTextOnly); +- cgHtml.sync(); +- +- // view()->settings()->setAttribute(QWebEngineSettings::ZoomTextOnly, !zoomTextOnly); +-} +- +-void WebEngineBrowserExtension::toogleZoomToDPI() +-{ +- if (!view()) +- return; +- +- bool zoomToDPI = !WebEngineSettings::self()->zoomToDPI(); +- WebEngineSettings::self()->setZoomToDPI(zoomToDPI); +- +- if (zoomToDPI) +- view()->setZoomFactor(view()->zoomFactor() * view()->logicalDpiY() / 96.0f); +- else +- view()->setZoomFactor(view()->zoomFactor() * 96.0f / view()->logicalDpiY()); +- +- // Recompute default font-sizes since they are only DPI dependent when zoomToDPI is false. +- WebEngineSettings::self()->computeFontSizes(view()->logicalDpiY()); +-} +- +-void WebEngineBrowserExtension::slotSelectAll() +-{ +- if (view()) +- view()->triggerPageAction(QWebEnginePage::SelectAll); +-} +- +-void WebEngineBrowserExtension::slotSaveImageAs() +-{ +- if (view()) +- view()->triggerPageAction(QWebEnginePage::DownloadImageToDisk); +-} +- +-void WebEngineBrowserExtension::slotSendImage() +-{ +-#if QTWEBENGINE_VERSION >= QT_VERSION_CHECK(5, 7, 0) +- if (!view()) +- return; +- +- QStringList urls; +- urls.append(view()->contextMenuResult().mediaUrl().path()); +- const QString subject = view()->contextMenuResult().mediaUrl().path(); +- KToolInvocation::invokeMailer(QString(), QString(), QString(), subject, +- QString(), //body +- QString(), +- urls); // attachments +-#endif +-} +- +-void WebEngineBrowserExtension::slotCopyImageURL() +-{ +-#if QTWEBENGINE_VERSION >= QT_VERSION_CHECK(5, 7, 0) +- if (!view()) +- return; +- +- QUrl safeURL = view()->contextMenuResult().mediaUrl(); +- safeURL.setPassword(QString()); +- // Set it in both the mouse selection and in the clipboard +- QMimeData* mimeData = new QMimeData; +-//TODO: Porting: test +- QList<QUrl> safeURLList; +- safeURLList.append(safeURL); +- mimeData->setUrls(safeURLList); +- QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); +- +- mimeData = new QMimeData; +- mimeData->setUrls(safeURLList); +- QApplication::clipboard()->setMimeData(mimeData, QClipboard::Selection); +-#endif +-} +- +- +-void WebEngineBrowserExtension::slotCopyImage() +-{ +-#if QTWEBENGINE_VERSION >= QT_VERSION_CHECK(5, 7, 0) +- if (!view()) +- return; +- +- QUrl safeURL; //(view()->contextMenuResult().imageUrl()); +- safeURL.setPassword(QString()); +- +- // Set it in both the mouse selection and in the clipboard +- QMimeData* mimeData = new QMimeData; +-// mimeData->setImageData(view()->contextMenuResult().pixmap()); +-//TODO: Porting: test +- QList<QUrl> safeURLList; +- safeURLList.append(safeURL); +- mimeData->setUrls(safeURLList); +- QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); +- +- mimeData = new QMimeData; +-// mimeData->setImageData(view()->contextMenuResult().pixmap()); +- mimeData->setUrls(safeURLList); +- QApplication::clipboard()->setMimeData(mimeData, QClipboard::Selection); +-#endif +-} +- +-void WebEngineBrowserExtension::slotViewImage() +-{ +-#if QTWEBENGINE_VERSION >= QT_VERSION_CHECK(5, 7, 0) +- if (view()) +- emit createNewWindow(view()->contextMenuResult().mediaUrl()); +-#endif +-} +- +-void WebEngineBrowserExtension::slotBlockImage() +-{ +-#if QTWEBENGINE_VERSION >= QT_VERSION_CHECK(5, 7, 0) +- if (!view()) +- return; +- +- bool ok = false; +- const QString url = QInputDialog::getText(view(), i18n("Add URL to Filter"), +- i18n("Enter the URL:"), QLineEdit::Normal, +- view()->contextMenuResult().mediaUrl().toString(), +- &ok); +- if (ok) { +- WebEngineSettings::self()->addAdFilter(url); +- reparseConfiguration(); +- } +-#endif +-} +- +-void WebEngineBrowserExtension::slotBlockHost() +-{ +- if (!view()) +- return; +- +- QUrl url; // (view()->contextMenuResult().imageUrl()); +- url.setPath(QL1S("/*")); +- WebEngineSettings::self()->addAdFilter(url.toString(QUrl::RemoveUserInfo | QUrl::RemovePort)); +- reparseConfiguration(); +-} +- +-void WebEngineBrowserExtension::slotCopyLinkURL() +-{ +- if (view()) +- view()->triggerPageAction(QWebEnginePage::CopyLinkToClipboard); +-} +- +-void WebEngineBrowserExtension::slotCopyLinkText() +-{ +-#if QTWEBENGINE_VERSION >= QT_VERSION_CHECK(5, 7, 0) +- if (view()) { +- QMimeData* data = new QMimeData; +- data->setText(view()->contextMenuResult().linkText()); +- QApplication::clipboard()->setMimeData(data, QClipboard::Clipboard); +- } +-#endif +-} +- +-void WebEngineBrowserExtension::slotCopyEmailAddress() +-{ +-#if QTWEBENGINE_VERSION >= QT_VERSION_CHECK(5, 7, 0) +- if (view()) { +- QMimeData* data = new QMimeData; +- const QUrl url(view()->contextMenuResult().linkUrl()); +- data->setText(url.path()); +- QApplication::clipboard()->setMimeData(data, QClipboard::Clipboard); +- } +-#endif +-} +- +-void WebEngineBrowserExtension::slotSaveLinkAs() +-{ +- if (view()) +- view()->triggerPageAction(QWebEnginePage::DownloadLinkToDisk); +-} +- +-void WebEngineBrowserExtension::slotViewDocumentSource() +-{ +- if (!view()) +- return; +- +- const QUrl pageUrl (view()->url()); +- if (pageUrl.isLocalFile()) { +- KRun::runUrl(pageUrl, QL1S("text/plain"), view(), false); +- } else { +- view()->page()->toHtml([this](const QString& html) { +- QTemporaryFile tempFile; +- tempFile.setFileTemplate(tempFile.fileTemplate() + QL1S(".html")); +- tempFile.setAutoRemove(false); +- if (tempFile.open()) { +- tempFile.write(html.toUtf8()); +- KRun::runUrl(QUrl::fromLocalFile(tempFile.fileName()), QL1S("text/plain"), view(), true, false); +- } +- }); +- } +-} +- +-#if QTWEBENGINE_VERSION >= QT_VERSION_CHECK(5, 7, 0) +-static bool isMultimediaElement(QWebEngineContextMenuData::MediaType mediaType) +-{ +- switch(mediaType) +- { +- case QWebEngineContextMenuData::MediaTypeVideo: +- case QWebEngineContextMenuData::MediaTypeAudio: +- return true; +- default: +- return false; +- } +-} +-#endif +- +-void WebEngineBrowserExtension::slotLoopMedia() +-{ +-#if QTWEBENGINE_VERSION >= QT_VERSION_CHECK(5, 7, 0) +- if (!view()) +- return; +- +- QWebEngineContextMenuData data = view()->contextMenuResult(); +- if (!isMultimediaElement( data.mediaType())) +- return; +- view()->page()->triggerAction(QWebEnginePage::ToggleMediaLoop); +-#endif +-} +- +-void WebEngineBrowserExtension::slotMuteMedia() +-{ +-#if QTWEBENGINE_VERSION >= QT_VERSION_CHECK(5, 7, 0) +- if (!view()) +- return; +- +- QWebEngineContextMenuData data = view()->contextMenuResult(); +- if (!isMultimediaElement( data.mediaType())) +- return; +- view()->page()->triggerAction(QWebEnginePage::ToggleMediaMute); +-#endif +-} +- +-void WebEngineBrowserExtension::slotPlayMedia() +-{ +-#if QTWEBENGINE_VERSION >= QT_VERSION_CHECK(5, 7, 0) +- if (!view()) +- return; +- +- QWebEngineContextMenuData data = view()->contextMenuResult(); +- if (!isMultimediaElement( data.mediaType())) +- return; +- view()->page()->triggerAction(QWebEnginePage::ToggleMediaPlayPause); +-#endif +-} +- +-void WebEngineBrowserExtension::slotShowMediaControls() +-{ +-#if QTWEBENGINE_VERSION >= QT_VERSION_CHECK(5, 7, 0) +- if (!view()) +- return; +- +- QWebEngineContextMenuData data = view()->contextMenuResult(); +- if (!isMultimediaElement( data.mediaType())) +- return; +- view()->page()->triggerAction(QWebEnginePage::ToggleMediaControls); +-#endif +-} +- +-#if 0 +-static QUrl mediaUrlFrom(QWebElement& element) +-{ +- QWebFrame* frame = element.webFrame(); +- QString src = frame ? element.attribute(QL1S("src")) : QString(); +- if (src.isEmpty()) +- src = frame ? element.evaluateJavaScript(QL1S("this.src")).toString() : QString(); +- +- if (src.isEmpty()) +- return QUrl(); +- +- return QUrl(frame->baseUrl().resolved(QUrl::fromEncoded(QUrl::toPercentEncoding(src), QUrl::StrictMode))); +-} +-#endif +- +-void WebEngineBrowserExtension::slotSaveMedia() +-{ +-#if QTWEBENGINE_VERSION >= QT_VERSION_CHECK(5, 7, 0) +- if (!view()) +- return; +- +- QWebEngineContextMenuData data = view()->contextMenuResult(); +- if (!isMultimediaElement( data.mediaType())) +- return; +- emit saveUrl(data.mediaUrl()); +-#endif +-} +- +-void WebEngineBrowserExtension::slotCopyMedia() +-{ +-#if QTWEBENGINE_VERSION >= QT_VERSION_CHECK(5, 7, 0) +- if (!view()) +- return; +- QWebEngineContextMenuData data = view()->contextMenuResult(); +- if (!isMultimediaElement( data.mediaType())) +- return; +- +- QUrl safeURL(data.mediaUrl()); +- if (!safeURL.isValid()) +- return; +- +- safeURL.setPassword(QString()); +- // Set it in both the mouse selection and in the clipboard +- QMimeData* mimeData = new QMimeData; +-//TODO: Porting: test +- QList<QUrl> safeURLList; +- safeURLList.append(safeURL); +- mimeData->setUrls(safeURLList); +- QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); +- +- mimeData = new QMimeData; +- mimeData->setUrls(safeURLList); +- QApplication::clipboard()->setMimeData(mimeData, QClipboard::Selection); +-#endif +-} +- +-void WebEngineBrowserExtension::slotTextDirectionChanged() +-{ +- QAction* action = qobject_cast<QAction*>(sender()); +- if (action) { +- bool ok = false; +- const int value = action->data().toInt(&ok); +- if (ok) { +- view()->triggerPageAction(static_cast<QWebEnginePage::WebAction>(value)); +- } +- } +-} +- +-static QVariant execJScript(WebEngineView* view, const QString& script) +-{ +-#if 0 +- QWebElement element (view->contextMenuResult().element()); +- if (element.isNull()) +- return QVariant(); +- return element.evaluateJavaScript(script); +-#endif +- return QVariant(); +-} +- +-void WebEngineBrowserExtension::slotCheckSpelling() +-{ +- const QString text (execJScript(view(), QL1S("this.value")).toString()); +- +- if ( text.isEmpty() ) { +- return; +- } +- +- m_spellTextSelectionStart = 0; +- m_spellTextSelectionEnd = 0; +- +- Sonnet::BackgroundChecker *backgroundSpellCheck = new Sonnet::BackgroundChecker; +- Sonnet::Dialog* spellDialog = new Sonnet::Dialog(backgroundSpellCheck, view()); +- backgroundSpellCheck->setParent(spellDialog); +- spellDialog->setAttribute(Qt::WA_DeleteOnClose, true); +- spellDialog->showSpellCheckCompletionMessage(true); +- connect(spellDialog, SIGNAL(replace(QString,int,QString)), this, SLOT(spellCheckerCorrected(QString,int,QString))); +- connect(spellDialog, SIGNAL(misspelling(QString,int)), this, SLOT(spellCheckerMisspelling(QString,int))); +- spellDialog->setBuffer(text); +- spellDialog->show(); +-} +- +-void WebEngineBrowserExtension::slotSpellCheckSelection() +-{ +- QString text (execJScript(view(), QL1S("this.value")).toString()); +- +- if ( text.isEmpty() ) { +- return; +- } +- +- m_spellTextSelectionStart = qMax(0, execJScript(view(), QL1S("this.selectionStart")).toInt()); +- m_spellTextSelectionEnd = qMax(0, execJScript(view(), QL1S("this.selectionEnd")).toInt()); +- // kDebug() << "selection start:" << m_spellTextSelectionStart << "end:" << m_spellTextSelectionEnd; +- +- Sonnet::BackgroundChecker *backgroundSpellCheck = new Sonnet::BackgroundChecker; +- Sonnet::Dialog* spellDialog = new Sonnet::Dialog(backgroundSpellCheck, view()); +- backgroundSpellCheck->setParent(spellDialog); +- spellDialog->setAttribute(Qt::WA_DeleteOnClose, true); +- spellDialog->showSpellCheckCompletionMessage(true); +- connect(spellDialog, SIGNAL(replace(QString,int,QString)), this, SLOT(spellCheckerCorrected(QString,int,QString))); +- connect(spellDialog, SIGNAL(misspelling(QString,int)), this, SLOT(spellCheckerMisspelling(QString,int))); +- connect(spellDialog, SIGNAL(done(QString)), this, SLOT(slotSpellCheckDone(QString))); +- spellDialog->setBuffer(text.mid(m_spellTextSelectionStart, (m_spellTextSelectionEnd - m_spellTextSelectionStart))); +- spellDialog->show(); +-} +- +-void WebEngineBrowserExtension::spellCheckerCorrected(const QString& original, int pos, const QString& replacement) +-{ +- // Adjust the selection end... +- if (m_spellTextSelectionEnd > 0) { +- m_spellTextSelectionEnd += qMax (0, (replacement.length() - original.length())); +- } +- +- const int index = pos + m_spellTextSelectionStart; +- QString script(QL1S("this.value=this.value.substring(0,")); +- script += QString::number(index); +- script += QL1S(") + \""); +- script += replacement; +- script += QL1S("\" + this.value.substring("); +- script += QString::number(index + original.length()); +- script += QL1S(")"); +- +- //kDebug() << "**** script:" << script; +- execJScript(view(), script); +-} +- +-void WebEngineBrowserExtension::spellCheckerMisspelling(const QString& text, int pos) +-{ +- // kDebug() << text << pos; +- QString selectionScript (QL1S("this.setSelectionRange(")); +- selectionScript += QString::number(pos + m_spellTextSelectionStart); +- selectionScript += QL1C(','); +- selectionScript += QString::number(pos + text.length() + m_spellTextSelectionStart); +- selectionScript += QL1C(')'); +- execJScript(view(), selectionScript); +-} +- +-void WebEngineBrowserExtension::slotSpellCheckDone(const QString&) +-{ +- // Restore the text selection if one was present before we started the +- // spell check. +- if (m_spellTextSelectionStart > 0 || m_spellTextSelectionEnd > 0) { +- QString script (QL1S("; this.setSelectionRange(")); +- script += QString::number(m_spellTextSelectionStart); +- script += QL1C(','); +- script += QString::number(m_spellTextSelectionEnd); +- script += QL1C(')'); +- execJScript(view(), script); +- } +-} +- +- +-void WebEngineBrowserExtension::saveHistory() +-{ +- QWebEngineHistory* history = (view() ? view()->history() : 0); +- +- if (history && history->count() > 0) { +- //kDebug() << "Current history: index=" << history->currentItemIndex() << "url=" << history->currentItem().url(); +- QByteArray histData; +- QBuffer buff (&histData); +- m_historyData.clear(); +- if (buff.open(QIODevice::WriteOnly)) { +- QDataStream stream (&buff); +- stream << *history; +- m_historyData = qCompress(histData, 9); +- } +- QWidget* mainWidget = m_part ? m_part->widget() : 0; +- QWidget* frameWidget = mainWidget ? mainWidget->parentWidget() : 0; +- if (frameWidget) { +- emit saveHistory(frameWidget, m_historyData); +- // kDebug() << "# of items:" << history->count() << "current item:" << history->currentItemIndex() << "url:" << history->currentItem().url(); +- } +- } else { +- Q_ASSERT(false); // should never happen!!! +- } +-} +- +-void WebEngineBrowserExtension::slotPrintPreview() +-{ +-#if 0 +- // Make it non-modal, in case a redirection deletes the part +- QPointer<QPrintPreviewDialog> dlg (new QPrintPreviewDialog(view())); +- connect(dlg.data(), SIGNAL(paintRequested(QPrinter*)), +- view()->page()->currentFrame(), SLOT(print(QPrinter*))); +- dlg->exec(); +- delete dlg; +-#endif +-} +- +-void WebEngineBrowserExtension::slotOpenSelection() +-{ +- QAction *action = qobject_cast<QAction*>(sender()); +- if (action) { +- KParts::BrowserArguments browserArgs; +- browserArgs.frameName = QStringLiteral("_blank"); +- emit openUrlRequest(QUrl(action->data().toUrl()), KParts::OpenUrlArguments(), browserArgs); +- } +-} +- +-void WebEngineBrowserExtension::slotLinkInTop() +-{ +-#if QTWEBENGINE_VERSION >= QT_VERSION_CHECK(5, 7, 0) +- if (!view()) +- return; +- +- KParts::OpenUrlArguments uargs; +- uargs.setActionRequestedByUser(true); +- +- KParts::BrowserArguments bargs; +- bargs.frameName = QL1S("_top"); +- +- const QUrl url(view()->contextMenuResult().linkUrl()); +- +- emit openUrlRequest(url, uargs, bargs); +-#endif +-} +- +-//// +- +-WebEngineTextExtension::WebEngineTextExtension(WebEnginePart* part) +- : KParts::TextExtension(part) +-{ +- connect(part->view(), SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged())); +-} +- +-WebEnginePart* WebEngineTextExtension::part() const +-{ +- return static_cast<WebEnginePart*>(parent()); +-} +- +-bool WebEngineTextExtension::hasSelection() const +-{ +- return part()->view()->hasSelection(); +-} +- +-QString WebEngineTextExtension::selectedText(Format format) const +-{ +- switch(format) { +- case PlainText: +- return part()->view()->selectedText(); +- case HTML: +- // PORTING_TODO selectedText might not be html +- return part()->view()->selectedText(); +- } +- return QString(); +-} +- +-QString WebEngineTextExtension::completeText(Format format) const +-{ +- // TODO David will hunt me down with a rusty spork if he sees this +- QEventLoop ev; +- QString str; +- switch(format) { +- case PlainText: +- part()->view()->page()->toPlainText([&ev,&str](const QString& data) { +- str = data; +- ev.quit(); +- }); +- case HTML: +- part()->view()->page()->toHtml([&ev,&str](const QString& data) { +- str = data; +- ev.quit(); +- }); +- } +- ev.exec(); +- return QString(); +-} +- +-//// +- +-WebEngineHtmlExtension::WebEngineHtmlExtension(WebEnginePart* part) +- : KParts::HtmlExtension(part) +-{ +-} +- +- +-QUrl WebEngineHtmlExtension::baseUrl() const +-{ +- return part()->view()->page()->url(); +-} +- +-bool WebEngineHtmlExtension::hasSelection() const +-{ +- return part()->view()->hasSelection(); +-} +- +-KParts::SelectorInterface::QueryMethods WebEngineHtmlExtension::supportedQueryMethods() const +-{ +- return (KParts::SelectorInterface::EntireContent +- | KParts::SelectorInterface::SelectedContent); +-} +- +-#if 0 +-static KParts::SelectorInterface::Element convertWebElement(const QWebElement& webElem) +-{ +- KParts::SelectorInterface::Element element; +- element.setTagName(webElem.tagName()); +- Q_FOREACH(const QString &attr, webElem.attributeNames()) { +- element.setAttribute(attr, webElem.attribute(attr)); +- } +- return element; +-} +-#endif +- +-static QString queryOne(const QString& query) +-{ +- QString jsQuery = QL1S("(function(query) { var element; var selectedElement = window.getSelection().getRangeAt(0).cloneContents().querySelector(\""); +- jsQuery += query; +- jsQuery += QL1S("\"); if (selectedElement && selectedElement.length > 0) { element = new Object; " +- "element.tagName = String(selectedElements[0].tagName); element.href = String(selectedElements[0].href); } " +- "return element; }())"); +- return jsQuery; +-} +- +-static QString queryAll(const QString& query) +-{ +- QString jsQuery = QL1S("(function(query) { var elements = []; var selectedElements = window.getSelection().getRangeAt(0).cloneContents().querySelectorAll(\""); +- jsQuery += query; +- jsQuery += QL1S("\"); var numSelectedElements = (selectedElements ? selectedElements.length : 0);" +- "for (var i = 0; i < numSelectedElements; ++i) { var element = new Object; " +- "element.tagName = String(selectedElements[i].tagName); element.href = String(selectedElements[i].href);" +- "elements.push(element); } return elements; } ())"); +- return jsQuery; +-} +- +-static KParts::SelectorInterface::Element convertSelectionElement(const QVariant& variant) +-{ +- KParts::SelectorInterface::Element element; +- if (!variant.isNull() && variant.type() == QVariant::Map) { +- const QVariantMap elementMap (variant.toMap()); +- element.setTagName(elementMap.value(QL1S("tagName")).toString()); +- element.setAttribute(QL1S("href"), elementMap.value(QL1S("href")).toString()); +- } +- return element; +-} +- +-static QList<KParts::SelectorInterface::Element> convertSelectionElements(const QVariant& variant) +-{ +- QList<KParts::SelectorInterface::Element> elements; +- const QVariantList resultList (variant.toList()); +- Q_FOREACH(const QVariant& result, resultList) { +- const QVariantMap elementMap = result.toMap(); +- KParts::SelectorInterface::Element element; +- element.setTagName(elementMap.value(QL1S("tagName")).toString()); +- element.setAttribute(QL1S("href"), elementMap.value(QL1S("href")).toString()); +- elements.append(element); +- } +- return elements; +-} +- +-KParts::SelectorInterface::Element WebEngineHtmlExtension::querySelector(const QString& query, KParts::SelectorInterface::QueryMethod method) const +-{ +- KParts::SelectorInterface::Element element; +- +- // If the specified method is None, return an empty list... +- if (method == KParts::SelectorInterface::None) +- return element; +- +- // If the specified method is not supported, return an empty list... +- if (!(supportedQueryMethods() & method)) +- return element; +- +-#if 0 +- switch (method) { +- case KParts::SelectorInterface::EntireContent: { +- const QWebFrame* webFrame = part()->view()->page()->mainFrame(); +- element = convertWebElement(webFrame->findFirstElement(query)); +- break; +- } +- case KParts::SelectorInterface::SelectedContent: { +- QWebFrame* webFrame = part()->view()->page()->mainFrame(); +- element = convertSelectionElement(webFrame->evaluateJavaScript(queryOne(query))); +- break; +- } +- default: +- break; +- } +-#endif +- +- return element; +-} +- +-QList<KParts::SelectorInterface::Element> WebEngineHtmlExtension::querySelectorAll(const QString& query, KParts::SelectorInterface::QueryMethod method) const +-{ +- QList<KParts::SelectorInterface::Element> elements; +- +- // If the specified method is None, return an empty list... +- if (method == KParts::SelectorInterface::None) +- return elements; +- +- // If the specified method is not supported, return an empty list... +- if (!(supportedQueryMethods() & method)) +- return elements; +-#if 0 +- switch (method) { +- case KParts::SelectorInterface::EntireContent: { +- const QWebFrame* webFrame = part()->view()->page()->mainFrame(); +- const QWebElementCollection collection = webFrame->findAllElements(query); +- elements.reserve(collection.count()); +- Q_FOREACH(const QWebElement& element, collection) +- elements.append(convertWebElement(element)); +- break; +- } +- case KParts::SelectorInterface::SelectedContent: { +- QWebFrame* webFrame = part()->view()->page()->mainFrame(); +- elements = convertSelectionElements(webFrame->evaluateJavaScript(queryAll(query))); +- break; +- } +- default: +- break; +- } +-#endif +- return elements; +-} +- +-QVariant WebEngineHtmlExtension::htmlSettingsProperty(KParts::HtmlSettingsInterface::HtmlSettingsType type) const +-{ +- QWebEngineView* view = part() ? part()->view() : 0; +- QWebEnginePage* page = view ? view->page() : 0; +- QWebEngineSettings* settings = page ? page->settings() : 0; +- +- if (settings) { +- switch (type) { +- case KParts::HtmlSettingsInterface::AutoLoadImages: +- return settings->testAttribute(QWebEngineSettings::AutoLoadImages); +- case KParts::HtmlSettingsInterface::JavaEnabled: +- return false; // settings->testAttribute(QWebEngineSettings::JavaEnabled); +- case KParts::HtmlSettingsInterface::JavascriptEnabled: +- return settings->testAttribute(QWebEngineSettings::JavascriptEnabled); +- case KParts::HtmlSettingsInterface::PluginsEnabled: +- return settings->testAttribute(QWebEngineSettings::PluginsEnabled); +- case KParts::HtmlSettingsInterface::DnsPrefetchEnabled: +- return false; //settings->testAttribute(QWebEngineSettings::DnsPrefetchEnabled); +- case KParts::HtmlSettingsInterface::MetaRefreshEnabled: +- return view->pageAction(QWebEnginePage::Stop)->isEnabled(); +- case KParts::HtmlSettingsInterface::LocalStorageEnabled: +- return settings->testAttribute(QWebEngineSettings::LocalStorageEnabled); +- case KParts::HtmlSettingsInterface::OfflineStorageDatabaseEnabled: +- return false; //settings->testAttribute(QWebEngineSettings::OfflineStorageDatabaseEnabled); +- case KParts::HtmlSettingsInterface::OfflineWebApplicationCacheEnabled: +- return false ;//settings->testAttribute(QWebEngineSettings::OfflineWebApplicationCacheEnabled); +- case KParts::HtmlSettingsInterface::PrivateBrowsingEnabled: +- return false; //settings->testAttribute(QWebEngineSettings::PrivateBrowsingEnabled); +- case KParts::HtmlSettingsInterface::UserDefinedStyleSheetURL: +- return false; //settings->userStyleSheetUrl(); +- default: +- break; +- } +- } +- +- return QVariant(); +-} +- +-bool WebEngineHtmlExtension::setHtmlSettingsProperty(KParts::HtmlSettingsInterface::HtmlSettingsType type, const QVariant& value) +-{ +- QWebEngineView* view = part() ? part()->view() : 0; +- QWebEnginePage* page = view ? view->page() : 0; +- QWebEngineSettings* settings = page ? page->settings() : 0; +- +- if (settings) { +- switch (type) { +- case KParts::HtmlSettingsInterface::AutoLoadImages: +- settings->setAttribute(QWebEngineSettings::AutoLoadImages, value.toBool()); +- return true; +- case KParts::HtmlSettingsInterface::JavaEnabled: +- //settings->setAttribute(QWebESettings::JavaEnabled, value.toBool()); +- return false; +- case KParts::HtmlSettingsInterface::JavascriptEnabled: +- settings->setAttribute(QWebEngineSettings::JavascriptEnabled, value.toBool()); +- return true; +- case KParts::HtmlSettingsInterface::PluginsEnabled: +- settings->setAttribute(QWebEngineSettings::PluginsEnabled, value.toBool()); +- return true; +- case KParts::HtmlSettingsInterface::DnsPrefetchEnabled: +-// settings->setAttribute(QWebEngineSettings::DnsPrefetchEnabled, value.toBool()); +- return false; +- case KParts::HtmlSettingsInterface::MetaRefreshEnabled: +- view->triggerPageAction(QWebEnginePage::Stop); +- return true; +- case KParts::HtmlSettingsInterface::LocalStorageEnabled: +- settings->setAttribute(QWebEngineSettings::LocalStorageEnabled, value.toBool()); +- return false; +- case KParts::HtmlSettingsInterface::OfflineStorageDatabaseEnabled: +- //settings->setAttribute(QWebEngineSettings::OfflineStorageDatabaseEnabled, value.toBool()); +- return false; +- case KParts::HtmlSettingsInterface::OfflineWebApplicationCacheEnabled: +- //settings->setAttribute(QWebEngineSettings::OfflineWebApplicationCacheEnabled, value.toBool()); +- return false; +- case KParts::HtmlSettingsInterface::PrivateBrowsingEnabled: +- //settings->setAttribute(QWebEnngineSettings::PrivateBrowsingEnabled, value.toBool()); +- return false; +- case KParts::HtmlSettingsInterface::UserDefinedStyleSheetURL: +- //kDebug() << "Setting user style sheet for" << page << "to" << value.toUrl(); +- // settings->setUserStyleSheetUrl(value.toUrl()); +- return false; +- default: +- break; +- } +- } +- +- return false; +-} +- +-WebEnginePart* WebEngineHtmlExtension::part() const +-{ +- return static_cast<WebEnginePart*>(parent()); +-} +- +-WebEngineScriptableExtension::WebEngineScriptableExtension(WebEnginePart* part) +- : ScriptableExtension(part) +-{ +-} +- +-QVariant WebEngineScriptableExtension::rootObject() +-{ +- return QVariant::fromValue(KParts::ScriptableExtension::Object(this, reinterpret_cast<quint64>(this))); +-} +- +-bool WebEngineScriptableExtension::setException (KParts::ScriptableExtension* callerPrincipal, const QString& message) +-{ +- return KParts::ScriptableExtension::setException (callerPrincipal, message); +-} +- +-QVariant WebEngineScriptableExtension::get (KParts::ScriptableExtension* callerPrincipal, quint64 objId, const QString& propName) +-{ +- //kDebug() << "caller:" << callerPrincipal << "id:" << objId << "propName:" << propName; +- return callerPrincipal->get (0, objId, propName); +-} +- +-bool WebEngineScriptableExtension::put (KParts::ScriptableExtension* callerPrincipal, quint64 objId, const QString& propName, const QVariant& value) +-{ +- return KParts::ScriptableExtension::put (callerPrincipal, objId, propName, value); +-} +- +-static QVariant exception(const char* msg) +-{ +- qWarning() << msg; +- return QVariant::fromValue(KParts::ScriptableExtension::Exception(QString::fromLatin1(msg))); +-} +- +-QVariant WebEngineScriptableExtension::evaluateScript (KParts::ScriptableExtension* callerPrincipal, +- quint64 contextObjectId, +- const QString& code, +- KParts::ScriptableExtension::ScriptLanguage lang) +-{ +- Q_UNUSED(contextObjectId); +- Q_UNUSED(code) +- //kDebug() << "principal:" << callerPrincipal << "id:" << contextObjectId << "language:" << lang << "code:" << code; +- +- if (lang != ECMAScript) +- return exception("unsupported language"); +- +- +- KParts::ReadOnlyPart* part = callerPrincipal ? qobject_cast<KParts::ReadOnlyPart*>(callerPrincipal->parent()) : 0; +- // QWebFrame* frame = part ? qobject_cast<QWebFrame*>(part->parent()) : 0; +- // if (!frame) +- return exception("failed to resolve principal"); +-#if 0 +- QVariant result (frame->evaluateJavaScript(code)); +- +- if (result.type() == QVariant::Map) { +- const QVariantMap map (result.toMap()); +- for (QVariantMap::const_iterator it = map.constBegin(), itEnd = map.constEnd(); it != itEnd; ++it) { +- callerPrincipal->put(callerPrincipal, 0, it.key(), it.value()); +- } +- } else { +- const QString propName(code.contains(QLatin1String("__nsplugin")) ? QLatin1String("__nsplugin") : QString()); +- callerPrincipal->put(callerPrincipal, 0, propName, result.toString()); +- } +- +- return QVariant::fromValue(ScriptableExtension::Null()); +-#endif +-} +- +-bool WebEngineScriptableExtension::isScriptLanguageSupported (KParts::ScriptableExtension::ScriptLanguage lang) const +-{ +- return (lang == KParts::ScriptableExtension::ECMAScript); +-} +- +-QVariant WebEngineScriptableExtension::encloserForKid (KParts::ScriptableExtension* kid) +-{ +-#if 0 +- KParts::ReadOnlyPart* part = kid ? qobject_cast<KParts::ReadOnlyPart*>(kid->parent()) : 0; +- QWebFrame* frame = part ? qobject_cast<QWebFrame*>(part->parent()) : 0; +- if (frame) { +- return QVariant::fromValue(KParts::ScriptableExtension::Object(kid, reinterpret_cast<quint64>(kid))); +- } +-#endif +- +- return QVariant::fromValue(ScriptableExtension::Null()); +-} +- +-WebEnginePart* WebEngineScriptableExtension::part() +-{ +- return qobject_cast<WebEnginePart*>(parent()); +-} +- +diff --git a/webenginepart/src/webenginepart_ext.h a/webenginepart/src/webenginepart_ext.h +deleted file mode 100644 +index 550daa7d8..000000000 +--- a/webenginepart/src/webenginepart_ext.h ++++ /dev/null +@@ -1,201 +0,0 @@ +-/* +- * This file is part of the KDE project. +- * +- * Copyright (C) 2009 Dawit Alemayehu <adawit@kde.org> +- * +- * This library is free software; you can redistribute it and/or modify it +- * under the terms of the GNU Lesser General Public License as published by the +- * Free Software Foundation; either version 2.1 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 Lesser General Public License for more +- * details. +- * +- * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- */ +- +-#ifndef WEBENGINEPART_EXT_H +-#define WEBENGINEPART_EXT_H +- +-#include "kwebenginepartlib_export.h" +- +-#include <QPointer> +- +-#include <KParts/BrowserExtension> +-#include <KParts/TextExtension> +-#include <KParts/HtmlExtension> +-#include <KParts/HtmlSettingsInterface> +-#include <KParts/ScriptableExtension> +-#include <KParts/SelectorInterface> +- +-class QUrl; +-class WebEnginePart; +-class WebEngineView; +-class QPrinter; +-class KWEBENGINEPARTLIB_EXPORT WebEngineBrowserExtension : public KParts::BrowserExtension +-{ +- Q_OBJECT +- +-public: +- WebEngineBrowserExtension(WebEnginePart *parent, const QByteArray& cachedHistoryData); +- ~WebEngineBrowserExtension(); +- +- virtual int xOffset() override; +- virtual int yOffset() override; +- virtual void saveState(QDataStream &) override; +- virtual void restoreState(QDataStream &) override; +- void saveHistory(); +- +-Q_SIGNALS: +- void saveUrl(const QUrl &); +- void saveHistory(QObject*, const QByteArray&); +- +-public Q_SLOTS: +- void cut(); +- void copy(); +- void paste(); +- void print(); +- +- void slotSaveDocument(); +- void slotSaveFrame(); +- void searchProvider(); +- void reparseConfiguration(); +- void disableScrolling(); +- +- void zoomIn(); +- void zoomOut(); +- void zoomNormal(); +- void toogleZoomTextOnly(); +- void toogleZoomToDPI(); +- void slotSelectAll(); +- +- void slotSaveImageAs(); +- void slotSendImage(); +- void slotCopyImageURL(); +- void slotCopyImage(); +- void slotViewImage(); +- void slotBlockImage(); +- void slotBlockHost(); +- +- void slotCopyLinkURL(); +- void slotCopyLinkText(); +- void slotSaveLinkAs(); +- void slotCopyEmailAddress(); +- +- void slotViewDocumentSource(); +- +- void updateEditActions(); +- void updateActions(); +- +- void slotPlayMedia(); +- void slotMuteMedia(); +- void slotLoopMedia(); +- void slotShowMediaControls(); +- void slotSaveMedia(); +- void slotCopyMedia(); +- void slotTextDirectionChanged(); +- void slotCheckSpelling(); +- void slotSpellCheckSelection(); +- void slotSpellCheckDone(const QString&); +- void spellCheckerCorrected(const QString&, int, const QString&); +- void spellCheckerMisspelling(const QString&, int); +- //void slotPrintRequested(QWebFrame*); +- void slotPrintPreview(); +- +- void slotOpenSelection(); +- void slotLinkInTop(); +- +-private Q_SLOTS: +- void slotHandlePagePrinted(bool result); +-private: +- WebEngineView* view(); +- QPointer<WebEnginePart> m_part; +- QPointer<WebEngineView> m_view; +- quint32 m_spellTextSelectionStart; +- quint32 m_spellTextSelectionEnd; +- QByteArray m_historyData; +- QPrinter *mCurrentPrinter; +-}; +- +-/** +- * @internal +- * Implements the TextExtension interface +- */ +-class WebEngineTextExtension : public KParts::TextExtension +-{ +- Q_OBJECT +-public: +- WebEngineTextExtension(WebEnginePart* part); +- +- bool hasSelection() const Q_DECL_OVERRIDE; +- QString selectedText(Format format) const Q_DECL_OVERRIDE; +- QString completeText(Format format) const Q_DECL_OVERRIDE; +- +-private: +- WebEnginePart* part() const; +-}; +- +-/** +- * @internal +- * Implements the HtmlExtension interface +- */ +-class WebEngineHtmlExtension : public KParts::HtmlExtension, +- public KParts::SelectorInterface, +- public KParts::HtmlSettingsInterface +-{ +- Q_OBJECT +- Q_INTERFACES(KParts::SelectorInterface) +- Q_INTERFACES(KParts::HtmlSettingsInterface) +- +-public: +- WebEngineHtmlExtension(WebEnginePart* part); +- +- // HtmlExtension +- QUrl baseUrl() const Q_DECL_OVERRIDE; +- bool hasSelection() const Q_DECL_OVERRIDE; +- +- // SelectorInterface +- QueryMethods supportedQueryMethods() const Q_DECL_OVERRIDE; +- Element querySelector(const QString& query, KParts::SelectorInterface::QueryMethod method) const Q_DECL_OVERRIDE; +- QList<Element> querySelectorAll(const QString& query, KParts::SelectorInterface::QueryMethod method) const Q_DECL_OVERRIDE; +- +- // HtmlSettingsInterface +- QVariant htmlSettingsProperty(HtmlSettingsType type) const Q_DECL_OVERRIDE; +- bool setHtmlSettingsProperty(HtmlSettingsType type, const QVariant& value) Q_DECL_OVERRIDE; +- +-private: +- WebEnginePart* part() const; +-}; +- +-class WebEngineScriptableExtension : public KParts::ScriptableExtension +-{ +- Q_OBJECT +- +-public: +- WebEngineScriptableExtension(WebEnginePart* part); +- +- QVariant rootObject() Q_DECL_OVERRIDE; +- +- QVariant get(ScriptableExtension* callerPrincipal, quint64 objId, const QString& propName) Q_DECL_OVERRIDE; +- +- bool put(ScriptableExtension* callerPrincipal, quint64 objId, const QString& propName, const QVariant& value) Q_DECL_OVERRIDE; +- +- bool setException(ScriptableExtension* callerPrincipal, const QString& message) Q_DECL_OVERRIDE; +- +- QVariant evaluateScript(ScriptableExtension* callerPrincipal, +- quint64 contextObjectId, +- const QString& code, +- ScriptLanguage language = ECMAScript) Q_DECL_OVERRIDE; +- +- bool isScriptLanguageSupported(ScriptLanguage lang) const Q_DECL_OVERRIDE; +- +-private: +- QVariant encloserForKid(KParts::ScriptableExtension* kid) Q_DECL_OVERRIDE; +- WebEnginePart* part(); +-}; +- +-#endif // WEBENGINEPART_EXT_H +diff --git a/webenginepart/src/webenginepartfactory.cpp a/webenginepart/src/webenginepartfactory.cpp +deleted file mode 100644 +index 04853bd27..000000000 +--- a/webenginepart/src/webenginepartfactory.cpp ++++ /dev/null +@@ -1,65 +0,0 @@ +-/* +- * This file is part of the KDE project. +- * +- * Copyright (C) 2008 Laurent Montel <montel@kde.org> +- * +- * This library is free software; you can redistribute it and/or modify it +- * under the terms of the GNU Lesser General Public License as published by the +- * Free Software Foundation; either version 2.1 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 Lesser General Public License for more +- * details. +- * +- * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- */ +- +-#include "webenginepartfactory.h" +-#include "webenginepart_ext.h" +-#include "webenginepart.h" +- +-#include <QWidget> +- +-WebEngineFactory::~WebEngineFactory() +-{ +- // kDebug() << this; +-} +- +-QObject *WebEngineFactory::create(const char* iface, QWidget *parentWidget, QObject *parent, const QVariantList &args, const QString& keyword) +-{ +- Q_UNUSED(iface); +- Q_UNUSED(keyword); +- Q_UNUSED(args); +- +- qDebug() << parentWidget << parent; +- connect(parentWidget, SIGNAL(destroyed(QObject*)), this, SLOT(slotDestroyed(QObject*))); +- +- // NOTE: The code below is what makes it possible to properly integrate QtWebEngine's PORTING_TODO +- // history management with any KParts based application. +- QByteArray histData (m_historyBufContainer.value(parentWidget)); +- if (!histData.isEmpty()) histData = qUncompress(histData); +- WebEnginePart* part = new WebEnginePart(parentWidget, parent, histData); +- WebEngineBrowserExtension* ext = qobject_cast<WebEngineBrowserExtension*>(part->browserExtension()); +- if (ext) { +- connect(ext, SIGNAL(saveHistory(QObject*,QByteArray)), this, SLOT(slotSaveHistory(QObject*,QByteArray))); +- } +- return part; +-} +- +-void WebEngineFactory::slotSaveHistory(QObject* widget, const QByteArray& buffer) +-{ +- // kDebug() << "Caching history data from" << widget; +- m_historyBufContainer.insert(widget, buffer); +-} +- +-void WebEngineFactory::slotDestroyed(QObject* object) +-{ +- // kDebug() << "Removing cached history data of" << object; +- m_historyBufContainer.remove(object); +-} +- +-K_EXPORT_PLUGIN(WebEngineFactory) +diff --git a/webenginepart/src/webenginepartfactory.h a/webenginepart/src/webenginepartfactory.h +deleted file mode 100644 +index 1eaaf42ba..000000000 +--- a/webenginepart/src/webenginepartfactory.h ++++ /dev/null +@@ -1,47 +0,0 @@ +-/* +- * This file is part of the KDE project. +- * +- * Copyright (C) 2008 Laurent Montel <montel@kde.org> +- * +- * This library is free software; you can redistribute it and/or modify it +- * under the terms of the GNU Lesser General Public License as published by the +- * Free Software Foundation; either version 2.1 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 Lesser General Public License for more +- * details. +- * +- * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- */ +- +-#ifndef WEBENGINEPARTFACTORY +-#define WEBENGINEPARTFACTORY +- +-#include <kpluginfactory.h> +- +-#include <QHash> +- +-class QWidget; +- +-class WebEngineFactory : public KPluginFactory +-{ +- Q_OBJECT +- Q_PLUGIN_METADATA(IID "org.kde.KPluginFactory" FILE "") +- Q_INTERFACES(KPluginFactory) +-public: +- virtual ~WebEngineFactory(); +- QObject *create(const char* iface, QWidget *parentWidget, QObject *parent, const QVariantList& args, const QString &keyword) Q_DECL_OVERRIDE; +- +-private Q_SLOTS: +- void slotDestroyed(QObject* object); +- void slotSaveHistory(QObject* widget, const QByteArray&); +- +-private: +- QHash<QObject*, QByteArray> m_historyBufContainer; +-}; +- +-#endif // WEBENGINEPARTFACTORY +diff --git a/webenginepart/src/webengineview.cpp a/webenginepart/src/webengineview.cpp +deleted file mode 100644 +index 1bed6110f..000000000 +--- a/webenginepart/src/webengineview.cpp ++++ /dev/null +@@ -1,594 +0,0 @@ +-/* +- * This file is part of the KDE project. +- * +- * Copyright (C) 2007 Trolltech ASA +- * Copyright (C) 2008 - 2010 Urs Wolfer <uwolfer @ kde.org> +- * Copyright (C) 2008 Laurent Montel <montel@kde.org> +- * Copyright (C) 2009 Dawit Alemayehu <adawit@kde.org> +- * +- * This library is free software; you can redistribute it and/or modify it +- * under the terms of the GNU Lesser General Public License as published by the +- * Free Software Foundation; either version 2.1 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 Lesser General Public License for more +- * details. +- * +- * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- */ +- +-#include "webengineview.h" +-#include "webenginepage.h" +-#include "webenginepart.h" +-#include "settings/webenginesettings.h" +- +-#include <kio/global.h> +-#include <KAboutData> +-#include <KActionCollection> +-#include <KConfigGroup> +-#include <KService> +-#include <KUriFilter> +-#include <KActionMenu> +-#include <KIO/AccessManager> +-#include <KStringHandler> +-#include <KLocalizedString> +- +-#include <QTimer> +-#include <QMimeData> +-#include <QDropEvent> +-#include <QLabel> +-#include <QNetworkRequest> +-#include <QToolTip> +-#include <QCoreApplication> +-#include <unistd.h> +-#include <QMimeType> +-#include <QMimeDatabase> +- +-#define QL1S(x) QLatin1String(x) +-#define QL1C(x) QLatin1Char(x) +- +-#define ALTERNATE_DEFAULT_WEB_SHORTCUT QL1S("google") +-#define ALTERNATE_WEB_SHORTCUTS QStringList() << QL1S("google") << QL1S("wikipedia") << QL1S("webster") << QL1S("dmoz") +- +-WebEngineView::WebEngineView(WebEnginePart* part, QWidget* parent) +- :QWebEngineView(parent), +- m_actionCollection(new KActionCollection(this)), +- m_part(part), +- m_autoScrollTimerId(-1), +- m_verticalAutoScrollSpeed(0), +- m_horizontalAutoScrollSpeed(0) +-{ +- setAcceptDrops(true); +- +- // Create the custom page... +- setPage(new WebEnginePage(part, this)); +- +- connect(this, SIGNAL(loadStarted()), this, SLOT(slotStopAutoScroll())); +- +- if (WebEngineSettings::self()->zoomToDPI()) +- setZoomFactor(logicalDpiY() / 96.0f); +- +-#ifndef HAVE_WEBENGINECONTEXTMENUDATA +- m_result = 0; +-#endif +-} +- +-WebEngineView::~WebEngineView() +-{ +- //kDebug(); +-} +- +-void WebEngineView::loadUrl(const QUrl& url, const KParts::OpenUrlArguments& args, const KParts::BrowserArguments& bargs) +-{ +- page()->setProperty("NavigationTypeUrlEntered", true); +- +- if (args.reload() && url == this->url()) { +- reload(); +- return; +- } +- +- QNetworkRequest request(url); +- if (args.reload()) { +- request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork); +- } +- +- if (bargs.postData.isEmpty()) { +- QWebEngineView::load(url); +- } else { +- // QWebEngineView::load(url, QNetworkAccessManager::PostOperation, bargs.postData); +- } +-} +- +-QWebEngineContextMenuData WebEngineView::contextMenuResult() const +-{ +- return m_result; +-} +- +-static void extractMimeTypeFor(const QUrl& url, QString& mimeType) +-{ +- const QString fname(url.fileName()); +- +- if (fname.isEmpty() || url.hasFragment() || url.hasQuery()) +- return; +- +- QMimeType pmt = QMimeDatabase().mimeTypeForFile(fname); +- +- // Further check for mime types guessed from the extension which, +- // on a web page, are more likely to be a script delivering content +- // of undecidable type. If the mime type from the extension is one +- // of these, don't use it. Retain the original type 'text/html'. +- if (pmt.isDefault() || +- pmt.inherits(QL1S("application/x-perl")) || +- pmt.inherits(QL1S("application/x-perl-module")) || +- pmt.inherits(QL1S("application/x-php")) || +- pmt.inherits(QL1S("application/x-python-bytecode")) || +- pmt.inherits(QL1S("application/x-python")) || +- pmt.inherits(QL1S("application/x-shellscript"))) +- return; +- +- mimeType = pmt.name(); +-} +- +-void WebEngineView::contextMenuEvent(QContextMenuEvent* e) +-{ +-#ifdef HAVE_WEBENGINECONTEXTMENUDATA +- m_result = page()->contextMenuData(); +- +- // Clear the previous collection entries first... +- m_actionCollection->clear(); +- +- KParts::BrowserExtension::PopupFlags flags = KParts::BrowserExtension::DefaultPopupItems; +- KParts::BrowserExtension::ActionGroupMap mapAction; +- QString mimeType (QL1S("text/html")); +- bool forcesNewWindow = false; +- +- QUrl emitUrl; +- +- if (m_result.isContentEditable()) { +- flags |= KParts::BrowserExtension::ShowTextSelectionItems; +- editableContentActionPopupMenu(mapAction); +- } else if (m_result.mediaType() == QWebEngineContextMenuData::MediaTypeVideo || m_result.mediaType() == QWebEngineContextMenuData::MediaTypeAudio) { +- multimediaActionPopupMenu(mapAction); +- } else if (!m_result.linkUrl().isValid()) { +- if (m_result.mediaType() == QWebEngineContextMenuData::MediaTypeImage) { +- emitUrl = m_result.mediaUrl(); +- extractMimeTypeFor(emitUrl, mimeType); +- } else { +- flags |= KParts::BrowserExtension::ShowBookmark; +- emitUrl = m_part->url(); +- +- if (!m_result.selectedText().isEmpty()) { +- flags |= KParts::BrowserExtension::ShowTextSelectionItems; +- selectActionPopupMenu(mapAction); +- } +- } +- partActionPopupMenu(mapAction); +- } else { +- flags |= KParts::BrowserExtension::ShowBookmark; +- flags |= KParts::BrowserExtension::IsLink; +- emitUrl = m_result.linkUrl(); +- linkActionPopupMenu(mapAction); +- if (emitUrl.isLocalFile()) +- mimeType = QMimeDatabase().mimeTypeForUrl(emitUrl).name(); +- else +- extractMimeTypeFor(emitUrl, mimeType); +- partActionPopupMenu(mapAction); +- +- // Show the OpenInThisWindow context menu item +-// forcesNewWindow = (page()->currentFrame() != m_result.linkTargetFrame()); +- } +- +- if (!mapAction.isEmpty()) { +- KParts::OpenUrlArguments args; +- KParts::BrowserArguments bargs; +- args.setMimeType(mimeType); +- bargs.setForcesNewWindow(forcesNewWindow); +- e->accept(); +- emit m_part->browserExtension()->popupMenu(e->globalPos(), emitUrl, static_cast<mode_t>(-1), args, bargs, flags, mapAction); +- return; +- } +- +-#endif +- QWebEngineView::contextMenuEvent(e); +-} +- +-void WebEngineView::keyPressEvent(QKeyEvent* e) +-{ +- if (e && hasFocus()) { +- const int key = e->key(); +- if (e->modifiers() & Qt::ShiftModifier) { +- switch (key) { +- case Qt::Key_Up: +- /* if (!isEditableElement(page()))*/ { +- m_verticalAutoScrollSpeed--; +- if (m_autoScrollTimerId == -1) +- m_autoScrollTimerId = startTimer(100); +- e->accept(); +- return; +- } +- break; +- case Qt::Key_Down: +- /*if (!isEditableElement(page()))*/ { +- m_verticalAutoScrollSpeed++; +- if (m_autoScrollTimerId == -1) +- m_autoScrollTimerId = startTimer(100); +- e->accept(); +- return; +- } +- break; +- case Qt::Key_Left: +- /*if (!isEditableElement(page()))*/ { +- m_horizontalAutoScrollSpeed--; +- if (m_autoScrollTimerId == -1) +- m_autoScrollTimerId = startTimer(100); +- e->accept(); +- return; +- } +- break; +- case Qt::Key_Right: +- /*if (!isEditableElement(page()))*/ { +- m_horizontalAutoScrollSpeed--; +- if (m_autoScrollTimerId == -1) +- m_autoScrollTimerId = startTimer(100); +- e->accept(); +- return; +- } +- break; +- default: +- break; +- } +- } else if (m_autoScrollTimerId != -1) { +- // kDebug() << "scroll timer id:" << m_autoScrollTimerId; +- slotStopAutoScroll(); +- e->accept(); +- return; +- } +- } +- QWebEngineView::keyPressEvent(e); +-} +- +-void WebEngineView::keyReleaseEvent(QKeyEvent *e) +-{ +- QWebEngineView::keyReleaseEvent(e); +-} +- +-void WebEngineView::mouseReleaseEvent(QMouseEvent* e) +-{ +- QWebEngineView::mouseReleaseEvent(e); +-} +- +-void WebEngineView::wheelEvent (QWheelEvent* e) +-{ +- QWebEngineView::wheelEvent(e); +-} +- +- +-void WebEngineView::timerEvent(QTimerEvent* e) +-{ +-#if 0 +- if (e && e->timerId() == m_autoScrollTimerId) { +- // do the scrolling +- scroll(m_horizontalAutoScrollSpeed, m_verticalAutoScrollSpeed); +- // check if we reached the end +- const int y = page()->scrollPosition().y(); +- if (y == page()->currentFrame()->scrollBarMinimum(Qt::Vertical) || +- y == page()->currentFrame()->scrollBarMaximum(Qt::Vertical)) { +- m_verticalAutoScrollSpeed = 0; +- } +- +- const int x = page()->scrollPosition().x(); +- if (x == page()->currentFrame()->scrollBarMinimum(Qt::Horizontal) || +- x == page()->currentFrame()->scrollBarMaximum(Qt::Horizontal)) { +- m_horizontalAutoScrollSpeed = 0; +- } +- +- // Kill the timer once the max/min scroll limit is reached. +- if (m_horizontalAutoScrollSpeed == 0 && m_verticalAutoScrollSpeed == 0) { +- killTimer(m_autoScrollTimerId); +- m_autoScrollTimerId = -1; +- } +- e->accept(); +- return; +- } +-#endif +- QWebEngineView::timerEvent(e); +-} +- +-void WebEngineView::editableContentActionPopupMenu(KParts::BrowserExtension::ActionGroupMap& partGroupMap) +-{ +- QList<QAction*> editableContentActions; +- +- QActionGroup* group = new QActionGroup(this); +- group->setExclusive(true); +- +- QAction* action = new QAction(m_actionCollection); +- action->setSeparator(true); +- editableContentActions.append(action); +- +- action = m_actionCollection->addAction(KStandardAction::Copy, QL1S("copy"), m_part->browserExtension(), SLOT(copy())); +- action->setEnabled(pageAction(QWebEnginePage::Copy)->isEnabled()); +- editableContentActions.append(action); +- +- action = m_actionCollection->addAction(KStandardAction::Cut, QL1S("cut"), m_part->browserExtension(), SLOT(cut())); +- action->setEnabled(pageAction(QWebEnginePage::Cut)->isEnabled()); +- editableContentActions.append(action); +- +- action = m_actionCollection->addAction(KStandardAction::Paste, QL1S("paste"), m_part->browserExtension(), SLOT(paste())); +- action->setEnabled(pageAction(QWebEnginePage::Paste)->isEnabled()); +- editableContentActions.append(action); +- +- action = new QAction(m_actionCollection); +- action->setSeparator(true); +- editableContentActions.append(action); +- +- editableContentActions.append(pageAction(QWebEnginePage::SelectAll)); +- editableContentActions.append(pageAction(QWebEnginePage::InspectElement)); +- +- partGroupMap.insert(QStringLiteral("editactions") , editableContentActions); +-} +- +- +-void WebEngineView::partActionPopupMenu(KParts::BrowserExtension::ActionGroupMap& partGroupMap) +-{ +- QList<QAction*> partActions; +- +-#ifdef HAVE_WEBENGINECONTEXTMENUDATA +- if (m_result.mediaUrl().isValid()) { +- QAction *action; +- action = new QAction(i18n("Save Image As..."), this); +- m_actionCollection->addAction(QL1S("saveimageas"), action); +- connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(slotSaveImageAs())); +- partActions.append(action); +- +- action = new QAction(i18n("Send Image..."), this); +- m_actionCollection->addAction(QL1S("sendimage"), action); +- connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(slotSendImage())); +- partActions.append(action); +- +- action = new QAction(i18n("Copy Image URL"), this); +- m_actionCollection->addAction(QL1S("copyimageurl"), action); +- connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(slotCopyImageURL())); +- partActions.append(action); +- +-#if 0 +- action = new QAction(i18n("Copy Image"), this); +- m_actionCollection->addAction(QL1S("copyimage"), action); +- connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(slotCopyImage())); +- action->setEnabled(!m_result.pixmap().isNull()); +- partActions.append(action); +-#endif +- +- action = new QAction(i18n("View Image (%1)", QUrl(m_result.mediaUrl()).fileName()), this); +- m_actionCollection->addAction(QL1S("viewimage"), action); +- connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(slotViewImage())); +- partActions.append(action); +- +- if (WebEngineSettings::self()->isAdFilterEnabled()) { +- action = new QAction(i18n("Block Image..."), this); +- m_actionCollection->addAction(QL1S("blockimage"), action); +- connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(slotBlockImage())); +- partActions.append(action); +- +- if (!m_result.mediaUrl().host().isEmpty() && +- !m_result.mediaUrl().scheme().isEmpty()) +- { +- action = new QAction(i18n("Block Images From %1" , m_result.mediaUrl().host()), this); +- m_actionCollection->addAction(QL1S("blockhost"), action); +- connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(slotBlockHost())); +- partActions.append(action); +- } +- } +- } +-#endif +- +- { +- QAction *separatorAction = new QAction(m_actionCollection); +- separatorAction->setSeparator(true); +- partActions.append(separatorAction); +- } +- +- partActions.append(m_part->actionCollection()->action(QStringLiteral("viewDocumentSource"))); +- +- partActions.append(pageAction(QWebEnginePage::InspectElement)); +- +- partGroupMap.insert(QStringLiteral("partactions"), partActions); +-} +- +-void WebEngineView::selectActionPopupMenu(KParts::BrowserExtension::ActionGroupMap& selectGroupMap) +-{ +- QList<QAction*> selectActions; +- +- QAction* copyAction = m_actionCollection->addAction(KStandardAction::Copy, QL1S("copy"), m_part->browserExtension(), SLOT(copy())); +- copyAction->setText(i18n("&Copy Text")); +- copyAction->setEnabled(m_part->browserExtension()->isActionEnabled("copy")); +- selectActions.append(copyAction); +- +- addSearchActions(selectActions, this); +- +- KUriFilterData data (selectedText().simplified().left(256)); +- data.setCheckForExecutables(false); +- if (KUriFilter::self()->filterUri(data, QStringList() << QStringLiteral("kshorturifilter") << QStringLiteral("fixhosturifilter")) && +- data.uri().isValid() && data.uriType() == KUriFilterData::NetProtocol) { +- QAction *action = new QAction(QIcon::fromTheme(QStringLiteral("window-new")), i18nc("open selected url", "Open '%1'", +- KStringHandler::rsqueeze(data.uri().url(), 18)), this); +- m_actionCollection->addAction(QL1S("openSelection"), action); +- action->setData(QUrl(data.uri())); +- connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(slotOpenSelection())); +- selectActions.append(action); +- } +- +- selectGroupMap.insert(QStringLiteral("editactions"), selectActions); +-} +- +-void WebEngineView::linkActionPopupMenu(KParts::BrowserExtension::ActionGroupMap& linkGroupMap) +-{ +-#ifdef HAVE_WEBENGINECONTEXTMENUDATA +- Q_ASSERT(!m_result.linkUrl().isEmpty()); +- +- const QUrl url(m_result.linkUrl()); +-#else +- const QUrl url; +-#endif +- +- QList<QAction*> linkActions; +- +- QAction* action; +- +-#ifdef HAVE_WEBENGINECONTEXTMENUDATA +- if (!m_result.selectedText().isEmpty()) { +- action = m_actionCollection->addAction(KStandardAction::Copy, QL1S("copy"), m_part->browserExtension(), SLOT(copy())); +- action->setText(i18n("&Copy Text")); +- action->setEnabled(m_part->browserExtension()->isActionEnabled("copy")); +- linkActions.append(action); +- } +-#endif +- +- if (url.scheme() == QLatin1String("mailto")) { +-#ifdef HAVE_WEBENGINECONTEXTMENUDATA +- action = new QAction(i18n("&Copy Email Address"), this); +- m_actionCollection->addAction(QL1S("copylinklocation"), action); +- connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(slotCopyEmailAddress())); +- linkActions.append(action); +-#endif +- } else { +-#ifdef HAVE_WEBENGINECONTEXTMENUDATA +- if (!m_result.linkText().isEmpty()) { +- action = new QAction(QIcon::fromTheme(QStringLiteral("edit-copy")), i18n("Copy Link &Text"), this); +- m_actionCollection->addAction(QL1S("copylinktext"), action); +- connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(slotCopyLinkText())); +- linkActions.append(action); +- } +-#endif +- +- action = new QAction(i18n("Copy Link &URL"), this); +- m_actionCollection->addAction(QL1S("copylinkurl"), action); +- connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(slotCopyLinkURL())); +- linkActions.append(action); +- +- action = new QAction(i18n("&Save Link As..."), this); +- m_actionCollection->addAction(QL1S("savelinkas"), action); +- connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(slotSaveLinkAs())); +- linkActions.append(action); +- } +- +- linkGroupMap.insert(QStringLiteral("linkactions"), linkActions); +-} +- +-void WebEngineView::multimediaActionPopupMenu(KParts::BrowserExtension::ActionGroupMap& mmGroupMap) +-{ +-#ifdef HAVE_WEBENGINECONTEXTMENUDATA +- QList<QAction*> multimediaActions; +- +- const bool isVideoElement = m_result.mediaType() == QWebEngineContextMenuData::MediaTypeVideo; +- const bool isAudioElement = m_result.mediaType() == QWebEngineContextMenuData::MediaTypeAudio; +- +- QAction* action = new QAction(i18n("&Play/Pause"), this); +- m_actionCollection->addAction(QL1S("playmultimedia"), action); +- connect(action, SIGNAL(triggered()), m_part->browserExtension(), SLOT(slotPlayMedia())); +- multimediaActions.append(action); +- +- action = new QAction(i18n("Un&mute/&Mute"), this); +- m_actionCollection->addAction(QL1S("mutemultimedia"), action); +- connect(action, SIGNAL(triggered()), m_part->browserExtension(), SLOT(slotMuteMedia())); +- multimediaActions.append(action); +- +- action = new QAction(i18n("Toggle &Loop"), this); +- m_actionCollection->addAction(QL1S("loopmultimedia"), action); +- connect(action, SIGNAL(triggered()), m_part->browserExtension(), SLOT(slotLoopMedia())); +- multimediaActions.append(action); +- +- action = new QAction(i18n("Toggle &Controls"), this); +- m_actionCollection->addAction(QL1S("showmultimediacontrols"), action); +- connect(action, SIGNAL(triggered()), m_part->browserExtension(), SLOT(slotShowMediaControls())); +- multimediaActions.append(action); +- +- action = new QAction(m_actionCollection); +- action->setSeparator(true); +- multimediaActions.append(action); +- +- QString saveMediaText, copyMediaText; +- if (isVideoElement) { +- saveMediaText = i18n("Sa&ve Video As..."); +- copyMediaText = i18n("C&opy Video URL"); +- } else if (isAudioElement) { +- saveMediaText = i18n("Sa&ve Audio As..."); +- copyMediaText = i18n("C&opy Audio URL"); +- } else { +- saveMediaText = i18n("Sa&ve Media As..."); +- copyMediaText = i18n("C&opy Media URL"); +- } +- +- action = new QAction(saveMediaText, this); +- m_actionCollection->addAction(QL1S("savemultimedia"), action); +- connect(action, SIGNAL(triggered()), m_part->browserExtension(), SLOT(slotSaveMedia())); +- multimediaActions.append(action); +- +- action = new QAction(copyMediaText, this); +- m_actionCollection->addAction(QL1S("copymultimediaurl"), action); +- connect(action, SIGNAL(triggered()), m_part->browserExtension(), SLOT(slotCopyMedia())); +- multimediaActions.append(action); +- +- mmGroupMap.insert(QStringLiteral("partactions"), multimediaActions); +-#endif +-} +- +-void WebEngineView::slotStopAutoScroll() +-{ +- if (m_autoScrollTimerId == -1) { +- return; +- } +- +- killTimer(m_autoScrollTimerId); +- m_autoScrollTimerId = -1; +- m_verticalAutoScrollSpeed = 0; +- m_horizontalAutoScrollSpeed = 0; +- +-} +- +-void WebEngineView::addSearchActions(QList<QAction*>& selectActions, QWebEngineView* view) +-{ +- // search text +- const QString selectedText = view->selectedText().simplified(); +- if (selectedText.isEmpty()) +- return; +- +- KUriFilterData data; +- data.setData(selectedText); +- data.setAlternateDefaultSearchProvider(ALTERNATE_DEFAULT_WEB_SHORTCUT); +- data.setAlternateSearchProviders(ALTERNATE_WEB_SHORTCUTS); +- +- if (KUriFilter::self()->filterSearchUri(data, KUriFilter::NormalTextFilter)) { +- const QString squeezedText = KStringHandler::rsqueeze(selectedText, 20); +- QAction *action = new QAction(QIcon::fromTheme(data.iconName()), +- i18nc("Search \"search provider\" for \"text\"", "Search %1 for '%2'", +- data.searchProvider(), squeezedText), view); +- action->setData(QUrl(data.uri())); +- connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(searchProvider())); +- m_actionCollection->addAction(QL1S("defaultSearchProvider"), action); +- selectActions.append(action); +- +- +- const QStringList preferredSearchProviders = data.preferredSearchProviders(); +- if (!preferredSearchProviders.isEmpty()) { +- KActionMenu* providerList = new KActionMenu(i18nc("Search for \"text\" with", +- "Search for '%1' with", squeezedText), view); +- Q_FOREACH(const QString &searchProvider, preferredSearchProviders) { +- if (searchProvider == data.searchProvider()) +- continue; +- +- QAction *action = new QAction(QIcon::fromTheme(data.iconNameForPreferredSearchProvider(searchProvider)), searchProvider, view); +- action->setData(data.queryForPreferredSearchProvider(searchProvider)); +- m_actionCollection->addAction(searchProvider, action); +- connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(searchProvider())); +- +- providerList->addAction(action); +- } +- m_actionCollection->addAction(QL1S("searchProviderList"), providerList); +- selectActions.append(providerList); +- } +- } +-} +diff --git a/webenginepart/src/webengineview.h a/webenginepart/src/webengineview.h +deleted file mode 100644 +index 25b13eae9..000000000 +--- a/webenginepart/src/webengineview.h ++++ /dev/null +@@ -1,132 +0,0 @@ +-/* +- * This file is part of the KDE project. +- * +- * Copyright (C) 2007 Trolltech ASA +- * Copyright (C) 2008 Urs Wolfer <uwolfer @ kde.org> +- * Copyright (C) 2008 Laurent Montel <montel@kde.org> +- * Copyright (C) 2009 Dawit Alemayehu <adawit@kde.org> +- * +- * This library is free software; you can redistribute it and/or modify it +- * under the terms of the GNU Lesser General Public License as published by the +- * Free Software Foundation; either version 2.1 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 Lesser General Public License for more +- * details. +- * +- * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- */ +-#ifndef WEBENGINEVIEW_H +-#define WEBENGINEVIEW_H +- +-#include <QPointer> +-#include <KParts/BrowserExtension> +- +-#include <QWebEngineView> +-#include <QtWebEngine/QtWebEngineVersion> +-#if QTWEBENGINE_VERSION >= QT_VERSION_CHECK(5, 7, 0) +-#define HAVE_WEBENGINECONTEXTMENUDATA +-#include <QWebEngineContextMenuData> +-#else +-typedef void* QWebEngineContextMenuData; +-#endif +- +-class QUrl; +-class WebEnginePart; +- +-class WebEngineView : public QWebEngineView +-{ +- Q_OBJECT +-public: +- WebEngineView(WebEnginePart* part, QWidget* parent); +- ~WebEngineView(); +- +- /** +- * Same as QWebEnginePage::load, but with KParts style arguments instead. +- * +- * @see KParts::OpenUrlArguments, KParts::BrowserArguments. +- * +- * @param url the url to load. +- * @param args reference to a OpenUrlArguments object. +- * @param bargs reference to a BrowserArguments object. +- */ +- void loadUrl(const QUrl& url, const KParts::OpenUrlArguments& args, const KParts::BrowserArguments& bargs); +- +- QWebEngineContextMenuData contextMenuResult() const; +- +-protected: +- /** +- * Reimplemented for internal reasons, the API is not affected. +- * +- * @see QWidget::contextMenuEvent +- * @internal +- */ +- void contextMenuEvent(QContextMenuEvent*) Q_DECL_OVERRIDE; +- +- /** +- * Reimplemented for internal reasons, the API is not affected. +- * +- * @see QWidget::keyPressEvent +- * @internal +- */ +- void keyPressEvent(QKeyEvent*) Q_DECL_OVERRIDE; +- +- /** +- * Reimplemented for internal reasons, the API is not affected. +- * +- * @see QWidget::keyReleaseEvent +- * @internal +- */ +- void keyReleaseEvent(QKeyEvent*) Q_DECL_OVERRIDE; +- +- /** +- * Reimplemented for internal reasons, the API is not affected. +- * +- * @see QWidget::mouseReleaseEvent +- * @internal +- */ +- void mouseReleaseEvent(QMouseEvent*) Q_DECL_OVERRIDE; +- +- /** +- * Reimplemented for internal reasons, the API is not affected. +- * +- * @see QObject::timerEvent +- * @internal +- */ +- void timerEvent(QTimerEvent*) Q_DECL_OVERRIDE; +- +- /** +- * Reimplemented for internal reasons, the API is not affected. +- * +- * @see QWidget::wheelEvent +- * @internal +- */ +- void wheelEvent(QWheelEvent*) Q_DECL_OVERRIDE; +- +-private Q_SLOTS: +- void slotStopAutoScroll(); +- +-private: +- void editableContentActionPopupMenu(KParts::BrowserExtension::ActionGroupMap&); +- void selectActionPopupMenu(KParts::BrowserExtension::ActionGroupMap&); +- void linkActionPopupMenu(KParts::BrowserExtension::ActionGroupMap&); +- void partActionPopupMenu(KParts::BrowserExtension::ActionGroupMap &); +- void multimediaActionPopupMenu(KParts::BrowserExtension::ActionGroupMap&); +- void addSearchActions(QList<QAction*>& selectActions, QWebEngineView*); +- +- KActionCollection* m_actionCollection; +- QWebEngineContextMenuData m_result; +- QPointer<WebEnginePart> m_part; +- +- qint32 m_autoScrollTimerId; +- qint32 m_verticalAutoScrollSpeed; +- qint32 m_horizontalAutoScrollSpeed; +- +- QHash<QString, QChar> m_duplicateLinkElements; +-}; +- +-#endif // WEBENGINEVIEW_H +diff --git a/webenginepart/src/webhistoryinterface.cpp a/webenginepart/src/webhistoryinterface.cpp +deleted file mode 100644 +index 74e2c096e..000000000 +--- a/webenginepart/src/webhistoryinterface.cpp ++++ /dev/null +@@ -1,38 +0,0 @@ +-/* +- * This file is part of the KDE project. +- * +- * Copyright (C) 2011 Dawit Alemayehu <adawit@kde.org> +- * +- * This library is free software; you can redistribute it and/or modify it +- * under the terms of the GNU Lesser General Public License as published by the +- * Free Software Foundation; either version 2.1 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 Lesser General Public License for more +- * details. +- * +- * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- */ +- +-#include "webhistoryinterface.h" +- +-#include <KParts/HistoryProvider> +- +- +-WebHistoryInterface::WebHistoryInterface(QObject* parent) +-{ +-} +- +-void WebHistoryInterface::addHistoryEntry(const QString& url) +-{ +- KParts::HistoryProvider::self()->insert(url); +-} +- +-bool WebHistoryInterface::historyContains(const QString& url) const +-{ +- return KParts::HistoryProvider::self()->contains(url); +-} +diff --git a/webenginepart/src/webhistoryinterface.h a/webenginepart/src/webhistoryinterface.h +deleted file mode 100644 +index fbc6d6f8b..000000000 +--- a/webenginepart/src/webhistoryinterface.h ++++ /dev/null +@@ -1,34 +0,0 @@ +-/* +- * This file is part of the KDE project. +- * +- * Copyright (C) 2011 Dawit Alemayehu <adawit@kde.org> +- * +- * This library is free software; you can redistribute it and/or modify it +- * under the terms of the GNU Lesser General Public License as published by the +- * Free Software Foundation; either version 2.1 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 Lesser General Public License for more +- * details. +- * +- * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- */ +-#ifndef WEBHISTORYINTERFACE_H +-#define WEBHISTORYINTERFACE_H +- +-#include <QObject> +- +- +-class WebHistoryInterface +-{ +-public: +- WebHistoryInterface(QObject* parent = Q_NULLPTR); +- void addHistoryEntry (const QString & url); +- bool historyContains (const QString & url) const; +-}; +- +-#endif //WEBHISTORYINTERFACE_H +diff --git a/webenginepart/src/websslinfo.cpp a/webenginepart/src/websslinfo.cpp +deleted file mode 100644 +index 7960007d0..000000000 +--- a/webenginepart/src/websslinfo.cpp ++++ /dev/null +@@ -1,224 +0,0 @@ +-/* +- * This file is part of the KDE project. +- * +- * Copyright (C) 2009 Dawit Alemayehu <adawit@kde.org> +- * +- * This library is free software; you can redistribute it and/or modify it +- * under the terms of the GNU Lesser General Public License as published by the +- * Free Software Foundation; either version 2.1 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 Lesser General Public License for more +- * details. +- * +- * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- */ +- +-#include "websslinfo.h" +- +-#include <QVariant> +- +- +-class WebSslInfo::WebSslInfoPrivate +-{ +-public: +- WebSslInfoPrivate() +- : usedCipherBits(0), supportedCipherBits(0) {} +- +- QUrl url; +- QString ciphers; +- QString protocol; +- QString certErrors; +- QHostAddress peerAddress; +- QHostAddress parentAddress; +- QList<QSslCertificate> certificateChain; +- +- int usedCipherBits; +- int supportedCipherBits; +-}; +- +-WebSslInfo::WebSslInfo() +- :d(new WebSslInfo::WebSslInfoPrivate) +-{ +-} +- +-WebSslInfo::WebSslInfo(const WebSslInfo& other) +- :d(new WebSslInfo::WebSslInfoPrivate) +-{ +- *this = other; +-} +- +-WebSslInfo::~WebSslInfo() +-{ +- delete d; +- d = 0; +-} +- +-bool WebSslInfo::isValid() const +-{ +- return (d ? !d->peerAddress.isNull() : false); +-} +- +-QUrl WebSslInfo::url() const +-{ +- return (d ? d->url : QUrl()); +-} +- +-QHostAddress WebSslInfo::parentAddress() const +-{ +- return (d ? d->parentAddress : QHostAddress()); +-} +- +-QHostAddress WebSslInfo::peerAddress() const +-{ +- return (d ? d->peerAddress : QHostAddress()); +-} +- +-QString WebSslInfo::protocol() const +-{ +- return (d ? d->protocol : QString()); +-} +- +-QString WebSslInfo::ciphers() const +-{ +- return (d ? d->ciphers : QString()); +-} +- +-QString WebSslInfo::certificateErrors() const +-{ +- return (d ? d->certErrors : QString()); +-} +- +-int WebSslInfo::supportedChiperBits () const +-{ +- return (d ? d->supportedCipherBits : 0); +-} +- +-int WebSslInfo::usedChiperBits () const +-{ +- return (d ? d->usedCipherBits : 0); +-} +- +-QList<QSslCertificate> WebSslInfo::certificateChain() const +-{ +- return (d ? d->certificateChain : QList<QSslCertificate>()); +-} +- +-WebSslInfo& WebSslInfo::operator=(const WebSslInfo& other) +-{ +- if (d) { +- d->ciphers = other.d->ciphers; +- d->protocol = other.d->protocol; +- d->certErrors = other.d->certErrors; +- d->peerAddress = other.d->peerAddress; +- d->parentAddress = other.d->parentAddress; +- d->certificateChain = other.d->certificateChain; +- +- d->usedCipherBits = other.d->usedCipherBits; +- d->supportedCipherBits = other.d->supportedCipherBits; +- d->url = other.d->url; +- } +- +- return *this; +-} +- +-bool WebSslInfo::saveTo(QMap<QString, QVariant>& data) const +-{ +- const bool ok = isValid(); +- if (ok) { +- data.insert(QStringLiteral("ssl_in_use"), true); +- data.insert(QStringLiteral("ssl_peer_ip"), d->peerAddress.toString()); +- data.insert(QStringLiteral("ssl_parent_ip"), d->parentAddress.toString()); +- data.insert(QStringLiteral("ssl_protocol_version"), d->protocol); +- data.insert(QStringLiteral("ssl_cipher"), d->ciphers); +- data.insert(QStringLiteral("ssl_cert_errors"), d->certErrors); +- data.insert(QStringLiteral("ssl_cipher_used_bits"), d->usedCipherBits); +- data.insert(QStringLiteral("ssl_cipher_bits"), d->supportedCipherBits); +- QByteArray certChain; +- Q_FOREACH(const QSslCertificate& cert, d->certificateChain) +- certChain += cert.toPem(); +- data.insert(QStringLiteral("ssl_peer_chain"), certChain); +- } +- +- return ok; +-} +- +-void WebSslInfo::restoreFrom(const QVariant& value, const QUrl& url, bool reset) +-{ +- if (reset) { +- *this = WebSslInfo(); +- } +- +- if (value.isValid() && value.type() == QVariant::Map) { +- QMap<QString,QVariant> metaData = value.toMap(); +- if (metaData.value(QStringLiteral("ssl_in_use"), false).toBool()) { +- setCertificateChain(metaData.value(QStringLiteral("ssl_peer_chain")).toByteArray()); +- setPeerAddress(metaData.value(QStringLiteral("ssl_peer_ip")).toString()); +- setParentAddress(metaData.value(QStringLiteral("ssl_parent_ip")).toString()); +- setProtocol(metaData.value(QStringLiteral("ssl_protocol_version")).toString()); +- setCiphers(metaData.value(QStringLiteral("ssl_cipher")).toString()); +- setCertificateErrors(metaData.value(QStringLiteral("ssl_cert_errors")).toString()); +- setUsedCipherBits(metaData.value(QStringLiteral("ssl_cipher_used_bits")).toString()); +- setSupportedCipherBits(metaData.value(QStringLiteral("ssl_cipher_bits")).toString()); +- setUrl(url); +- } +- } +-} +- +-void WebSslInfo::setUrl (const QUrl &url) +-{ +- if (d) +- d->url = url; +-} +- +-void WebSslInfo::setPeerAddress(const QString& address) +-{ +- if (d) +- d->peerAddress = address; +-} +- +-void WebSslInfo::setParentAddress(const QString& address) +-{ +- if (d) +- d->parentAddress = address; +-} +- +-void WebSslInfo::setProtocol(const QString& protocol) +-{ +- if (d) +- d->protocol = protocol; +-} +- +-void WebSslInfo::setCertificateChain(const QByteArray& chain) +-{ +- if (d) +- d->certificateChain = QSslCertificate::fromData(chain); +-} +- +-void WebSslInfo::setCiphers(const QString& ciphers) +-{ +- if (d) +- d->ciphers = ciphers; +-} +- +-void WebSslInfo::setUsedCipherBits(const QString& bits) +-{ +- if (d) +- d->usedCipherBits = bits.toInt(); +-} +- +-void WebSslInfo::setSupportedCipherBits(const QString& bits) +-{ +- if (d) +- d->supportedCipherBits = bits.toInt(); +-} +- +-void WebSslInfo::setCertificateErrors(const QString& certErrors) +-{ +- if (d) +- d->certErrors = certErrors; +-} +diff --git a/webenginepart/src/websslinfo.h a/webenginepart/src/websslinfo.h +deleted file mode 100644 +index 7c7d09ca7..000000000 +--- a/webenginepart/src/websslinfo.h ++++ /dev/null +@@ -1,70 +0,0 @@ +-/* +- * This file is part of the KDE project. +- * +- * Copyright (C) 2009 Dawit Alemayehu <adawit@kde.org> +- * +- * This library is free software; you can redistribute it and/or modify it +- * under the terms of the GNU Lesser General Public License as published by the +- * Free Software Foundation; either version 2.1 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 Lesser General Public License for more +- * details. +- * +- * You should have received a copy of the GNU Lesser General Public +- * License along with this library. If not, see <http://www.gnu.org/licenses/>. +- * +- */ +-#ifndef WEBSSLINFO_H +-#define WEBSSLINFO_H +- +-//#include <kdemacros.h> +- +-#include <QUrl> +-#include <QList> +-#include <QString> +-#include <QHostAddress> +-#include <QSslCertificate> +- +-class WebSslInfo +-{ +-public: +- WebSslInfo(); +- WebSslInfo(const WebSslInfo&); +- virtual ~WebSslInfo(); +- +- bool isValid() const; +- QUrl url() const; +- QHostAddress peerAddress() const; +- QHostAddress parentAddress() const; +- QString ciphers() const; +- QString protocol() const; +- QString certificateErrors() const; +- int supportedChiperBits () const; +- int usedChiperBits () const; +- QList<QSslCertificate> certificateChain() const; +- +- bool saveTo(QMap<QString, QVariant>&) const; +- void restoreFrom(const QVariant &, const QUrl& = QUrl(), bool reset = false); +- +- void setUrl (const QUrl &url); +- WebSslInfo& operator = (const WebSslInfo&); +- +-protected: +- void setCiphers(const QString& ciphers); +- void setProtocol(const QString& protocol); +- void setPeerAddress(const QString& address); +- void setParentAddress(const QString& address); +- void setCertificateChain(const QByteArray& chain); +- void setCertificateErrors(const QString& certErrors); +- void setUsedCipherBits(const QString& bits); +- void setSupportedCipherBits(const QString& bits); +- +-private: +- class WebSslInfoPrivate; +- WebSslInfoPrivate* d; +-}; +- +-#endif // WEBSSLINFO_H +diff --git a/webenginepart/testfiles/embed_tag_test.html a/webenginepart/testfiles/embed_tag_test.html +deleted file mode 100644 +index 8afe2d611..000000000 +--- a/webenginepart/testfiles/embed_tag_test.html ++++ /dev/null +@@ -1,20 +0,0 @@ +-<html> +-<head> +- <title> <EMBED> tests</title> +-</head> +-<body> +- <h1>KDE e.V. Report 2011 Q2</h1> +- <center> +- <embed type="application/pdf" src="http://ev.kde.org/reports/ev-quarterly-2011_Q2.pdf" width="75%" height="400"/> +- </center> +- <p/> +- <h1>KDE e.V. Report 2011 Q1</h1> +- <center> +- <embed type="application/pdf" src="http://ev.kde.org/reports/ev-quarterly-2011_Q1.pdf" width="75%" height="400"/> +- </center> +- <p/> +- <center> +- <video src="http://blip.tv/file/get/Sebasje-ThePlasmaDesktopShellInKDE42312.ogv" controls="controls" width="75%" height="450"/> +- </center> +-</body> +-</html> +diff --git a/webenginepart/testfiles/form_save_restore_test.html a/webenginepart/testfiles/form_save_restore_test.html +deleted file mode 100644 +index d1adaeb76..000000000 +--- a/webenginepart/testfiles/form_save_restore_test.html ++++ /dev/null +@@ -1,68 +0,0 @@ +-<html> +-<head> +- <title>Form save restore test</title> +-</head> +-<body> +- +-<form name="testform"> +-<label for="testedit">Enter text:</label> +-<input type="text" name="testinputtext" id="testedit"> +-<br> +-<label>Check this box</label> +-<input type="checkbox" name="testinputcheckbox" value="checked"> +-<br> +-<label>File to upload:</label> +-<input type="file" name="testinputfile"> +-<br> +-<input type="radio" name="testinputradio" value="one">One</input> +-<br> +-<input type="radio" name="testinputradio" value="two">Two</input> +-<br> +-<input type="radio" name="testinputradio" value="three">Three</input> +-<br> +-</form> +- +-<p> +-Enter some text in the box below:<br/> +-<textarea name="testtextarea"></textarea> +-</p> +- +-<p> +-Disabled text area:<br/> +-<textarea name="testtextarea" disabled></textarea> +-</p> +- +-<p> +-Read only text area:<br/> +-<textarea name="testtextarea" readonly>This is a read only text area.</textarea> +-</p> +- +-<p> +-Text area with spell check disabled:<br/> +-<textarea name="testtextarea" spellcheck="false"></textarea> +-</p> +- +-<p> +-Choose one: +-<select name="testcombobox"> +-<option>First</option> +-<option>Second</option> +-<option>Third</option> +-<option>Fourth</option> +-<option>Fifth</option> +-</select> +-</p><p/> +- +-<p> +-Select one or more items:<br/> +-<select name="testlist" multiple> +-<option>One</option> +-<option>Two</option> +-<option>Three</option> +-<option>Four</option> +-<option>Five</option> +-</select> +-</p> +- +-</body> +-</html> +diff --git a/webenginepart/testfiles/frameset_test.html a/webenginepart/testfiles/frameset_test.html +deleted file mode 100644 +index 25a295937..000000000 +--- a/webenginepart/testfiles/frameset_test.html ++++ /dev/null +@@ -1,9 +0,0 @@ +-<html> +-<head> +-<title><FRAMESET> test</title> +-</head> +-<frameset cols="120,*"> +- <frame src="frametest/frame_navigation.html" /> +- <frame src="frametest/frame_a.html" name="showframe" /> +-</frameset> +-</html> +diff --git a/webenginepart/testfiles/frametest/frame_a.html a/webenginepart/testfiles/frametest/frame_a.html +deleted file mode 100644 +index 0ea08f3f6..000000000 +--- a/webenginepart/testfiles/frametest/frame_a.html ++++ /dev/null +@@ -1,7 +0,0 @@ +-<html> +-<body bgcolor="#8F8FBD"> +- +-<h3>Frame A</h3> +- +-</body> +-</html> +diff --git a/webenginepart/testfiles/frametest/frame_b.html a/webenginepart/testfiles/frametest/frame_b.html +deleted file mode 100644 +index fe36a8d98..000000000 +--- a/webenginepart/testfiles/frametest/frame_b.html ++++ /dev/null +@@ -1,7 +0,0 @@ +-<html> +-<body bgcolor="#EBC79E"> +- +-<h3>Frame B</h3> +- +-</body> +-</html> +\ No newline at end of file +diff --git a/webenginepart/testfiles/frametest/frame_c.html a/webenginepart/testfiles/frametest/frame_c.html +deleted file mode 100644 +index 3ed0e0e67..000000000 +--- a/webenginepart/testfiles/frametest/frame_c.html ++++ /dev/null +@@ -1,7 +0,0 @@ +-<html> +-<body bgcolor="#FFFFCC"> +- +-<h3>Frame C</h3> +-<a href="http://www.kde.org">Go to KDE website</a> +-</body> +-</html> +\ No newline at end of file +diff --git a/webenginepart/testfiles/frametest/frame_navigation.html a/webenginepart/testfiles/frametest/frame_navigation.html +deleted file mode 100644 +index 3632a0d8b..000000000 +--- a/webenginepart/testfiles/frametest/frame_navigation.html ++++ /dev/null +@@ -1,9 +0,0 @@ +-<html> +-<body> +-<a href ="frame_a.html" target ="showframe">Frame a</a><br/> +-<a href ="frame_b.html" target ="showframe">Frame b</a><br/> +-<a href ="frame_c.html" target ="showframe">Frame c</a><br/> +-<a href ="frame_d.html" target ="showframe">Invalid frame</a><br/> +-<a href ="https://bugs.kde.org" target ="showframe">bugs.kde.org</a> +-</body> +-</html> +\ No newline at end of file +diff --git a/webenginepart/testfiles/js.html a/webenginepart/testfiles/js.html +deleted file mode 100644 +index 4c03c3473..000000000 +--- a/webenginepart/testfiles/js.html ++++ /dev/null +@@ -1,52 +0,0 @@ +-<html> +-<head> +-<title>Javascript Link Tests</title> +-<script type="text/javascript"> +-function resize() +-{ +- window.resizeTo(580, 420); +-} +- +-function move() +-{ +- window.moveTo(180, 120); +-} +- +-function promptAndAlertMessage() +-{ +- var message = prompt("Enter a message.", ""); +- alert(message); +-} +- +-function statusMessage() +-{ +- window.status = 'A new status message.'; +-} +- +-function openWindow() +-{ +- window.open("about:blank", "NewWindowTest1", "width=300, height=400"); +-} +- +-function openWindowFrameTest() +-{ +- var new_window = window.open('about:blank','testpage','width=800,height=600'); +- new_window.location="frameset_test.html"; +-} +- +-</script> +-</head> +-<body> +-<script type="text/javascript"> +-document.writeln("navigator.appName: " + navigator.appName + "<br />"); +-document.writeln("navigator.appVersion: " + navigator.appVersion + "<br />"); +-</script> +-<h1>Javascript Link Tests</h1> +-<a href="javascript:resize()">resizeTo</a><br /> +-<a href="javascript:move()">moveTo</a><br /> +-<a href="javascript:promptAndAlertMessage()">promptAndAlertMessage</a><br /> +-<a href="javascript:statusMessage()">status</a><br /> +-<a href="javascript:window.open('about:blank', 'NewWindowTest1', 'width=300, height=400')">JS open new window</a><br /> +-<a href="javascript:openWindowFrameTest()">JS open new frameset</a><br /> +-</body> +-</html> +diff --git a/webenginepart/testfiles/link_tests.html a/webenginepart/testfiles/link_tests.html +deleted file mode 100644 +index f2d73007a..000000000 +--- a/webenginepart/testfiles/link_tests.html ++++ /dev/null +@@ -1,136 +0,0 @@ +-<html> +-<head> +- <title>Link Tests</title> +-</head> +-<script type="text/javascript"> +- function delayedRedirect() { +- setTimeout(window.open("http://kde-look.org/CONTENT/content-files/52338-kÃy.jpg"), 3000) +- } +- function openWin(url,name,features) { +- url = url || '' +- name = name || '' +- features = features || 'width=200,height=100' +- var myWindow = window.open(url,name,features); +- if (!url) { +- myWindow.document.write("<p>This is 'myWindow'</p>"); +- myWindow.focus(); +- } +- } +-</script> +-<body> +-<h2>MAILTO Link Tests</h2> +- <a href="mailto:joe@xyz.com&CC=bob@xyz.com&BCC=bob@xyz.com&attach=%2Fetc%2Fpasswd&subject=hello&body=hello">Email link #1</a> +- <br/> +- <a href="mailto:joe@xyz.com">Email link #2</a> +- <br/> +-<h2>FTP Link Tests</h2> +- <a href="ftp://ftp.kde.org" target="_blank">FTP link #1 (new window)</a> +- <br/> +- <a href="ftp://ftp.kde.org/pub" target="_blank">FTP link #2 (new window)</a> +- <br/> +- <a href="ftp://upload.kde.org">FTP link #3</a> +- <br/> +- <a href="ftp://ftp.kde.org/pub/kde/README_UPLOAD">Text File Link</a> +- <br/> +- <a href="#fragments" target="_top">Anchor test</a> +- <br/> +- <a href="#fragments" target="_blank">Anchor test (new window)</a> +- <br/> +-<h2>HTTP Link Tests</h2> +- <a href="http://www.kde.org" target="_blank">Web site link (new window)</a> +- <br/> +- <a href="http://foo@www.kde.org">Web site link with bogus username</a> +- <br/> +- <a href="http://bar@www.kde.org">Web site link with different bogus username</a> +- <br/> +- <a href="http://ev.kde.org/reports/ev-quarterly-2012_Q1.pdf">PDF link</a> +- <br/> +- <a href="http://ev.kde.org/reports/ev-quarterly-2012_Q1.pdf" target="_blank">PDF link (new window)</a> +- <br/> +- <a href="http://ev.kde.org/reports/ev-quarterly-2012_Q1.pdf" target="_blank">Duplicate PDF link (new window)</a> +- <br/> +- <a href="http://blip.tv/file/get/Sebasje-WindowManagingFeaturesInKDEPlasma44222.ogg">Movie link</a> +- <br/> +- <a href="http://blip.tv/file/get/Sebasje-WindowManagingFeaturesInKDEPlasma44222.ogg" target="_blank">Movie link (new window)</a> +- <br/> +- <a href="http://www.ietf.org/rfc/rfc2344.txt">Text Document Link</a> +- <br/> +- <a href="http://www.microsoft.com%26item%3Dq209354rexsddiuyjkiuylkuryt2583453453fsesfsdfsfasfdfdsf@www.kde.org/">Bogus link</a> +- <br/> +-<h2>Javascript Link Tests</h2> +- <a href="javascript:openWin('http://www.kde.org','', 'width=600,height=600,statusbar=no,toolbar=no')">Open dialog like window link #1</a> +- <br/> +- <a href="javascript:openWin('file:///usr/local/src/KDE/git/extragear/kwebkitpart/tests/link_tests.html','','dialog','width=600,height=600,statusbar=no,toolbar=no')">Open dialog like window link #2</a> +- <br/> +- <a href="javascript:openWin('http://www.kde.org','', 'width=0,height=0')">Open new window link #2 (might be opened as Tab)</a> +- <br/> +- <a href="javascript:openWin('http://ev.kde.org/reports/ev-quarterly-2009Q1.pdf', '_blank', 'width=600,height=600,statusbar=no,toolbar=no')">Open PDF Document (new window)</a> +- <br/> +- <a href='empty.html' onclick="openWin('empty.html', 'dz_orders','toolbar=false,height=100,width=100,resizable=1,scrollbars=1')" target='dz_orders'>Javscript + Target test</a> +- <br/> +- <a href="javascript:window.close">Close window</a> +- <br/> +- <a href="" onmouseover="openWin()">On mouse over open window test</a> +- <br/> +- <a href="javascript:setTimeout(delayedRedirect(), 3000)" target="_blank">Redirect test</a> +- <br/> +-<h2>KDE specific URL Tests</h2> +- <a href="applications:/Internet/">Text Document Link</a> +- <br/> +-<h2>Form Tests</h2> +- <form action="mailto:someone@example.com?CC='bob@example.com&attach=%2fetc%2fpasswd&body=" method="post" enctype="application/x-www-form-urlencoded"> +- Choose file to upload:<br /> +- <input type="file" name="upload_file" size="20" /><br/> +- <input type="submit" value="Send" /> +- <input type="reset" value="Reset" /> +- </form> +- <br/> +- <a name="fragments"><h2>URL Fragment Test</h2></a> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +- <br/> +-</body> +-</html> +diff --git a/webenginepart/testfiles/meta_tag_refresh_test.html a/webenginepart/testfiles/meta_tag_refresh_test.html +deleted file mode 100644 +index 4ea95a59c..000000000 +--- a/webenginepart/testfiles/meta_tag_refresh_test.html ++++ /dev/null +@@ -1,14 +0,0 @@ +-<html> +-<head> +- <title>Meta redirect test</title> +- <meta HTTP-EQUIV="Refresh" CONTENT="10;URL=http://kde.org"> +-</head> +-<body> +-You will be redirected to <a href="http://www.kde.org">kde.org</a> in 10 seconds.<br/> +-<p> +-If the stop button is active (not disabled) after the page has completely loaded, it +-means the rendering engine allows you to cancel <META> based redirect requests. +-Otherwise, you are not able to stop redirects or refresh requests set by web pages. +-</p> +-</body> +-</html> +\ No newline at end of file +diff --git a/webenginepart/tests/CMakeLists.txt a/webenginepart/tests/CMakeLists.txt +deleted file mode 100644 +index 5589c1b18..000000000 +--- a/webenginepart/tests/CMakeLists.txt ++++ /dev/null +@@ -1,2 +0,0 @@ +-add_executable(webenginepart_tester webenginepart_tester.cpp) +-target_link_libraries(webenginepart_tester kwebenginepartlib Qt5::Core Qt5::Gui Qt5::Widgets Qt5::WebEngineWidgets KF5::I18n KF5::KDELibs4Support) +diff --git a/webenginepart/tests/webenginepart_tester.cpp a/webenginepart/tests/webenginepart_tester.cpp +deleted file mode 100644 +index 069a4323f..000000000 +--- a/webenginepart/tests/webenginepart_tester.cpp ++++ /dev/null +@@ -1,437 +0,0 @@ +-/* +- * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) +- * Copyright (C) 2006 George Staikos <staikos@kde.org> +- * Copyright (C) 2006 Dirk Mueller <mueller@kde.org> +- * Copyright (C) 2006 Zack Rusin <zack@kde.org> +- * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org> +- * +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions +- * are met: +- * 1. Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * 2. Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * +- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY +- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR +- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#include <KApplication> +-#include <KAboutData> +-#include <KCmdLineArgs> +-#include <KDebug> +-#include <KIO/AccessManager> +-#include <KUriFilter> +-#include <KInputDialog> +-#include <KLineEdit> +-#include <webenginepart.h> +- +-#include <QInputDialog> +- +-//#include <QUiLoader> +-//#include <QWebEnginePage> +-#include <QWebEngineView> +-//#include <QWebFrame> +-#include <QWebEngineSettings> +-//#include <QWebElement> +-//#include <QWebElementCollection> +- +-#if !defined(QT_NO_PRINTER) +-#include <QPrintPreviewDialog> +-#endif +- +-#include <QAction> +-#include <QCompleter> +-#include <QMainWindow> +-#include <QMenu> +-#include <QMenuBar> +-#include <QProgressBar> +-#include <QStatusBar> +-#include <QStringListModel> +-#include <QToolBar> +-#include <QToolTip> +-#include <QDir> +-#include <QFile> +-#include <QVector> +-#include <QTextStream> +-#include <QApplication> +-#include <KAboutData> +-#include <KLocalizedString> +-#include <QCommandLineParser> +- +- +-class MainWindow : public QMainWindow +-{ +- Q_OBJECT +-public: +- MainWindow(const QString& url = QString()): currentZoom(100) { +- view = new WebEnginePart(this); +- setCentralWidget(view->widget()); +- +- connect(view->view(), &QWebEngineView::loadFinished, +- this, &MainWindow::loadFinished); +- connect(view->view(), SIGNAL(titleChanged(QString)), +- this, SLOT(setWindowTitle(QString))); +- connect(view->view()->page(), SIGNAL(linkHovered(QString)), +- this, SLOT(showLinkHover(QString))); +- connect(view->view()->page(), SIGNAL(windowCloseRequested()), this, SLOT(deleteLater())); +- +- setupUI(); +- +- QUrl qurl(KUriFilter::self()->filteredUri(url, QStringList() << QStringLiteral("kshorturifilter"))); +- if (qurl.isValid()) { +- urlEdit->setText(qurl.toEncoded()); +- view->openUrl(qurl); +- +- // the zoom values are chosen to be like in Mozilla Firefox 3 +- zoomLevels << 30 << 50 << 67 << 80 << 90; +- zoomLevels << 100; +- zoomLevels << 110 << 120 << 133 << 150 << 170 << 200 << 240 << 300; +- } +- } +- +- QWebEnginePage* webPage() const { +- return view->view()->page(); +- } +- +- QWebEngineView* webView() const { +- return view->view(); +- } +- +-protected slots: +- +- void changeLocation() { +- QUrl url (KUriFilter::self()->filteredUri(urlEdit->text(), QStringList() << QStringLiteral("kshorturifilter"))); +- view->openUrl(url); +- view->view()->setFocus(Qt::OtherFocusReason); +- } +- +- void loadFinished() { +- urlEdit->setText(view->url().toString()); +- +- QUrl::FormattingOptions opts; +- opts |= QUrl::RemoveScheme; +- opts |= QUrl::RemoveUserInfo; +- opts |= QUrl::StripTrailingSlash; +- QString s = view->url().toString(opts); +- s = s.mid(2); +- if (s.isEmpty()) +- return; +- +- if (!urlList.contains(s)) +- urlList += s; +- urlModel.setStringList(urlList); +- } +- +- void showLinkHover(const QString &link) { +- statusBar()->showMessage(link); +- } +- +- void zoomIn() { +- int i = zoomLevels.indexOf(currentZoom); +- Q_ASSERT(i >= 0); +- if (i < zoomLevels.count() - 1) +- currentZoom = zoomLevels[i + 1]; +- +- view->view()->setZoomFactor(qreal(currentZoom)/100.0); +- } +- +- void zoomOut() { +- int i = zoomLevels.indexOf(currentZoom); +- Q_ASSERT(i >= 0); +- if (i > 0) +- currentZoom = zoomLevels[i - 1]; +- +- view->view()->setZoomFactor(qreal(currentZoom)/100.0); +- } +- +- void resetZoom() +- { +- currentZoom = 100; +- view->view()->setZoomFactor(1.0); +- } +- +- void toggleZoomTextOnly(bool b) +- { +-// view->view()->page()->settings()->setAttribute(QWebEngineSettings::ZoomTextOnly, b); +- } +- +- void print() { +-#if !defined(QT_NO_PRINTER) +- QScopedPointer<QPrintPreviewDialog> dlg (new QPrintPreviewDialog(this)); +- connect(dlg.data(), SIGNAL(paintRequested(QPrinter*)), +- view, SLOT(print(QPrinter*))); +- dlg->exec(); +-#endif +- } +- +- void setEditable(bool on) { +-// view->view()->page()->setContentEditable(on); +- formatMenuAction->setVisible(on); +- } +- +- void dumpHtml() { +- view->view()->page()->toHtml([](const QString& text) { +- kDebug() << "HTML: " << text; +- }); +- } +- +- void selectElements() { +- bool ok; +- QString str = QInputDialog::getText(this, i18nc("input dialog window title for selecting html elements", "Select elements"), +- i18nc("input dialog text for selecting html elements", "Choose elements"), QLineEdit::Normal, +- QStringLiteral("a"), &ok); +- if (ok && !str.isEmpty()) { +- //QWebElementCollection collection = view->page()->mainFrame()->findAllElements(str); +- //const int count = collection.count(); +- //for (int i=0; i < count; i++) +- // collection.at(i).setStyleProperty("background-color", "yellow"); +- //statusBar()->showMessage(i18np("%1 element selected", "%1 elements selected", count), 5000); +- } +- } +- +-public slots: +- +- void newWindow(const QString &url = QString()) { +- MainWindow *mw = new MainWindow(url); +- mw->show(); +- } +- +-private: +- +- QVector<int> zoomLevels; +- int currentZoom; +- +- // create the status bar, tool bar & menu +- void setupUI() { +- progress = new QProgressBar(this); +- progress->setRange(0, 100); +- progress->setMinimumSize(100, 20); +- progress->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); +- progress->hide(); +- statusBar()->addPermanentWidget(progress); +- +- connect(view->view(), SIGNAL(loadProgress(int)), progress, SLOT(show())); +- connect(view->view(), SIGNAL(loadProgress(int)), progress, SLOT(setValue(int))); +- connect(view->view(), SIGNAL(loadFinished(bool)), progress, SLOT(hide())); +- +- urlEdit = new KLineEdit(this); +- urlEdit->setSizePolicy(QSizePolicy::Expanding, urlEdit->sizePolicy().verticalPolicy()); +- connect(urlEdit, SIGNAL(returnPressed()), +- SLOT(changeLocation())); +- QCompleter *completer = new QCompleter(this); +- urlEdit->setCompleter(completer); +- completer->setModel(&urlModel); +- +- QToolBar *bar = addToolBar(QStringLiteral("Navigation")); +- bar->addAction(view->view()->pageAction(QWebEnginePage::Back)); +- bar->addAction(view->view()->pageAction(QWebEnginePage::Forward)); +- bar->addAction(view->view()->pageAction(QWebEnginePage::Reload)); +- bar->addAction(view->view()->pageAction(QWebEnginePage::Stop)); +- bar->addWidget(urlEdit); +- +- QMenu *fileMenu = menuBar()->addMenu(i18n("&File")); +- QAction *newWindow = fileMenu->addAction(i18n("New Window"), this, SLOT(newWindow())); +- +- fileMenu->addAction(i18n("Print"), this, SLOT(print())); +- fileMenu->addAction(i18n("Close"), this, SLOT(close())); +- +- QMenu *editMenu = menuBar()->addMenu(i18n("&Edit")); +- editMenu->addAction(view->view()->pageAction(QWebEnginePage::Undo)); +- editMenu->addAction(view->view()->pageAction(QWebEnginePage::Redo)); +- editMenu->addSeparator(); +- editMenu->addAction(view->view()->pageAction(QWebEnginePage::Cut)); +- editMenu->addAction(view->view()->pageAction(QWebEnginePage::Copy)); +- editMenu->addAction(view->view()->pageAction(QWebEnginePage::Paste)); +- editMenu->addSeparator(); +- QAction *setEditable = editMenu->addAction(i18n("Set Editable"), this, SLOT(setEditable(bool))); +- setEditable->setCheckable(true); +- +- QMenu *viewMenu = menuBar()->addMenu(i18n("&View")); +- viewMenu->addAction(view->view()->pageAction(QWebEnginePage::Stop)); +- viewMenu->addAction(view->view()->pageAction(QWebEnginePage::Reload)); +- viewMenu->addSeparator(); +- QAction *zoomIn = viewMenu->addAction(i18n("Zoom &In"), this, SLOT(zoomIn())); +- QAction *zoomOut = viewMenu->addAction(i18n("Zoom &Out"), this, SLOT(zoomOut())); +- QAction *resetZoom = viewMenu->addAction(i18n("Reset Zoom"), this, SLOT(resetZoom())); +- QAction *zoomTextOnly = viewMenu->addAction(i18n("Zoom Text Only"), this, SLOT(toggleZoomTextOnly(bool))); +- zoomTextOnly->setCheckable(true); +- zoomTextOnly->setChecked(false); +- viewMenu->addSeparator(); +- viewMenu->addAction(i18n("Dump HTML"), this, SLOT(dumpHtml())); +- +-#if 0 +- QMenu *formatMenu = new QMenu(i18n("F&ormat")); +- formatMenuAction = menuBar()->addMenu(formatMenu); +- formatMenuAction->setVisible(false); +- formatMenu->addAction(view->view()->pageAction(QWebEnginePage::ToggleBold)); +- formatMenu->addAction(view->view()->pageAction(QWebEnginePage::ToggleItalic)); +- formatMenu->addAction(view->view()->pageAction(QWebEnginePage::ToggleUnderline)); +- QMenu *writingMenu = formatMenu->addMenu(i18n("Writing Direction")); +- writingMenu->addAction(view->view()->pageAction(QWebEnginePage::SetTextDirectionDefault)); +- writingMenu->addAction(view->view()->pageAction(QWebEnginePage::SetTextDirectionLeftToRight)); +- writingMenu->addAction(view->view()->pageAction(QWebEnginePage::SetTextDirectionRightToLeft)); +-#endif +- newWindow->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_N)); +- view->view()->pageAction(QWebEnginePage::Back)->setShortcut(QKeySequence::Back); +- view->view()->pageAction(QWebEnginePage::Stop)->setShortcut(Qt::Key_Escape); +- view->view()->pageAction(QWebEnginePage::Forward)->setShortcut(QKeySequence::Forward); +- view->view()->pageAction(QWebEnginePage::Reload)->setShortcut(QKeySequence::Refresh); +- view->view()->pageAction(QWebEnginePage::Undo)->setShortcut(QKeySequence::Undo); +- view->view()->pageAction(QWebEnginePage::Redo)->setShortcut(QKeySequence::Redo); +- view->view()->pageAction(QWebEnginePage::Cut)->setShortcut(QKeySequence::Cut); +- view->view()->pageAction(QWebEnginePage::Copy)->setShortcut(QKeySequence::Copy); +- view->view()->pageAction(QWebEnginePage::Paste)->setShortcut(QKeySequence::Paste); +- zoomIn->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Plus)); +- zoomOut->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Minus)); +- resetZoom->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_0)); +-// view->view()->pageAction(QWebEnginePage::ToggleBold)->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_B)); +-// view->view()->pageAction(QWebEnginePage::ToggleItalic)->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_I)); +-// view->view()->pageAction(QWebEnginePage::ToggleUnderline)->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_U)); +- +- QMenu *toolsMenu = menuBar()->addMenu(i18n("&Tools")); +- toolsMenu->addAction(i18n("Select elements..."), this, SLOT(selectElements())); +- +- } +- +- WebEnginePart *view; +- KLineEdit *urlEdit; +- QProgressBar *progress; +- +- QAction *formatMenuAction; +- +- QStringList urlList; +- QStringListModel urlModel; +-}; +- +-class URLLoader : public QObject +-{ +- Q_OBJECT +-public: +- URLLoader(QWebEngineView* view, const QString& inputFileName) +- : m_view(view) +- , m_stdOut(stdout) +- { +- init(inputFileName); +- } +- +-public slots: +- void loadNext() +- { +- QString qstr; +- if (getUrl(qstr)) { +- QUrl url(qstr, QUrl::StrictMode); +- if (url.isValid()) { +- m_stdOut << "Loading " << qstr << " ......" << endl; +- m_view->load(url); +- } else +- loadNext(); +- } else +- disconnect(m_view, 0, this, 0); +- } +- +-private: +- void init(const QString& inputFileName) +- { +- QFile inputFile(inputFileName); +- if (inputFile.open(QIODevice::ReadOnly | QIODevice::Text)) { +- QTextStream stream(&inputFile); +- QString line; +- while (true) { +- line = stream.readLine(); +- if (line.isNull()) +- break; +- m_urls.append(line); +- } +- } else { +- kDebug() << "Can't open list file"; +- exit(0); +- } +- m_index = 0; +- inputFile.close(); +- } +- +- bool getUrl(QString& qstr) +- { +- if (m_index == m_urls.size()) +- return false; +- +- qstr = m_urls[m_index++]; +- return true; +- } +- +-private: +- QVector<QString> m_urls; +- int m_index; +- QWebEngineView* m_view; +- QTextStream m_stdOut; +-}; +- +- +-int main(int argc, char **argv) +-{ +- KAboutData about(QStringLiteral("KDELauncher"), i18n("KDELauncher"), QStringLiteral("0.0000013")); +- QApplication app(argc, argv); +- QCommandLineParser parser; +- KAboutData::setApplicationData(about); +- parser.addVersionOption(); +- parser.addHelpOption(); +- //PORTING SCRIPT: adapt aboutdata variable if necessary +- about.setupCommandLine(&parser); +- parser.process(app); +- about.processCommandLine(&parser); +- +- QString url = QStringLiteral("%1/%2").arg(QDir::homePath()).arg(QStringLiteral("index.html")); +- +-// QWebEngineSettings::globalSettings()->setMaximumPagesInCache(4); +- +-// QWebEngineSettings::setObjectCacheCapacities((16*1024*1024) / 8, (16*1024*1024) / 8, 16*1024*1024); +- +- QWebEngineSettings::globalSettings()->setAttribute(QWebEngineSettings::PluginsEnabled, true); +-// QWebEngineSettings::globalSettings()->setAttribute(QWebEngineSettings::DeveloperExtrasEnabled, true); +- +- const QStringList args = app.arguments(); +- +- if (args.contains(QStringLiteral("-r"))) { +- // robotized +- QString listFile = args.at(2); +- if (!(args.count() == 3) && QFile::exists(listFile)) { +- kDebug() << "Usage: KDELauncher -r listfile"; +- exit(0); +- } +- MainWindow window; +- QWebEngineView *view = window.webView(); +- URLLoader loader(view, listFile); +- QObject::connect(view, SIGNAL(loadFinished(bool)), &loader, SLOT(loadNext())); +- loader.loadNext(); +- window.show(); +- return app.exec(); +- } else { +- if (args.count() > 1) +- url = args.at(1); +- +- MainWindow window(url); +- +- // Opens every given urls in new windows +- for (int i = 2; i < args.count(); i++) +- window.newWindow(args.at(i)); +- +- window.show(); +- return app.exec(); +- } +-} +- +-#include "webenginepart_tester.moc" +diff --git a/webenginepart/webenginepart.lsm a/webenginepart/webenginepart.lsm +deleted file mode 100644 +index 99b4fbe5a..000000000 +--- a/webenginepart/webenginepart.lsm ++++ /dev/null +@@ -1,18 +0,0 @@ +-Begin3 +-Title: webenginepart +-Version: 1.2.0 +-Entered-date: 06APR2011 +-Description: A WebEngine browser component for KDE (KPart) +-Keywords: webengine, webenginepart +-Author: Trolltech ASA +- Urs Wolfer <uwolfer @ kde.org> +- Laurent Montel <montel@kde.org> +- Dawit Alemayehu <adawit@kde.org> +- Sune Vuorela <sune@kde.org> +-Maintained-by: Sune Vuorela <sune@kde.org> +-Primary-site: +-Home-Page: +-Original-site: None +-Platforms: KF5 and higher +-Copying-policy: LGPL +-End +diff --git b/webkitpart/CMakeLists.txt b/webkitpart/CMakeLists.txt +new file mode 100644 +index 000000000..b62735e8b +--- /dev/null ++++ b/webkitpart/CMakeLists.txt +@@ -0,0 +1,4 @@ ++add_subdirectory(icons) ++add_subdirectory(src) ++add_subdirectory(tests) ++add_subdirectory(autotests) +diff --git b/webkitpart/COPYING.LIB b/webkitpart/COPYING.LIB +new file mode 100644 +index 000000000..01148ab6f +--- /dev/null ++++ b/webkitpart/COPYING.LIB +@@ -0,0 +1,486 @@ ++NOTE! The LGPL below is copyrighted by the Free Software Foundation, but ++the instance of code that it refers to (the kde libraries) are copyrighted ++by the authors who actually wrote it. ++ ++--------------------------------------------------------------------------- ++ GNU LIBRARY GENERAL PUBLIC LICENSE ++ Version 2, June 1991 ++ ++ Copyright (C) 1991 Free Software Foundation, Inc. ++ 51 Franklin Street, Fifth Floor ++ Boston, MA 02110-1301, USA. ++ Everyone is permitted to copy and distribute verbatim copies ++ of this license document, but changing it is not allowed. ++ ++[This is the first released version of the library GPL. It is ++ numbered 2 because it goes with version 2 of the ordinary GPL.] ++ ++ Preamble ++ ++ The licenses for most software are designed to take away your ++freedom to share and change it. By contrast, the GNU General Public ++Licenses are intended to guarantee your freedom to share and change ++free software--to make sure the software is free for all its users. ++ ++ This license, the Library General Public License, applies to some ++specially designated Free Software Foundation software, and to any ++other libraries whose authors decide to use it. You can use it for ++your libraries, too. ++ ++ When we speak of free software, we are referring to freedom, not ++price. Our General Public Licenses are designed to make sure that you ++have the freedom to distribute copies of free software (and charge for ++this service if you wish), that you receive source code or can get it ++if you want it, that you can change the software or use pieces of it ++in new free programs; and that you know you can do these things. ++ ++ To protect your rights, we need to make restrictions that forbid ++anyone to deny you these rights or to ask you to surrender the rights. ++These restrictions translate to certain responsibilities for you if ++you distribute copies of the library, or if you modify it. ++ ++ For example, if you distribute copies of the library, whether gratis ++or for a fee, you must give the recipients all the rights that we gave ++you. You must make sure that they, too, receive or can get the source ++code. If you link a program with the library, you must provide ++complete object files to the recipients so that they can relink them ++with the library, after making changes to the library and recompiling ++it. And you must show them these terms so they know their rights. ++ ++ Our method of protecting your rights has two steps: (1) copyright ++the library, and (2) offer you this license which gives you legal ++permission to copy, distribute and/or modify the library. ++ ++ Also, for each distributor's protection, we want to make certain ++that everyone understands that there is no warranty for this free ++library. If the library is modified by someone else and passed on, we ++want its recipients to know that what they have is not the original ++version, so that any problems introduced by others will not reflect on ++the original authors' reputations. ++ ++ Finally, any free program is threatened constantly by software ++patents. We wish to avoid the danger that companies distributing free ++software will individually obtain patent licenses, thus in effect ++transforming the program into proprietary software. To prevent this, ++we have made it clear that any patent must be licensed for everyone's ++free use or not licensed at all. ++ ++ Most GNU software, including some libraries, is covered by the ordinary ++GNU General Public License, which was designed for utility programs. This ++license, the GNU Library General Public License, applies to certain ++designated libraries. This license is quite different from the ordinary ++one; be sure to read it in full, and don't assume that anything in it is ++the same as in the ordinary license. ++ ++ The reason we have a separate public license for some libraries is that ++they blur the distinction we usually make between modifying or adding to a ++program and simply using it. Linking a program with a library, without ++changing the library, is in some sense simply using the library, and is ++analogous to running a utility program or application program. However, in ++a textual and legal sense, the linked executable is a combined work, a ++derivative of the original library, and the ordinary General Public License ++treats it as such. ++ ++ Because of this blurred distinction, using the ordinary General ++Public License for libraries did not effectively promote software ++sharing, because most developers did not use the libraries. We ++concluded that weaker conditions might promote sharing better. ++ ++ However, unrestricted linking of non-free programs would deprive the ++users of those programs of all benefit from the free status of the ++libraries themselves. This Library General Public License is intended to ++permit developers of non-free programs to use free libraries, while ++preserving your freedom as a user of such programs to change the free ++libraries that are incorporated in them. (We have not seen how to achieve ++this as regards changes in header files, but we have achieved it as regards ++changes in the actual functions of the Library.) The hope is that this ++will lead to faster development of free libraries. ++ ++ The precise terms and conditions for copying, distribution and ++modification follow. Pay close attention to the difference between a ++"work based on the library" and a "work that uses the library". The ++former contains code derived from the library, while the latter only ++works together with the library. ++ ++ Note that it is possible for a library to be covered by the ordinary ++General Public License rather than by this special one. ++ ++ GNU LIBRARY GENERAL PUBLIC LICENSE ++ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION ++ ++ 0. This License Agreement applies to any software library which ++contains a notice placed by the copyright holder or other authorized ++party saying it may be distributed under the terms of this Library ++General Public License (also called "this License"). Each licensee is ++addressed as "you". ++ ++ A "library" means a collection of software functions and/or data ++prepared so as to be conveniently linked with application programs ++(which use some of those functions and data) to form executables. ++ ++ The "Library", below, refers to any such software library or work ++which has been distributed under these terms. A "work based on the ++Library" means either the Library or any derivative work under ++copyright law: that is to say, a work containing the Library or a ++portion of it, either verbatim or with modifications and/or translated ++straightforwardly into another language. (Hereinafter, translation is ++included without limitation in the term "modification".) ++ ++ "Source code" for a work means the preferred form of the work for ++making modifications to it. For a library, complete source code means ++all the source code for all modules it contains, plus any associated ++interface definition files, plus the scripts used to control compilation ++and installation of the library. ++ ++ Activities other than copying, distribution and modification are not ++covered by this License; they are outside its scope. The act of ++running a program using the Library is not restricted, and output from ++such a program is covered only if its contents constitute a work based ++on the Library (independent of the use of the Library in a tool for ++writing it). Whether that is true depends on what the Library does ++and what the program that uses the Library does. ++ ++ 1. You may copy and distribute verbatim copies of the Library's ++complete source code as you receive it, in any medium, provided that ++you conspicuously and appropriately publish on each copy an ++appropriate copyright notice and disclaimer of warranty; keep intact ++all the notices that refer to this License and to the absence of any ++warranty; and distribute a copy of this License along with the ++Library. ++ ++ You may charge a fee for the physical act of transferring a copy, ++and you may at your option offer warranty protection in exchange for a ++fee. ++ ++ 2. You may modify your copy or copies of the Library or any portion ++of it, thus forming a work based on the Library, and copy and ++distribute such modifications or work under the terms of Section 1 ++above, provided that you also meet all of these conditions: ++ ++ a) The modified work must itself be a software library. ++ ++ b) You must cause the files modified to carry prominent notices ++ stating that you changed the files and the date of any change. ++ ++ c) You must cause the whole of the work to be licensed at no ++ charge to all third parties under the terms of this License. ++ ++ d) If a facility in the modified Library refers to a function or a ++ table of data to be supplied by an application program that uses ++ the facility, other than as an argument passed when the facility ++ is invoked, then you must make a good faith effort to ensure that, ++ in the event an application does not supply such function or ++ table, the facility still operates, and performs whatever part of ++ its purpose remains meaningful. ++ ++ (For example, a function in a library to compute square roots has ++ a purpose that is entirely well-defined independent of the ++ application. Therefore, Subsection 2d requires that any ++ application-supplied function or table used by this function must ++ be optional: if the application does not supply it, the square ++ root function must still compute square roots.) ++ ++These requirements apply to the modified work as a whole. If ++identifiable sections of that work are not derived from the Library, ++and can be reasonably considered independent and separate works in ++themselves, then this License, and its terms, do not apply to those ++sections when you distribute them as separate works. But when you ++distribute the same sections as part of a whole which is a work based ++on the Library, the distribution of the whole must be on the terms of ++this License, whose permissions for other licensees extend to the ++entire whole, and thus to each and every part regardless of who wrote ++it. ++ ++Thus, it is not the intent of this section to claim rights or contest ++your rights to work written entirely by you; rather, the intent is to ++exercise the right to control the distribution of derivative or ++collective works based on the Library. ++ ++In addition, mere aggregation of another work not based on the Library ++with the Library (or with a work based on the Library) on a volume of ++a storage or distribution medium does not bring the other work under ++the scope of this License. ++ ++ 3. You may opt to apply the terms of the ordinary GNU General Public ++License instead of this License to a given copy of the Library. To do ++this, you must alter all the notices that refer to this License, so ++that they refer to the ordinary GNU General Public License, version 2, ++instead of to this License. (If a newer version than version 2 of the ++ordinary GNU General Public License has appeared, then you can specify ++that version instead if you wish.) Do not make any other change in ++these notices. ++ ++ Once this change is made in a given copy, it is irreversible for ++that copy, so the ordinary GNU General Public License applies to all ++subsequent copies and derivative works made from that copy. ++ ++ This option is useful when you wish to copy part of the code of ++the Library into a program that is not a library. ++ ++ 4. You may copy and distribute the Library (or a portion or ++derivative of it, under Section 2) in object code or executable form ++under the terms of Sections 1 and 2 above provided that you accompany ++it with the complete corresponding machine-readable source code, which ++must be distributed under the terms of Sections 1 and 2 above on a ++medium customarily used for software interchange. ++ ++ If distribution of object code is made by offering access to copy ++from a designated place, then offering equivalent access to copy the ++source code from the same place satisfies the requirement to ++distribute the source code, even though third parties are not ++compelled to copy the source along with the object code. ++ ++ 5. A program that contains no derivative of any portion of the ++Library, but is designed to work with the Library by being compiled or ++linked with it, is called a "work that uses the Library". Such a ++work, in isolation, is not a derivative work of the Library, and ++therefore falls outside the scope of this License. ++ ++ However, linking a "work that uses the Library" with the Library ++creates an executable that is a derivative of the Library (because it ++contains portions of the Library), rather than a "work that uses the ++library". The executable is therefore covered by this License. ++Section 6 states terms for distribution of such executables. ++ ++ When a "work that uses the Library" uses material from a header file ++that is part of the Library, the object code for the work may be a ++derivative work of the Library even though the source code is not. ++Whether this is true is especially significant if the work can be ++linked without the Library, or if the work is itself a library. The ++threshold for this to be true is not precisely defined by law. ++ ++ If such an object file uses only numerical parameters, data ++structure layouts and accessors, and small macros and small inline ++functions (ten lines or less in length), then the use of the object ++file is unrestricted, regardless of whether it is legally a derivative ++work. (Executables containing this object code plus portions of the ++Library will still fall under Section 6.) ++ ++ Otherwise, if the work is a derivative of the Library, you may ++distribute the object code for the work under the terms of Section 6. ++Any executables containing that work also fall under Section 6, ++whether or not they are linked directly with the Library itself. ++ ++ 6. As an exception to the Sections above, you may also compile or ++link a "work that uses the Library" with the Library to produce a ++work containing portions of the Library, and distribute that work ++under terms of your choice, provided that the terms permit ++modification of the work for the customer's own use and reverse ++engineering for debugging such modifications. ++ ++ You must give prominent notice with each copy of the work that the ++Library is used in it and that the Library and its use are covered by ++this License. You must supply a copy of this License. If the work ++during execution displays copyright notices, you must include the ++copyright notice for the Library among them, as well as a reference ++directing the user to the copy of this License. Also, you must do one ++of these things: ++ ++ a) Accompany the work with the complete corresponding ++ machine-readable source code for the Library including whatever ++ changes were used in the work (which must be distributed under ++ Sections 1 and 2 above); and, if the work is an executable linked ++ with the Library, with the complete machine-readable "work that ++ uses the Library", as object code and/or source code, so that the ++ user can modify the Library and then relink to produce a modified ++ executable containing the modified Library. (It is understood ++ that the user who changes the contents of definitions files in the ++ Library will not necessarily be able to recompile the application ++ to use the modified definitions.) ++ ++ b) Accompany the work with a written offer, valid for at ++ least three years, to give the same user the materials ++ specified in Subsection 6a, above, for a charge no more ++ than the cost of performing this distribution. ++ ++ c) If distribution of the work is made by offering access to copy ++ from a designated place, offer equivalent access to copy the above ++ specified materials from the same place. ++ ++ d) Verify that the user has already received a copy of these ++ materials or that you have already sent this user a copy. ++ ++ For an executable, the required form of the "work that uses the ++Library" must include any data and utility programs needed for ++reproducing the executable from it. However, as a special exception, ++the source code distributed need not include anything that is normally ++distributed (in either source or binary form) with the major ++components (compiler, kernel, and so on) of the operating system on ++which the executable runs, unless that component itself accompanies ++the executable. ++ ++ It may happen that this requirement contradicts the license ++restrictions of other proprietary libraries that do not normally ++accompany the operating system. Such a contradiction means you cannot ++use both them and the Library together in an executable that you ++distribute. ++ ++ 7. You may place library facilities that are a work based on the ++Library side-by-side in a single library together with other library ++facilities not covered by this License, and distribute such a combined ++library, provided that the separate distribution of the work based on ++the Library and of the other library facilities is otherwise ++permitted, and provided that you do these two things: ++ ++ a) Accompany the combined library with a copy of the same work ++ based on the Library, uncombined with any other library ++ facilities. This must be distributed under the terms of the ++ Sections above. ++ ++ b) Give prominent notice with the combined library of the fact ++ that part of it is a work based on the Library, and explaining ++ where to find the accompanying uncombined form of the same work. ++ ++ 8. You may not copy, modify, sublicense, link with, or distribute ++the Library except as expressly provided under this License. Any ++attempt otherwise to copy, modify, sublicense, link with, or ++distribute the Library is void, and will automatically terminate your ++rights under this License. However, parties who have received copies, ++or rights, from you under this License will not have their licenses ++terminated so long as such parties remain in full compliance. ++ ++ 9. You are not required to accept this License, since you have not ++signed it. However, nothing else grants you permission to modify or ++distribute the Library or its derivative works. These actions are ++prohibited by law if you do not accept this License. Therefore, by ++modifying or distributing the Library (or any work based on the ++Library), you indicate your acceptance of this License to do so, and ++all its terms and conditions for copying, distributing or modifying ++the Library or works based on it. ++ ++ 10. Each time you redistribute the Library (or any work based on the ++Library), the recipient automatically receives a license from the ++original licensor to copy, distribute, link with or modify the Library ++subject to these terms and conditions. You may not impose any further ++restrictions on the recipients' exercise of the rights granted herein. ++You are not responsible for enforcing compliance by third parties to ++this License. ++ ++ 11. If, as a consequence of a court judgment or allegation of patent ++infringement or for any other reason (not limited to patent issues), ++conditions are imposed on you (whether by court order, agreement or ++otherwise) that contradict the conditions of this License, they do not ++excuse you from the conditions of this License. If you cannot ++distribute so as to satisfy simultaneously your obligations under this ++License and any other pertinent obligations, then as a consequence you ++may not distribute the Library at all. For example, if a patent ++license would not permit royalty-free redistribution of the Library by ++all those who receive copies directly or indirectly through you, then ++the only way you could satisfy both it and this License would be to ++refrain entirely from distribution of the Library. ++ ++If any portion of this section is held invalid or unenforceable under any ++particular circumstance, the balance of the section is intended to apply, ++and the section as a whole is intended to apply in other circumstances. ++ ++It is not the purpose of this section to induce you to infringe any ++patents or other property right claims or to contest validity of any ++such claims; this section has the sole purpose of protecting the ++integrity of the free software distribution system which is ++implemented by public license practices. Many people have made ++generous contributions to the wide range of software distributed ++through that system in reliance on consistent application of that ++system; it is up to the author/donor to decide if he or she is willing ++to distribute software through any other system and a licensee cannot ++impose that choice. ++ ++This section is intended to make thoroughly clear what is believed to ++be a consequence of the rest of this License. ++ ++ 12. If the distribution and/or use of the Library is restricted in ++certain countries either by patents or by copyrighted interfaces, the ++original copyright holder who places the Library under this License may add ++an explicit geographical distribution limitation excluding those countries, ++so that distribution is permitted only in or among countries not thus ++excluded. In such case, this License incorporates the limitation as if ++written in the body of this License. ++ ++ 13. The Free Software Foundation may publish revised and/or new ++versions of the Library General Public License from time to time. ++Such new versions will be similar in spirit to the present version, ++but may differ in detail to address new problems or concerns. ++ ++Each version is given a distinguishing version number. If the Library ++specifies a version number of this License which applies to it and ++"any later version", you have the option of following the terms and ++conditions either of that version or of any later version published by ++the Free Software Foundation. If the Library does not specify a ++license version number, you may choose any version ever published by ++the Free Software Foundation. ++ ++ 14. If you wish to incorporate parts of the Library into other free ++programs whose distribution conditions are incompatible with these, ++write to the author to ask for permission. For software which is ++copyrighted by the Free Software Foundation, write to the Free ++Software Foundation; we sometimes make exceptions for this. Our ++decision will be guided by the two goals of preserving the free status ++of all derivatives of our free software and of promoting the sharing ++and reuse of software generally. ++ ++ NO WARRANTY ++ ++ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO ++WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. ++EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR ++OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY ++KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE ++IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE ++LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME ++THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. ++ ++ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN ++WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY ++AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU ++FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR ++CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE ++LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING ++RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A ++FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF ++SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH ++DAMAGES. ++ ++ END OF TERMS AND CONDITIONS ++ How to Apply These Terms to Your New Libraries ++ ++ If you develop a new library, and you want it to be of the greatest ++possible use to the public, we recommend making it free software that ++everyone can redistribute and change. You can do so by permitting ++redistribution under these terms (or, alternatively, under the terms of the ++ordinary General Public License). ++ ++ To apply these terms, attach the following notices to the library. It is ++safest to attach them to the start of each source file to most effectively ++convey the exclusion of warranty; and each file should have at least the ++"copyright" line and a pointer to where the full notice is found. ++ ++ <one line to give the library's name and a brief idea of what it does.> ++ Copyright (C) <year> <name of author> ++ ++ This library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser 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 ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with this library; if not, write to the Free Software ++ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ ++Also add information on how to contact you by electronic and paper mail. ++ ++You should also get your employer (if you work as a programmer) or your ++school, if any, to sign a "copyright disclaimer" for the library, if ++necessary. Here is a sample; alter the names: ++ ++ Yoyodyne, Inc., hereby disclaims all copyright interest in the ++ library `Frob' (a library for tweaking knobs) written by James Random Hacker. ++ ++ <signature of Ty Coon>, 1 April 1990 ++ Ty Coon, President of Vice ++ ++That's all there is to it! +diff --git b/webkitpart/Mainpage.dox b/webkitpart/Mainpage.dox +new file mode 100644 +index 000000000..832196aef +--- /dev/null ++++ b/webkitpart/Mainpage.dox +@@ -0,0 +1,4 @@ ++/** @mainpage ++* ++* Main Doxygen page for KWebKitPart. ++*/ +diff --git b/webkitpart/Messages.sh b/webkitpart/Messages.sh +new file mode 100644 +index 000000000..ce16bc912 +--- /dev/null ++++ b/webkitpart/Messages.sh +@@ -0,0 +1,4 @@ ++#! /usr/bin/env bash ++$EXTRACTRC `find . -name '*.rc' -or -name '*.ui'` >> rc.cpp || exit 11 ++$XGETTEXT `find . -name '*.cpp' | grep -v '/tests/'` -o $podir/webkitpart.pot ++rm -f rc.cpp +diff --git b/webkitpart/README b/webkitpart/README +new file mode 100644 +index 000000000..f73bfc864 +--- /dev/null ++++ b/webkitpart/README +@@ -0,0 +1,40 @@ ++KWebKitPart ++=========== ++ ++KWebKitPart is a KDE component (KPart) wrapper for QtWebKit. It is intended to ++allow KPart based KDE applications such as Konqueror to use it in place of other ++browser engine, such as KHTML, to browse the web in Konqueror. ++ ++Known limitations and unimplemented features are listed in the following ++documents: ++ ++* https://projects.kde.org/projects/kde/kdelibs/repository/revisions/master/entry/kdewebkit/ISSUES ++* https://projects.kde.org/projects/extragear/base/kwebkitpart/repository/revisions/master/entry/TODO ++ ++Please report any issues to: https://bugs.kde.org ++IMPORTANT NOTE: Do not select "konqueror" as product, but "kwebkitpart"! ++ ++There is also a public mailing list available for support: ++ ++ webkit-devel @ kde.org ++ ++How to use KWebKitPart in Konqueror ++=================================== ++ ++You can switch between the different rendering engines: ++View -> View Mode -> {KHTML, WebKit} (website needs to be open) ++If WebKit does not show up in Konqueror, run 'kbuildsycoca4' and ++restart Konqueror. Note that this change does not persist. If you ++press the reload button or open a new website, it will fall back ++to the default rendering engine. ++ ++If you want to set KWebKitPart as default for any website, run: ++'keditfiletype text/html' ++and move "WebKit (kwebkitpart)" in the "Embedding" tab to the top. ++ ++In KDE 4.6 and higher you can choose the default rendering engine ++in Konqueror's configuration dialog under the "General" section. ++ ++For more information about this project please see also: ++http://techbase.kde.org/Projects/WebKit ++ +diff --git b/webkitpart/TODO b/webkitpart/TODO +new file mode 100644 +index 000000000..f6ba03459 +--- /dev/null ++++ b/webkitpart/TODO +@@ -0,0 +1,23 @@ ++* Proper support for KWebKitPart in the following Konqueror plugins: ++ - adblock This plugin's GUI needs to be changed to use the KPart plugin ++ extensions so that it is not khtml specific. Other than that ++ kwebkitpart supports the ad filtering functionalities supported ++ by khtml. ++ ++* Add KPartStatusBarExtension support for the following plugins/features: ++ - Popup blocker (non-plugin) ++ ++* Implement some means of showing information about the webkit rendering engine: ++ - KWebKitPart's version # ++ - QtWebKit's version # ++ - UserAgent string ??? ++ ++* Look through all of Konqueror's web configuration options and make sure we ++ honor all those we possibly can. Here is a non-complete list of features ++ that are either partially implemented or not implemented at all: ++ - Change cursor over links (TODO, QtWebKit ???). ++ - Smooth scrolling support (TODO, QtWebKit ???). ++ - Underline links support (Partial, does not work as intended). ++ - Enable access key navigation with Ctrl key (TODO, QtWebKit ???). ++ - Animations (TODO, QtWebKit ???). ++ - Draw frames around not completely loaded images (TODO, QtWebKit ???). +diff --git b/webkitpart/autotests/CMakeLists.txt b/webkitpart/autotests/CMakeLists.txt +new file mode 100644 +index 000000000..69a14a1a1 +--- /dev/null ++++ b/webkitpart/autotests/CMakeLists.txt +@@ -0,0 +1,14 @@ ++include(ECMAddTests) ++ ++find_package(Qt5Test ${QT_MIN_VERSION} CONFIG REQUIRED) ++ ++macro(webkitpart_unit_tests) ++ foreach(_testname ${ARGN}) ++ ecm_add_test(${_testname}.cpp TEST_NAME ${_testname} ++ LINK_LIBRARIES kwebkitpartlib Qt5::Test) ++ endforeach() ++endmacro(webkitpart_unit_tests) ++ ++webkitpart_unit_tests( ++ webkit_partapi_test ++) +diff --git b/webkitpart/autotests/data/hello.html b/webkitpart/autotests/data/hello.html +new file mode 100644 +index 000000000..e965047ad +--- /dev/null ++++ b/webkitpart/autotests/data/hello.html +@@ -0,0 +1 @@ ++Hello +diff --git b/webkitpart/autotests/data/page-with-link.html b/webkitpart/autotests/data/page-with-link.html +new file mode 100644 +index 000000000..df85219d6 +--- /dev/null ++++ b/webkitpart/autotests/data/page-with-link.html +@@ -0,0 +1 @@ ++<a href="hello.html" id="linkid">click me</a> +diff --git b/webkitpart/autotests/webkit_partapi_test.cpp b/webkitpart/autotests/webkit_partapi_test.cpp +new file mode 100644 +index 000000000..107677692 +--- /dev/null ++++ b/webkitpart/autotests/webkit_partapi_test.cpp +@@ -0,0 +1,133 @@ ++/* ++ Copyright (c) 2016 David Faure <faure@kde.org> ++ ++ This library is free software; you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as published by ++ the Free Software Foundation; either version 2 of the License or ( at ++ your option ) version 3 or, at the discretion of KDE e.V. ( which shall ++ act as a proxy as in section 14 of the GPLv3 ), 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 Lesser 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 <webkitpart.h> ++#include "webkit_testutils.h" ++ ++#include <KIO/Job> ++#include <KParts/BrowserExtension> ++ ++#include <QTest> ++#include <QObject> ++#include <QSignalSpy> ++#include <QWebView> ++ ++class WebKitPartApiTest : public QObject ++{ ++ Q_OBJECT ++private Q_SLOTS: ++ void initTestCase(); ++ void shouldHaveBrowserExtension(); ++ void shouldEmitStartedAndCompleted(); ++ void shouldEmitSetWindowCaption(); ++ void shouldEmitOpenUrlNotifyOnClick(); ++ ++}; ++ ++void WebKitPartApiTest::initTestCase() ++{ ++ qRegisterMetaType<KIO::Job *>(); // for the KParts started signal ++} ++ ++void WebKitPartApiTest::shouldHaveBrowserExtension() ++{ ++ // GIVEN ++ WebKitPart part; ++ ++ // WHEN ++ KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject(&part); ++ ++ // THEN ++ QVERIFY(ext); ++} ++ ++void WebKitPartApiTest::shouldEmitStartedAndCompleted() ++{ ++ // GIVEN ++ WebKitPart part; ++ QSignalSpy spyStarted(&part, &KParts::ReadOnlyPart::started); ++ QSignalSpy spyCompleted(&part, SIGNAL(completed(bool))); ++ QSignalSpy spySetWindowCaption(&part, &KParts::ReadOnlyPart::setWindowCaption); ++ KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject(&part); ++ QSignalSpy spyOpenUrlNotify(ext, &KParts::BrowserExtension::openUrlNotify); ++ const QUrl url(QStringLiteral("data:text/html, <p>Hello World</p>")); ++ ++ // WHEN ++ part.openUrl(url); ++ ++ // THEN ++ QVERIFY(spyStarted.wait()); ++ QVERIFY(spySetWindowCaption.wait()); ++ QCOMPARE(spySetWindowCaption.at(0).at(0).toUrl().toString(), url.toString()); ++ QVERIFY(spyCompleted.wait()); ++ QVERIFY(!spyCompleted.at(0).at(0).toBool()); ++ QVERIFY(spyOpenUrlNotify.isEmpty()); ++} ++ ++void WebKitPartApiTest::shouldEmitSetWindowCaption() ++{ ++ // GIVEN ++ WebKitPart part; ++ QSignalSpy spyStarted(&part, &KParts::ReadOnlyPart::started); ++ QSignalSpy spyCompleted(&part, SIGNAL(completed(bool))); ++ QSignalSpy spySetWindowCaption(&part, &KParts::ReadOnlyPart::setWindowCaption); ++ ++ // WHEN opening a URL with a title tag ++ part.openUrl(QUrl(QStringLiteral("data:text/html, <title>Custom Title</title><p>Hello World</p>"))); ++ ++ // THEN ++ QVERIFY(spyStarted.wait()); ++ QVERIFY(spyCompleted.wait()); ++ QVERIFY(!spyCompleted.at(0).at(0).toBool()); ++ QCOMPARE(spySetWindowCaption.count(), 2); ++ QCOMPARE(spySetWindowCaption.at(1).at(0).toUrl().toString(), QStringLiteral("Custom Title")); ++} ++ ++void WebKitPartApiTest::shouldEmitOpenUrlNotifyOnClick() ++{ ++ // GIVEN ++ WebKitPart part; ++ QSignalSpy spyStarted(&part, &KParts::ReadOnlyPart::started); ++ QSignalSpy spyCompleted(&part, SIGNAL(completed(bool))); ++ QSignalSpy spySetWindowCaption(&part, &KParts::ReadOnlyPart::setWindowCaption); ++ KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject(&part); ++ QSignalSpy spyOpenUrlNotify(ext, &KParts::BrowserExtension::openUrlNotify); ++ const QString file = QFINDTESTDATA("data/page-with-link.html"); ++ QVERIFY(!file.isEmpty()); ++ const QUrl url = QUrl::fromLocalFile(file); ++ part.openUrl(url); ++ QVERIFY(spyCompleted.wait()); ++ QVERIFY(spyOpenUrlNotify.isEmpty()); ++ QWebPage *page = part.view()->page(); ++ const QPoint pos = elementCenter(page, QStringLiteral("linkid")); // doesn't seem fully correct... ++ part.widget()->show(); ++ spyCompleted.clear(); ++ ++ // WHEN clicking on the link ++ QTest::mouseClick(part.view()->focusProxy(), Qt::LeftButton, Qt::KeyboardModifiers(), pos); ++ ++ // THEN ++ QVERIFY(spyCompleted.wait()); ++ QCOMPARE(spyOpenUrlNotify.count(), 1); ++ QCOMPARE(part.url().fileName(), QStringLiteral("hello.html")); ++} ++ ++QTEST_MAIN(WebKitPartApiTest) ++#include "webkit_partapi_test.moc" +diff --git b/webkitpart/autotests/webkit_testutils.h b/webkitpart/autotests/webkit_testutils.h +new file mode 100644 +index 000000000..73ac53d85 +--- /dev/null ++++ b/webkitpart/autotests/webkit_testutils.h +@@ -0,0 +1,108 @@ ++/**************************************************************************** ++ ** ++ ** Copyright (C) 2016 The Qt Company Ltd. ++ ** Contact: https://www.qt.io/licensing/ ++ ** ++ ** This file is part of the QtWebKit module of the Qt Toolkit. ++ ** ++ ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ++ ** Commercial License Usage ++ ** Licensees holding valid commercial Qt licenses may use this file in ++ ** accordance with the commercial license agreement provided with the ++ ** Software or, alternatively, in accordance with the terms contained in ++ ** a written agreement between you and The Qt Company. For licensing terms ++ ** and conditions see https://www.qt.io/terms-conditions. For further ++ ** information use the contact form at https://www.qt.io/contact-us. ++ ** ++ ** GNU General Public License Usage ++ ** Alternatively, this file may be used under the terms of the GNU ++ ** General Public License version 3 as published by the Free Software ++ ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ++ ** included in the packaging of this file. Please review the following ++ ** information to ensure the GNU General Public License requirements will ++ ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ++ ** ++ ** $QT_END_LICENSE$ ++ ** ++ ****************************************************************************/ ++ ++#include <QEventLoop> ++#include <QTimer> ++#include <QWebPage> ++ ++template<typename T, typename R> ++struct RefWrapper { ++ R &ref; ++ void operator()(const T& result) { ++ ref(result); ++ } ++}; ++ ++template<typename T> ++class CallbackSpy { ++public: ++ CallbackSpy() : called(false) { ++ timeoutTimer.setSingleShot(true); ++ QObject::connect(&timeoutTimer, SIGNAL(timeout()), &eventLoop, SLOT(quit())); ++ } ++ ++ T waitForResult() { ++ if (!called) { ++ timeoutTimer.start(10000); ++ eventLoop.exec(); ++ } ++ return result; ++ } ++ ++ bool wasCalled() const { ++ return called; ++ } ++ ++ void operator()(const T &result) { ++ this->result = result; ++ called = true; ++ eventLoop.quit(); ++ } ++ ++ // Cheap rip-off of boost/std::ref ++ RefWrapper<T, CallbackSpy<T> > ref() ++ { ++ RefWrapper<T, CallbackSpy<T> > wrapper = {*this}; ++ return wrapper; ++ } ++ ++private: ++ Q_DISABLE_COPY(CallbackSpy) ++ bool called; ++ QTimer timeoutTimer; ++ QEventLoop eventLoop; ++ T result; ++}; ++ ++// taken from the qwebkit unittests ++static inline QVariant evaluateJavaScriptSync(QWebPage *page, const QString &script) ++{ ++ CallbackSpy<QVariant> spy; ++ page->runJavaScript(script, spy.ref()); ++ return spy.waitForResult(); ++} ++ ++// Taken from QtWebKit's tst_qwebkitpage.cpp ++static QPoint elementCenter(QWebPage *page, const QString &id) ++{ ++ QVariantList rectList = evaluateJavaScriptSync(page, ++ "(function(){" ++ "var elem = document.getElementById('" + id + "');" ++ "var rect = elem.getBoundingClientRect();" ++ "return [rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top];" ++ "})()").toList(); ++ ++ if (rectList.count() != 4) { ++ qWarning("elementCenter failed."); ++ return QPoint(); ++ } ++ const QRect rect(rectList.at(0).toInt(), rectList.at(1).toInt(), ++ rectList.at(2).toInt(), rectList.at(3).toInt()); ++ return rect.center(); ++} ++ +diff --git b/webkitpart/icons/CMakeLists.txt b/webkitpart/icons/CMakeLists.txt +new file mode 100644 +index 000000000..4b820aeb3 +--- /dev/null ++++ b/webkitpart/icons/CMakeLists.txt +@@ -0,0 +1,2 @@ ++include(ECMInstallIcons) ++ecm_install_icons(${ICON_INSTALL_DIR}) +diff --git b/webkitpart/icons/hi128-apps-webkit.png b/webkitpart/icons/hi128-apps-webkit.png +new file mode 100644 +index 000000000..f6580be51 +Binary files /dev/null and b/webkitpart/icons/hi128-apps-webkit.png differ +diff --git b/webkitpart/icons/hi16-apps-webkit.png b/webkitpart/icons/hi16-apps-webkit.png +new file mode 100644 +index 000000000..17c14d129 +Binary files /dev/null and b/webkitpart/icons/hi16-apps-webkit.png differ +diff --git b/webkitpart/icons/hi22-apps-webkit.png b/webkitpart/icons/hi22-apps-webkit.png +new file mode 100644 +index 000000000..03f0a4f38 +Binary files /dev/null and b/webkitpart/icons/hi22-apps-webkit.png differ +diff --git b/webkitpart/icons/hi32-apps-webkit.png b/webkitpart/icons/hi32-apps-webkit.png +new file mode 100644 +index 000000000..4325d32a0 +Binary files /dev/null and b/webkitpart/icons/hi32-apps-webkit.png differ +diff --git b/webkitpart/icons/hi48-apps-webkit.png b/webkitpart/icons/hi48-apps-webkit.png +new file mode 100644 +index 000000000..3d9c79853 +Binary files /dev/null and b/webkitpart/icons/hi48-apps-webkit.png differ +diff --git b/webkitpart/icons/hi64-apps-webkit.png b/webkitpart/icons/hi64-apps-webkit.png +new file mode 100644 +index 000000000..e915bfa0d +Binary files /dev/null and b/webkitpart/icons/hi64-apps-webkit.png differ +diff --git b/webkitpart/icons/webkit.svg b/webkitpart/icons/webkit.svg +new file mode 100644 +index 000000000..ac2e6b9af +--- /dev/null ++++ b/webkitpart/icons/webkit.svg +@@ -0,0 +1,104 @@ ++<?xml version="1.0" encoding="UTF-8" standalone="no"?> ++<!-- Created with Inkscape (http://www.inkscape.org/) --> ++ ++<svg ++ xmlns:dc="http://purl.org/dc/elements/1.1/" ++ xmlns:cc="http://creativecommons.org/ns#" ++ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" ++ xmlns:svg="http://www.w3.org/2000/svg" ++ xmlns="http://www.w3.org/2000/svg" ++ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" ++ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" ++ width="64" ++ height="64" ++ id="svg3360" ++ version="1.1" ++ inkscape:version="0.91 r13725" ++ viewBox="0 0 64 64" ++ sodipodi:docname="webkit.svg" ++ inkscape:export-filename="/home/sune/git/kwebkitpart/icons/hi128-app-webkit.png" ++ inkscape:export-xdpi="180" ++ inkscape:export-ydpi="180"> ++ <defs ++ id="defs3362" /> ++ <sodipodi:namedview ++ id="base" ++ pagecolor="#ffffff" ++ bordercolor="#666666" ++ borderopacity="1.0" ++ inkscape:pageopacity="0.0" ++ inkscape:pageshadow="2" ++ inkscape:zoom="5.5" ++ inkscape:cx="-5.0909091" ++ inkscape:cy="24.727273" ++ inkscape:current-layer="layer1" ++ showgrid="true" ++ inkscape:document-units="px" ++ inkscape:grid-bbox="true" ++ inkscape:window-width="3200" ++ inkscape:window-height="1685" ++ inkscape:window-x="0" ++ inkscape:window-y="0" ++ inkscape:window-maximized="1" /> ++ <metadata ++ id="metadata3365"> ++ <rdf:RDF> ++ <cc:Work ++ rdf:about=""> ++ <dc:format>image/svg+xml</dc:format> ++ <dc:type ++ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> ++ <dc:title></dc:title> ++ </cc:Work> ++ </rdf:RDF> ++ </metadata> ++ <g ++ id="layer1" ++ inkscape:label="Layer 1" ++ inkscape:groupmode="layer"> ++ <text ++ xml:space="preserve" ++ style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#0079b1;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" ++ x="1.6363635" ++ y="32.545456" ++ id="text3368" ++ sodipodi:linespacing="125%"><tspan ++ sodipodi:role="line" ++ id="tspan3370" ++ x="1.6363635" ++ y="32.545456">W</tspan></text> ++ <text ++ xml:space="preserve" ++ style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b0009d;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" ++ x="14.545453" ++ y="46" ++ id="text4172" ++ sodipodi:linespacing="125%"><tspan ++ sodipodi:role="line" ++ id="tspan4174" ++ x="14.545453" ++ y="46">E</tspan></text> ++ <text ++ xml:space="preserve" ++ style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#b0009d;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" ++ x="39.40696" ++ y="32.398262" ++ id="text4172-3" ++ sodipodi:linespacing="125%"><tspan ++ sodipodi:role="line" ++ id="tspan4174-6" ++ x="39.40696" ++ y="32.398262">E</tspan></text> ++ <text ++ xml:space="preserve" ++ style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#848400;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" ++ x="28" ++ y="59.818184" ++ id="text4194" ++ sodipodi:linespacing="125%"><tspan ++ sodipodi:role="line" ++ id="tspan4196" ++ x="28" ++ y="59.818184">B</tspan></text> ++ </g> ++</svg> +diff --git b/webkitpart/scripts/codingstyle.sh b/webkitpart/scripts/codingstyle.sh +new file mode 100755 +index 000000000..1761942d6 +--- /dev/null ++++ b/webkitpart/scripts/codingstyle.sh +@@ -0,0 +1,19 @@ ++#!/bin/sh ++# ++# Kdelibs coding style is defined in http://techbase.kde.org/Policies/Kdelibs_Coding_Style ++# ++ ++PWD=$(pwd) ++cd $PWD ++ ++echo "Applying astyle rules..." ++astyle -v --indent=spaces=4 \ ++ --brackets=linux \ ++ --indent-labels \ ++ --pad=oper --unpad=paren \ ++ --one-line=keep-statements \ ++ --convert-tabs --indent-preprocessor \ ++ `find -type f -name '*.cpp' -or -name '*.h' -or -name '*.cc' | grep -Ev "\./.+/settings/"` ++ ++echo "Done!" ++ +diff --git b/webkitpart/scripts/create_release_package.sh b/webkitpart/scripts/create_release_package.sh +new file mode 100755 +index 000000000..a8694c897 +--- /dev/null ++++ b/webkitpart/scripts/create_release_package.sh +@@ -0,0 +1,16 @@ ++#!/bin/sh ++ ++VERSION=${1} ++GITREPO=${2} ++OUTPUTDIR=${3} ++ ++if [ -z ${VERSION} ] || [ -z {GITREPO} ]; then ++ echo "Usage: `basename ${0}` <VERSION> <GITREPO> [<OUTPUTDIR>]" ++ exit 1 ++fi ++ ++if [ -z $OUTPUTDIR ] || [ ! -d $OUTPUTDIR ]; then ++ OUTPUTDIR="${PWD}" ++fi ++ ++git archive --format=tar --prefix=kwebkitpart-${VERSION}/ ${GITREPO} | bzip2 -9 > ${OUTPUTDIR}/kwebkitpart-${VERSION}.tar.bz2 +diff --git b/webkitpart/src/CMakeLists.txt b/webkitpart/src/CMakeLists.txt +new file mode 100644 +index 000000000..9685b28e6 +--- /dev/null ++++ b/webkitpart/src/CMakeLists.txt +@@ -0,0 +1,41 @@ ++include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_BINARY_DIR}) ++ ++set(kwebkitpartlib_LIB_SRCS ++ webkitpart.cpp ++ webkitpart_ext.cpp ++ webkitview.cpp ++ webkitpage.cpp ++ websslinfo.cpp ++ webhistoryinterface.cpp ++ settings/webkitsettings.cpp ++ settings/webkit_filter.cpp ++ ui/searchbar.cpp ++ ui/passwordbar.cpp ++ ui/featurepermissionbar.cpp ++) ++ ++qt5_wrap_ui(kwebkitpartlib_LIB_SRCS ++ ui/searchbar.ui ++) ++ ++add_library(kwebkitpartlib ${kwebkitpartlib_LIB_SRCS}) ++ ++generate_export_header(kwebkitpartlib) ++ ++target_link_libraries(kwebkitpartlib Qt5::Core Qt5::DBus Qt5::Gui Qt5::Widgets Qt5::WebKitWidgets Qt5::PrintSupport KF5::Parts KF5::SonnetCore) ++ ++target_include_directories(kwebkitpartlib PUBLIC ++ "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/>" ++) ++ ++install(TARGETS kwebkitpartlib ${KF5_INSTALL_TARGETS_DEFAULT_ARGS}) ++ ++add_library(webkitpart MODULE webkitpartfactory.cpp) ++ ++target_link_libraries(webkitpart kwebkitpartlib) ++ ++install(TARGETS webkitpart DESTINATION ${KDE_INSTALL_PLUGINDIR}/kf5/parts) ++ ++install(FILES webkitpart.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}) ++ ++install(FILES webkitpart.rc DESTINATION ${KDE_INSTALL_KXMLGUI5DIR}/webkitpart) +diff --git b/webkitpart/src/settings/webkit_filter.cpp b/webkitpart/src/settings/webkit_filter.cpp +new file mode 100644 +index 000000000..f70620053 +--- /dev/null ++++ b/webkitpart/src/settings/webkit_filter.cpp +@@ -0,0 +1,344 @@ ++/* This file is part of the KDE project ++ ++ Copyright (C) 2005 Ivor Hewitt <ivor@kde.org> ++ Copyright (C) 2008 Maksim Orlovich <maksim@kde.org> ++ Copyright (C) 2008 Vyacheslav Tokarev <tsjoker@gmail.com> ++ ++ This library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Library 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 "webkit_filter.h" ++ ++#include <QHash> ++#include <QBitArray> ++ ++// rolling hash parameters ++#define HASH_P (1997) ++#define HASH_Q (17509) ++// HASH_MOD = (HASH_P^7) % HASH_Q ++#define HASH_MOD (523) ++ ++ ++using namespace KDEPrivate; ++ ++// Updateable Multi-String Matcher based on Rabin-Karp's algorithm ++class StringsMatcher { ++public: ++ // add filter to matching set ++ void addString(const QString& pattern) ++ { ++ if (pattern.length() < 8) { ++ // handle short string differently ++ shortStringFilters.append(pattern); ++ } else { ++ // use modified Rabin-Karp's algorithm with 8-length string hash ++ // i.e. store hash of first 8 chars in the HashMap for fast look-up ++ stringFilters.append(pattern); ++ int ind = stringFilters.size() - 1; ++ int current = 0; ++ ++ // compute hash using rolling hash ++ // hash for string: x0,x1,x2...xn-1 will be: ++ // (p^(n-1)*x0 + p^(n-2)*x1 + ... + p * xn-2 + xn-1) % q ++ // where p and q some wisely-chosen integers ++ /*for (int k = 0; k < 8; ++k)*/ ++ int len = pattern.length(); ++ for (int k = len - 8; k < len; ++k) ++ current = (current * HASH_P + pattern[k].unicode()) % HASH_Q; ++ ++ // insert computed hash value into HashMap ++ QHash<int, QVector<int> >::iterator it = stringFiltersHash.find(current + 1); ++ if (it == stringFiltersHash.end()) { ++ QVector<int> list; ++ list.append(ind); ++ stringFiltersHash.insert(current + 1, list); ++ fastLookUp.setBit(current); ++ } else { ++ it->append(ind); ++ } ++ } ++ } ++ ++ ++ // check if string match at least one string from matching set ++ bool isMatched(const QString& str, QString *by = 0) const ++ { ++ // check short strings first ++ for (int i = 0; i < shortStringFilters.size(); ++i) { ++ if (str.contains(shortStringFilters[i])) ++ { ++ if (by != 0) *by = shortStringFilters[i]; ++ return true; ++ } ++ } ++ ++ int len = str.length(); ++ int k; ++ ++ int current = 0; ++ int next = 0; ++ // compute hash for first 8 characters ++ for (k = 0; k < 8 && k < len; ++k) ++ current = (current * HASH_P + str[k].unicode()) % HASH_Q; ++ ++ QHash<int, QVector<int> >::const_iterator hashEnd = stringFiltersHash.end(); ++ // main Rabin-Karp's algorithm loop ++ for (k = 7; k < len; ++k, current = next) { ++ // roll the hash if not at the end ++ // (calculate hash for the next iteration) ++ if (k + 1 < len) ++ next = (HASH_P * ((current + HASH_Q - ((HASH_MOD * str[k - 7].unicode()) % HASH_Q)) % HASH_Q) + str[k + 1].unicode()) % HASH_Q; ++ ++ if (!fastLookUp.testBit(current)) ++ continue; ++ ++ // look-up the hash in the HashMap and check all strings ++ QHash<int, QVector<int> >::const_iterator it = stringFiltersHash.find(current + 1); ++ ++ // check possible strings ++ if (it != hashEnd) { ++ for (int j = 0; j < it->size(); ++j) { ++ int index = it->value(j); ++ // check if we got simple string or REs prefix ++ if (index >= 0) { ++ int flen = stringFilters[index].length(); ++ if (k - flen + 1 >= 0 && stringFilters[index] == str.midRef(k - flen + 1 , flen)) ++ { ++ if (by != 0) *by = stringFilters[index]; ++ return true; ++ } ++ } else { ++ index = -index - 1; ++ int flen = rePrefixes[index].length(); ++ if (k - 8 + flen < len && rePrefixes[index] == str.midRef(k - 7, flen)) ++ { ++ int remStart = k - 7 + flen; ++ QString remainder = QString::fromRawData(str.unicode() + remStart, ++ str.length() - remStart); ++ if (reFilters[index].exactMatch(remainder)) { ++ if (by != 0) *by = rePrefixes[index]+reFilters[index].pattern(); ++ return true; ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ return false; ++ } ++ ++ // add filter to matching set with wildcards (*,?) in it ++ void addWildedString(const QString& prefix, const QRegExp& rx) ++ { ++ rePrefixes.append(prefix); ++ reFilters.append(rx); ++ int index = -rePrefixes.size(); ++ ++ int current = 0; ++ for (int k = 0; k < 8; ++k) ++ current = (current * HASH_P + prefix[k].unicode()) % HASH_Q; ++ ++ // insert computed hash value into HashMap ++ QHash<int, QVector<int> >::iterator it = stringFiltersHash.find(current + 1); ++ if (it == stringFiltersHash.end()) { ++ QVector<int> list; ++ list.append(index); ++ stringFiltersHash.insert(current + 1, list); ++ fastLookUp.setBit(current); ++ } else { ++ it->append(index); ++ } ++ } ++ ++ void clear() ++ { ++ stringFilters.clear(); ++ shortStringFilters.clear(); ++ reFilters.clear(); ++ rePrefixes.clear(); ++ stringFiltersHash.clear(); ++ fastLookUp.resize(HASH_Q); ++ fastLookUp.fill(0, 0, HASH_Q); ++ } ++ ++private: ++ QVector<QString> stringFilters; ++ QVector<QString> shortStringFilters; ++ QVector<QRegExp> reFilters; ++ QVector<QString> rePrefixes; ++ QBitArray fastLookUp; ++ ++ QHash<int, QVector<int> > stringFiltersHash; ++}; ++ ++ ++// We only want a subset of features of wildcards -- just the ++// star, so we escape the rest before passing to QRegExp. ++// The \ is escaped due to a QRegExp bug. ++// ### we really should rather parse it ourselves, in order to ++// handle adblock-special things like | and ^ properly. ++static QRegExp fromAdBlockWildcard(const QString& wcStr) { ++ QRegExp rx; ++ rx.setPatternSyntax(QRegExp::Wildcard); ++ ++ QString out; ++ for (int p = 0; p < wcStr.length(); ++p) { ++ QChar c = wcStr[p]; ++ if (c == QLatin1Char('?')) ++ out += QLatin1String("[?]"); ++ else if (c == QLatin1Char('[')) ++ out += QLatin1String("[[]"); ++ else if (c == QLatin1Char('\\')) ++ out += QLatin1String("[\\]"); ++ else ++ out += c; ++ } ++ ++ rx.setPattern(out); ++ return rx; ++} ++ ++FilterSet::FilterSet() ++ :stringFiltersMatcher(new StringsMatcher) ++{ ++} ++ ++FilterSet::~FilterSet() ++{ ++ delete stringFiltersMatcher; ++} ++ ++void FilterSet::addFilter(const QString& filterStr) ++{ ++ QString filter = filterStr; ++ ++ /** ignore special lines starting with "[", "!", "&", or "#" or contain "#" (comments or features are not supported by KHTML's AdBlock */ ++ QChar firstChar = filter.at(0); ++ if (firstChar == QLatin1Char('[') || firstChar == QLatin1Char('!') || firstChar == QLatin1Char('&') || firstChar == QLatin1Char('#') || filter.contains(QLatin1Char('#'))) ++ return; ++ ++ // Strip leading @@ ++ int first = 0; ++ int last = filter.length() - 1; ++ if (filter.startsWith(QLatin1String("@@"))) ++ first = 2; ++ ++ // Strip options, we ignore them for now. ++ // TODO: Add support for filters with options. See #310230. ++ int dollar = filter.lastIndexOf(QLatin1Char('$')); ++ if (dollar != -1) { ++ return; ++ } ++ ++ // Perhaps nothing left? ++ if (first > last) ++ return; ++ ++ filter = filter.mid(first, last - first + 1); ++ ++ // Is it a regexp filter? ++ if (filter.length()>2 && filter.startsWith(QLatin1Char('/')) && filter.endsWith(QLatin1Char('/'))) ++ { ++ QString inside = filter.mid(1, filter.length()-2); ++ QRegExp rx(inside); ++ reFilters.append(rx); ++// qDebug() << "R:" << inside; ++ } ++ else ++ { ++ // Nope, a wildcard one. ++ // Note: For these, we also need to handle |. ++ ++ // Strip wildcards at the ends ++ first = 0; ++ last = filter.length() - 1; ++ ++ while (first < filter.length() && filter[first] == QLatin1Char('*')) ++ ++first; ++ ++ while (last >= 0 && filter[last] == QLatin1Char('*')) ++ --last; ++ ++ if (first > last) ++ filter = QStringLiteral("*"); // erm... Well, they asked for it. ++ else ++ filter = filter.mid(first, last - first + 1); ++ ++ // Now, do we still have any wildcard stuff left? ++ if (filter.contains(QLatin1String("*"))) ++ { ++ // check if we can use RK first (and then check full RE for the rest) for better performance ++ int aPos = filter.indexOf('*'); ++ if (aPos < 0) ++ aPos = filter.length(); ++ if (aPos > 7) { ++ QRegExp rx = fromAdBlockWildcard(filter.mid(aPos) + QLatin1Char('*')); ++ // We pad the final r.e. with * so we can check for an exact match ++ stringFiltersMatcher->addWildedString(filter.mid(0, aPos), rx); ++ } else { ++ QRegExp rx = fromAdBlockWildcard(filter); ++ reFilters.append(rx); ++ } ++ } ++ else ++ { ++ // Fast path ++ stringFiltersMatcher->addString(filter); ++ } ++ } ++} ++ ++bool FilterSet::isUrlMatched(const QString& url) ++{ ++ if (stringFiltersMatcher->isMatched(url)) ++ return true; ++ ++ for (int c = 0; c < reFilters.size(); ++c) ++ { ++ if (url.contains(reFilters[c])) ++ return true; ++ } ++ ++ return false; ++} ++ ++QString FilterSet::urlMatchedBy(const QString& url) ++{ ++ QString by; ++ ++ if (stringFiltersMatcher->isMatched(url, &by)) ++ return by; ++ ++ for (int c = 0; c < reFilters.size(); ++c) ++ { ++ if (url.contains(reFilters[c])) ++ { ++ by = reFilters[c].pattern(); ++ break; ++ } ++ } ++ ++ return by; ++} ++ ++void FilterSet::clear() ++{ ++ reFilters.clear(); ++ stringFiltersMatcher->clear(); ++} ++ ++// kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on; +diff --git b/webkitpart/src/settings/webkit_filter.h b/webkitpart/src/settings/webkit_filter.h +new file mode 100644 +index 000000000..732cf1538 +--- /dev/null ++++ b/webkitpart/src/settings/webkit_filter.h +@@ -0,0 +1,60 @@ ++/* This file is part of the KDE project ++ ++ Copyright (C) 2005 Ivor Hewitt <ivor@kde.org> ++ Copyright (C) 2008 Maksim Orlovich <maksim@kde.org> ++ Copyright (C) 2008 Vyacheslav Tokarev <tsjoker@gmail.com> ++ ++ This library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Library 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 WEBENGNINE_FILTER_P_H ++#define WEBENGNINE_FILTER_P_H ++ ++#include <QString> ++#include <QRegExp> ++#include <QVector> ++#include <webkitpart.h> ++ ++class StringsMatcher; ++ ++namespace KDEPrivate ++{ ++// This represents a set of filters that may match URLs. ++// Currently it supports a subset of AddBlock Plus functionality. ++class FilterSet { ++public: ++ FilterSet(); ++ ~FilterSet(); ++ ++ // Parses and registers a filter. This will also strip @@ for exclusion rules, skip comments, etc. ++ // The user does have to split black and white lists into separate sets, however ++ void addFilter(const QString& filter); ++ ++ bool isUrlMatched(const QString& url); ++ QString urlMatchedBy(const QString& url); ++ ++ void clear(); ++ ++private: ++ QVector<QRegExp> reFilters; ++ StringsMatcher* stringFiltersMatcher; ++}; ++ ++} ++ ++#endif // WEBKIT_FILTER_P_H ++ ++// kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on; +diff --git b/webkitpart/src/settings/webkitsettings.cpp b/webkitpart/src/settings/webkitsettings.cpp +new file mode 100644 +index 000000000..d20e320b5 +--- /dev/null ++++ b/webkitpart/src/settings/webkitsettings.cpp +@@ -0,0 +1,1276 @@ ++/* This file is part of the KDE project ++ Copyright (C) 1999 David Faure <faure@kde.org> ++ ++ This library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Library 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 "webkitsettings.h" ++ ++#include "webkit_filter.h" ++ ++#include <KConfig> ++#include <KSharedConfig> ++#include <KLocalizedString> ++#include <KConfigGroup> ++#include <KJob> ++#include <KIO/Job> ++#include <KMessageBox> ++ ++#include <QtWebKit/QWebSettings> ++#include <QFontDatabase> ++#include <QFileInfo> ++ ++// browser window color defaults -- Bernd ++#define HTML_DEFAULT_LNK_COLOR Qt::blue ++#define HTML_DEFAULT_TXT_COLOR Qt::black ++#define HTML_DEFAULT_VLNK_COLOR Qt::magenta ++#define HTML_DEFAULT_BASE_COLOR Qt::white ++ ++#define HTML_DEFAULT_VIEW_FONT "Sans Serif" ++#define HTML_DEFAULT_VIEW_FIXED_FONT "Monospace" ++#define HTML_DEFAULT_VIEW_SERIF_FONT "Serif" ++#define HTML_DEFAULT_VIEW_SANSSERIF_FONT "Sans Serif" ++#define HTML_DEFAULT_VIEW_CURSIVE_FONT "Sans Serif" ++#define HTML_DEFAULT_VIEW_FANTASY_FONT "Sans Serif" ++#define HTML_DEFAULT_MIN_FONT_SIZE 7 // everything smaller is usually unreadable. ++ ++/** ++ * @internal ++ * Contains all settings which are both available globally and per-domain ++ */ ++struct KPerDomainSettings { ++ bool m_bEnableJava : 1; ++ bool m_bEnableJavaScript : 1; ++ bool m_bEnablePlugins : 1; ++ // don't forget to maintain the bitfields as the enums grow ++ KParts::HtmlSettingsInterface::JSWindowOpenPolicy m_windowOpenPolicy : 2; ++ KParts::HtmlSettingsInterface::JSWindowStatusPolicy m_windowStatusPolicy : 1; ++ KParts::HtmlSettingsInterface::JSWindowFocusPolicy m_windowFocusPolicy : 1; ++ KParts::HtmlSettingsInterface::JSWindowMovePolicy m_windowMovePolicy : 1; ++ KParts::HtmlSettingsInterface::JSWindowResizePolicy m_windowResizePolicy : 1; ++ ++#ifdef DEBUG_SETTINGS ++ void dump(const QString &infix = QString()) const { ++ kDebug() << "KPerDomainSettings " << infix << " @" << this << ":"; ++ kDebug() << " m_bEnableJava: " << m_bEnableJava; ++ kDebug() << " m_bEnableJavaScript: " << m_bEnableJavaScript; ++ kDebug() << " m_bEnablePlugins: " << m_bEnablePlugins; ++ kDebug() << " m_windowOpenPolicy: " << m_windowOpenPolicy; ++ kDebug() << " m_windowStatusPolicy: " << m_windowStatusPolicy; ++ kDebug() << " m_windowFocusPolicy: " << m_windowFocusPolicy; ++ kDebug() << " m_windowMovePolicy: " << m_windowMovePolicy; ++ kDebug() << " m_windowResizePolicy: " << m_windowResizePolicy; ++ } ++#endif ++}; ++ ++typedef QMap<QString,KPerDomainSettings> PolicyMap; ++ ++class WebSettingsData ++{ ++public: ++ bool m_bChangeCursor : 1; ++ bool m_bOpenMiddleClick : 1; ++ bool m_underlineLink : 1; ++ bool m_hoverLink : 1; ++ bool m_bEnableJavaScriptDebug : 1; ++ bool m_bEnableJavaScriptErrorReporting : 1; ++ bool enforceCharset : 1; ++ bool m_bAutoLoadImages : 1; ++ bool m_bUnfinishedImageFrame : 1; ++ bool m_formCompletionEnabled : 1; ++ bool m_autoDelayedActionsEnabled : 1; ++ bool m_jsErrorsEnabled : 1; ++ bool m_follow_system_colors : 1; ++ bool m_allowTabulation : 1; ++ bool m_autoSpellCheck : 1; ++ bool m_adFilterEnabled : 1; ++ bool m_hideAdsEnabled : 1; ++ bool m_jsPopupBlockerPassivePopup : 1; ++ bool m_accessKeysEnabled : 1; ++ bool m_zoomTextOnly : 1; ++ bool m_useCookieJar : 1; ++ bool m_bAutoRefreshPage: 1; ++ bool m_bEnableFavicon:1; ++ bool m_disableInternalPluginHandling:1; ++ bool m_offerToSaveWebSitePassword:1; ++ bool m_loadPluginsOnDemand:1; ++ bool m_enableLocalStorage:1; ++ bool m_enableOfflineStorageDb:1; ++ bool m_enableOfflineWebAppCache:1; ++ bool m_enableWebGL:1; ++ bool m_zoomToDPI:1; ++ bool m_allowActiveMixedContent:1; ++ bool m_allowMixedContentDisplay:1; ++ ++ // the virtual global "domain" ++ KPerDomainSettings global; ++ ++ int m_fontSize; ++ int m_minFontSize; ++ int m_maxFormCompletionItems; ++ WebSettings::KAnimationAdvice m_showAnimations; ++ WebSettings::KSmoothScrollingMode m_smoothScrolling; ++ ++ QString m_encoding; ++ QString m_userSheet; ++ ++ QColor m_textColor; ++ QColor m_baseColor; ++ QColor m_linkColor; ++ QColor m_vLinkColor; ++ ++ PolicyMap domainPolicy; ++ QStringList fonts; ++ QStringList defaultFonts; ++ ++ KDEPrivate::FilterSet adBlackList; ++ KDEPrivate::FilterSet adWhiteList; ++ QList< QPair< QString, QChar > > m_fallbackAccessKeysAssignments; ++ ++ KSharedConfig::Ptr nonPasswordStorableSites; ++}; ++ ++class WebSettingsPrivate : public QObject, public WebSettingsData ++{ ++ Q_OBJECT ++public: ++ void adblockFilterLoadList(const QString& filename) ++ { ++ /** load list file and process each line */ ++ QFile file(filename); ++ if (file.open(QIODevice::ReadOnly)) { ++ QTextStream ts(&file); ++ QString line = ts.readLine(); ++ while (!line.isEmpty()) { ++ //kDebug() << "Adding filter:" << line; ++ /** white list lines start with "@@" */ ++ if (line.startsWith(QLatin1String("@@"))) ++ adWhiteList.addFilter(line); ++ else ++ adBlackList.addFilter(line); ++ line = ts.readLine(); ++ } ++ file.close(); ++ } ++ } ++ ++public Q_SLOTS: ++ void adblockFilterResult(KJob *job) ++ { ++ KIO::StoredTransferJob *tJob = qobject_cast<KIO::StoredTransferJob*>(job); ++ Q_ASSERT(tJob); ++ ++ if ( job->error() == KJob::NoError ) ++ { ++ const QByteArray byteArray = tJob->data(); ++ const QString localFileName = tJob->property( "websettings_adBlock_filename" ).toString(); ++ ++ QFile file(localFileName); ++ if ( file.open(QFile::WriteOnly) ) ++ { ++ const bool success = (file.write(byteArray) == byteArray.size()); ++ if ( success ) ++ adblockFilterLoadList(localFileName); ++ else ++ qWarning() << "Could not write" << byteArray.size() << "to file" << localFileName; ++ file.close(); ++ } ++ else ++ qDebug() << "Cannot open file" << localFileName << "for filter list"; ++ } ++ else ++ qDebug() << "Downloading" << tJob->url() << "failed with message:" << job->errorText(); ++ } ++}; ++ ++ ++/** Returns a writeable per-domains settings instance for the given domain ++ * or a deep copy of the global settings if not existent. ++ */ ++static KPerDomainSettings &setup_per_domain_policy(WebSettingsPrivate* const d, const QString &domain) ++{ ++ if (domain.isEmpty()) ++ qWarning() << "setup_per_domain_policy: domain is empty"; ++ ++ const QString ldomain = domain.toLower(); ++ PolicyMap::iterator it = d->domainPolicy.find(ldomain); ++ if (it == d->domainPolicy.end()) { ++ // simply copy global domain settings (they should have been initialized ++ // by this time) ++ it = d->domainPolicy.insert(ldomain,d->global); ++ } ++ return *it; ++} ++ ++template<typename T> ++static T readEntry(const KConfigGroup& config, const QString& key, int defaultValue) ++{ ++ return static_cast<T>(config.readEntry(key, defaultValue)); ++} ++ ++void WebSettings::readDomainSettings(const KConfigGroup &config, bool reset, ++ bool global, KPerDomainSettings &pd_settings) ++{ ++ const QString javaPrefix ((global ? QString() : QStringLiteral("java."))); ++ const QString jsPrefix ((global ? QString() : QStringLiteral("javascript."))); ++ const QString pluginsPrefix (global ? QString() : QStringLiteral("plugins.")); ++ ++ // The setting for Java ++ QString key = javaPrefix + QLatin1String("EnableJava"); ++ if ( (global && reset) || config.hasKey( key ) ) ++ pd_settings.m_bEnableJava = config.readEntry( key, false ); ++ else if ( !global ) ++ pd_settings.m_bEnableJava = d->global.m_bEnableJava; ++ ++ // The setting for Plugins ++ key = pluginsPrefix + QLatin1String("EnablePlugins"); ++ if ( (global && reset) || config.hasKey( key ) ) ++ pd_settings.m_bEnablePlugins = config.readEntry( key, true ); ++ else if ( !global ) ++ pd_settings.m_bEnablePlugins = d->global.m_bEnablePlugins; ++ ++ // The setting for JavaScript ++ key = jsPrefix + QLatin1String("EnableJavaScript"); ++ if ( (global && reset) || config.hasKey( key ) ) ++ pd_settings.m_bEnableJavaScript = config.readEntry( key, true ); ++ else if ( !global ) ++ pd_settings.m_bEnableJavaScript = d->global.m_bEnableJavaScript; ++ ++ // window property policies ++ key = jsPrefix + QLatin1String("WindowOpenPolicy"); ++ if ( (global && reset) || config.hasKey( key ) ) ++ pd_settings.m_windowOpenPolicy = readEntry<KParts::HtmlSettingsInterface::JSWindowOpenPolicy>(config, key, KParts::HtmlSettingsInterface::JSWindowOpenSmart); ++ else if ( !global ) ++ pd_settings.m_windowOpenPolicy = d->global.m_windowOpenPolicy; ++ ++ key = jsPrefix + QLatin1String("WindowMovePolicy"); ++ if ( (global && reset) || config.hasKey( key ) ) ++ pd_settings.m_windowMovePolicy = readEntry<KParts::HtmlSettingsInterface::JSWindowMovePolicy>(config, key, KParts::HtmlSettingsInterface::JSWindowMoveAllow); ++ else if ( !global ) ++ pd_settings.m_windowMovePolicy = d->global.m_windowMovePolicy; ++ ++ key = jsPrefix + QLatin1String("WindowResizePolicy"); ++ if ( (global && reset) || config.hasKey( key ) ) ++ pd_settings.m_windowResizePolicy = readEntry<KParts::HtmlSettingsInterface::JSWindowResizePolicy>(config, key, KParts::HtmlSettingsInterface::JSWindowResizeAllow); ++ else if ( !global ) ++ pd_settings.m_windowResizePolicy = d->global.m_windowResizePolicy; ++ ++ key = jsPrefix + QLatin1String("WindowStatusPolicy"); ++ if ( (global && reset) || config.hasKey( key ) ) ++ pd_settings.m_windowStatusPolicy = readEntry<KParts::HtmlSettingsInterface::JSWindowStatusPolicy>(config, key, KParts::HtmlSettingsInterface::JSWindowStatusAllow); ++ else if ( !global ) ++ pd_settings.m_windowStatusPolicy = d->global.m_windowStatusPolicy; ++ ++ key = jsPrefix + QLatin1String("WindowFocusPolicy"); ++ if ( (global && reset) || config.hasKey( key ) ) ++ pd_settings.m_windowFocusPolicy = readEntry<KParts::HtmlSettingsInterface::JSWindowFocusPolicy>(config, key, KParts::HtmlSettingsInterface::JSWindowFocusAllow); ++ else if ( !global ) ++ pd_settings.m_windowFocusPolicy = d->global.m_windowFocusPolicy; ++} ++ ++ ++WebSettings::WebSettings() ++ :d (new WebSettingsPrivate) ++{ ++ init(); ++} ++ ++WebSettings::~WebSettings() ++{ ++ delete d; ++} ++ ++bool WebSettings::changeCursor() const ++{ ++ return d->m_bChangeCursor; ++} ++ ++bool WebSettings::underlineLink() const ++{ ++ return d->m_underlineLink; ++} ++ ++bool WebSettings::hoverLink() const ++{ ++ return d->m_hoverLink; ++} ++ ++void WebSettings::init() ++{ ++ initWebSettings(); ++ ++ KConfig global( QStringLiteral("khtmlrc"), KConfig::NoGlobals ); ++ init( &global, true ); ++ ++ KSharedConfig::Ptr local = KSharedConfig::openConfig(); ++ if ( local ) { ++ init( local.data(), false ); ++ } ++ ++ initNSPluginSettings(); ++ initCookieJarSettings(); ++} ++ ++void WebSettings::init( KConfig * config, bool reset ) ++{ ++ KConfigGroup cg( config, "MainView Settings" ); ++ if (reset || cg.exists() ) ++ { ++ if ( reset || cg.hasKey( "OpenMiddleClick" ) ) ++ d->m_bOpenMiddleClick = cg.readEntry( "OpenMiddleClick", true ); ++ } ++ ++ KConfigGroup cgAccess(config,"Access Keys" ); ++ if (reset || cgAccess.exists() ) { ++ d->m_accessKeysEnabled = cgAccess.readEntry( "Enabled", true ); ++ } ++ ++ KConfigGroup cgFilter( config, "Filter Settings" ); ++ ++ if ((reset || cgFilter.exists()) && (d->m_adFilterEnabled = cgFilter.readEntry("Enabled", false))) ++ { ++ d->m_hideAdsEnabled = cgFilter.readEntry("Shrink", false); ++ ++ d->adBlackList.clear(); ++ d->adWhiteList.clear(); ++ ++ /** read maximum age for filter list files, minimum is one day */ ++ int htmlFilterListMaxAgeDays = cgFilter.readEntry(QStringLiteral("HTMLFilterListMaxAgeDays")).toInt(); ++ if (htmlFilterListMaxAgeDays < 1) ++ htmlFilterListMaxAgeDays = 1; ++ ++ QMapIterator<QString,QString> it (cgFilter.entryMap()); ++ while (it.hasNext()) ++ { ++ it.next(); ++ int id = -1; ++ const QString name = it.key(); ++ const QString url = it.value(); ++ ++ if (name.startsWith(QLatin1String("Filter"))) ++ { ++ if (url.startsWith(QLatin1String("@@"))) ++ d->adWhiteList.addFilter(url); ++ else ++ d->adBlackList.addFilter(url); ++ } ++ else if (name.startsWith(QLatin1String("HTMLFilterListName-")) && (id = name.midRef(19).toInt()) > 0) ++ { ++ /** check if entry is enabled */ ++ bool filterEnabled = cgFilter.readEntry(QStringLiteral("HTMLFilterListEnabled-").append(QString::number(id))) != QLatin1String("false"); ++ ++ /** get url for HTMLFilterList */ ++ QUrl url(cgFilter.readEntry(QStringLiteral("HTMLFilterListURL-").append(QString::number(id)))); ++ ++ if (filterEnabled && url.isValid()) { ++ /** determine where to cache HTMLFilterList file */ ++ QString localFile = cgFilter.readEntry(QStringLiteral("HTMLFilterListLocalFilename-").append(QString::number(id))); ++ localFile = QStandardPaths::locate(QStandardPaths::ConfigLocation, "khtml/" + localFile); ++ ++ /** determine existence and age of cache file */ ++ QFileInfo fileInfo(localFile); ++ ++ /** load cached file if it exists, irrespective of age */ ++ if (fileInfo.exists()) ++ d->adblockFilterLoadList( localFile ); ++ ++ /** if no cache list file exists or if it is too old ... */ ++ if (!fileInfo.exists() || fileInfo.lastModified().daysTo(QDateTime::currentDateTime()) > htmlFilterListMaxAgeDays) ++ { ++ /** ... in this case, refetch list asynchronously */ ++ // kDebug() << "Fetching filter list from" << url << "to" << localFile; ++ KIO::StoredTransferJob *job = KIO::storedGet( url, KIO::Reload, KIO::HideProgressInfo ); ++ QObject::connect( job, SIGNAL(result(KJob*)), d, SLOT(adblockFilterResult(KJob*)) ); ++ /** for later reference, store name of cache file */ ++ job->setProperty("websettings_adBlock_filename", localFile); ++ } ++ } ++ } ++ } ++ } ++ ++ KConfigGroup cgHtml( config, "HTML Settings" ); ++ if (reset || cgHtml.exists() ) ++ { ++ // Fonts and colors ++ if( reset ) { ++ d->defaultFonts = QStringList(); ++ d->defaultFonts.append( cgHtml.readEntry( "StandardFont", QFontDatabase::systemFont(QFontDatabase::GeneralFont).family() ) ); ++ d->defaultFonts.append( cgHtml.readEntry( "FixedFont", QFontDatabase::systemFont(QFontDatabase::FixedFont).family() )); ++ d->defaultFonts.append( cgHtml.readEntry( "SerifFont", HTML_DEFAULT_VIEW_SERIF_FONT ) ); ++ d->defaultFonts.append( cgHtml.readEntry( "SansSerifFont", HTML_DEFAULT_VIEW_SANSSERIF_FONT ) ); ++ d->defaultFonts.append( cgHtml.readEntry( "CursiveFont", HTML_DEFAULT_VIEW_CURSIVE_FONT ) ); ++ d->defaultFonts.append( cgHtml.readEntry( "FantasyFont", HTML_DEFAULT_VIEW_FANTASY_FONT ) ); ++ d->defaultFonts.append( QStringLiteral( "0" ) ); // font size adjustment ++ } ++ ++ if ( reset || cgHtml.hasKey( "MinimumFontSize" ) ) ++ d->m_minFontSize = cgHtml.readEntry( "MinimumFontSize", HTML_DEFAULT_MIN_FONT_SIZE ); ++ ++ if ( reset || cgHtml.hasKey( "MediumFontSize" ) ) ++ d->m_fontSize = cgHtml.readEntry( "MediumFontSize", 12 ); ++ ++ d->fonts = cgHtml.readEntry( "Fonts", QStringList() ); ++ ++ if ( reset || cgHtml.hasKey( "DefaultEncoding" ) ) ++ d->m_encoding = cgHtml.readEntry( "DefaultEncoding", "" ); ++ ++ if ( reset || cgHtml.hasKey( "EnforceDefaultCharset" ) ) ++ d->enforceCharset = cgHtml.readEntry( "EnforceDefaultCharset", false ); ++ ++ // Behavior ++ ++ if ( reset || cgHtml.hasKey("UnderlineLinks") ) ++ d->m_underlineLink = cgHtml.readEntry( "UnderlineLinks", true ); ++ ++ if ( reset || cgHtml.hasKey( "HoverLinks" ) ) ++ { ++ if ( (d->m_hoverLink = cgHtml.readEntry( "HoverLinks", false ))) ++ d->m_underlineLink = false; ++ } ++ ++ if ( reset || cgHtml.hasKey( "AllowTabulation" ) ) ++ d->m_allowTabulation = cgHtml.readEntry( "AllowTabulation", false ); ++ ++ if ( reset || cgHtml.hasKey( "AutoSpellCheck" ) ) ++ d->m_autoSpellCheck = cgHtml.readEntry( "AutoSpellCheck", true ); ++ ++ // Other ++ if ( reset || cgHtml.hasKey( "AutoLoadImages" ) ) ++ d->m_bAutoLoadImages = cgHtml.readEntry( "AutoLoadImages", true ); ++ ++ if ( reset || cgHtml.hasKey( "AutoDelayedActions" ) ) ++ d->m_bAutoRefreshPage = cgHtml.readEntry( "AutoDelayedActions", true ); ++ ++ if ( reset || cgHtml.hasKey( "UnfinishedImageFrame" ) ) ++ d->m_bUnfinishedImageFrame = cgHtml.readEntry( "UnfinishedImageFrame", true ); ++ ++ if ( reset || cgHtml.hasKey( "ShowAnimations" ) ) ++ { ++ QString value = cgHtml.readEntry( "ShowAnimations").toLower(); ++ if (value == QLatin1String("disabled")) ++ d->m_showAnimations = KAnimationDisabled; ++ else if (value == QLatin1String("looponce")) ++ d->m_showAnimations = KAnimationLoopOnce; ++ else ++ d->m_showAnimations = KAnimationEnabled; ++ } ++ ++ if ( reset || cgHtml.hasKey( "SmoothScrolling" ) ) ++ { ++ QString value = cgHtml.readEntry( "SmoothScrolling", "whenefficient" ).toLower(); ++ if (value == QLatin1String("disabled")) ++ d->m_smoothScrolling = KSmoothScrollingDisabled; ++ else if (value == QLatin1String("whenefficient")) ++ d->m_smoothScrolling = KSmoothScrollingWhenEfficient; ++ else ++ d->m_smoothScrolling = KSmoothScrollingEnabled; ++ } ++ ++ if ( reset || cgHtml.hasKey( "ZoomTextOnly" ) ) { ++ d->m_zoomTextOnly = cgHtml.readEntry( "ZoomTextOnly", false ); ++ } ++ ++ if ( reset || cgHtml.hasKey( "ZoomToDPI" ) ) { ++ d->m_zoomToDPI = cgHtml.readEntry( "ZoomToDPI", false ); ++ } ++ ++ if (cgHtml.readEntry("UserStyleSheetEnabled", false)) { ++ if (reset || cgHtml.hasKey("UserStyleSheet")) ++ d->m_userSheet = cgHtml.readEntry("UserStyleSheet", QString()); ++ } else { ++ d->m_userSheet.clear(); ++ } ++ ++ d->m_formCompletionEnabled = cgHtml.readEntry("FormCompletion", true); ++ d->m_maxFormCompletionItems = cgHtml.readEntry("MaxFormCompletionItems", 10); ++ d->m_autoDelayedActionsEnabled = cgHtml.readEntry ("AutoDelayedActions", true); ++ d->m_jsErrorsEnabled = cgHtml.readEntry("ReportJSErrors", true); ++ const QStringList accesskeys = cgHtml.readEntry("FallbackAccessKeysAssignments", QStringList()); ++ d->m_fallbackAccessKeysAssignments.clear(); ++ for( QStringList::ConstIterator it = accesskeys.begin(); it != accesskeys.end(); ++it ) ++ if( (*it).length() > 2 && (*it)[ 1 ] == ':' ) ++ d->m_fallbackAccessKeysAssignments.append( qMakePair( (*it).mid( 2 ), (*it)[ 0 ] )); ++ ++ d->m_bEnableFavicon = cgHtml.readEntry("EnableFavicon", true); ++ d->m_offerToSaveWebSitePassword = cgHtml.readEntry("OfferToSaveWebsitePassword", true); ++ } ++ ++ // Colors ++ //In which group ????? ++ if ( reset || cg.hasKey( "FollowSystemColors" ) ) ++ d->m_follow_system_colors = cg.readEntry( "FollowSystemColors", false ); ++ ++ KConfigGroup cgGeneral( config, "General" ); ++ if ( reset || cgGeneral.exists( ) ) ++ { ++ if ( reset || cgGeneral.hasKey( "foreground" ) ) { ++ QColor def(HTML_DEFAULT_TXT_COLOR); ++ d->m_textColor = cgGeneral.readEntry( "foreground", def ); ++ } ++ ++ if ( reset || cgGeneral.hasKey( "linkColor" ) ) { ++ QColor def(HTML_DEFAULT_LNK_COLOR); ++ d->m_linkColor = cgGeneral.readEntry( "linkColor", def ); ++ } ++ ++ if ( reset || cgGeneral.hasKey( "visitedLinkColor" ) ) { ++ QColor def(HTML_DEFAULT_VLNK_COLOR); ++ d->m_vLinkColor = cgGeneral.readEntry( "visitedLinkColor", def); ++ } ++ ++ if ( reset || cgGeneral.hasKey( "background" ) ) { ++ QColor def(HTML_DEFAULT_BASE_COLOR); ++ d->m_baseColor = cgGeneral.readEntry( "background", def); ++ } ++ } ++ ++ KConfigGroup cgJava( config, "Java/JavaScript Settings" ); ++ if( reset || cgJava.exists() ) ++ { ++ // The global setting for JavaScript debugging ++ // This is currently always enabled by default ++ if ( reset || cgJava.hasKey( "EnableJavaScriptDebug" ) ) ++ d->m_bEnableJavaScriptDebug = cgJava.readEntry( "EnableJavaScriptDebug", false ); ++ ++ // The global setting for JavaScript error reporting ++ if ( reset || cgJava.hasKey( "ReportJavaScriptErrors" ) ) ++ d->m_bEnableJavaScriptErrorReporting = cgJava.readEntry( "ReportJavaScriptErrors", false ); ++ ++ // The global setting for popup block passive popup ++ if ( reset || cgJava.hasKey( "PopupBlockerPassivePopup" ) ) ++ d->m_jsPopupBlockerPassivePopup = cgJava.readEntry("PopupBlockerPassivePopup", true ); ++ ++ // Read options from the global "domain" ++ readDomainSettings(cgJava,reset,true,d->global); ++#ifdef DEBUG_SETTINGS ++ d->global.dump("init global"); ++#endif ++ ++ // The domain-specific settings. ++ ++ static const char *const domain_keys[] = { // always keep order of keys ++ "ECMADomains", "JavaDomains", "PluginDomains" ++ }; ++ bool check_old_ecma_settings = true; ++ bool check_old_java_settings = true; ++ // merge all domains into one list ++ QSet<QString> domainList; ++ for (unsigned i = 0; i < sizeof domain_keys/sizeof domain_keys[0]; ++i) { ++ if (reset || cgJava.hasKey(domain_keys[i])) { ++ if (i == 0) check_old_ecma_settings = false; ++ else if (i == 1) check_old_java_settings = false; ++ const QStringList dl = cgJava.readEntry( domain_keys[i], QStringList() ); ++ const QSet<QString>::Iterator notfound = domainList.end(); ++ QStringList::ConstIterator it = dl.begin(); ++ const QStringList::ConstIterator itEnd = dl.end(); ++ for (; it != itEnd; ++it) { ++ const QString domain = (*it).toLower(); ++ QSet<QString>::Iterator pos = domainList.find(domain); ++ if (pos == notfound) domainList.insert(domain); ++ }/*next it*/ ++ } ++ }/*next i*/ ++ ++ if (reset) ++ d->domainPolicy.clear(); ++ ++ { ++ QSet<QString>::ConstIterator it = domainList.constBegin(); ++ const QSet<QString>::ConstIterator itEnd = domainList.constEnd(); ++ for ( ; it != itEnd; ++it) ++ { ++ const QString domain = *it; ++ KConfigGroup cg( config, domain ); ++ readDomainSettings(cg,reset,false,d->domainPolicy[domain]); ++#ifdef DEBUG_SETTINGS ++ d->domainPolicy[domain].dump("init "+domain); ++#endif ++ } ++ } ++ ++ bool check_old_java = true; ++ if( (reset || cgJava.hasKey("JavaDomainSettings")) && check_old_java_settings) ++ { ++ check_old_java = false; ++ const QStringList domainList = cgJava.readEntry( "JavaDomainSettings", QStringList() ); ++ QStringList::ConstIterator it = domainList.constBegin(); ++ const QStringList::ConstIterator itEnd = domainList.constEnd(); ++ for ( ; it != itEnd; ++it) ++ { ++ QString domain; ++ KParts::HtmlSettingsInterface::JavaScriptAdvice javaAdvice; ++ KParts::HtmlSettingsInterface::JavaScriptAdvice javaScriptAdvice; ++ KParts::HtmlSettingsInterface::splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice); ++ setup_per_domain_policy(d,domain).m_bEnableJava = javaAdvice == KParts::HtmlSettingsInterface::JavaScriptAccept; ++#ifdef DEBUG_SETTINGS ++ setup_per_domain_policy(d,domain).dump("JavaDomainSettings 4 "+domain); ++#endif ++ } ++ } ++ ++ bool check_old_ecma = true; ++ if( ( reset || cgJava.hasKey( "ECMADomainSettings" ) ) && check_old_ecma_settings ) ++ { ++ check_old_ecma = false; ++ const QStringList domainList = cgJava.readEntry( "ECMADomainSettings", QStringList() ); ++ QStringList::ConstIterator it = domainList.constBegin(); ++ const QStringList::ConstIterator itEnd = domainList.constEnd(); ++ for ( ; it != itEnd; ++it) ++ { ++ QString domain; ++ KParts::HtmlSettingsInterface::JavaScriptAdvice javaAdvice; ++ KParts::HtmlSettingsInterface::JavaScriptAdvice javaScriptAdvice; ++ KParts::HtmlSettingsInterface::splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice); ++ setup_per_domain_policy(d,domain).m_bEnableJavaScript = javaScriptAdvice == KParts::HtmlSettingsInterface::JavaScriptAccept; ++#ifdef DEBUG_SETTINGS ++ setup_per_domain_policy(d,domain).dump("ECMADomainSettings 4 "+domain); ++#endif ++ } ++ } ++ ++ if( ( reset || cgJava.hasKey( "JavaScriptDomainAdvice" ) ) ++ && ( check_old_java || check_old_ecma ) ++ && ( check_old_ecma_settings || check_old_java_settings ) ) ++ { ++ const QStringList domainList = cgJava.readEntry( "JavaScriptDomainAdvice", QStringList() ); ++ QStringList::ConstIterator it = domainList.constBegin(); ++ const QStringList::ConstIterator itEnd = domainList.constEnd(); ++ for ( ; it != itEnd; ++it) ++ { ++ QString domain; ++ KParts::HtmlSettingsInterface::JavaScriptAdvice javaAdvice; ++ KParts::HtmlSettingsInterface::JavaScriptAdvice javaScriptAdvice; ++ KParts::HtmlSettingsInterface::splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice); ++ if( check_old_java ) ++ setup_per_domain_policy(d,domain).m_bEnableJava = javaAdvice == KParts::HtmlSettingsInterface::JavaScriptAccept; ++ if( check_old_ecma ) ++ setup_per_domain_policy(d,domain).m_bEnableJavaScript = javaScriptAdvice == KParts::HtmlSettingsInterface::JavaScriptAccept; ++#ifdef DEBUG_SETTINGS ++ setup_per_domain_policy(d,domain).dump("JavaScriptDomainAdvice 4 "+domain); ++#endif ++ } ++ } ++ } ++ ++#if 0 ++ // DNS Prefect support... ++ if ( reset || cgHtml.hasKey( "DNSPrefetch" ) ) ++ { ++ // Enabled, Disabled, OnlyWWWAndSLD ++ QString value = cgHtml.readEntry( "DNSPrefetch", "Enabled" ).toLower(); ++ ++ if (value == "enabled") ++ QWebSettings::globalSettings()->setAttribute(QWebSettings::DnsPrefetchEnabled, true); ++ else ++ QWebSettings::globalSettings()->setAttribute(QWebSettings::DnsPrefetchEnabled, false); ++ } ++ ++ // Sync with QWebSettings. ++ if (!d->m_encoding.isEmpty()) ++ QWebSettings::globalSettings()->setDefaultTextEncoding(d->m_encoding); ++ QWebSettings::globalSettings()->setUserStyleSheetUrl(QUrl::fromUserInput(userStyleSheet())); ++#endif ++ ++ QWebSettings::globalSettings()->setAttribute(QWebSettings::AutoLoadImages, autoLoadImages()); ++ QWebSettings::globalSettings()->setAttribute(QWebSettings::JavascriptEnabled, isJavaScriptEnabled()); ++// QWebSettings::globalSettings()->setAttribute(QWebSettings::JavaEnabled, isJavaEnabled()); ++ QWebSettings::globalSettings()->setAttribute(QWebSettings::PluginsEnabled, isPluginsEnabled()); ++ ++ // By default disable JS window.open when policy is deny or smart. ++ const KParts::HtmlSettingsInterface::JSWindowOpenPolicy policy = windowOpenPolicy(); ++ if (policy == KParts::HtmlSettingsInterface::JSWindowOpenDeny || policy == KParts::HtmlSettingsInterface::JSWindowOpenSmart) ++ QWebSettings::globalSettings()->setAttribute(QWebSettings::JavascriptCanOpenWindows, false); ++ else ++ QWebSettings::globalSettings()->setAttribute(QWebSettings::JavascriptCanOpenWindows, true); ++ ++// QWebSettings::globalSettings()->setAttribute(QWebSettings::ZoomTextOnly, zoomTextOnly()); ++// QWebSettings::globalSettings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, isJavaScriptDebugEnabled()); ++ QWebSettings::globalSettings()->setFontFamily(QWebSettings::StandardFont, stdFontName()); ++ QWebSettings::globalSettings()->setFontFamily(QWebSettings::FixedFont, fixedFontName()); ++ QWebSettings::globalSettings()->setFontFamily(QWebSettings::SerifFont, serifFontName()); ++ QWebSettings::globalSettings()->setFontFamily(QWebSettings::SansSerifFont, sansSerifFontName()); ++ QWebSettings::globalSettings()->setFontFamily(QWebSettings::CursiveFont, cursiveFontName()); ++ QWebSettings::globalSettings()->setFontFamily(QWebSettings::FantasyFont, fantasyFontName()); ++ ++ // TODO: Create a webkit config module that gets embeded into Konqueror's kcm. ++ // Turn on WebGL support ++// QWebSettings::globalSettings()->setAttribute(QWebSettings::WebGLEnabled, d->m_enableWebGL); ++ // Turn on HTML 5 local and offline storage capabilities... ++// QWebSettings::globalSettings()->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, d->m_enableOfflineStorageDb); ++// QWebSettings::globalSettings()->setAttribute(QWebSettings::OfflineWebApplicationCacheEnabled, d->m_enableOfflineWebAppCache); ++ QWebSettings::globalSettings()->setAttribute(QWebSettings::LocalStorageEnabled, d->m_enableLocalStorage); ++ ++ QWebSettings::globalSettings()->setAttribute(QWebSettings::ScrollAnimatorEnabled, smoothScrolling() != KSmoothScrollingDisabled); ++ ++ // These numbers should be calculated from real "logical" DPI/72, using a default dpi of 96 for now ++ computeFontSizes(96); ++} ++ ++ ++void WebSettings::computeFontSizes( int logicalDpi ) ++{ ++ if (zoomToDPI()) ++ logicalDpi = 96; ++ ++ float toPix = logicalDpi/72.0; ++ ++ if (toPix < 96.0/72.0) ++ toPix = 96.0/72.0; ++ ++ QWebSettings::globalSettings()->setFontSize(QWebSettings::MinimumFontSize, qRound(minFontSize() * toPix)); ++ QWebSettings::globalSettings()->setFontSize(QWebSettings::DefaultFontSize, qRound(mediumFontSize() * toPix)); ++} ++ ++bool WebSettings::zoomToDPI() const ++{ ++ return d->m_zoomToDPI; ++} ++ ++void WebSettings::setZoomToDPI(bool enabled) ++{ ++ d->m_zoomToDPI = enabled; ++ // save it ++ KConfigGroup cg( KSharedConfig::openConfig(), "HTML Settings"); ++ cg.writeEntry("ZoomToDPI", enabled); ++ cg.sync(); ++} ++ ++/** Local helper for retrieving per-domain settings. ++ * ++ * In case of doubt, the global domain is returned. ++ */ ++static const KPerDomainSettings& lookup_hostname_policy(const WebSettingsPrivate* const d, ++ const QString& hostname) ++{ ++#ifdef DEBUG_SETTINGS ++ kDebug() << "lookup_hostname_policy(" << hostname << ")"; ++#endif ++ if (hostname.isEmpty()) { ++#ifdef DEBUG_SETTINGS ++ d->global.dump("global"); ++#endif ++ return d->global; ++ } ++ ++ const PolicyMap::const_iterator notfound = d->domainPolicy.constEnd(); ++ ++ // First check whether there is a perfect match. ++ PolicyMap::const_iterator it = d->domainPolicy.find(hostname); ++ if( it != notfound ) { ++#ifdef DEBUG_SETTINGS ++ kDebug() << "perfect match"; ++ (*it).dump(hostname); ++#endif ++ // yes, use it (unless dunno) ++ return *it; ++ } ++ ++ // Now, check for partial match. Chop host from the left until ++ // there's no dots left. ++ QString host_part = hostname; ++ int dot_idx = -1; ++ while( (dot_idx = host_part.indexOf(QChar('.'))) >= 0 ) { ++ host_part.remove(0,dot_idx); ++ it = d->domainPolicy.find(host_part); ++ Q_ASSERT(notfound == d->domainPolicy.end()); ++ if( it != notfound ) { ++#ifdef DEBUG_SETTINGS ++ kDebug() << "partial match"; ++ (*it).dump(host_part); ++#endif ++ return *it; ++ } ++ // assert(host_part[0] == QChar('.')); ++ host_part.remove(0,1); // Chop off the dot. ++ } ++ ++ // No domain-specific entry: use global domain ++#ifdef DEBUG_SETTINGS ++ kDebug() << "no match"; ++ d->global.dump("global"); ++#endif ++ return d->global; ++} ++ ++bool WebSettings::isOpenMiddleClickEnabled() ++{ ++ return d->m_bOpenMiddleClick; ++} ++ ++bool WebSettings::accessKeysEnabled() const ++{ ++ return d->m_accessKeysEnabled; ++} ++ ++bool WebSettings::favIconsEnabled() const ++{ ++ return d->m_bEnableFavicon; ++} ++ ++bool WebSettings::isAdFilterEnabled() const ++{ ++ return d->m_adFilterEnabled; ++} ++ ++bool WebSettings::isHideAdsEnabled() const ++{ ++ return d->m_hideAdsEnabled; ++} ++ ++bool WebSettings::isAdFiltered( const QString &url ) const ++{ ++ if (!d->m_adFilterEnabled) ++ return false; ++ ++ if (url.startsWith(QLatin1String("data:"))) ++ return false; ++ ++ return d->adBlackList.isUrlMatched(url) && !d->adWhiteList.isUrlMatched(url); ++} ++ ++QString WebSettings::adFilteredBy( const QString &url, bool *isWhiteListed ) const ++{ ++ QString m = d->adWhiteList.urlMatchedBy(url); ++ ++ if (!m.isEmpty()) { ++ if (isWhiteListed != 0) ++ *isWhiteListed = true; ++ return m; ++ } ++ ++ m = d->adBlackList.urlMatchedBy(url); ++ if (m.isEmpty()) ++ return QString(); ++ ++ if (isWhiteListed != 0) ++ *isWhiteListed = false; ++ return m; ++} ++ ++void WebSettings::addAdFilter( const QString &url ) ++{ ++ KConfigGroup config = KSharedConfig::openConfig( QStringLiteral("khtmlrc"), KConfig::NoGlobals )->group( "Filter Settings" ); ++ ++ QRegExp rx; ++ ++ // Try compiling to avoid invalid stuff. Only support the basic syntax here... ++ // ### refactor somewhat ++ if (url.length()>2 && url[0]=='/' && url[url.length()-1] == '/') ++ { ++ const QString inside = url.mid(1, url.length()-2); ++ rx.setPattern(inside); ++ } ++ else ++ { ++ rx.setPatternSyntax(QRegExp::Wildcard); ++ rx.setPattern(url); ++ } ++ ++ if (rx.isValid()) ++ { ++ int last=config.readEntry("Count", 0); ++ const QString key = "Filter-" + QString::number(last); ++ config.writeEntry(key, url); ++ config.writeEntry("Count",last+1); ++ config.sync(); ++ ++ if (url.startsWith(QLatin1String("@@"))) ++ d->adWhiteList.addFilter(url); ++ else ++ d->adBlackList.addFilter(url); ++ } ++ else ++ { ++ KMessageBox::error(0, ++ rx.errorString(), ++ i18n("Filter error")); ++ } ++} ++ ++bool WebSettings::isJavaEnabled( const QString& hostname ) const ++{ ++ return lookup_hostname_policy(d,hostname.toLower()).m_bEnableJava; ++} ++ ++bool WebSettings::isJavaScriptEnabled( const QString& hostname ) const ++{ ++ return lookup_hostname_policy(d,hostname.toLower()).m_bEnableJavaScript; ++} ++ ++bool WebSettings::isJavaScriptDebugEnabled( const QString& /*hostname*/ ) const ++{ ++ // debug setting is global for now, but could change in the future ++ return d->m_bEnableJavaScriptDebug; ++} ++ ++bool WebSettings::isJavaScriptErrorReportingEnabled( const QString& /*hostname*/ ) const ++{ ++ // error reporting setting is global for now, but could change in the future ++ return d->m_bEnableJavaScriptErrorReporting; ++} ++ ++bool WebSettings::isPluginsEnabled( const QString& hostname ) const ++{ ++ return lookup_hostname_policy(d,hostname.toLower()).m_bEnablePlugins; ++} ++ ++KParts::HtmlSettingsInterface::JSWindowOpenPolicy WebSettings::windowOpenPolicy(const QString& hostname) const { ++ return lookup_hostname_policy(d,hostname.toLower()).m_windowOpenPolicy; ++} ++ ++KParts::HtmlSettingsInterface::JSWindowMovePolicy WebSettings::windowMovePolicy(const QString& hostname) const { ++ return lookup_hostname_policy(d,hostname.toLower()).m_windowMovePolicy; ++} ++ ++KParts::HtmlSettingsInterface::JSWindowResizePolicy WebSettings::windowResizePolicy(const QString& hostname) const { ++ return lookup_hostname_policy(d,hostname.toLower()).m_windowResizePolicy; ++} ++ ++KParts::HtmlSettingsInterface::JSWindowStatusPolicy WebSettings::windowStatusPolicy(const QString& hostname) const { ++ return lookup_hostname_policy(d,hostname.toLower()).m_windowStatusPolicy; ++} ++ ++KParts::HtmlSettingsInterface::JSWindowFocusPolicy WebSettings::windowFocusPolicy(const QString& hostname) const { ++ return lookup_hostname_policy(d,hostname.toLower()).m_windowFocusPolicy; ++} ++ ++int WebSettings::mediumFontSize() const ++{ ++ return d->m_fontSize; ++} ++ ++int WebSettings::minFontSize() const ++{ ++ return d->m_minFontSize; ++} ++ ++QString WebSettings::settingsToCSS() const ++{ ++ // lets start with the link properties ++ QString str = QStringLiteral("a:link {\ncolor: "); ++ str += d->m_linkColor.name(); ++ str += ';'; ++ if(d->m_underlineLink) ++ str += QLatin1String("\ntext-decoration: underline;"); ++ ++ if( d->m_bChangeCursor ) ++ { ++ str += QLatin1String("\ncursor: pointer;"); ++ str += QLatin1String("\n}\ninput[type=image] { cursor: pointer;"); ++ } ++ str += QLatin1String("\n}\n"); ++ str += QLatin1String("a:visited {\ncolor: "); ++ str += d->m_vLinkColor.name(); ++ str += ';'; ++ if(d->m_underlineLink) ++ str += QLatin1String("\ntext-decoration: underline;"); ++ ++ if( d->m_bChangeCursor ) ++ str += QLatin1String("\ncursor: pointer;"); ++ str += QLatin1String("\n}\n"); ++ ++ if(d->m_hoverLink) ++ str += QLatin1String("a:link:hover, a:visited:hover { text-decoration: underline; }\n"); ++ ++ return str; ++} ++ ++QString WebSettings::lookupFont(int i) const ++{ ++ if (d->fonts.count() > i) { ++ return d->fonts.at(i); ++ } ++ ++ if (d->defaultFonts.count() > i) { ++ return d->defaultFonts.at(i); ++ } ++ ++ return QString(); ++} ++ ++QString WebSettings::stdFontName() const ++{ ++ return lookupFont(0); ++} ++ ++QString WebSettings::fixedFontName() const ++{ ++ return lookupFont(1); ++} ++ ++QString WebSettings::serifFontName() const ++{ ++ return lookupFont(2); ++} ++ ++QString WebSettings::sansSerifFontName() const ++{ ++ return lookupFont(3); ++} ++ ++QString WebSettings::cursiveFontName() const ++{ ++ return lookupFont(4); ++} ++ ++QString WebSettings::fantasyFontName() const ++{ ++ return lookupFont(5); ++} ++ ++void WebSettings::setStdFontName(const QString &n) ++{ ++ while(d->fonts.count() <= 0) ++ d->fonts.append(QString()); ++ d->fonts[0] = n; ++} ++ ++void WebSettings::setFixedFontName(const QString &n) ++{ ++ while(d->fonts.count() <= 1) ++ d->fonts.append(QString()); ++ d->fonts[1] = n; ++} ++ ++QString WebSettings::userStyleSheet() const ++{ ++ return d->m_userSheet; ++} ++ ++bool WebSettings::isFormCompletionEnabled() const ++{ ++ return d->m_formCompletionEnabled; ++} ++ ++int WebSettings::maxFormCompletionItems() const ++{ ++ return d->m_maxFormCompletionItems; ++} ++ ++const QString &WebSettings::encoding() const ++{ ++ return d->m_encoding; ++} ++ ++bool WebSettings::followSystemColors() const ++{ ++ return d->m_follow_system_colors; ++} ++ ++const QColor& WebSettings::textColor() const ++{ ++ return d->m_textColor; ++} ++ ++const QColor& WebSettings::baseColor() const ++{ ++ return d->m_baseColor; ++} ++ ++const QColor& WebSettings::linkColor() const ++{ ++ return d->m_linkColor; ++} ++ ++const QColor& WebSettings::vLinkColor() const ++{ ++ return d->m_vLinkColor; ++} ++ ++bool WebSettings::autoPageRefresh() const ++{ ++ return d->m_bAutoRefreshPage; ++} ++ ++bool WebSettings::autoLoadImages() const ++{ ++ return d->m_bAutoLoadImages; ++} ++ ++bool WebSettings::unfinishedImageFrame() const ++{ ++ return d->m_bUnfinishedImageFrame; ++} ++ ++WebSettings::KAnimationAdvice WebSettings::showAnimations() const ++{ ++ return d->m_showAnimations; ++} ++ ++WebSettings::KSmoothScrollingMode WebSettings::smoothScrolling() const ++{ ++ return d->m_smoothScrolling; ++} ++ ++bool WebSettings::zoomTextOnly() const ++{ ++ return d->m_zoomTextOnly; ++} ++ ++bool WebSettings::isAutoDelayedActionsEnabled() const ++{ ++ return d->m_autoDelayedActionsEnabled; ++} ++ ++bool WebSettings::jsErrorsEnabled() const ++{ ++ return d->m_jsErrorsEnabled; ++} ++ ++void WebSettings::setJSErrorsEnabled(bool enabled) ++{ ++ d->m_jsErrorsEnabled = enabled; ++ // save it ++ KConfigGroup cg( KSharedConfig::openConfig(), "HTML Settings"); ++ cg.writeEntry("ReportJSErrors", enabled); ++ cg.sync(); ++} ++ ++bool WebSettings::allowTabulation() const ++{ ++ return d->m_allowTabulation; ++} ++ ++bool WebSettings::autoSpellCheck() const ++{ ++ return d->m_autoSpellCheck; ++} ++ ++QList< QPair< QString, QChar > > WebSettings::fallbackAccessKeysAssignments() const ++{ ++ return d->m_fallbackAccessKeysAssignments; ++} ++ ++void WebSettings::setJSPopupBlockerPassivePopup(bool enabled) ++{ ++ d->m_jsPopupBlockerPassivePopup = enabled; ++ // save it ++ KConfigGroup cg( KSharedConfig::openConfig(), "Java/JavaScript Settings"); ++ cg.writeEntry("PopupBlockerPassivePopup", enabled); ++ cg.sync(); ++} ++ ++bool WebSettings::jsPopupBlockerPassivePopup() const ++{ ++ return d->m_jsPopupBlockerPassivePopup; ++} ++ ++bool WebSettings::isCookieJarEnabled() const ++{ ++ return d->m_useCookieJar; ++} ++ ++// Password storage... ++static KConfigGroup nonPasswordStorableSitesCg(KSharedConfig::Ptr& configPtr) ++{ ++ if (!configPtr) { ++ configPtr = KSharedConfig::openConfig(QStandardPaths::locate(QStandardPaths::DataLocation, QStringLiteral("khtml/formcompletions")), KConfig::NoGlobals); ++ } ++ ++ return KConfigGroup(configPtr, "NonPasswordStorableSites"); ++} ++ ++bool WebSettings::isNonPasswordStorableSite(const QString &host) const ++{ ++ KConfigGroup cg = nonPasswordStorableSitesCg(d->nonPasswordStorableSites); ++ const QStringList sites = cg.readEntry("Sites", QStringList()); ++ return sites.contains(host); ++} ++ ++void WebSettings::addNonPasswordStorableSite(const QString &host) ++{ ++ KConfigGroup cg = nonPasswordStorableSitesCg(d->nonPasswordStorableSites); ++ QStringList sites = cg.readEntry("Sites", QStringList()); ++ sites.append(host); ++ cg.writeEntry("Sites", sites); ++ cg.sync(); ++} ++ ++void WebSettings::removeNonPasswordStorableSite(const QString &host) ++{ ++ KConfigGroup cg = nonPasswordStorableSitesCg(d->nonPasswordStorableSites); ++ QStringList sites = cg.readEntry("Sites", QStringList()); ++ sites.removeOne(host); ++ cg.writeEntry("Sites", sites); ++ cg.sync(); ++} ++ ++bool WebSettings::askToSaveSitePassword() const ++{ ++ return d->m_offerToSaveWebSitePassword; ++} ++ ++bool WebSettings::isInternalPluginHandlingDisabled() const ++{ ++ return d->m_disableInternalPluginHandling; ++} ++ ++bool WebSettings::isLoadPluginsOnDemandEnabled() const ++{ ++ return d->m_loadPluginsOnDemand; ++} ++ ++bool WebSettings::allowMixedContentDisplay() const ++{ ++ return d->m_allowMixedContentDisplay; ++} ++ ++bool WebSettings::alowActiveMixedContent() const ++{ ++ return d->m_allowActiveMixedContent; ++} ++ ++ ++void WebSettings::initWebSettings() ++{ ++ KConfig cfg (QStringLiteral("webkitpartrc"), KConfig::NoGlobals); ++ KConfigGroup generalCfg (&cfg, "General"); ++ d->m_disableInternalPluginHandling = generalCfg.readEntry("DisableInternalPluginHandling", false); ++ d->m_enableLocalStorage = generalCfg.readEntry("EnableLocalStorage", true); ++ d->m_enableOfflineStorageDb = generalCfg.readEntry("EnableOfflineStorageDatabase", true); ++ d->m_enableOfflineWebAppCache = generalCfg.readEntry("EnableOfflineWebApplicationCache", true); ++ d->m_enableWebGL = generalCfg.readEntry("EnableWebGL", true); ++ d->m_allowActiveMixedContent = generalCfg.readEntry("AllowActiveMixedContent", false); ++ d->m_allowMixedContentDisplay = generalCfg.readEntry("AllowMixedContentDisplay", true); ++ ++ // Force the reloading of the non password storable sites settings. ++ d->nonPasswordStorableSites.reset(); ++} ++ ++void WebSettings::initCookieJarSettings() ++{ ++ KSharedConfig::Ptr cookieCfgPtr = KSharedConfig::openConfig(QStringLiteral("kcookiejarrc"), KConfig::NoGlobals); ++ KConfigGroup cookieCfg ( cookieCfgPtr, "Cookie Policy"); ++ d->m_useCookieJar = cookieCfg.readEntry("Cookies", false); ++} ++ ++void WebSettings::initNSPluginSettings() ++{ ++ KSharedConfig::Ptr cookieCfgPtr = KSharedConfig::openConfig(QStringLiteral("kcmnspluginrc"), KConfig::NoGlobals); ++ KConfigGroup cookieCfg ( cookieCfgPtr, "Misc"); ++ d->m_loadPluginsOnDemand = cookieCfg.readEntry("demandLoad", false); ++} ++ ++ ++WebSettings* WebSettings::self() ++{ ++ static WebSettings s_WebSettings; ++ return &s_WebSettings; ++} ++ ++#include "webkitsettings.moc" +diff --git b/webkitpart/src/settings/webkitsettings.h b/webkitpart/src/settings/webkitsettings.h +new file mode 100644 +index 000000000..bf850c980 +--- /dev/null ++++ b/webkitpart/src/settings/webkitsettings.h +@@ -0,0 +1,213 @@ ++/* This file is part of the KDE project ++ Copyright (C) 1999 David Faure <faure@kde.org> ++ ++ This library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Library 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 WEBSETTINGS_H ++#define WEBSETTINGS_H ++ ++class KConfig; ++class KConfigGroup; ++ ++#include <QColor> ++#include <QStringList> ++#include <QPair> ++ ++#include <KParts/HtmlExtension> ++#include <KParts/HtmlSettingsInterface> ++ ++struct KPerDomainSettings; ++class WebSettingsPrivate; ++ ++/** ++ * Settings for the HTML view. ++ */ ++class WebSettings ++{ ++public: ++ ++ enum KAnimationAdvice { ++ KAnimationDisabled=0, ++ KAnimationLoopOnce, ++ KAnimationEnabled ++ }; ++ ++ enum KSmoothScrollingMode { ++ KSmoothScrollingDisabled=0, ++ KSmoothScrollingWhenEfficient, ++ KSmoothScrollingEnabled ++ }; ++ ++ /** ++ * Called by constructor and reparseConfiguration ++ */ ++ void init(); ++ ++ /** ++ * Destructor. Don't delete any instance by yourself. ++ */ ++ virtual ~WebSettings(); ++ ++ void computeFontSizes(int logicalDpi); ++ bool zoomToDPI() const; ++ void setZoomToDPI(bool b); ++ ++ // Automatic page reload/refresh... ++ bool autoPageRefresh() const; ++ ++ bool isOpenMiddleClickEnabled(); ++ ++ // Java and JavaScript ++ bool isJavaEnabled( const QString& hostname = QString() ) const; ++ bool isJavaScriptEnabled( const QString& hostname = QString() ) const; ++ bool isJavaScriptDebugEnabled( const QString& hostname = QString() ) const; ++ bool isJavaScriptErrorReportingEnabled( const QString& hostname = QString() ) const; ++ bool isPluginsEnabled( const QString& hostname = QString() ) const; ++ bool isLoadPluginsOnDemandEnabled() const; ++ bool isInternalPluginHandlingDisabled() const; ++ ++ // AdBlocK Filtering ++ bool isAdFiltered( const QString &url ) const; ++ bool isAdFilterEnabled() const; ++ bool isHideAdsEnabled() const; ++ void addAdFilter( const QString &url ); ++ QString adFilteredBy( const QString &url, bool *isWhiteListed = 0 ) const; ++ ++ // Access Keys ++ bool accessKeysEnabled() const; ++ ++ // Favicons ++ bool favIconsEnabled() const; ++ ++ KParts::HtmlSettingsInterface::JSWindowOpenPolicy windowOpenPolicy( const QString& hostname = QString() ) const; ++ KParts::HtmlSettingsInterface::JSWindowMovePolicy windowMovePolicy( const QString& hostname = QString() ) const; ++ KParts::HtmlSettingsInterface::JSWindowResizePolicy windowResizePolicy( const QString& hostname = QString() ) const; ++ KParts::HtmlSettingsInterface::JSWindowStatusPolicy windowStatusPolicy( const QString& hostname = QString() ) const; ++ KParts::HtmlSettingsInterface::JSWindowFocusPolicy windowFocusPolicy( const QString& hostname = QString() ) const; ++ ++ QString settingsToCSS() const; ++ QString userStyleSheet() const; ++ ++ // Form completion ++ bool isFormCompletionEnabled() const; ++ int maxFormCompletionItems() const; ++ ++ // Meta refresh/redirect (http-equiv) ++ bool isAutoDelayedActionsEnabled () const; ++ ++ // CookieJar... ++ bool isCookieJarEnabled() const; ++ ++ // Password storage... ++ bool isNonPasswordStorableSite(const QString &host) const; ++ void addNonPasswordStorableSite(const QString &host); ++ void removeNonPasswordStorableSite(const QString &host); ++ bool askToSaveSitePassword() const; ++ ++ // Mixed content ++ bool alowActiveMixedContent() const; ++ bool allowMixedContentDisplay() const; ++ ++ // Global config object stuff. ++ static WebSettings* self(); ++ ++private: ++ /** ++ * Read settings from @p config. ++ * @param config is a pointer to KConfig object. ++ * @param reset if true, settings are always set; if false, ++ * settings are only set if the config file has a corresponding key. ++ */ ++ void init( KConfig * config, bool reset = true ); ++ ++ // Behavior settings ++ bool changeCursor() const; ++ bool underlineLink() const; ++ bool hoverLink() const; ++ bool allowTabulation() const; ++ bool autoSpellCheck() const; ++ KAnimationAdvice showAnimations() const; ++ KSmoothScrollingMode smoothScrolling() const; ++ bool zoomTextOnly() const; ++ ++ // Font settings ++ QString stdFontName() const; ++ QString fixedFontName() const; ++ QString serifFontName() const; ++ QString sansSerifFontName() const; ++ QString cursiveFontName() const; ++ QString fantasyFontName() const; ++ ++ // these two can be set. Mainly for historical reasons (the method in KHTMLPart exists...) ++ void setStdFontName(const QString &n); ++ void setFixedFontName(const QString &n); ++ ++ int minFontSize() const; ++ int mediumFontSize() const; ++ ++ bool jsErrorsEnabled() const; ++ void setJSErrorsEnabled(bool enabled); ++ ++ const QString &encoding() const; ++ ++ bool followSystemColors() const; ++ ++ // Color settings ++ const QColor& textColor() const; ++ const QColor& baseColor() const; ++ const QColor& linkColor() const; ++ const QColor& vLinkColor() const; ++ ++ // Autoload images ++ bool autoLoadImages() const; ++ bool unfinishedImageFrame() const; ++ ++ /** ++ * reads from @p config's current group, forcing initialization ++ * if @p reset is true. ++ * @param config is a pointer to KConfig object. ++ * @param reset true if initialization is to be forced. ++ * @param global true if the global domain is to be read. ++ * @param pd_settings will be initialised with the computed (inherited) ++ * settings. ++ */ ++ void readDomainSettings(const KConfigGroup &config, bool reset, ++ bool global, KPerDomainSettings &pd_settings); ++ ++ ++ QList< QPair< QString, QChar > > fallbackAccessKeysAssignments() const; ++ ++ // Whether to show passive popup when windows are blocked ++ void setJSPopupBlockerPassivePopup(bool enabled); ++ bool jsPopupBlockerPassivePopup() const; ++ ++ ++ QString lookupFont(int i) const; ++ ++ void initWebSettings(); ++ void initCookieJarSettings(); ++ void initNSPluginSettings(); ++ ++ /** ++ * @internal Constructor ++ */ ++ WebSettings(); ++ ++ WebSettingsPrivate* const d; ++}; ++ ++#endif +diff --git b/webkitpart/src/ui/featurepermissionbar.cpp b/webkitpart/src/ui/featurepermissionbar.cpp +new file mode 100644 +index 000000000..538c658aa +--- /dev/null ++++ b/webkitpart/src/ui/featurepermissionbar.cpp +@@ -0,0 +1,75 @@ ++/* ++ * This file is part of the KDE project. ++ * ++ * Copyright (C) 2009 Dawit Alemayehu <adawit @ kde.org> ++ * Copyright (C) 2013 Allan Sandfeld Jensen <sandfeld@kde.org> ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Library 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 "featurepermissionbar.h" ++ ++#include <KLocalizedString> ++ ++#include <QAction> ++ ++ ++FeaturePermissionBar::FeaturePermissionBar(QWidget *parent) ++ :KMessageWidget(parent) ++{ ++ setCloseButtonVisible(false); ++ setMessageType(KMessageWidget::Information); ++ ++ QAction* action = new QAction(i18nc("@action:deny access", "&Deny access"), this); ++ connect(action, SIGNAL(triggered()), this, SLOT(onDeniedButtonClicked())); ++ addAction(action); ++ ++ action = new QAction(i18nc("@action:grant access", "&Grant access"), this); ++ connect(action, SIGNAL(triggered()), this, SLOT(onGrantedButtonClicked())); ++ addAction(action); ++ ++ // FIXME: Add option to allow and remember for this site. ++} ++ ++FeaturePermissionBar::~FeaturePermissionBar() ++{ ++} ++ ++QWebPage::Feature FeaturePermissionBar::feature() const ++{ ++ return m_feature; ++} ++ ++void FeaturePermissionBar::setFeature (QWebPage::Feature feature) ++{ ++ m_feature = feature; ++} ++ ++void FeaturePermissionBar::onDeniedButtonClicked() ++{ ++ animatedHide(); ++ emit permissionDenied(m_feature); ++ emit done(); ++} ++ ++void FeaturePermissionBar::onGrantedButtonClicked() ++{ ++ animatedHide(); ++ emit permissionGranted(m_feature); ++ emit done(); ++} ++ ++#include "featurepermissionbar.moc" +diff --git b/webkitpart/src/ui/featurepermissionbar.h b/webkitpart/src/ui/featurepermissionbar.h +new file mode 100644 +index 000000000..ca4b7e6eb +--- /dev/null ++++ b/webkitpart/src/ui/featurepermissionbar.h +@@ -0,0 +1,54 @@ ++/* ++ * This file is part of the KDE project. ++ * ++ * Copyright (C) 2013 Allan Sandfeld Jensen <sandfeld @ kde.org> ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Library General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 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 FEATUREPERMISSIONBAR_H ++#define FEATUREPERMISSIONBAR_H ++ ++#include <KMessageWidget> ++ ++#include <QtWebKitWidgets/QWebPage> ++ ++ ++class FeaturePermissionBar : public KMessageWidget ++{ ++ Q_OBJECT ++public: ++ explicit FeaturePermissionBar(QWidget *parent = Q_NULLPTR); ++ ~FeaturePermissionBar(); ++ ++ QWebPage::Feature feature() const; ++ ++ void setFeature(QWebPage::Feature); ++ ++Q_SIGNALS: ++ void permissionGranted(QWebPage::Feature); ++ void permissionDenied(QWebPage::Feature); ++ void done(); ++ ++private Q_SLOTS: ++ void onDeniedButtonClicked(); ++ void onGrantedButtonClicked(); ++ ++private: ++ QWebPage::Feature m_feature; ++}; ++ ++#endif // FEATUREPERMISSIONBAR_H +diff --git b/webkitpart/src/ui/passwordbar.cpp b/webkitpart/src/ui/passwordbar.cpp +new file mode 100644 +index 000000000..b6dde17ed +--- /dev/null ++++ b/webkitpart/src/ui/passwordbar.cpp +@@ -0,0 +1,105 @@ ++/* ++ * This file is part of the KDE project. ++ * ++ * Copyright (C) 2009 Dawit Alemayehu <adawit @ kde.org> ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Library 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 "passwordbar.h" ++ ++#include "settings/websettings.h" ++ ++#include <KColorScheme> ++#include <KLocalizedString> ++ ++#include <QCoreApplication> ++#include <QAction> ++#include <QPalette> ++ ++ ++PasswordBar::PasswordBar(QWidget *parent) ++ :KMessageWidget(parent) ++{ ++ setCloseButtonVisible(false); ++ setMessageType(KMessageWidget::Information); ++ ++ QAction* action = new QAction(i18nc("@action:remember password", "&Remember"), this); ++ connect(action, SIGNAL(triggered()), this, SLOT(onRememberButtonClicked())); ++ addAction(action); ++ ++ action = new QAction(i18nc("@action:never for this site", "Ne&ver for this site"), this); ++ connect(action, SIGNAL(triggered()), this, SLOT(onNeverButtonClicked())); ++ addAction(action); ++ ++ action = new QAction(i18nc("@action:not now", "N&ot now"), this); ++ connect(action, SIGNAL(triggered()), this, SLOT(onNotNowButtonClicked())); ++ addAction(action); ++} ++ ++PasswordBar::~PasswordBar() ++{ ++} ++ ++QUrl PasswordBar::url() const ++{ ++ return m_url; ++} ++ ++QString PasswordBar::requestKey() const ++{ ++ return m_requestKey; ++} ++ ++void PasswordBar::setUrl (const QUrl& url) ++{ ++ m_url = url; ++} ++ ++void PasswordBar::setRequestKey (const QString& key) ++{ ++ m_requestKey = key; ++} ++ ++void PasswordBar::onNotNowButtonClicked() ++{ ++ animatedHide(); ++ emit saveFormDataRejected (m_requestKey); ++ emit done(); ++ clear(); ++} ++ ++void PasswordBar::onNeverButtonClicked() ++{ ++ WebSettings::self()->addNonPasswordStorableSite(m_url.host()); ++ onNotNowButtonClicked(); ++} ++ ++void PasswordBar::onRememberButtonClicked() ++{ ++ animatedHide(); ++ emit saveFormDataAccepted(m_requestKey); ++ emit done(); ++ clear(); ++} ++ ++void PasswordBar::clear() ++{ ++ m_requestKey.clear(); ++ m_url.clear(); ++} ++ ++#include "passwordbar.moc" +diff --git b/webkitpart/src/ui/passwordbar.h b/webkitpart/src/ui/passwordbar.h +new file mode 100644 +index 000000000..9f641a625 +--- /dev/null ++++ b/webkitpart/src/ui/passwordbar.h +@@ -0,0 +1,60 @@ ++/* ++ * This file is part of the KDE project. ++ * ++ * Copyright (C) 2009 Dawit Alemayehu <adawit @ kde.org> ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Library 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 PASSWORDBAR_H ++#define PASSWORDBAR_H ++ ++#include <KMessageWidget> ++ ++#include <QUrl> ++ ++ ++class PasswordBar : public KMessageWidget ++{ ++ Q_OBJECT ++public: ++ explicit PasswordBar(QWidget *parent = Q_NULLPTR); ++ ~PasswordBar(); ++ ++ QUrl url() const; ++ QString requestKey() const; ++ ++ void setUrl(const QUrl&); ++ void setRequestKey(const QString&); ++ ++Q_SIGNALS: ++ void saveFormDataRejected(const QString &key); ++ void saveFormDataAccepted(const QString &key); ++ void done(); ++ ++private Q_SLOTS: ++ void onNotNowButtonClicked(); ++ void onNeverButtonClicked(); ++ void onRememberButtonClicked(); ++ ++private: ++ void clear(); ++ ++ QUrl m_url; ++ QString m_requestKey; ++}; ++ ++#endif // PASSWORDBAR_H +diff --git b/webkitpart/src/ui/searchbar.cpp b/webkitpart/src/ui/searchbar.cpp +new file mode 100644 +index 000000000..aca133ff6 +--- /dev/null ++++ b/webkitpart/src/ui/searchbar.cpp +@@ -0,0 +1,194 @@ ++/* ++ * This file is part of the KDE project. ++ * ++ * Copyright (C) 2008 Laurent Montel <montel@kde.org> ++ * Copyright (C) 2008 Benjamin C. Meyer <ben@meyerhome.net> ++ * Copyright (C) 2008 Urs Wolfer <uwolfer @ kde.org> ++ * Copyright (C) 2009 Dawit Alemayehu <adawit @ kde.org> ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Library 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 "searchbar.h" ++ ++#include <KLineEdit> ++#include <KColorScheme> ++#include <QIcon> ++#include <KLocalizedString> ++ ++#include <QResizeEvent> ++ ++ ++SearchBar::SearchBar(QWidget *parent) ++ :QWidget(parent) ++{ ++ ++ // Get the widget that currently has the focus so we can properly ++ // restore it when the filter bar is closed. ++ QWidget* widgetWindow = (parent ? parent->window() : 0); ++ m_focusWidget = (widgetWindow ? widgetWindow->focusWidget() : 0); ++ ++ // Initialize the user interface... ++ m_ui.setupUi(this); ++ m_ui.optionsButton->addAction(m_ui.actionMatchCase); ++ m_ui.optionsButton->addAction(m_ui.actionHighlightMatch); ++ m_ui.optionsButton->addAction(m_ui.actionSearchAutomatically); ++ m_ui.closeButton->setIcon(QIcon::fromTheme(QStringLiteral("dialog-close"))); ++ m_ui.previousButton->setIcon(QIcon::fromTheme(QStringLiteral("go-up-search"))); ++ m_ui.nextButton->setIcon(QIcon::fromTheme(QStringLiteral("go-down-search"))); ++ m_ui.previousButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); ++ m_ui.nextButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); ++ m_ui.searchInfo->setText(i18nc("label for input line to find text", "&Find:")); ++ ++ setFocusProxy(m_ui.searchComboBox); ++ ++ connect(m_ui.nextButton, SIGNAL(clicked()), ++ this, SLOT(findNext())); ++ connect(m_ui.previousButton, SIGNAL(clicked()), ++ this, SLOT(findPrevious())); ++ connect(m_ui.searchComboBox, SIGNAL(returnPressed()), ++ this, SLOT(findNext())); ++ connect(m_ui.searchComboBox, SIGNAL(editTextChanged(QString)), ++ this, SLOT(textChanged(QString))); ++ ++ // Start off hidden by default... ++ setVisible(false); ++} ++ ++SearchBar::~SearchBar() ++{ ++ // NOTE: For some reason, if we do not clear the focus from the line edit ++ // widget before we delete this object, it seems to cause a crash!! ++ m_ui.searchComboBox->clearFocus(); ++} ++ ++void SearchBar::clear() ++{ ++ m_ui.searchComboBox->clear(); ++} ++ ++void SearchBar::setVisible (bool visible) ++{ ++ if (visible) { ++ m_ui.searchComboBox->setFocus(Qt::ActiveWindowFocusReason); ++ m_ui.searchComboBox->lineEdit()->selectAll(); ++ } else { ++ m_ui.searchComboBox->setPalette(QPalette()); ++ emit searchTextChanged(QString()); ++ } ++ ++ QWidget::setVisible(visible); ++} ++ ++QString SearchBar::searchText() const ++{ ++ return m_ui.searchComboBox->currentText(); ++} ++ ++bool SearchBar::caseSensitive() const ++{ ++ return m_ui.actionMatchCase->isChecked(); ++} ++ ++bool SearchBar::highlightMatches() const ++{ ++ return m_ui.actionHighlightMatch->isChecked(); ++} ++ ++void SearchBar::setSearchText(const QString& text) ++{ ++ show(); ++ m_ui.searchComboBox->setEditText(text); ++} ++ ++void SearchBar::setFoundMatch(bool match) ++{ ++ //kDebug() << match; ++ if (m_ui.searchComboBox->currentText().isEmpty()) { ++ m_ui.searchComboBox->setPalette(QPalette()); ++ return; ++ } ++ ++ KColorScheme::BackgroundRole role = (match ? KColorScheme::PositiveBackground : KColorScheme::NegativeBackground); ++ QPalette newPal(m_ui.searchComboBox->palette()); ++ KColorScheme::adjustBackground(newPal, role); ++ m_ui.searchComboBox->setPalette(newPal); ++} ++ ++void SearchBar::findNext() ++{ ++ if (!isVisible()) ++ return; ++ ++ const QString text (m_ui.searchComboBox->currentText()); ++ if (m_ui.searchComboBox->findText(text) == -1) { ++ m_ui.searchComboBox->addItem(text); ++ } ++ ++ emit searchTextChanged(text); ++} ++ ++void SearchBar::findPrevious() ++{ ++ if (!isVisible()) ++ return; ++ ++ const QString text (m_ui.searchComboBox->currentText()); ++ if (m_ui.searchComboBox->findText(text) == -1) { ++ m_ui.searchComboBox->addItem(text); ++ } ++ ++ emit searchTextChanged(m_ui.searchComboBox->currentText(), true); ++} ++ ++void SearchBar::textChanged(const QString &text) ++{ ++ if (text.isEmpty()) { ++ m_ui.searchComboBox->setPalette(QPalette()); ++ m_ui.nextButton->setEnabled(false); ++ m_ui.previousButton->setEnabled(false); ++ } else { ++ m_ui.nextButton->setEnabled(true); ++ m_ui.previousButton->setEnabled(true); ++ } ++ ++ if (m_ui.actionSearchAutomatically->isChecked()) { ++ emit searchTextChanged(m_ui.searchComboBox->currentText()); ++ } ++} ++ ++bool SearchBar::event(QEvent* e) ++{ ++ // Close the bar when Escape is pressed. Note we cannot ++ // assign Escape as a shortcut key because it would cause ++ // a conflict with the Stop button. ++ if (e->type() == QEvent::ShortcutOverride) { ++ QKeyEvent* kev = static_cast<QKeyEvent*>(e); ++ if (kev->key() == Qt::Key_Escape) { ++ e->accept(); ++ close(); ++ if (m_focusWidget) { ++ m_focusWidget->setFocus(); ++ m_focusWidget = 0; ++ } ++ return true; ++ } ++ } ++ return QWidget::event(e); ++} ++ ++#include "searchbar.moc" +diff --git b/webkitpart/src/ui/searchbar.h b/webkitpart/src/ui/searchbar.h +new file mode 100644 +index 000000000..598fe69ff +--- /dev/null ++++ b/webkitpart/src/ui/searchbar.h +@@ -0,0 +1,68 @@ ++/* ++ * This file is part of the KDE project. ++ * ++ * Copyright (C) 2008 Laurent Montel <montel@kde.org> ++ * Copyright 2008 Benjamin C. Meyer <ben@meyerhome.net> ++ * Copyright (C) 2008 Urs Wolfer <uwolfer @ kde.org> ++ * Copyright (C) 2009 Dawit Alemayehu <adawit @ kde.org> ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Library 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 SEARCHBAR_P_H ++#define SEARCHBAR_P_H ++ ++#include <QWidget> ++ ++#include "ui_searchbar.h" ++ ++class QEvent; ++ ++/** ++ * This is the widget that shows up when the search is initiated. ++ */ ++class SearchBar : public QWidget ++{ ++ Q_OBJECT ++ ++public: ++ SearchBar(QWidget *parent = Q_NULLPTR); ++ ~SearchBar(); ++ ++ QString searchText() const; ++ bool caseSensitive() const; ++ bool highlightMatches() const; ++ void setFoundMatch(bool match); ++ void setSearchText(const QString&); ++ ++ bool event(QEvent* e) Q_DECL_OVERRIDE; ++ ++public Q_SLOTS: ++ void setVisible(bool visible) Q_DECL_OVERRIDE; ++ void clear(); ++ void findNext(); ++ void findPrevious(); ++ void textChanged(const QString&); ++ ++Q_SIGNALS: ++ void searchTextChanged(const QString& text, bool backward = false); ++ ++private: ++ Ui::SearchBar m_ui; ++ QPointer<QWidget> m_focusWidget; ++}; ++ ++#endif // SEARCHBAR_P_H +diff --git b/webkitpart/src/ui/searchbar.ui b/webkitpart/src/ui/searchbar.ui +new file mode 100644 +index 000000000..0ed50bdda +--- /dev/null ++++ b/webkitpart/src/ui/searchbar.ui +@@ -0,0 +1,168 @@ ++<?xml version="1.0" encoding="UTF-8"?> ++<ui version="4.0"> ++ <class>SearchBar</class> ++ <widget class="QWidget" name="SearchBar"> ++ <property name="geometry"> ++ <rect> ++ <x>0</x> ++ <y>0</y> ++ <width>564</width> ++ <height>34</height> ++ </rect> ++ </property> ++ <property name="sizePolicy"> ++ <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> ++ <horstretch>0</horstretch> ++ <verstretch>0</verstretch> ++ </sizepolicy> ++ </property> ++ <layout class="QHBoxLayout" name="horizontalLayout"> ++ <item> ++ <widget class="QToolButton" name="closeButton"> ++ <property name="toolTip"> ++ <string>Close the search bar</string> ++ </property> ++ <property name="autoRaise"> ++ <bool>true</bool> ++ </property> ++ </widget> ++ </item> ++ <item> ++ <widget class="QLabel" name="searchInfo"> ++ <property name="text"> ++ <string>&Find:</string> ++ </property> ++ <property name="buddy"> ++ <cstring>searchComboBox</cstring> ++ </property> ++ </widget> ++ </item> ++ <item> ++ <widget class="KHistoryComboBox" name="searchComboBox"> ++ <property name="sizePolicy"> ++ <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> ++ <horstretch>0</horstretch> ++ <verstretch>0</verstretch> ++ </sizepolicy> ++ </property> ++ </widget> ++ </item> ++ <item> ++ <widget class="QToolButton" name="nextButton"> ++ <property name="enabled"> ++ <bool>false</bool> ++ </property> ++ <property name="toolTip"> ++ <string>Find the next match for the current search phrase</string> ++ </property> ++ <property name="text"> ++ <string>&Next</string> ++ </property> ++ </widget> ++ </item> ++ <item> ++ <widget class="QToolButton" name="previousButton"> ++ <property name="enabled"> ++ <bool>false</bool> ++ </property> ++ <property name="toolTip"> ++ <string>Find the previous match for the current search phrase</string> ++ </property> ++ <property name="text"> ++ <string>&Previous</string> ++ </property> ++ </widget> ++ </item> ++ <item> ++ <widget class="QToolButton" name="optionsButton"> ++ <property name="toolTip"> ++ <string>Find the previous match for the current search phrase</string> ++ </property> ++ <property name="text"> ++ <string>&Options</string> ++ </property> ++ <property name="popupMode"> ++ <enum>QToolButton::InstantPopup</enum> ++ </property> ++ </widget> ++ </item> ++ <item> ++ <spacer name="horizontalSpacer"> ++ <property name="orientation"> ++ <enum>Qt::Horizontal</enum> ++ </property> ++ <property name="sizeType"> ++ <enum>QSizePolicy::MinimumExpanding</enum> ++ </property> ++ <property name="sizeHint" stdset="0"> ++ <size> ++ <width>20</width> ++ <height>20</height> ++ </size> ++ </property> ++ </spacer> ++ </item> ++ </layout> ++ <action name="actionMatchCase"> ++ <property name="checkable"> ++ <bool>true</bool> ++ </property> ++ <property name="text"> ++ <string>&Match Case</string> ++ </property> ++ </action> ++ <action name="actionSearchAutomatically"> ++ <property name="checkable"> ++ <bool>true</bool> ++ </property> ++ <property name="checked"> ++ <bool>true</bool> ++ </property> ++ <property name="text"> ++ <string>&Search As You Type</string> ++ </property> ++ </action> ++ <action name="actionHighlightMatch"> ++ <property name="checkable"> ++ <bool>true</bool> ++ </property> ++ <property name="text"> ++ <string>&Highlight All Matches</string> ++ </property> ++ <property name="toolTip"> ++ <string>Highlight Matches</string> ++ </property> ++ </action> ++ </widget> ++ <customwidgets> ++ <customwidget> ++ <class>KComboBox</class> ++ <extends>QComboBox</extends> ++ <header>kcombobox.h</header> ++ </customwidget> ++ <customwidget> ++ <class>KHistoryComboBox</class> ++ <extends>KComboBox</extends> ++ <header>khistorycombobox.h</header> ++ </customwidget> ++ </customwidgets> ++ <resources/> ++ <connections> ++ <connection> ++ <sender>closeButton</sender> ++ <signal>clicked()</signal> ++ <receiver>SearchBar</receiver> ++ <slot>close()</slot> ++ <hints> ++ <hint type="sourcelabel"> ++ <x>16</x> ++ <y>16</y> ++ </hint> ++ <hint type="destinationlabel"> ++ <x>290</x> ++ <y>16</y> ++ </hint> ++ </hints> ++ </connection> ++ </connections> ++</ui> +diff --git b/webkitpart/src/utils.h b/webkitpart/src/utils.h +new file mode 100644 +index 000000000..fc35a28c2 +--- /dev/null ++++ b/webkitpart/src/utils.h +@@ -0,0 +1,16 @@ ++#ifndef WEBKITPART_UTILS_H ++#define WEBKITPART_UTILS_H ++ ++namespace Utils ++{ ++ ++#define QL1S(x) QLatin1String(x) ++#define QL1C(x) QLatin1Char(x) ++ ++inline bool isBlankUrl(const QUrl& url) ++{ ++ return (url.isEmpty() || url.url() == QL1S("about:blank")); ++} ++ ++} ++#endif // WEBKITPART_UTILS_H +diff --git b/webkitpart/src/webhistoryinterface.cpp b/webkitpart/src/webhistoryinterface.cpp +new file mode 100644 +index 000000000..74e2c096e +--- /dev/null ++++ b/webkitpart/src/webhistoryinterface.cpp +@@ -0,0 +1,38 @@ ++/* ++ * This file is part of the KDE project. ++ * ++ * Copyright (C) 2011 Dawit Alemayehu <adawit@kde.org> ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Lesser General Public License as published by the ++ * Free Software Foundation; either version 2.1 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 Lesser General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library. If not, see <http://www.gnu.org/licenses/>. ++ * ++ */ ++ ++#include "webhistoryinterface.h" ++ ++#include <KParts/HistoryProvider> ++ ++ ++WebHistoryInterface::WebHistoryInterface(QObject* parent) ++{ ++} ++ ++void WebHistoryInterface::addHistoryEntry(const QString& url) ++{ ++ KParts::HistoryProvider::self()->insert(url); ++} ++ ++bool WebHistoryInterface::historyContains(const QString& url) const ++{ ++ return KParts::HistoryProvider::self()->contains(url); ++} +diff --git b/webkitpart/src/webhistoryinterface.h b/webkitpart/src/webhistoryinterface.h +new file mode 100644 +index 000000000..fbc6d6f8b +--- /dev/null ++++ b/webkitpart/src/webhistoryinterface.h +@@ -0,0 +1,34 @@ ++/* ++ * This file is part of the KDE project. ++ * ++ * Copyright (C) 2011 Dawit Alemayehu <adawit@kde.org> ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Lesser General Public License as published by the ++ * Free Software Foundation; either version 2.1 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 Lesser General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library. If not, see <http://www.gnu.org/licenses/>. ++ * ++ */ ++#ifndef WEBHISTORYINTERFACE_H ++#define WEBHISTORYINTERFACE_H ++ ++#include <QObject> ++ ++ ++class WebHistoryInterface ++{ ++public: ++ WebHistoryInterface(QObject* parent = Q_NULLPTR); ++ void addHistoryEntry (const QString & url); ++ bool historyContains (const QString & url) const; ++}; ++ ++#endif //WEBHISTORYINTERFACE_H +diff --git b/webkitpart/src/webkitpage.cpp b/webkitpart/src/webkitpage.cpp +new file mode 100644 +index 000000000..1cef75875 +--- /dev/null ++++ b/webkitpart/src/webkitpage.cpp +@@ -0,0 +1,887 @@ ++/* ++ * This file is part of the KDE project. ++ * ++ * Copyright (C) 2008 Dirk Mueller <mueller@kde.org> ++ * Copyright (C) 2008 - 2010 Urs Wolfer <uwolfer @ kde.org> ++ * Copyright (C) 2009 Dawit Alemayehu <adawit@kde.org> ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Lesser General Public License as published by the ++ * Free Software Foundation; either version 2.1 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 Lesser General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library. If not, see <http://www.gnu.org/licenses/>. ++ * ++ */ ++ ++#include "webkitpage.h" ++ ++#include "webkitpart.h" ++#include "websslinfo.h" ++#include "webkitview.h" ++#include "settings/webkitsettings.h" ++#include <QWebSettings> ++ ++#include <KMessageBox> ++#include <KRun> ++#include <KLocalizedString> ++#include <KShell> ++#include <KAuthorized> ++#include <KStringHandler> ++#include <KUrlAuthorized> ++#include <KSharedConfig> ++#include <KIO/Job> ++#include <KIO/AccessManager> ++#include <KIO/Scheduler> ++#include <KParts/HtmlExtension> ++#include <QStandardPaths> ++#include <QDesktopWidget> ++ ++#include <QFile> ++#include <QApplication> ++#include <QTextDocument> // Qt::escape ++#include <QNetworkReply> ++#include <QWebHistory> ++#include <QWebHistoryItem> ++#include <QWebDownloadItem> ++#include <QUrlQuery> ++#include <KConfigGroup> ++//#include <QWebSecurityOrigin> ++#include "utils.h" ++ ++ ++WebPage::WebPage(WebKitPart *part, QWidget *parent) ++ : QWebPage(parent), ++ m_kioErrorCode(0), ++ m_ignoreError(false), ++ m_part(part) ++{ ++ if (view()) ++ WebSettings::self()->computeFontSizes(view()->logicalDpiY()); ++ ++ //setForwardUnsupportedContent(true); ++ ++ connect(this, &QWebPage::geometryChangeRequested, ++ this, &WebPage::slotGeometryChangeRequested); ++// connect(this, SIGNAL(unsupportedContent(QNetworkReply*)), ++// this, SLOT(slotUnsupportedContent(QNetworkReply*))); ++ connect(this, &QWebPage::featurePermissionRequested, ++ this, &WebPage::slotFeaturePermissionRequested); ++ connect(this, &QWebPage::loadFinished, ++ this, &WebPage::slotLoadFinished); ++ connect(this->profile(), this, &WebPage::downloadRequest); ++ if(!this->profile()->httpUserAgent().contains(QLatin1String("Konqueror"))) ++ { ++ this->profile()->setHttpUserAgent(this->profile()->httpUserAgent() + " Konqueror (WebKitPart)"); ++ } ++} ++ ++WebPage::~WebPage() ++{ ++ //kDebug() << this; ++} ++ ++const WebSslInfo& WebPage::sslInfo() const ++{ ++ return m_sslInfo; ++} ++ ++void WebPage::setSslInfo (const WebSslInfo& info) ++{ ++ m_sslInfo = info; ++} ++ ++static void checkForDownloadManager(QWidget* widget, QString& cmd) ++{ ++ cmd.clear(); ++ KConfigGroup cfg (KSharedConfig::openConfig(QStringLiteral("konquerorrc"), KConfig::NoGlobals), "HTML Settings"); ++ const QString fileName (cfg.readPathEntry("DownloadManager", QString())); ++ if (fileName.isEmpty()) ++ return; ++ ++ const QString exeName = QStandardPaths::findExecutable(fileName); ++ if (exeName.isEmpty()) { ++ KMessageBox::detailedSorry(widget, ++ i18n("The download manager (%1) could not be found in your installation.", fileName), ++ i18n("Try to reinstall it and make sure that it is available in $PATH. \n\nThe integration will be disabled.")); ++ cfg.writePathEntry("DownloadManager", QString()); ++ cfg.sync(); ++ return; ++ } ++ ++ cmd = exeName; ++} ++ ++void WebPage::downloadRequest(QWebDownloadItem* request) ++{ ++ const QUrl url(request->url()); ++ ++ // Integration with a download manager... ++ if (!url.isLocalFile()) { ++ QString managerExe; ++ checkForDownloadManager(view(), managerExe); ++ if (!managerExe.isEmpty()) { ++ //kDebug() << "Calling command" << cmd; ++ KRun::runCommand((managerExe + QLatin1Char(' ') + KShell::quoteArg(url.url())), view()); ++ return; ++ } ++ } ++ request->accept(); ++ ++} ++ ++QWebPage *WebPage::createWindow(WebWindowType type) ++{ ++ //qDebug() << "window type:" << type; ++ // Crete an instance of NewWindowPage class to capture all the ++ // information we need to create a new window. See documentation of ++ // the class for more information... ++ NewWindowPage* page = new NewWindowPage(type, part()); ++ return page; ++} ++ ++// Returns true if the scheme and domain of the two urls match... ++static bool domainSchemeMatch(const QUrl& u1, const QUrl& u2) ++{ ++ if (u1.scheme() != u2.scheme()) ++ return false; ++ ++ QStringList u1List = u1.host().split(QL1C('.'), QString::SkipEmptyParts); ++ QStringList u2List = u2.host().split(QL1C('.'), QString::SkipEmptyParts); ++ ++ if (qMin(u1List.count(), u2List.count()) < 2) ++ return false; // better safe than sorry... ++ ++ while (u1List.count() > 2) ++ u1List.removeFirst(); ++ ++ while (u2List.count() > 2) ++ u2List.removeFirst(); ++ ++ return (u1List == u2List); ++} ++ ++bool WebPage::acceptNavigationRequest(const QUrl& url, NavigationType type, bool isMainFrame) ++{ ++ qDebug() << url << "type=" << type; ++ QUrl reqUrl(url); ++ ++ // Handle "mailto:" url here... ++ if (handleMailToUrl(reqUrl, type)) ++ return false; ++ ++ const bool isTypedUrl = property("NavigationTypeUrlEntered").toBool(); ++ ++ /* ++ NOTE: We use a dynamic QObject property called "NavigationTypeUrlEntered" ++ to distinguish between requests generated by user entering a url vs those ++ that were generated programatically through javascript (AJAX requests). ++ */ ++ if (isMainFrame && isTypedUrl) ++ setProperty("NavigationTypeUrlEntered", QVariant()); ++ ++ // inPage requests are those generarted within the current page through ++ // link clicks, javascript queries, and button clicks (form submission). ++ bool inPageRequest = true; ++ switch (type) { ++ case QWebPage::NavigationTypeFormSubmitted: ++ //if (!checkFormData(request)) ++ // return false; ++ break; ++#if 0 ++ case QWebPage::NavigationTypeFormResubmitted: ++ if (!checkFormData(request)) ++ return false; ++ if (KMessageBox::warningContinueCancel(view(), ++ i18n("<qt><p>To display the requested web page again, " ++ "the browser needs to resend information you have " ++ "previously submitted.</p>" ++ "<p>If you were shopping online and made a purchase, " ++ "click the Cancel button to prevent a duplicate purchase." ++ "Otherwise, click the Continue button to display the web" ++ "page again.</p>"), ++ i18n("Resubmit Information")) == KMessageBox::Cancel) { ++ return false; ++ } ++ break; ++#endif ++ case QWebPage::NavigationTypeBackForward: ++ // If history navigation is locked, ignore all such requests... ++ if (property("HistoryNavigationLocked").toBool()) { ++ setProperty("HistoryNavigationLocked", QVariant()); ++ qDebug() << "Rejected history navigation because 'HistoryNavigationLocked' property is set!"; ++ return false; ++ } ++ //kDebug() << "Navigating to item (" << history()->currentItemIndex() ++ // << "of" << history()->count() << "):" << history()->currentItem().url(); ++ inPageRequest = false; ++ break; ++ case QWebPage::NavigationTypeReload: ++// setRequestMetaData(QL1S("cache"), QL1S("reload")); ++ inPageRequest = false; ++ break; ++ case QWebPage::NavigationTypeOther: // triggered by javascript ++ qDebug() << "Triggered by javascript"; ++ inPageRequest = !isTypedUrl; ++ break; ++ default: ++ break; ++ } ++ ++ if (inPageRequest) { ++ // if (!checkLinkSecurity(request, type)) ++ // return false; ++ ++ // if (m_sslInfo.isValid()) ++ // setRequestMetaData(QL1S("ssl_was_in_use"), QL1S("TRUE")); ++ } ++ ++ ++ // Honor the enabling/disabling of plugins per host. ++ settings()->setAttribute(QWebSettings::PluginsEnabled, WebSettings::self()->isPluginsEnabled(reqUrl.host())); ++ // Insert the request into the queue... ++ return QWebPage::acceptNavigationRequest(url, type, isMainFrame); ++} ++ ++#if 0 ++static int errorCodeFromReply(QNetworkReply* reply) ++{ ++ // First check if there is a KIO error code sent back and use that, ++ // if not attempt to convert QNetworkReply's NetworkError to KIO::Error. ++ QVariant attr = reply->attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::KioError)); ++ if (attr.isValid() && attr.type() == QVariant::Int) ++ return attr.toInt(); ++ ++ switch (reply->error()) { ++ case QNetworkReply::ConnectionRefusedError: ++ return KIO::ERR_COULD_NOT_CONNECT; ++ case QNetworkReply::HostNotFoundError: ++ return KIO::ERR_UNKNOWN_HOST; ++ case QNetworkReply::TimeoutError: ++ return KIO::ERR_SERVER_TIMEOUT; ++ case QNetworkReply::OperationCanceledError: ++ return KIO::ERR_USER_CANCELED; ++ case QNetworkReply::ProxyNotFoundError: ++ return KIO::ERR_UNKNOWN_PROXY_HOST; ++ case QNetworkReply::ContentAccessDenied: ++ return KIO::ERR_ACCESS_DENIED; ++ case QNetworkReply::ContentOperationNotPermittedError: ++ return KIO::ERR_WRITE_ACCESS_DENIED; ++ case QNetworkReply::ContentNotFoundError: ++ return KIO::ERR_NO_CONTENT; ++ case QNetworkReply::AuthenticationRequiredError: ++ return KIO::ERR_COULD_NOT_AUTHENTICATE; ++ case QNetworkReply::ProtocolUnknownError: ++ return KIO::ERR_UNSUPPORTED_PROTOCOL; ++ case QNetworkReply::ProtocolInvalidOperationError: ++ return KIO::ERR_UNSUPPORTED_ACTION; ++ case QNetworkReply::UnknownNetworkError: ++ return KIO::ERR_UNKNOWN; ++ case QNetworkReply::NoError: ++ default: ++ break; ++ } ++ ++ return 0; ++} ++#endif ++ ++WebPart* WebPage::part() const ++{ ++ return m_part.data(); ++} ++ ++void WebPage::setPart(WebPart* part) ++{ ++ m_part = part; ++} ++ ++void WebPage::slotLoadFinished(bool ok) ++{ ++ QUrl requestUrl = url(); ++ requestUrl.setUserInfo(QString()); ++ const bool shouldResetSslInfo = (m_sslInfo.isValid() && !domainSchemeMatch(requestUrl, m_sslInfo.url())); ++#if 0 ++ QWebFrame* frame = qobject_cast<QWebFrame *>(reply->request().originatingObject()); ++ if (!frame) ++ return; ++ const bool isMainFrameRequest = (frame == mainFrame()); ++#else ++ // PORTING_TODO ++ const bool isMainFrameRequest = true; ++#endif ++ ++#if 0 ++ // Only deal with non-redirect responses... ++ const QVariant redirectVar = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); ++ ++ if (isMainFrameRequest && redirectVar.isValid()) { ++ m_sslInfo.restoreFrom(reply->attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::MetaData)), ++ reply->url(), shouldResetSslInfo); ++ return; ++ } ++ ++ const int errCode = errorCodeFromReply(reply); ++ kDebug() << frame << "is main frame request?" << isMainFrameRequest << requestUrl; ++#endif ++ ++ if (ok) { ++ if (isMainFrameRequest) { ++#if 0 ++ m_sslInfo.restoreFrom(reply->attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::MetaData)), ++ reply->url(), shouldResetSslInfo); ++#endif ++ setPageJScriptPolicy(url()); ++ } ++ } else { ++ // Handle any error... ++#if 0 ++ switch (errCode) { ++ case 0: ++ case KIO::ERR_NO_CONTENT: ++ break; ++ case KIO::ERR_ABORTED: ++ case KIO::ERR_USER_CANCELED: // Do nothing if request is cancelled/aborted ++ //kDebug() << "User aborted request!"; ++ m_ignoreError = true; ++ emit loadAborted(QUrl()); ++ return; ++ // Handle the user clicking on a link that refers to a directory ++ // Since KIO cannot automatically convert a GET request to a LISTDIR one. ++ case KIO::ERR_IS_DIRECTORY: ++ m_ignoreError = true; ++ emit loadAborted(reply->url()); ++ return; ++ default: ++ // Make sure the saveFrameStateRequested signal is emitted so ++ // the page can restored properly. ++ if (isMainFrameRequest) ++ emit saveFrameStateRequested(frame, 0); ++ ++ m_ignoreError = (reply->attribute(QNetworkRequest::User).toInt() == QNetworkReply::ContentAccessDenied); ++ m_kioErrorCode = errCode; ++ break; ++#endif ++ } ++ ++ if (isMainFrameRequest) { ++ const WebPageSecurity security = (m_sslInfo.isValid() ? PageEncrypted : PageUnencrypted); ++ emit m_part->browserExtension()->setPageSecurity(security); ++ } ++} ++ ++void WebPage::slotUnsupportedContent(QNetworkReply* reply) ++{ ++#if 0 ++ //kDebug() << reply->url(); ++ QString mimeType; ++ KIO::MetaData metaData; ++ ++ KIO::AccessManager::putReplyOnHold(reply); ++ QString downloadCmd; ++ checkForDownloadManager(view(), downloadCmd); ++ if (!downloadCmd.isEmpty()) { ++ reply->setProperty("DownloadManagerExe", downloadCmd); ++ } ++ ++ if (QWePage::handleReply(reply, &mimeType, &metaData)) { ++ reply->deleteLater(); ++ if (qobject_cast<NewWindowPage*>(this) && isBlankUrl(m_part->url())) { ++ m_part->closeUrl(); ++ if (m_part->arguments().metaData().contains(QL1S("new-window"))) { ++ m_part->widget()->topLevelWidget()->close(); ++ } else { ++ delete m_part; ++ } ++ } ++ return; ++ } ++ ++ //kDebug() << "mimetype=" << mimeType << "metadata:" << metaData; ++ ++ if (reply->request().originatingObject() == this->mainFrame()) { ++ KParts::OpenUrlArguments args; ++ args.setMimeType(mimeType); ++ args.metaData() = metaData; ++ emit m_part->browserExtension()->openUrlRequest(reply->url(), args, KParts::BrowserArguments()); ++ return; ++ } ++#endif ++ reply->deleteLater(); ++ ++} ++void WebPage::slotFeaturePermissionRequested(const QUrl& url, QWebPage::Feature feature) ++{ ++ if (url == this->url()) { ++ part()->slotShowFeaturePermissionBar(feature); ++ return; ++ } ++ switch(feature) { ++ case QWebPage::Notifications: ++ // FIXME: We should have a setting to tell if this is enabled, but so far it is always enabled. ++ setFeaturePermission(url, feature, QWebPage::PermissionGrantedByUser); ++ break; ++ case QWebPage::Geolocation: ++ if (KMessageBox::warningContinueCancel(0, i18n("This site is attempting to " ++ "access information about your " ++ "physical location.\n" ++ "Do you want to allow it access?"), ++ i18n("Network Transmission"), ++ KGuiItem(i18n("Allow access")), ++ KStandardGuiItem::cancel(), ++ QStringLiteral("WarnGeolocation")) == KMessageBox::Cancel) { ++ setFeaturePermission(url, feature, QWebPage::PermissionDeniedByUser); ++ } else { ++ setFeaturePermission(url, feature, QWebPage::PermissionGrantedByUser); ++ } ++ break; ++ default: ++ setFeaturePermission(url, feature, QWebPage::PermissionUnknown); ++ break; ++ } ++} ++ ++void WebPage::slotGeometryChangeRequested(const QRect & rect) ++{ ++ const QString host = url().host(); ++ ++ // NOTE: If a new window was created from another window which is in ++ // maximized mode and its width and/or height were not specified at the ++ // time of its creation, which is always the case in QWebPage::createWindow, ++ // then any move operation will seem not to work. That is because the new ++ // window will be in maximized mode where moving it will not be possible... ++ if (WebSettings::self()->windowMovePolicy(host) == KParts::HtmlSettingsInterface::JSWindowMoveAllow && ++ (view()->x() != rect.x() || view()->y() != rect.y())) ++ emit m_part->browserExtension()->moveTopLevelWidget(rect.x(), rect.y()); ++ ++ const int height = rect.height(); ++ const int width = rect.width(); ++ ++ // parts of following code are based on kjs_window.cpp ++ // Security check: within desktop limits and bigger than 100x100 (per spec) ++ if (width < 100 || height < 100) { ++ qWarning() << "Window resize refused, window would be too small (" << width << "," << height << ")"; ++ return; ++ } ++ ++ QRect sg = QApplication::desktop()->screenGeometry(view()); ++ ++ if (width > sg.width() || height > sg.height()) { ++ qWarning() << "Window resize refused, window would be too big (" << width << "," << height << ")"; ++ return; ++ } ++ ++ if (WebSettings::self()->windowResizePolicy(host) == KParts::HtmlSettingsInterface::JSWindowResizeAllow) { ++ //kDebug() << "resizing to " << width << "x" << height; ++ emit m_part->browserExtension()->resizeTopLevelWidget(width, height); ++ } ++ ++ // If the window is out of the desktop, move it up/left ++ // (maybe we should use workarea instead of sg, otherwise the window ends up below kicker) ++ const int right = view()->x() + view()->frameGeometry().width(); ++ const int bottom = view()->y() + view()->frameGeometry().height(); ++ int moveByX = 0, moveByY = 0; ++ if (right > sg.right()) ++ moveByX = - right + sg.right(); // always <0 ++ if (bottom > sg.bottom()) ++ moveByY = - bottom + sg.bottom(); // always <0 ++ ++ if ((moveByX || moveByY) && WebSettings::self()->windowMovePolicy(host) == KParts::HtmlSettingsInterface::JSWindowMoveAllow) ++ emit m_part->browserExtension()->moveTopLevelWidget(view()->x() + moveByX, view()->y() + moveByY); ++} ++ ++bool WebPage::checkLinkSecurity(const QNetworkRequest &req, NavigationType type) const ++{ ++ // Check whether the request is authorized or not... ++ if (!KUrlAuthorized::authorizeUrlAction(QStringLiteral("redirect"), url(), req.url())) { ++ ++ //kDebug() << "*** Failed security check: base-url=" << mainFrame()->url() << ", dest-url=" << req.url(); ++ QString buttonText, title, message; ++ ++ int response = KMessageBox::Cancel; ++ QUrl linkUrl (req.url()); ++ ++ if (type == QWebPage::NavigationTypeLinkClicked) { ++ message = i18n("<qt>This untrusted page links to<br/><b>%1</b>." ++ "<br/>Do you want to follow the link?</qt>", linkUrl.url()); ++ title = i18n("Security Warning"); ++ buttonText = i18nc("follow link despite of security warning", "Follow"); ++ } else { ++ title = i18n("Security Alert"); ++ message = i18n("<qt>Access by untrusted page to<br/><b>%1</b><br/> denied.</qt>", ++ linkUrl.toDisplayString().toHtmlEscaped()); ++ } ++ ++ if (buttonText.isEmpty()) { ++ KMessageBox::error( 0, message, title); ++ } else { ++ // Dangerous flag makes the Cancel button the default ++ response = KMessageBox::warningContinueCancel(0, message, title, ++ KGuiItem(buttonText), ++ KStandardGuiItem::cancel(), ++ QString(), // no don't ask again info ++ KMessageBox::Notify | KMessageBox::Dangerous); ++ } ++ ++ return (response == KMessageBox::Continue); ++ } ++ ++ return true; ++} ++ ++bool WebPage::checkFormData(const QNetworkRequest &req) const ++{ ++ const QString scheme (req.url().scheme()); ++ ++ if (m_sslInfo.isValid() && ++ !scheme.compare(QL1S("https")) && !scheme.compare(QL1S("mailto")) && ++ (KMessageBox::warningContinueCancel(0, ++ i18n("Warning: This is a secure form " ++ "but it is attempting to send " ++ "your data back unencrypted.\n" ++ "A third party may be able to " ++ "intercept and view this " ++ "information.\nAre you sure you " ++ "want to send the data unencrypted?"), ++ i18n("Network Transmission"), ++ KGuiItem(i18n("&Send Unencrypted"))) == KMessageBox::Cancel)) { ++ ++ return false; ++ } ++ ++ ++ if (scheme.compare(QL1S("mailto")) == 0 && ++ (KMessageBox::warningContinueCancel(0, i18n("This site is attempting to " ++ "submit form data via email.\n" ++ "Do you want to continue?"), ++ i18n("Network Transmission"), ++ KGuiItem(i18n("&Send Email")), ++ KStandardGuiItem::cancel(), ++ QStringLiteral("WarnTriedEmailSubmit")) == KMessageBox::Cancel)) { ++ return false; ++ } ++ ++ return true; ++} ++ ++// Sanitizes the "mailto:" url, e.g. strips out any "attach" parameters. ++static QUrl sanitizeMailToUrl(const QUrl &url, QStringList& files) { ++ QUrl sanitizedUrl; ++ ++ // NOTE: This is necessary to ensure we can properly use QUrl's query ++ // related APIs to process 'mailto:' urls of form 'mailto:foo@bar.com'. ++ if (url.hasQuery()) ++ sanitizedUrl = url; ++ else ++ sanitizedUrl = QUrl(url.scheme() + QL1S(":?") + url.path()); ++ ++ QUrlQuery query(sanitizedUrl); ++ const QList<QPair<QString, QString> > items (query.queryItems()); ++ ++ QUrlQuery sanitizedQuery; ++ for(auto queryItem : items) { ++ if (queryItem.first.contains(QL1C('@')) && queryItem.second.isEmpty()) { ++ // ### DF: this hack breaks mailto:faure@kde.org, kmail doesn't expect mailto:?to=faure@kde.org ++ queryItem.second = queryItem.first; ++ queryItem.first = QStringLiteral("to"); ++ } else if (QString::compare(queryItem.first, QL1S("attach"), Qt::CaseInsensitive) == 0) { ++ files << queryItem.second; ++ continue; ++ } ++ sanitizedQuery.addQueryItem(queryItem.first, queryItem.second); ++ } ++ ++ sanitizedUrl.setQuery(sanitizedQuery); ++ return sanitizedUrl; ++} ++ ++bool WebPage::handleMailToUrl (const QUrl &url, NavigationType type) const ++{ ++ if (QString::compare(url.scheme(), QL1S("mailto"), Qt::CaseInsensitive) == 0) { ++ QStringList files; ++ QUrl mailtoUrl (sanitizeMailToUrl(url, files)); ++ ++ switch (type) { ++ case QWebPage::NavigationTypeLinkClicked: ++ if (!files.isEmpty() && KMessageBox::warningContinueCancelList(0, ++ i18n("<qt>Do you want to allow this site to attach " ++ "the following files to the email message?</qt>"), ++ files, i18n("Email Attachment Confirmation"), ++ KGuiItem(i18n("&Allow attachments")), ++ KGuiItem(i18n("&Ignore attachments")), QL1S("WarnEmailAttachment")) == KMessageBox::Continue) { ++ ++ // Re-add the attachments... ++ QStringListIterator filesIt (files); ++ QUrlQuery query(mailtoUrl); ++ while (filesIt.hasNext()) { ++ query.addQueryItem(QL1S("attach"), filesIt.next()); ++ } ++ mailtoUrl.setQuery(query); ++ } ++ break; ++ case QWebPage::NavigationTypeFormSubmitted: ++ //case QWebPage::NavigationTypeFormResubmitted: ++ if (!files.isEmpty()) { ++ KMessageBox::information(0, i18n("This site attempted to attach a file from your " ++ "computer in the form submission. The attachment " ++ "was removed for your protection."), ++ i18n("Attachment Removed"), QStringLiteral("InfoTriedAttach")); ++ } ++ break; ++ default: ++ break; ++ } ++ ++ //kDebug() << "Emitting openUrlRequest with " << mailtoUrl; ++ emit m_part->browserExtension()->openUrlRequest(mailtoUrl); ++ return true; ++ } ++ ++ return false; ++} ++ ++void WebPage::setPageJScriptPolicy(const QUrl &url) ++{ ++ const QString hostname (url.host()); ++ settings()->setAttribute(QWebSettings::JavascriptEnabled, ++ WebSettings::self()->isJavaScriptEnabled(hostname)); ++ ++ const KParts::HtmlSettingsInterface::JSWindowOpenPolicy policy = WebSettings::self()->windowOpenPolicy(hostname); ++ settings()->setAttribute(QWebSettings::JavascriptCanOpenWindows, ++ (policy != KParts::HtmlSettingsInterface::JSWindowOpenDeny && ++ policy != KParts::HtmlSettingsInterface::JSWindowOpenSmart)); ++} ++ ++ ++ ++ ++ ++/************************************* Begin NewWindowPage ******************************************/ ++ ++NewWindowPage::NewWindowPage(WebWindowType type, WebPart* part, QWidget* parent) ++ :WebPage(part, parent) , m_type(type) , m_createNewWindow(true) ++{ ++ Q_ASSERT_X (part, "NewWindowPage", "Must specify a valid KPart"); ++ ++ connect(this, SIGNAL(menuBarVisibilityChangeRequested(bool)), ++ this, SLOT(slotMenuBarVisibilityChangeRequested(bool))); ++ connect(this, SIGNAL(toolBarVisibilityChangeRequested(bool)), ++ this, SLOT(slotToolBarVisibilityChangeRequested(bool))); ++ connect(this, SIGNAL(statusBarVisibilityChangeRequested(bool)), ++ this, SLOT(slotStatusBarVisibilityChangeRequested(bool))); ++ connect(this, SIGNAL(loadFinished(bool)), this, SLOT(slotLoadFinished(bool))); ++#if QTWEBKIT_VERSION >= QT_VERSION_CHECK(5, 602, 3) ++ if (m_type == WebBrowserBackgroundTab) { ++ m_windowArgs.setLowerWindow(true); ++ } ++#endif ++} ++ ++NewWindowPage::~NewWindowPage() ++{ ++} ++ ++static KParts::BrowserArguments browserArgs(WebPage::WebWindowType type) ++{ ++ KParts::BrowserArguments bargs; ++ switch (type) { ++ case WebPage::WebDialog: ++ case WebPage::WebBrowserWindow: ++ bargs.setForcesNewWindow(true); ++ break; ++ case WebPage::WebBrowserTab: ++#if QTWEBKIT_VERSION >= QT_VERSION_CHECK(5, 602, 3) ++ case WebPage::WebBrowserBackgroundTab: ++#endif ++ // let konq decide, based on user configuration ++ //bargs.setNewTab(true); ++ break; ++ } ++ return bargs; ++} ++ ++bool NewWindowPage::acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame) ++{ ++ //qDebug() << "url:" << url << ", type:" << type << ", isMainFrame:" << isMainFrame << "m_createNewWindow=" << m_createNewWindow; ++ if (m_createNewWindow) { ++ const QUrl reqUrl (url); ++ ++ const bool actionRequestedByUser = type != QWebPage::NavigationTypeOther; ++ ++ if (actionRequestedByUser) { ++ if (!part() && !isMainFrame) { ++ return false; ++ } ++ const KParts::HtmlSettingsInterface::JSWindowOpenPolicy policy = WebSettings::self()->windowOpenPolicy(reqUrl.host()); ++ switch (policy) { ++ case KParts::HtmlSettingsInterface::JSWindowOpenDeny: ++ // TODO: Implement support for dealing with blocked pop up windows. ++ this->deleteLater(); ++ return false; ++ case KParts::HtmlSettingsInterface::JSWindowOpenAsk: { ++ const QString message = (reqUrl.isEmpty() ? ++ i18n("This site is requesting to open a new popup window.\n" ++ "Do you want to allow this?") : ++ i18n("<qt>This site is requesting to open a popup window to" ++ "<p>%1</p><br/>Do you want to allow this?</qt>", ++ KStringHandler::rsqueeze(reqUrl.toDisplayString().toHtmlEscaped(), 100))); ++ if (KMessageBox::questionYesNo(view(), message, ++ i18n("Javascript Popup Confirmation"), ++ KGuiItem(i18n("Allow")), ++ KGuiItem(i18n("Do Not Allow"))) == KMessageBox::No) { ++ // TODO: Implement support for dealing with blocked pop up windows. ++ this->deleteLater(); ++ return false; ++ } ++ break; ++ } ++ default: ++ break; ++ } ++ } ++ ++ // Browser args... ++ KParts::BrowserArguments bargs = browserArgs(m_type); ++ ++ // OpenUrl args... ++ KParts::OpenUrlArguments uargs; ++ uargs.setMimeType(QL1S("text/html")); ++ uargs.setActionRequestedByUser(actionRequestedByUser); ++ ++ // Window args... ++ KParts::WindowArgs wargs (m_windowArgs); ++ ++ KParts::ReadOnlyPart* newWindowPart =0; ++ part()->browserExtension()->createNewWindow(QUrl(), uargs, bargs, wargs, &newWindowPart); ++ qDebug() << "Created new window" << newWindowPart; ++ ++ if (!newWindowPart) { ++ return false; ++ } else if (newWindowPart->widget()->topLevelWidget() != part()->widget()->topLevelWidget()) { ++ KParts::OpenUrlArguments args; ++ args.metaData().insert(QL1S("new-window"), QL1S("true")); ++ newWindowPart->setArguments(args); ++ } ++ ++ // Get the webview... ++ WebPart* webkitPart = qobject_cast<WebKitPart*>(newWindowPart); ++ WebView* webView = webkitPart ? qobject_cast<WebView*>(webkitPart->view()) : 0; ++ ++ // If the newly created window is NOT a webkitpart... ++ if (!webView) { ++ qDebug() << "Opening URL on" << newWindowPart; ++ newWindowPart->openUrl(reqUrl); ++ this->deleteLater(); ++ return false; ++ } ++ // Reparent this page to the new webview to prevent memory leaks. ++ setParent(webView); ++ // Replace the webpage of the new webview with this one. Nice trick... ++ webView->setPage(this); ++ // Set the new part as the one this page will use going forward. ++ setPart(webkitPart); ++ // Connect all the signals from this page to the slots in the new part. ++ webkitPart->connectWebPageSignals(this); ++ //Set the create new window flag to false... ++ m_createNewWindow = false; ++ } ++ ++ return WebPage::acceptNavigationRequest(url, type, isMainFrame); ++} ++ ++void NewWindowPage::slotGeometryChangeRequested(const QRect & rect) ++{ ++ if (!rect.isValid()) ++ return; ++ ++ if (!m_createNewWindow) { ++ WebPage::slotGeometryChangeRequested(rect); ++ return; ++ } ++ ++ m_windowArgs.setX(rect.x()); ++ m_windowArgs.setY(rect.y()); ++ m_windowArgs.setWidth(qMax(rect.width(), 100)); ++ m_windowArgs.setHeight(qMax(rect.height(), 100)); ++} ++ ++void NewWindowPage::slotMenuBarVisibilityChangeRequested(bool visible) ++{ ++ //kDebug() << visible; ++ m_windowArgs.setMenuBarVisible(visible); ++} ++ ++void NewWindowPage::slotStatusBarVisibilityChangeRequested(bool visible) ++{ ++ //kDebug() << visible; ++ m_windowArgs.setStatusBarVisible(visible); ++} ++ ++void NewWindowPage::slotToolBarVisibilityChangeRequested(bool visible) ++{ ++ //kDebug() << visible; ++ m_windowArgs.setToolBarsVisible(visible); ++} ++ ++// When is this called? (and acceptNavigationRequest is not called?) ++// The only case I found is Ctrl+click on link to data URL (like in konqviewmgrtest), that's quite specific... ++// Everything else seems to work with this method being commented out... ++void NewWindowPage::slotLoadFinished(bool ok) ++{ ++ Q_UNUSED(ok) ++ qDebug() << ok; ++ if (!m_createNewWindow) ++ return; ++ ++ const bool actionRequestedByUser = true; // ### we don't have the information here, unlike in acceptNavigationRequest ++ ++ // Browser args... ++ KParts::BrowserArguments bargs = browserArgs(m_type); ++ //bargs.frameName = mainFrame()->frameName(); ++ ++ // OpenUrl args... ++ KParts::OpenUrlArguments uargs; ++ uargs.setMimeType(QL1S("text/html")); ++ uargs.setActionRequestedByUser(actionRequestedByUser); ++ ++ // Window args... ++ KParts::WindowArgs wargs (m_windowArgs); ++ ++ KParts::ReadOnlyPart* newWindowPart =0; ++ part()->browserExtension()->createNewWindow(QUrl(), uargs, bargs, wargs, &newWindowPart); ++ ++ qDebug() << "Created new window or tab" << newWindowPart; ++ ++ // Get the webview... ++ WebKitPart* webkitPart = newWindowPart ? qobject_cast<WebKitPart*>(newWindowPart) : 0; ++ WebView* webView = webkitPart ? qobject_cast<WebView*>(webkitPart->view()) : 0; ++ ++ if (webView) { ++ // if a new window is created, set a new window meta-data flag. ++ if (newWindowPart->widget()->topLevelWidget() != part()->widget()->topLevelWidget()) { ++ KParts::OpenUrlArguments args; ++ args.metaData().insert(QL1S("new-window"), QL1S("true")); ++ newWindowPart->setArguments(args); ++ } ++ // Reparent this page to the new webview to prevent memory leaks. ++ setParent(webView); ++ // Replace the webpage of the new webview with this one. Nice trick... ++ webView->setPage(this); ++ // Set the new part as the one this page will use going forward. ++ setPart(webkitPart); ++ // Connect all the signals from this page to the slots in the new part. ++ webkitPart->connectWebPageSignals(this); ++ } ++ ++ //Set the create new window flag to false... ++ m_createNewWindow = false; ++} ++ ++/****************************** End NewWindowPage *************************************************/ ++ +diff --git b/webkitpart/src/webkitpage.h b/webkitpart/src/webkitpage.h +new file mode 100644 +index 000000000..489f32881 +--- /dev/null ++++ b/webkitpart/src/webkitpage.h +@@ -0,0 +1,162 @@ ++/* ++ * This file is part of the KDE project. ++ * ++ * Copyright (C) 2008 Dirk Mueller <mueller@kde.org> ++ * Copyright (C) 2008 Urs Wolfer <uwolfer @ kde.org> ++ * Copyright (C) 2009 Dawit Alemayehu <adawit@kde.org> ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Lesser General Public License as published by the ++ * Free Software Foundation; either version 2.1 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 Lesser General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library. If not, see <http://www.gnu.org/licenses/>. ++ * ++ */ ++ ++#ifndef WEBKITPAGE_H ++#define WEBKITPAGE_H ++ ++#include "websslinfo.h" ++ ++#include <KParts/BrowserExtension> ++#include <QtWebKitWidgets/QWebPage> ++ ++#include <QUrl> ++#include <QDebug> ++#include <QMultiHash> ++#include <QPointer> ++ ++class QUrl; ++class WebSslInfo; ++class WebKitPart; ++class QWebDownloadItem; ++ ++ ++class WebPage : public QWebPage ++{ ++ Q_OBJECT ++public: ++ explicit WebPage(WebKitPart *wpart, QWidget *parent = Q_NULLPTR); ++ ~WebPage(); ++ ++ /** ++ * Returns the SSL information for the current page. ++ * ++ * @see WebSslInfo. ++ */ ++ const WebSslInfo& sslInfo() const; ++ ++ /** ++ * Sets the page's SSL information to @p other. ++ * ++ * @see WebSslInfo ++ */ ++ void setSslInfo (const WebSslInfo &other); ++ ++ /** ++ * Reimplemented for internal reasons. The API is not affected. ++ * ++ * @internal ++ * @see KWebPage::downloadRequest. ++ */ ++ void downloadRequest(QWebDownloadItem* request); ++ ++Q_SIGNALS: ++ /** ++ * This signal is emitted whenever a user cancels/aborts a load resource ++ * request. ++ */ ++ void loadAborted(const QUrl &url); ++ ++protected: ++ /** ++ * Returns the webkit part in use by this object. ++ * @internal ++ */ ++ WebKitPart* part() const; ++ ++ /** ++ * Sets the webkit part to be used by this object. ++ * @internal ++ */ ++ void setPart(WebKitPart*); ++ ++ /** ++ * Reimplemented for internal reasons, the API is not affected. ++ * @internal ++ */ ++ QWebPage* createWindow(WebWindowType type) Q_DECL_OVERRIDE; ++ ++ /** ++ * Reimplemented for internal reasons, the API is not affected. ++ * @internal ++ */ ++ bool acceptNavigationRequest(const QUrl& request, NavigationType type, bool isMainFrame) Q_DECL_OVERRIDE; ++ ++protected Q_SLOTS: ++ void slotLoadFinished(bool ok); ++ void slotUnsupportedContent(QNetworkReply* reply); ++ virtual void slotGeometryChangeRequested(const QRect& rect); ++ void slotFeaturePermissionRequested(const QUrl& url, QWebPage::Feature feature); ++ ++private: ++ bool checkLinkSecurity(const QNetworkRequest& req, NavigationType type) const; ++ bool checkFormData(const QNetworkRequest& req) const; ++ bool handleMailToUrl (const QUrl& , NavigationType type) const; ++ void setPageJScriptPolicy(const QUrl& url); ++ ++private: ++ enum WebPageSecurity { PageUnencrypted, PageEncrypted, PageMixed }; ++ ++ int m_kioErrorCode; ++ bool m_ignoreError; ++ ++ WebSslInfo m_sslInfo; ++ QPointer<WebKitPart> m_part; ++}; ++ ++ ++/** ++ * This is a fake implementation of WebPage to workaround the ugly API used ++ * to request for the creation of a new window from javascript in QtWebKit. PORTING_TODO ++ * ++ * The KPart API for creating new windows requires all the information about the ++ * new window up front. Unfortunately QWebPage::createWindow function does not ++ * provide any of these necessary information except for the window type. All ++ * the other necessary information is emitted as signals instead! Hence, the ++ * need for this class to collect all of the necessary information, such as ++ * window name, size and position, before calling KPart's createNewWindow ++ * function. ++ */ ++class NewWindowPage : public WebPage ++{ ++ Q_OBJECT ++public: ++ NewWindowPage(WebWindowType windowType, WebKitPart* part, ++ QWidget* parent = Q_NULLPTR); ++ virtual ~NewWindowPage(); ++ ++protected: ++ bool acceptNavigationRequest(const QUrl& request, NavigationType type, bool isMainFrame) Q_DECL_OVERRIDE; ++ ++private Q_SLOTS: ++ void slotGeometryChangeRequested(const QRect& rect) override; ++ void slotMenuBarVisibilityChangeRequested(bool visible); ++ void slotStatusBarVisibilityChangeRequested(bool visible); ++ void slotToolBarVisibilityChangeRequested(bool visible); ++ void slotLoadFinished(bool); ++ ++private: ++ KParts::WindowArgs m_windowArgs; ++ WebWindowType m_type; ++ bool m_createNewWindow; ++}; ++ ++#endif // WEBPAGE_H +diff --git b/webkitpart/src/webkitpart.cpp b/webkitpart/src/webkitpart.cpp +new file mode 100644 +index 000000000..096475c63 +--- /dev/null ++++ b/webkitpart/src/webkitpart.cpp +@@ -0,0 +1,925 @@ ++/* ++ * This file is part of the KDE project. ++ * ++ * Copyright (C) 2007 Trolltech ASA ++ * Copyright (C) 2008 - 2010 Urs Wolfer <uwolfer @ kde.org> ++ * Copyright (C) 2008 Laurent Montel <montel@kde.org> ++ * Copyright (C) 2009 Dawit Alemayehu <adawit@kde.org> ++ * Copyright (C) 2013 Allan Sandfeld Jensen <sandfeld@kde.org> ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Lesser General Public License as published by the ++ * Free Software Foundation; either version 2.1 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 Lesser General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library. If not, see <http://www.gnu.org/licenses/>. ++ * ++ */ ++ ++#include "webkitpart.h" ++ ++//#include <QWebHistoryItem> ++#include <QWebSettings> ++#include <QUrlQuery> ++ ++#include "webkitpart_ext.h" ++#include "webkitview.h" ++#include "webkitpage.h" ++#include "websslinfo.h" ++#include "webhistoryinterface.h" ++ ++#include "ui/searchbar.h" ++#include "ui/passwordbar.h" ++#include "ui/featurepermissionbar.h" ++#include "settings/webkitsettings.h" ++ ++#include <kcodecaction.h> ++#include <kio/global.h> ++ ++#include <KActionCollection> ++#include <KAboutData> ++#include <KUrlLabel> ++#include <KMessageBox> ++#include <KStringHandler> ++#include <KToolInvocation> ++#include <KAcceleratorManager> ++#include <KFileItem> ++#include <KMessageWidget> ++#include <KProtocolInfo> ++#include <KToggleAction> ++#include <KParts/StatusBarExtension> ++#include <KParts/GUIActivateEvent> ++#include <KLocalizedString> ++#include <KConfigGroup> ++#include <KSharedConfig> ++#include <KSslInfoDialog> ++ ++#include <QUrl> ++#include <QFile> ++#include <QTextCodec> ++#include <QCoreApplication> ++#include <QVBoxLayout> ++#include <QDBusInterface> ++#include <QMenu> ++#include <QStatusBar> ++#include "utils.h" ++ ++WebKitPart::WebKitPart(QWidget *parentWidget, QObject *parent, ++ const QByteArray& cachedHistory, const QStringList& /*args*/) ++ :KParts::ReadOnlyPart(parent), ++ m_emitOpenUrlNotify(true), ++ m_hasCachedFormData(false), ++ m_doLoadFinishedActions(false), ++ m_statusBarWalletLabel(0), ++ m_searchBar(0), ++ m_passwordBar(0), ++ m_featurePermissionBar(0) ++{ ++ KAboutData about = KAboutData(QStringLiteral("webkitpart"), ++ i18nc("Program Name", "WebKitPart"), ++ /*version*/ QStringLiteral("1.3.0"), ++ i18nc("Short Description", "QtWebKit Browser Engine Component"), ++ KAboutLicense::LGPL, ++ i18n("(C) 2009-2010 Dawit Alemayehu\n" ++ "(C) 2008-2010 Urs Wolfer\n" ++ "(C) 2007 Trolltech ASA")); ++ ++ about.addAuthor(i18n("Sune Vuorela"), i18n("Maintainer, Developer"), QStringLiteral("sune@kde.org")); ++ about.addAuthor(i18n("Dawit Alemayehu"), i18n("Developer"), QStringLiteral("adawit@kde.org")); ++ about.addAuthor(i18n("Urs Wolfer"), i18n("Maintainer, Developer"), QStringLiteral("uwolfer@kde.org")); ++ about.addAuthor(i18n("Michael Howell"), i18n("Developer"), QStringLiteral("mhowell123@gmail.com")); ++ about.addAuthor(i18n("Laurent Montel"), i18n("Developer"), QStringLiteral("montel@kde.org")); ++ about.addAuthor(i18n("Dirk Mueller"), i18n("Developer"), QStringLiteral("mueller@kde.org")); ++ about.setProductName("webkitpart/general"); ++// KComponentData componentData(&about); ++ setComponentData(about, false /*don't load plugins yet*/); ++ ++#if 0 ++ // NOTE: If the application does not set its version number, we automatically ++ // set it to KDE's version number so that the default user-agent string contains ++ // proper application version number information. See QWebPage::userAgentForUrl... ++ if (QCoreApplication::applicationVersion().isEmpty()) ++ QCoreApplication::setApplicationVersion(QString("%1.%2.%3") ++ .arg(KDE::versionMajor()) ++ .arg(KDE::versionMinor()) ++ .arg(KDE::versionRelease())); ++#endif ++ setXMLFile(QL1S("webkitpart.rc")); ++ ++ // Create this KPart's widget ++ QWidget *mainWidget = new QWidget (parentWidget); ++ mainWidget->setObjectName(QStringLiteral("webkitpart")); ++ ++ // Create the WebView... ++ m_webView = new WebView (this, parentWidget); ++ ++ // Create the browser extension. ++ m_browserExtension = new WebBrowserExtension(this, cachedHistory); ++ ++ // Add status bar extension... ++ m_statusBarExtension = new KParts::StatusBarExtension(this); ++ ++ // Add a web history interface for storing visited links. ++// if (!QWebHistoryInterface::defaultInterface()) ++// QWebHistoryInterface::setDefaultInterface(new WebHistoryInterface(this)); ++ ++ // Add text and html extensions... ++ new WebTextExtension(this); ++ new WebHtmlExtension(this); ++ new WebScriptableExtension(this); ++ ++ ++ // Layout the GUI... ++ QVBoxLayout* l = new QVBoxLayout(mainWidget); ++ l->setContentsMargins(0, 0, 0, 0); ++ l->setSpacing(0); ++ l->addWidget(m_webView); ++ ++ // Set the part's widget ++ setWidget(mainWidget); ++ ++ // Set the web view as the the focus object ++ mainWidget->setFocusProxy(m_webView); ++ ++ // Connect the signals from the webview ++ connect(m_webView, &QWebView::titleChanged, ++ this, &Part::setWindowCaption); ++ connect(m_webView, &QWebView::urlChanged, ++ this, &WebKitPart::slotUrlChanged); ++// connect(m_webView, SIGNAL(linkMiddleOrCtrlClicked(QUrl)), ++// this, SLOT(slotLinkMiddleOrCtrlClicked(QUrl))); ++// connect(m_webView, SIGNAL(selectionClipboardUrlPasted(QUrl,QString)), ++// this, SLOT(slotSelectionClipboardUrlPasted(QUrl,QString))); ++ connect(m_webView, &QWebView::loadFinished, ++ this, &WebKitPart::slotLoadFinished); ++ ++ // Connect the signals from the page... ++ connectWebPageSignals(page()); ++ ++ // Init the QAction we are going to use... ++ initActions(); ++ ++ // Load plugins once we are fully ready ++ loadPlugins(); ++} ++ ++WebKitPart::~WebKitPart() ++{ ++} ++ ++WebPage* WebKitPart::page() ++{ ++ if (m_webView) ++ return qobject_cast<WebPage*>(m_webView->page()); ++ return Q_NULLPTR; ++} ++ ++const WebPage* WebKitPart::page() const ++{ ++ if (m_webView) ++ return qobject_cast<const WebPage*>(m_webView->page()); ++ return Q_NULLPTR; ++} ++ ++void WebKitPart::initActions() ++{ ++ actionCollection()->addAction(KStandardAction::SaveAs, QStringLiteral("saveDocument"), ++ m_browserExtension, SLOT(slotSaveDocument())); ++ ++ QAction* action = new QAction(i18n("Save &Frame As..."), this); ++ actionCollection()->addAction(QStringLiteral("saveFrame"), action); ++ connect(action, &QAction::triggered, m_browserExtension, &WebBrowserExtension::slotSaveFrame); ++ ++ action = new QAction(QIcon::fromTheme(QStringLiteral("document-print-preview")), i18n("Print Preview"), this); ++ actionCollection()->addAction(QStringLiteral("printPreview"), action); ++ connect(action, &QAction::triggered, m_browserExtension, &WebBrowserExtension::slotPrintPreview); ++ ++ action = new QAction(QIcon::fromTheme(QStringLiteral("zoom-in")), i18nc("zoom in action", "Zoom In"), this); ++ actionCollection()->addAction(QStringLiteral("zoomIn"), action); ++ actionCollection()->setDefaultShortcuts(action, QList<QKeySequence> () << QKeySequence(QStringLiteral("CTRL++")) << QKeySequence(QStringLiteral("CTRL+="))); ++ connect(action, &QAction::triggered, m_browserExtension, &WebBrowserExtension::zoomIn); ++ ++ action = new QAction(QIcon::fromTheme(QStringLiteral("zoom-out")), i18nc("zoom out action", "Zoom Out"), this); ++ actionCollection()->addAction(QStringLiteral("zoomOut"), action); ++ actionCollection()->setDefaultShortcuts(action, QList<QKeySequence> () << QKeySequence(QStringLiteral("CTRL+-")) << QKeySequence(QStringLiteral("CTRL+_"))); ++ connect(action, &QAction::triggered, m_browserExtension, &WebBrowserExtension::zoomOut); ++ ++ action = new QAction(QIcon::fromTheme(QStringLiteral("zoom-original")), i18nc("reset zoom action", "Actual Size"), this); ++ actionCollection()->addAction(QStringLiteral("zoomNormal"), action); ++ actionCollection()->setDefaultShortcut(action, QKeySequence(QStringLiteral("CTRL+0"))); ++ connect(action, &QAction::triggered, m_browserExtension, &WebBrowserExtension::zoomNormal); ++ ++ action = new QAction(i18n("Zoom Text Only"), this); ++ action->setCheckable(true); ++ KConfigGroup cgHtml(KSharedConfig::openConfig(), "HTML Settings"); ++ bool zoomTextOnly = cgHtml.readEntry("ZoomTextOnly", false); ++ action->setChecked(zoomTextOnly); ++ actionCollection()->addAction(QStringLiteral("zoomTextOnly"), action); ++ connect(action, &QAction::triggered, m_browserExtension, &WebBrowserExtension::toogleZoomTextOnly); ++ ++ action = new QAction(i18n("Zoom To DPI"), this); ++ action->setCheckable(true); ++ bool zoomToDPI = cgHtml.readEntry("ZoomToDPI", false); ++ action->setChecked(zoomToDPI); ++ actionCollection()->addAction(QStringLiteral("zoomToDPI"), action); ++ connect(action, &QAction::triggered, m_browserExtension, &WebBrowserExtension::toogleZoomToDPI); ++ ++ action = actionCollection()->addAction(KStandardAction::SelectAll, QStringLiteral("selectAll"), ++ m_browserExtension, SLOT(slotSelectAll())); ++ action->setShortcutContext(Qt::WidgetShortcut); ++ m_webView->addAction(action); ++ ++ KCodecAction *codecAction = new KCodecAction( QIcon::fromTheme(QStringLiteral("character-set")), i18n( "Set &Encoding" ), this, true ); ++ actionCollection()->addAction( QStringLiteral("setEncoding"), codecAction ); ++ connect(codecAction, SIGNAL(triggered(QTextCodec*)), SLOT(slotSetTextEncoding(QTextCodec*))); ++ ++ action = new QAction(i18n("View Do&cument Source"), this); ++ actionCollection()->addAction(QStringLiteral("viewDocumentSource"), action); ++ actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_U)); ++ connect(action, &QAction::triggered, m_browserExtension, &WebBrowserExtension::slotViewDocumentSource); ++ ++ action = new QAction(i18nc("Secure Sockets Layer", "SSL"), this); ++ actionCollection()->addAction(QStringLiteral("security"), action); ++ connect(action, &QAction::triggered, this, &WebKitPart::slotShowSecurity); ++ ++ action = actionCollection()->addAction(KStandardAction::Find, QStringLiteral("find"), this, SLOT(slotShowSearchBar())); ++ action->setWhatsThis(i18nc("find action \"whats this\" text", "<h3>Find text</h3>" ++ "Shows a dialog that allows you to find text on the displayed page.")); ++} ++ ++void WebKitPart::updateActions() ++{ ++ m_browserExtension->updateActions(); ++ ++ QAction* action = actionCollection()->action(QL1S("saveDocument")); ++ if (action) { ++ const QString protocol (url().scheme()); ++ action->setEnabled(protocol != QL1S("about") && protocol != QL1S("error")); ++ } ++ ++ action = actionCollection()->action(QL1S("printPreview")); ++ if (action) { ++ action->setEnabled(m_browserExtension->isActionEnabled("print")); ++ } ++ ++} ++ ++void WebKitPart::connectWebPageSignals(WebPage* page) ++{ ++ if (!page) ++ return; ++ ++ connect(page, SIGNAL(loadStarted()), ++ this, SLOT(slotLoadStarted())); ++ connect(page, SIGNAL(loadAborted(QUrl)), ++ this, SLOT(slotLoadAborted(QUrl))); ++ connect(page, &QWebPage::linkHovered, ++ this, &WebKitPart::slotLinkHovered); ++// connect(page, SIGNAL(saveFrameStateRequested(QWebFrame*,QWebHistoryItem*)), ++// this, SLOT(slotSaveFrameState(QWebFrame*,QWebHistoryItem*))); ++// connect(page, SIGNAL(restoreFrameStateRequested(QWebFrame*)), ++// this, SLOT(slotRestoreFrameState(QWebFrame*))); ++// connect(page, SIGNAL(statusBarMessage(QString)), ++// this, SLOT(slotSetStatusBarText(QString))); ++ connect(page, SIGNAL(windowCloseRequested()), ++ this, SLOT(slotWindowCloseRequested())); ++// connect(page, SIGNAL(printRequested(QWebFrame*)), ++// m_browserExtension, SLOT(slotPrintRequested(QWebFrame*))); ++ // connect(page, SIGNAL(frameCreated(QWebFrame*)), ++ // this, SLOT(slotFrameCreated(QWebFrame*))); ++ ++// connect(m_webView, SIGNAL(linkShiftClicked(QUrl)), ++// page, SLOT(downloadUrl(QUrl))); ++ ++ connect(page, SIGNAL(loadProgress(int)), ++ m_browserExtension, SIGNAL(loadingProgress(int))); ++ connect(page, SIGNAL(selectionChanged()), ++ m_browserExtension, SLOT(updateEditActions())); ++// connect(m_browserExtension, SIGNAL(saveUrl(QUrl)), ++// page, SLOT(downloadUrl(QUrl))); ++ ++ connect(page, &QWebPage::iconUrlChanged, [page, this](const QUrl& url) { ++ if (WebSettings::self()->favIconsEnabled() ++ && !page->profile()->isOffTheRecord()){ ++ m_browserExtension->setIconUrl(url); ++ } ++ }); ++ ++#if 0 ++ KWebWallet *wallet = page->wallet(); ++ if (wallet) { ++ connect(wallet, SIGNAL(saveFormDataRequested(QString,QUrl)), ++ this, SLOT(slotSaveFormDataRequested(QString,QUrl))); ++ connect(wallet, SIGNAL(fillFormRequestCompleted(bool)), ++ this, SLOT(slotFillFormRequestCompleted(bool))); ++ connect(wallet, SIGNAL(walletClosed()), this, SLOT(slotWalletClosed())); ++ } ++#endif ++} ++ ++bool WebKitPart::openUrl(const QUrl &_u) ++{ ++ QUrl u (_u); ++ ++ qDebug() << u; ++ ++ // Ignore empty requests... ++ if (u.isEmpty()) ++ return false; ++ ++ // If the URL given is a supported local protocol, e.g. "bookmark" but lacks ++ // a path component, we set the path to "/" here so that the security context ++ // will properly allow access to local resources. ++ if (u.host().isEmpty() && u.path().isEmpty() ++ && KProtocolInfo::protocolClass(u.scheme()) == QL1S(":local")) { ++ u.setPath(QL1S("/")); ++ } ++ ++ // Do not emit update history when url is typed in since the host ++ // should handle that automatically itself. ++ m_emitOpenUrlNotify = false; ++ ++ // Pointer to the page object... ++ WebPage* p = page(); ++ Q_ASSERT(p); ++ ++ KParts::BrowserArguments bargs (m_browserExtension->browserArguments()); ++ KParts::OpenUrlArguments args (arguments()); ++ ++ if (!Utils::isBlankUrl(u)) { ++ // Get the SSL information sent, if any... ++ if (args.metaData().contains(QL1S("ssl_in_use"))) { ++ WebSslInfo sslInfo; ++ sslInfo.restoreFrom(KIO::MetaData(args.metaData()).toVariant()); ++ sslInfo.setUrl(u); ++ p->setSslInfo(sslInfo); ++ } ++ } ++ ++ // Set URL in KParts before emitting started; konq plugins rely on that. ++ setUrl(u); ++ m_doLoadFinishedActions = true; ++ m_webView->loadUrl(u, args, bargs); ++ return true; ++} ++ ++bool WebKitPart::closeUrl() ++{ ++ m_webView->triggerPageAction(QWebPage::Stop); ++ m_webView->stop(); ++ return true; ++} ++ ++QWebView* WebKitPart::view() ++{ ++ return m_webView; ++} ++ ++bool WebKitPart::isModified() const ++{ ++ //return m_webView->isModified(); ++ return false; ++} ++ ++void WebKitPart::guiActivateEvent(KParts::GUIActivateEvent *event) ++{ ++ if (event && event->activated() && m_webView) { ++ emit setWindowCaption(m_webView->title()); ++ } ++} ++ ++bool WebKitPart::openFile() ++{ ++ // never reached ++ return false; ++} ++ ++ ++/// slots... ++ ++void WebKitPart::slotLoadStarted() ++{ ++ if(!Utils::isBlankUrl(url())) ++ { ++ emit started(0); ++ } ++ updateActions(); ++ ++ // If "NoEmitOpenUrlNotification" property is set to true, do not ++ // emit the open url notification. Property is set by this part's ++ // extension to prevent openUrl notification being sent when ++ // handling history navigation requests (back/forward). ++ const bool doNotEmitOpenUrl = property("NoEmitOpenUrlNotification").toBool(); ++ if (doNotEmitOpenUrl) { ++ setProperty("NoEmitOpenUrlNotification", QVariant()); ++ } else { ++ if (m_emitOpenUrlNotify) { ++ emit m_browserExtension->openUrlNotify(); ++ } ++ } ++ // Unless we go via openUrl again, the next time we are here we emit (e.g. after clicking on a link) ++ m_emitOpenUrlNotify = true; ++} ++ ++void WebKitPart::slotLoadFinished (bool ok) ++{ ++ if (!ok || !m_doLoadFinishedActions) ++ return; ++ ++ slotWalletClosed(); ++ m_doLoadFinishedActions = false; ++ ++ // If the document contains no <title> tag, then set it to the current url. ++ if (m_webView->title().trimmed().isEmpty()) { ++ // If the document title is empty, then set it to the current url ++ const QUrl url (m_webView->url()); ++ const QString caption (url.toString((QUrl::RemoveQuery|QUrl::RemoveFragment))); ++ emit setWindowCaption(caption); ++ ++ // The urlChanged signal is emitted if and only if the main frame ++ // receives the title of the page so we manually invoke the slot as a ++ // work around here for pages that do not contain it, such as text ++ // documents... ++ slotUrlChanged(url); ++ } ++ if (!Utils::isBlankUrl(url())) { ++ m_hasCachedFormData = false; ++ ++ if (WebSettings::self()->isNonPasswordStorableSite(url().host())) { ++ addWalletStatusBarIcon(); ++ } else { ++// Attempt to fill the web form... ++// KWebWallet *webWallet = page() ? page()->wallet() : 0; ++// if (webWallet) { ++// webWallet->fillFormData(frame, false); ++// } ++ } ++ } ++ ++ bool pending = false; ++ // QWebFrame* frame = (page() ? page()->currentFrame() : 0); ++ // if (ok && ++ // frame == page()->mainFrame() && ++ // !frame->findFirstElement(QL1S("head>meta[http-equiv=refresh]")).isNull()) { ++ // if (WebSettings::self()->autoPageRefresh()) { ++ // pending = true; ++ // } else { ++ // frame->page()->triggerAction(QWebPage::Stop); ++ // } ++ // } ++ emit completed ((ok && pending)); ++ ++ updateActions(); ++} ++ ++void WebKitPart::slotLoadAborted(const QUrl & url) ++{ ++ closeUrl(); ++ m_doLoadFinishedActions = false; ++ if (url.isValid()) ++ emit m_browserExtension->openUrlRequest(url); ++ else ++ setUrl(m_webView->url()); ++} ++ ++void WebKitPart::slotUrlChanged(const QUrl& url) ++{ ++ // Ignore if empty ++ if (url.isEmpty()) ++ return; ++ ++ // Ignore if error url ++ if (url.scheme() == QL1S("error")) ++ return; ++ ++ const QUrl u (url); ++ ++ // Ignore if url has not changed! ++ if (this->url() == u) ++ return; ++ ++ m_doLoadFinishedActions = true; ++ setUrl(u); ++ ++ // Do not update the location bar with about:blank ++ if (!Utils::isBlankUrl(url)) { ++ //kDebug() << "Setting location bar to" << u.prettyUrl() << "current URL:" << this->url(); ++ emit m_browserExtension->setLocationBarUrl(u.toDisplayString()); ++ } ++} ++ ++void WebKitPart::slotShowSecurity() ++{ ++ if (!page()) ++ return; ++ ++ const WebSslInfo& sslInfo = page()->sslInfo(); ++ if (!sslInfo.isValid()) { ++ KMessageBox::information(0, i18n("The SSL information for this site " ++ "appears to be corrupt."), ++ i18nc("Secure Sockets Layer", "SSL")); ++ return; ++ } ++ ++ KSslInfoDialog *dlg = new KSslInfoDialog (widget()); ++ dlg->setSslInfo(sslInfo.certificateChain(), ++ sslInfo.peerAddress().toString(), ++ url().host(), ++ sslInfo.protocol(), ++ sslInfo.ciphers(), ++ sslInfo.usedChiperBits(), ++ sslInfo.supportedChiperBits(), ++ KSslInfoDialog::errorsFromString(sslInfo.certificateErrors())); ++ ++ dlg->open(); ++} ++ ++#if 0 ++void WebKitPart::slotSaveFrameState(QWebFrame *frame, QWebHistoryItem *item) ++{ ++ if (!frame || !item) { ++ return; ++ } ++ ++ // Handle actions that apply only to the mainframe... ++ if (frame == view()->page()->mainFrame()) { ++ } ++ ++ // For some reason, QtWebKit PORTING_TODO does not restore scroll position when ++ // QWebHistory is restored from persistent storage. Therefore, we ++ // preserve that information and restore it as needed. See ++ // slotRestoreFrameState. ++ const QPoint scrollPos (frame->scrollPosition()); ++ if (!scrollPos.isNull()) { ++ // kDebug() << "Saving scroll position:" << scrollPos; ++ item->setUserData(scrollPos); ++ } ++} ++#endif ++ ++#if 0 ++void WebKitPart::slotRestoreFrameState(QWebFrame *frame) ++{ ++ QWebPage* page = (frame ? frame->page() : 0); ++ QWebHistory* history = (page ? page->history() : 0); ++ ++ // No history item... ++ if (!history || history->count() < 1) ++ return; ++ ++ QWebHistoryItem currentHistoryItem (history->currentItem()); ++ ++ // Update the scroll position if needed. See comment in slotSaveFrameState above. ++ if (frame->baseUrl().resolved(frame->url()) == currentHistoryItem.url()) { ++ const QPoint currentPos (frame->scrollPosition()); ++ const QPoint desiredPos (currentHistoryItem.userData().toPoint()); ++ if (currentPos.isNull() && !desiredPos.isNull()) { ++ frame->setScrollPosition(desiredPos); ++ } ++ } ++} ++#endif ++ ++void WebKitPart::slotLinkHovered(const QString& _link) ++{ ++ QString message; ++ ++ if (_link.isEmpty()) { ++ message = QL1S(""); ++ emit m_browserExtension->mouseOverInfo(KFileItem()); ++ } else { ++ QUrl linkUrl (_link); ++ const QString scheme = linkUrl.scheme(); ++ ++ // Protect the user against URL spoofing! ++ linkUrl.setUserName(QString()); ++ const QString link (linkUrl.toString()); ++ ++ if (QString::compare(scheme, QL1S("mailto"), Qt::CaseInsensitive) == 0) { ++ message += i18nc("status bar text when hovering email links; looks like \"Email: xy@kde.org - CC: z@kde.org -BCC: x@kde.org - Subject: Hi translator\"", "Email: "); ++ ++ // Workaround: for QUrl's parsing deficiencies of "mailto:foo@bar.com". ++ if (!linkUrl.hasQuery()) ++ linkUrl = QUrl(scheme + '?' + linkUrl.path()); ++ ++ QMap<QString, QStringList> fields; ++ QUrlQuery query(linkUrl); ++ QList<QPair<QString, QString> > queryItems = query.queryItems(); ++ const int count = queryItems.count(); ++ ++ for(int i = 0; i < count; ++i) { ++ const QPair<QString, QString> queryItem (queryItems.at(i)); ++ //kDebug() << "query: " << queryItem.first << queryItem.second; ++ if (queryItem.first.contains(QL1C('@')) && queryItem.second.isEmpty()) ++ fields[QStringLiteral("to")] << queryItem.first; ++ if (QString::compare(queryItem.first, QL1S("to"), Qt::CaseInsensitive) == 0) ++ fields[QStringLiteral("to")] << queryItem.second; ++ if (QString::compare(queryItem.first, QL1S("cc"), Qt::CaseInsensitive) == 0) ++ fields[QStringLiteral("cc")] << queryItem.second; ++ if (QString::compare(queryItem.first, QL1S("bcc"), Qt::CaseInsensitive) == 0) ++ fields[QStringLiteral("bcc")] << queryItem.second; ++ if (QString::compare(queryItem.first, QL1S("subject"), Qt::CaseInsensitive) == 0) ++ fields[QStringLiteral("subject")] << queryItem.second; ++ } ++ ++ if (fields.contains(QL1S("to"))) ++ message += fields.value(QL1S("to")).join(QL1S(", ")); ++ if (fields.contains(QL1S("cc"))) ++ message += i18nc("status bar text when hovering email links; looks like \"Email: xy@kde.org - CC: z@kde.org -BCC: x@kde.org - Subject: Hi translator\"", " - CC: ") + fields.value(QL1S("cc")).join(QL1S(", ")); ++ if (fields.contains(QL1S("bcc"))) ++ message += i18nc("status bar text when hovering email links; looks like \"Email: xy@kde.org - CC: z@kde.org -BCC: x@kde.org - Subject: Hi translator\"", " - BCC: ") + fields.value(QL1S("bcc")).join(QL1S(", ")); ++ if (fields.contains(QL1S("subject"))) ++ message += i18nc("status bar text when hovering email links; looks like \"Email: xy@kde.org - CC: z@kde.org -BCC: x@kde.org - Subject: Hi translator\"", " - Subject: ") + fields.value(QL1S("subject")).join(QL1S(" ")); ++ } else if (scheme == QL1S("javascript")) { ++ message = KStringHandler::rsqueeze(link, 150); ++ if (link.startsWith(QL1S("javascript:window.open"))) ++ message += i18n(" (In new window)"); ++ } else { ++ message = link; ++#if 0 ++ QWebFrame* frame = page() ? page()->currentFrame() : 0; ++ if (frame) { ++ QWebHitTestResult result = frame->hitTestContent(page()->view()->mapFromGlobal(QCursor::pos())); ++ QWebFrame* target = result.linkTargetFrame(); ++ if (frame->parentFrame() && target == frame->parentFrame()) { ++ message += i18n(" (In parent frame)"); ++ } else if (!target || target != frame) { ++ message += i18n(" (In new window)"); ++ } ++ } ++#endif ++ KFileItem item (linkUrl, QString(), KFileItem::Unknown); ++ emit m_browserExtension->mouseOverInfo(item); ++ } ++ } ++ ++ emit setStatusBarText(message); ++} ++ ++void WebKitPart::slotSearchForText(const QString &text, bool backward) ++{ ++ QWebPage::FindFlags flags; // = QWebPage::FindWrapsAroundDocument; ++ ++ if (backward) ++ flags |= QWebPage::FindBackward; ++ ++ if (m_searchBar->caseSensitive()) ++ flags |= QWebPage::FindCaseSensitively; ++ ++ //kDebug() << "search for text:" << text << ", backward ?" << backward; ++ page()->findText(text, flags, [this](bool found) { ++ m_searchBar->setFoundMatch(found); ++ }); ++} ++ ++void WebKitPart::slotShowSearchBar() ++{ ++ if (!m_searchBar) { ++ // Create the search bar... ++ m_searchBar = new SearchBar(widget()); ++ connect(m_searchBar, SIGNAL(searchTextChanged(QString,bool)), ++ this, SLOT(slotSearchForText(QString,bool))); ++ ++ actionCollection()->addAction(KStandardAction::FindNext, QStringLiteral("findnext"), ++ m_searchBar, SLOT(findNext())); ++ actionCollection()->addAction(KStandardAction::FindPrev, QStringLiteral("findprev"), ++ m_searchBar, SLOT(findPrevious())); ++ ++ QBoxLayout* lay = qobject_cast<QBoxLayout*>(widget()->layout()); ++ if (lay) { ++ lay->addWidget(m_searchBar); ++ } ++ } ++ const QString text = m_webView->selectedText(); ++ m_searchBar->setSearchText(text.left(150)); ++} ++ ++void WebKitPart::slotLinkMiddleOrCtrlClicked(const QUrl& linkUrl) ++{ ++ emit m_browserExtension->createNewWindow(linkUrl); ++} ++ ++void WebKitPart::slotSelectionClipboardUrlPasted(const QUrl& selectedUrl, const QString& searchText) ++{ ++ if (!WebSettings::self()->isOpenMiddleClickEnabled()) ++ return; ++ ++ if (!searchText.isEmpty() && ++ KMessageBox::questionYesNo(m_webView, ++ i18n("<qt>Do you want to search for <b>%1</b>?</qt>", searchText), ++ i18n("Internet Search"), KGuiItem(i18n("&Search"), QStringLiteral("edit-find")), ++ KStandardGuiItem::cancel(), QStringLiteral("MiddleClickSearch")) != KMessageBox::Yes) ++ return; ++ ++ emit m_browserExtension->openUrlRequest(selectedUrl); ++} ++ ++void WebKitPart::slotWalletClosed() ++{ ++ if (!m_statusBarWalletLabel) ++ return; ++ ++ m_statusBarExtension->removeStatusBarItem(m_statusBarWalletLabel); ++ delete m_statusBarWalletLabel; ++ m_statusBarWalletLabel = 0; ++ m_hasCachedFormData = false; ++} ++ ++void WebKitPart::slotShowWalletMenu() ++{ ++ QMenu *menu = new QMenu(0); ++ ++ if (m_webView && WebSettings::self()->isNonPasswordStorableSite(m_webView->url().host())) ++ menu->addAction(i18n("&Allow password caching for this site"), this, SLOT(slotDeleteNonPasswordStorableSite())); ++ ++ if (m_hasCachedFormData) ++ menu->addAction(i18n("Remove all cached passwords for this site"), this, SLOT(slotRemoveCachedPasswords())); ++ ++ menu->addSeparator(); ++ menu->addAction(i18n("&Close Wallet"), this, SLOT(slotWalletClosed())); ++ ++ KAcceleratorManager::manage(menu); ++ menu->popup(QCursor::pos()); ++} ++ ++void WebKitPart::slotLaunchWalletManager() ++{ ++ QDBusInterface r(QStringLiteral("org.kde.kwalletmanager"), QStringLiteral("/kwalletmanager/MainWindow_1")); ++ if (r.isValid()) ++ r.call(QDBus::NoBlock, QStringLiteral("show")); ++ else ++ KToolInvocation::startServiceByDesktopName(QStringLiteral("kwalletmanager_show")); ++} ++ ++void WebKitPart::slotDeleteNonPasswordStorableSite() ++{ ++ if (m_webView) ++ WebSettings::self()->removeNonPasswordStorableSite(m_webView->url().host()); ++} ++ ++void WebKitPart::slotRemoveCachedPasswords() ++{ ++ if (!page()) // || !page()->wallet()) ++ return; ++ ++// page()->wallet()->removeFormData(page()->mainFrame(), true); ++ m_hasCachedFormData = false; ++} ++ ++void WebKitPart::slotSetTextEncoding(QTextCodec * codec) ++{ ++ // FIXME: The code below that sets the text encoding has been reported not to work. ++ if (!page()) ++ return; ++ ++ QWebSettings *localSettings = page()->settings(); ++ if (!localSettings) ++ return; ++ ++ qDebug() << "Encoding: new=>" << localSettings->defaultTextEncoding() << ", old=>" << codec->name(); ++ ++ localSettings->setDefaultTextEncoding(codec->name()); ++ page()->triggerAction(QWebPage::Reload); ++} ++ ++void WebKitPart::slotSetStatusBarText(const QString& text) ++{ ++ const QString host (page() ? page()->url().host() : QString()); ++ if (WebSettings::self()->windowStatusPolicy(host) == KParts::HtmlSettingsInterface::JSWindowStatusAllow) ++ emit setStatusBarText(text); ++} ++ ++void WebKitPart::slotWindowCloseRequested() ++{ ++ emit m_browserExtension->requestFocus(this); ++#if 0 ++ if (KMessageBox::questionYesNo(m_webView, ++ i18n("Close window?"), i18n("Confirmation Required"), ++ KStandardGuiItem::close(), KStandardGuiItem::cancel()) ++ != KMessageBox::Yes) ++ return; ++#endif ++ this->deleteLater(); ++} ++ ++void WebKitPart::slotShowFeaturePermissionBar(QWebPage::Feature feature) ++{ ++ // FIXME: Allow multiple concurrent feature permission requests. ++ if (m_featurePermissionBar && m_featurePermissionBar->isVisible()) ++ return; ++ ++ if (!m_featurePermissionBar) { ++ m_featurePermissionBar = new FeaturePermissionBar(widget()); ++ ++ connect(m_featurePermissionBar, SIGNAL(permissionGranted(QWebPage::Feature)), ++ this, SLOT(slotFeaturePermissionGranted(QWebPage::Feature))); ++ connect(m_featurePermissionBar, SIGNAL(permissionDenied(QWebPage::Feature)), ++ this, SLOT(slotFeaturePermissionDenied(QWebPage::Feature))); ++// connect(m_passwordBar, SIGNAL(done()), ++// this, SLOT(slotSaveFormDataDone())); ++ QBoxLayout* lay = qobject_cast<QBoxLayout*>(widget()->layout()); ++ if (lay) ++ lay->insertWidget(0, m_featurePermissionBar); ++ } ++ m_featurePermissionBar->setFeature(feature); ++// m_featurePermissionBar->setText(i18n("<html>Do you want to grant the site <b>%1</b> " ++// "access to information about your current physical location?", ++// url.host())); ++ m_featurePermissionBar->setText(i18n("<html>Do you want to grant the site " ++ "access to information about your current physical location?")); ++ m_featurePermissionBar->animatedShow(); ++} ++ ++void WebKitPart::slotFeaturePermissionGranted(QWebPage::Feature feature) ++{ ++ Q_ASSERT(m_featurePermissionBar && m_featurePermissionBar->feature() == feature); ++ page()->setFeaturePermission(page()->url(), feature, QWebPage::PermissionGrantedByUser); ++} ++ ++void WebKitPart::slotFeaturePermissionDenied(QWebPage::Feature feature) ++{ ++ Q_ASSERT(m_featurePermissionBar && m_featurePermissionBar->feature() == feature); ++ page()->setFeaturePermission(page()->url(), feature, QWebPage::PermissionDeniedByUser); ++} ++ ++void WebKitPart::slotSaveFormDataRequested (const QString& key, const QUrl& url) ++{ ++ if (WebSettings::self()->isNonPasswordStorableSite(url.host())) ++ return; ++ ++ if (!WebSettings::self()->askToSaveSitePassword()) ++ return; ++ ++ if (m_passwordBar && m_passwordBar->isVisible()) ++ return; ++ ++ if (!m_passwordBar) { ++ m_passwordBar = new PasswordBar(widget()); ++#if 0 ++ KWebWallet* wallet = page()->wallet(); ++ if (!wallet) { ++ kWarning() << "No wallet instance found! This should never happen!"; ++ return; ++ } ++ connect(m_passwordBar, SIGNAL(saveFormDataAccepted(QString)), ++ wallet, SLOT(acceptSaveFormDataRequest(QString))); ++ connect(m_passwordBar, SIGNAL(saveFormDataRejected(QString)), ++ wallet, SLOT(rejectSaveFormDataRequest(QString))); ++ connect(m_passwordBar, SIGNAL(done()), ++ this, SLOT(slotSaveFormDataDone())); ++#endif ++ } ++ ++ Q_ASSERT(m_passwordBar); ++ ++ m_passwordBar->setUrl(url); ++ m_passwordBar->setRequestKey(key); ++ m_passwordBar->setText(i18n("<html>Do you want %1 to remember the login " ++ "information for <b>%2</b>?</html>", ++ QCoreApplication::applicationName(), ++ url.host())); ++ ++ QBoxLayout* lay = qobject_cast<QBoxLayout*>(widget()->layout()); ++ if (lay) ++ lay->insertWidget(0, m_passwordBar); ++ ++ m_passwordBar->animatedShow(); ++} ++ ++void WebKitPart::slotSaveFormDataDone() ++{ ++ if (!m_passwordBar) ++ return; ++ ++ QBoxLayout* lay = qobject_cast<QBoxLayout*>(widget()->layout()); ++ if (lay) ++ lay->removeWidget(m_passwordBar); ++} ++ ++void WebKitPart::addWalletStatusBarIcon () ++{ ++ if (m_statusBarWalletLabel) { ++ m_statusBarExtension->removeStatusBarItem(m_statusBarWalletLabel); ++ } else { ++ m_statusBarWalletLabel = new KUrlLabel(m_statusBarExtension->statusBar()); ++ m_statusBarWalletLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum)); ++ m_statusBarWalletLabel->setUseCursor(false); ++ m_statusBarWalletLabel->setPixmap(QIcon::fromTheme(QStringLiteral("wallet-open")).pixmap(QSize(16,16))); ++ connect(m_statusBarWalletLabel, SIGNAL(leftClickedUrl()), SLOT(slotLaunchWalletManager())); ++ connect(m_statusBarWalletLabel, SIGNAL(rightClickedUrl()), SLOT(slotShowWalletMenu())); ++ } ++ m_statusBarExtension->addStatusBarItem(m_statusBarWalletLabel, 0, false); ++} ++ ++void WebKitPart::slotFillFormRequestCompleted (bool ok) ++{ ++ if ((m_hasCachedFormData = ok)) ++ addWalletStatusBarIcon(); ++} ++ +diff --git b/webkitpart/src/webkitpart.desktop b/webkitpart/src/webkitpart.desktop +new file mode 100644 +index 000000000..fb77cfc8e +--- /dev/null ++++ b/webkitpart/src/webkitpart.desktop +@@ -0,0 +1,65 @@ ++[Desktop Entry] ++Type=Service ++Comment=Embeddable HTML component ++Comment[ca]=Component HTML incrustable ++Comment[ca@valencia]=Component HTML incrustable ++Comment[cs]=Zapouzdřitelná HTML komponenta ++Comment[da]=HTML-komponent som kan indlejres ++Comment[de]=Einbettungsfähige HTML-Komponente ++Comment[en_GB]=Embeddable HTML component ++Comment[es]=Componente HTML empotrable ++Comment[et]=Põimitav HTML-komponent ++Comment[fi]=Upotettava HTML-osa ++Comment[it]=Componente HTML incorporabile ++Comment[ko]=끼워넣을 수 있는 HTML 구성 요소 ++Comment[nb]=Innebyggbar HTML-komponent ++Comment[nl]=In te bedden HTML-component ++Comment[nn]=Innebyggbar HTML-komponent ++Comment[pl]=Osadzalny składnik HTML ++Comment[pt]=Componente incorporada de HTML ++Comment[pt_BR]=Componete HTML embutido ++Comment[sk]=Vložiteľný HTML komponent ++Comment[sl]=Vgradljiv sestavni del HTML ++Comment[sr]=Угнездива ХТМЛ компонента ++Comment[sr@ijekavian]=Угњездива ХТМЛ компонента ++Comment[sr@ijekavianlatin]=Ugnjezdiva HTML komponenta ++Comment[sr@latin]=Ugnezdiva HTML komponenta ++Comment[sv]=Inbäddningsbar HTML-komponent ++Comment[uk]=Придатний до вбудовування компонент HTML ++Comment[x-test]=xxEmbeddable HTML componentxx ++Comment[zh_CN]=可嵌入的 HTML 组件 ++Comment[zh_TW]=可內嵌的 HTML 元件 ++Icon=webkit ++MimeType=text/html;application/xml;application/xhtml+xml; ++Name=WebKit ++Name[ca]=WebKit ++Name[ca@valencia]=WebKit ++Name[cs]=WebKit ++Name[da]=WebKit ++Name[de]=WebKit ++Name[en_GB]=WebKit ++Name[es]=Motor Web ++Name[et]=WebKit ++Name[fi]=WebKit ++Name[it]=WebKit ++Name[ko]=WebKit ++Name[nl]=WebKit ++Name[nn]=Vevmotor ++Name[pl]=SilnikSieciowy ++Name[pt]=Motor Web ++Name[pt_BR]=WebKit ++Name[sk]=WebKit ++Name[sl]=Spletni pogon ++Name[sr]=КуТ‑вебенџин ++Name[sr@ijekavian]=КуТ‑вебенџин ++Name[sr@ijekavianlatin]=QtWebKit ++Name[sr@latin]=QtWebKit ++Name[sv]=Webbgränssnitt ++Name[uk]=Вебрушій ++Name[x-test]=xxWebKitxx ++Name[zh_CN]=WebKit ++Name[zh_TW]=WebKit ++X-KDE-Default-UserAgent=Mozilla/5.0 (%PLATFORM%; %SECURITY%; %OSNAME% %OSVERSION% %SYSTYPE%; %LANGUAGE%) AppleWebKit/534.34 (KHTML, like Gecko) %APPVERSION% Safari/534.34 ++X-KDE-ServiceTypes=KParts/ReadOnlyPart,Browser/View ++X-KDE-Library=kf5/parts/webkitpart ++InitialPreference=12 +diff --git b/webkitpart/src/webkitpart.h b/webkitpart/src/webkitpart.h +new file mode 100644 +index 000000000..4ee00403d +--- /dev/null ++++ b/webkitpart/src/webkitpart.h +@@ -0,0 +1,165 @@ ++/* ++ * This file is part of the KDE project. ++ * ++ * Copyright (C) 2007 Trolltech ASA ++ * Copyright (C) 2008 Urs Wolfer <uwolfer @ kde.org> ++ * Copyright (C) 2009 Dawit Alemayehu <adawit@kde.org> ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Lesser General Public License as published by the ++ * Free Software Foundation; either version 2.1 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 Lesser General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library. If not, see <http://www.gnu.org/licenses/>. ++ * ++ */ ++#ifndef WEBKITPART_H ++#define WEBKITPART_H ++ ++#include "kwebkitpartlib_export.h" ++ ++#include <QtWebKitWidgets/QWebPage> ++ ++#include <KParts/ReadOnlyPart> ++#include <QUrl> ++ ++namespace KParts { ++ class BrowserExtension; ++ class StatusBarExtension; ++} ++ ++class QWebView; ++class WebView; ++class WebPage; ++class SearchBar; ++class PasswordBar; ++class FeaturePermissionBar; ++class KUrlLabel; ++class WebBrowserExtension; ++ ++/** ++ * A KPart wrapper for the QtWebKit's browser rendering engine. ++ * ++ * This class attempts to provide the same type of integration into KPart ++ * plugin applications, such as Konqueror, in much the same way as KHTML. ++ * ++ * Unlink the KHTML part however, access into the internals of the rendering ++ * engine are provided through existing QtWebKit class ; @see QWebView. ++ * ++ */ ++class KWEBKITPARTLIB_EXPORT WebKitPart : public KParts::ReadOnlyPart ++{ ++ Q_OBJECT ++ Q_PROPERTY( bool modified READ isModified ) ++public: ++ explicit WebKitPart(QWidget* parentWidget = 0, QObject* parent = Q_NULLPTR, ++ const QByteArray& cachedHistory = QByteArray(), ++ const QStringList& = QStringList()); ++ ~WebKitPart(); ++ ++ /** ++ * Re-implemented for internal reasons. API remains unaffected. ++ * ++ * @see KParts::ReadOnlyPart::openUrl ++ */ ++ bool openUrl(const QUrl &) Q_DECL_OVERRIDE; ++ ++ /** ++ * Re-implemented for internal reasons. API remains unaffected. ++ * ++ * @see KParts::ReadOnlyPart::closeUrl ++ */ ++ bool closeUrl() Q_DECL_OVERRIDE; ++ ++ /** ++ * Returns a pointer to the render widget used to display a web page. ++ * ++ * @see QWebView. ++ */ ++ virtual QWebView *view(); ++ ++ /** ++ * Checks whether the page contains unsubmitted form changes. ++ * ++ * @return @p true if form changes exist. ++ */ ++ bool isModified() const; ++ ++ /** ++ * Connects the appropriate signals from the given page to the slots ++ * in this class. ++ */ ++ void connectWebPageSignals(WebPage* page); ++ ++ void slotShowFeaturePermissionBar(QWebPage::Feature); ++protected: ++ /** ++ * Re-implemented for internal reasons. API remains unaffected. ++ * ++ * @see KParts::ReadOnlyPart::guiActivateEvent ++ */ ++ void guiActivateEvent(KParts::GUIActivateEvent *) Q_DECL_OVERRIDE; ++ ++ /** ++ * Re-implemented for internal reasons. API remains unaffected. ++ * ++ * @see KParts::ReadOnlyPart::openFile ++ */ ++ bool openFile() Q_DECL_OVERRIDE; ++ ++private Q_SLOTS: ++ void slotShowSecurity(); ++ void slotShowSearchBar(); ++ void slotLoadStarted(); ++ void slotLoadAborted(const QUrl &); ++ void slotLoadFinished(bool); ++ ++ void slotSearchForText(const QString &text, bool backward); ++ void slotLinkHovered(const QString &); ++ //void slotSaveFrameState(QWebFrame *frame, QWebHistoryItem *item); ++ //void slotRestoreFrameState(QWebFrame *frame); ++ void slotLinkMiddleOrCtrlClicked(const QUrl&); ++ void slotSelectionClipboardUrlPasted(const QUrl&, const QString&); ++ ++ void slotUrlChanged(const QUrl &); ++ void slotWalletClosed(); ++ void slotShowWalletMenu(); ++ void slotLaunchWalletManager(); ++ void slotDeleteNonPasswordStorableSite(); ++ void slotRemoveCachedPasswords(); ++ void slotSetTextEncoding(QTextCodec*); ++ void slotSetStatusBarText(const QString& text); ++ void slotWindowCloseRequested(); ++ void slotSaveFormDataRequested(const QString &, const QUrl &); ++ void slotSaveFormDataDone(); ++ void slotFillFormRequestCompleted(bool); ++ ++ void slotFeaturePermissionGranted(QWebPage::Feature); ++ void slotFeaturePermissionDenied(QWebPage::Feature); ++ ++private: ++ WebPage* page(); ++ const WebPage* page() const; ++ void initActions(); ++ void updateActions(); ++ void addWalletStatusBarIcon(); ++ ++ bool m_emitOpenUrlNotify; ++ bool m_hasCachedFormData; ++ bool m_doLoadFinishedActions; ++ KUrlLabel* m_statusBarWalletLabel; ++ SearchBar* m_searchBar; ++ PasswordBar* m_passwordBar; ++ FeaturePermissionBar* m_featurePermissionBar; ++ WebBrowserExtension* m_browserExtension; ++ KParts::StatusBarExtension* m_statusBarExtension; ++ WebView* m_webView; ++}; ++ ++#endif // WEBPART_H +diff --git b/webkitpart/src/webkitpart.rc b/webkitpart/src/webkitpart.rc +new file mode 100644 +index 000000000..2b564ca97 +--- /dev/null ++++ b/webkitpart/src/webkitpart.rc +@@ -0,0 +1,32 @@ ++<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> ++<kpartgui name="kwebkitpart" version="8"> ++<MenuBar> ++ <Menu name="file"> ++ <Action name="saveDocument" /> ++ <Action name="saveFrame" /> ++ <Separator /> ++ <Action name="printPreview" group="print" /> ++ </Menu> ++ <Menu name="edit"> ++ <Action name="selectAll" /> ++ <Separator /> ++ <Action name="find" /> ++ </Menu> ++ <Menu name="view"> ++ <Action name="zoomIn" /> ++ <Action name="zoomOut" /> ++ <Action name="zoomNormal" /> ++ <Action name="zoomTextOnly" /> ++ <Action name="zoomToDPI" /> ++ <Separator /> ++ <Action name="setEncoding" /> ++ <Action name="viewDocumentSource" /> ++ <ActionList name="debugScriptList" /> ++ </Menu> ++</MenuBar> ++<ToolBar name="htmlToolBar" iconText="icononly" iconSize="22" hidden="true"><text>HTML Toolbar</text> ++ <Action name="zoomIn" /> ++ <Action name="zoomOut" /> ++ <Action name="zoomNormal" /> ++</ToolBar> ++</kpartgui> +diff --git b/webkitpart/src/webkitpart_ext.cpp b/webkitpart/src/webkitpart_ext.cpp +new file mode 100644 +index 000000000..d47c7e8e0 +--- /dev/null ++++ b/webkitpart/src/webkitpart_ext.cpp +@@ -0,0 +1,1237 @@ ++/* ++ * This file is part of the KDE project. ++ * ++ * Copyright (C) 2009 Dawit Alemayehu <adawit@kde.org> ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Lesser General Public License as published by the ++ * Free Software Foundation; either version 2.1 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 Lesser General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library. If not, see <http://www.gnu.org/licenses/>. ++ * ++ */ ++ ++#include <QtWebKit/QtWebKitVersion> ++#include "webkitpart_ext.h" ++ ++#include "webkitpart.h" ++#include "webkitview.h" ++#include "webkitpage.h" ++#include "settings/webkitsettings.h" ++#include <QtWebKit/QWebSettings> ++ ++#include <KDesktopFile> ++#include <KConfigGroup> ++#include <KToolInvocation> ++#include <KSharedConfig> ++#include <KRun> ++#include <KProtocolInfo> ++#include <QInputDialog> ++#include <KLocalizedString> ++#include <QTemporaryFile> ++#include <KUriFilter> ++#include <Sonnet/Dialog> ++#include <sonnet/backgroundchecker.h> ++ ++#include <QBuffer> ++#include <QVariant> ++#include <QClipboard> ++#include <QApplication> ++#include <QAction> ++#include <QPrinter> ++#include <QPrintDialog> ++#include <QPrintPreviewDialog> ++#include <QInputDialog> ++#include <QWebHistory> ++#include <QMimeData> ++#define QL1S(x) QLatin1String(x) ++#define QL1C(x) QLatin1Char(x) ++ ++template<typename Arg, typename R, typename C> ++struct InvokeWrapper { ++ R *receiver; ++ void (C::*memberFun)(Arg); ++ void operator()(Arg result) ++ { ++ (receiver->*memberFun)(result); ++ } ++}; ++ ++template<typename Arg, typename R, typename C> ++InvokeWrapper<Arg, R, C> invoke(R *receiver, void (C::*memberFun)(Arg)) ++{ ++ InvokeWrapper<Arg, R, C> wrapper = {receiver, memberFun}; ++ return wrapper; ++} ++ ++WebBrowserExtension::WebBrowserExtension(WebKitPart *parent, const QByteArray& cachedHistoryData) ++ :KParts::BrowserExtension(parent), ++ m_part(parent), ++ mCurrentPrinter(Q_NULLPTR) ++{ ++ enableAction("cut", false); ++ enableAction("copy", false); ++ enableAction("paste", false); ++ enableAction("print", true); ++ ++ if (cachedHistoryData.isEmpty()) { ++ return; ++ } ++ ++ QBuffer buffer; ++ buffer.setData(cachedHistoryData); ++ if (!buffer.open(QIODevice::ReadOnly)) { ++ return; ++ } ++ ++ // NOTE: When restoring history, webkit PORTING_TODO automatically navigates to ++ // the previous "currentItem". Since we do not want that to happen, ++ // we set a property on the WebPage object that is used to allow or ++ // disallow history navigation in WebPage::acceptNavigationRequest. ++ view()->page()->setProperty("HistoryNavigationLocked", true); ++ QDataStream s (&buffer); ++ s >> *(view()->history()); ++} ++ ++WebBrowserExtension::~WebBrowserExtension() ++{ ++} ++ ++WebView* WebBrowserExtension::view() ++{ ++ if (!m_view && m_part) { ++ m_view = qobject_cast<WebView*>(m_part->view()); ++ } ++ ++ return m_view; ++} ++ ++int WebBrowserExtension::xOffset() ++{ ++#if QTWEBKIT_VERSION >= QT_VERSION_CHECK(5, 602, 3) ++ if (view()) ++ return view()->page()->scrollPosition().x(); ++#endif ++ ++ return KParts::BrowserExtension::xOffset(); ++} ++ ++int WebBrowserExtension::yOffset() ++{ ++#if QTWEBKIT_VERSION >= QT_VERSION_CHECK(5, 602, 3) ++ if (view()) ++ return view()->page()->scrollPosition().y(); ++#endif ++ ++ return KParts::BrowserExtension::yOffset(); ++} ++ ++void WebBrowserExtension::saveState(QDataStream &stream) ++{ ++ // TODO: Save information such as form data from the current page. ++ QWebHistory* history = (view() ? view()->history() : 0); ++ const int historyIndex = (history ? history->currentItemIndex() : -1); ++ const QUrl historyUrl = (history && historyIndex > -1) ? QUrl(history->currentItem().url()) : m_part->url(); ++ ++ stream << historyUrl ++ << static_cast<qint32>(xOffset()) ++ << static_cast<qint32>(yOffset()) ++ << historyIndex ++ << m_historyData; ++} ++ ++void WebBrowserExtension::restoreState(QDataStream &stream) ++{ ++ QUrl u; ++ QByteArray historyData; ++ qint32 xOfs = -1, yOfs = -1, historyItemIndex = -1; ++ stream >> u >> xOfs >> yOfs >> historyItemIndex >> historyData; ++ ++ QWebHistory* history = (view() ? view()->page()->history() : 0); ++ if (history) { ++ bool success = false; ++ if (history->count() == 0) { // Handle restoration: crash recovery, tab close undo, session restore ++ if (!historyData.isEmpty()) { ++ historyData = qUncompress(historyData); // uncompress the history data... ++ QBuffer buffer (&historyData); ++ if (buffer.open(QIODevice::ReadOnly)) { ++ QDataStream stream (&buffer); ++ view()->page()->setProperty("HistoryNavigationLocked", true); ++ stream >> *history; ++ QWebHistoryItem currentItem (history->currentItem()); ++ if (currentItem.isValid()) { ++ if (currentItem.isValid() && (xOfs != -1 || yOfs != -1)) { ++ const QPoint scrollPos (xOfs, yOfs); ++// currentItem.setUserData(scrollPos); ++ } ++ // NOTE 1: The following Konqueror specific workaround is necessary ++ // because Konqueror only preserves information for the last visited ++ // page. However, we save the entire history content in saveState and ++ // and hence need to elimiate all but the current item here. ++ // NOTE 2: This condition only applies when Konqueror is restored from ++ // abnormal termination ; a crash and/or a session restoration. ++ if (QCoreApplication::applicationName() == QLatin1String("konqueror")) { ++ history->clear(); ++ } ++ //kDebug() << "Restoring URL:" << currentItem.url(); ++ m_part->setProperty("NoEmitOpenUrlNotification", true); ++ history->goToItem(currentItem); ++ } ++ } ++ } ++ success = (history->count() > 0); ++ } else { // Handle navigation: back and forward button navigation. ++ //kDebug() << "history count:" << history->count() << "request index:" << historyItemIndex; ++ if (history->count() > historyItemIndex && historyItemIndex > -1) { ++ QWebHistoryItem item (history->itemAt(historyItemIndex)); ++ //kDebug() << "URL:" << u << "Item URL:" << item.url(); ++ if (u == item.url()) { ++ if (item.isValid() && (xOfs != -1 || yOfs != -1)) { ++ const QPoint scrollPos (xOfs, yOfs); ++// item.setUserData(scrollPos); ++ } ++ m_part->setProperty("NoEmitOpenUrlNotification", true); ++ history->goToItem(item); ++ success = true; ++ } ++ } ++ } ++ ++ if (success) { ++ return; ++ } ++ } ++ ++ // As a last resort, in case the history restoration logic above fails, ++ // attempt to open the requested URL directly. ++ qDebug() << "Normal history navgation logic failed! Falling back to opening url directly."; ++ m_part->openUrl(u); ++} ++ ++ ++void WebBrowserExtension::cut() ++{ ++ if (view()) ++ view()->triggerPageAction(QWebPage::Cut); ++} ++ ++void WebBrowserExtension::copy() ++{ ++ if (view()) ++ view()->triggerPageAction(QWebPage::Copy); ++} ++ ++void WebBrowserExtension::paste() ++{ ++ if (view()) ++ view()->triggerPageAction(QWebPage::Paste); ++} ++ ++void WebBrowserExtension::slotSaveDocument() ++{ ++ if (view()) ++ emit saveUrl(view()->url()); ++} ++ ++void WebBrowserExtension::slotSaveFrame() ++{ ++ if (view()) ++ emit saveUrl(view()->page()->url()); // TODO lol ++} ++ ++void WebBrowserExtension::print() ++{ ++#if QTWEBKIT_VERSION >= QT_VERSION_CHECK(5, 602, 3) ++ if (view()) { ++ mCurrentPrinter = new QPrinter(); ++ QPointer<QPrintDialog> dialog = new QPrintDialog(mCurrentPrinter, Q_NULLPTR); ++ dialog->setWindowTitle(i18n("Print Document")); ++ if (dialog->exec() != QDialog::Accepted) { ++ slotHandlePagePrinted(false); ++ delete dialog; ++ return; ++ } ++ delete dialog; ++ view()->page()->print(mCurrentPrinter, invoke(this, &WebBrowserExtension::slotHandlePagePrinted)); ++ } ++#endif ++} ++ ++void WebBrowserExtension::slotHandlePagePrinted(bool result) ++{ ++ Q_UNUSED(result); ++ delete mCurrentPrinter; ++ mCurrentPrinter = Q_NULLPTR; ++} ++ ++ ++void WebBrowserExtension::updateEditActions() ++{ ++ if (!view()) ++ return; ++ ++ enableAction("cut", view()->pageAction(QWebPage::Cut)->isEnabled()); ++ enableAction("copy", view()->pageAction(QWebPage::Copy)->isEnabled()); ++ enableAction("paste", view()->pageAction(QWebPage::Paste)->isEnabled()); ++} ++ ++void WebBrowserExtension::updateActions() ++{ ++ const QString protocol (m_part->url().scheme()); ++ const bool isValidDocument = (protocol != QL1S("about") && protocol != QL1S("error")); ++ enableAction("print", isValidDocument); ++} ++ ++void WebBrowserExtension::searchProvider() ++{ ++ if (!view()) ++ return; ++ ++ QAction *action = qobject_cast<QAction*>(sender()); ++ if (!action) ++ return; ++ ++ QUrl url = action->data().toUrl(); ++ ++ if (url.host().isEmpty()) { ++ KUriFilterData data; ++ data.setData(action->data().toString()); ++ if (KUriFilter::self()->filterSearchUri(data, KUriFilter::WebShortcutFilter)) ++ url = data.uri(); ++ } ++ ++ if (!url.isValid()) ++ return; ++ ++ KParts::BrowserArguments bargs; ++ bargs.frameName = QL1S("_blank"); ++ emit openUrlRequest(url, KParts::OpenUrlArguments(), bargs); ++} ++ ++void WebBrowserExtension::reparseConfiguration() ++{ ++ // Force the configuration stuff to reparse... ++ WebSettings::self()->init(); ++} ++ ++void WebBrowserExtension::disableScrolling() ++{ ++ QWebView* currentView = view(); ++ QWebPage* page = currentView ? currentView->page() : 0; ++ ++ if (!page) ++ return; ++ ++ page->runJavaScript(QStringLiteral("document.documentElement.style.overflow = 'hidden';")); ++} ++ ++void WebBrowserExtension::zoomIn() ++{ ++ if (view()) ++ view()->setZoomFactor(view()->zoomFactor() + 0.1); ++} ++ ++void WebBrowserExtension::zoomOut() ++{ ++ if (view()) ++ view()->setZoomFactor(view()->zoomFactor() - 0.1); ++} ++ ++void WebBrowserExtension::zoomNormal() ++{ ++ if (view()) { ++ if (WebSettings::self()->zoomToDPI()) ++ view()->setZoomFactor(view()->logicalDpiY() / 96.0f); ++ else ++ view()->setZoomFactor(1); ++ } ++} ++ ++void WebBrowserExtension::toogleZoomTextOnly() ++{ ++ if (!view()) ++ return; ++ ++ KConfigGroup cgHtml(KSharedConfig::openConfig(), "HTML Settings"); ++ bool zoomTextOnly = cgHtml.readEntry( "ZoomTextOnly", false ); ++ cgHtml.writeEntry("ZoomTextOnly", !zoomTextOnly); ++ cgHtml.sync(); ++ ++ // view()->settings()->setAttribute(QWebSettings::ZoomTextOnly, !zoomTextOnly); ++} ++ ++void WebBrowserExtension::toogleZoomToDPI() ++{ ++ if (!view()) ++ return; ++ ++ bool zoomToDPI = !WebSettings::self()->zoomToDPI(); ++ WebSettings::self()->setZoomToDPI(zoomToDPI); ++ ++ if (zoomToDPI) ++ view()->setZoomFactor(view()->zoomFactor() * view()->logicalDpiY() / 96.0f); ++ else ++ view()->setZoomFactor(view()->zoomFactor() * 96.0f / view()->logicalDpiY()); ++ ++ // Recompute default font-sizes since they are only DPI dependent when zoomToDPI is false. ++ WebSettings::self()->computeFontSizes(view()->logicalDpiY()); ++} ++ ++void WebBrowserExtension::slotSelectAll() ++{ ++ if (view()) ++ view()->triggerPageAction(QWebPage::SelectAll); ++} ++ ++void WebBrowserExtension::slotSaveImageAs() ++{ ++ if (view()) ++ view()->triggerPageAction(QWebPage::DownloadImageToDisk); ++} ++ ++void WebBrowserExtension::slotSendImage() ++{ ++#if QTWEBKIT_VERSION >= QT_VERSION_CHECK(5, 602, 3) ++ if (!view()) ++ return; ++ ++ QStringList urls; ++ urls.append(view()->contextMenuResult().mediaUrl().path()); ++ const QString subject = view()->contextMenuResult().mediaUrl().path(); ++ KToolInvocation::invokeMailer(QString(), QString(), QString(), subject, ++ QString(), //body ++ QString(), ++ urls); // attachments ++#endif ++} ++ ++void WebBrowserExtension::slotCopyImageURL() ++{ ++#if QTWEBKIT_VERSION >= QT_VERSION_CHECK(5, 602, 3) ++ if (!view()) ++ return; ++ ++ QUrl safeURL = view()->contextMenuResult().mediaUrl(); ++ safeURL.setPassword(QString()); ++ // Set it in both the mouse selection and in the clipboard ++ QMimeData* mimeData = new QMimeData; ++//TODO: Porting: test ++ QList<QUrl> safeURLList; ++ safeURLList.append(safeURL); ++ mimeData->setUrls(safeURLList); ++ QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); ++ ++ mimeData = new QMimeData; ++ mimeData->setUrls(safeURLList); ++ QApplication::clipboard()->setMimeData(mimeData, QClipboard::Selection); ++#endif ++} ++ ++ ++void WebBrowserExtension::slotCopyImage() ++{ ++#if QTWEBKIT_VERSION >= QT_VERSION_CHECK(5, 602, 3) ++ if (!view()) ++ return; ++ ++ QUrl safeURL; //(view()->contextMenuResult().imageUrl()); ++ safeURL.setPassword(QString()); ++ ++ // Set it in both the mouse selection and in the clipboard ++ QMimeData* mimeData = new QMimeData; ++// mimeData->setImageData(view()->contextMenuResult().pixmap()); ++//TODO: Porting: test ++ QList<QUrl> safeURLList; ++ safeURLList.append(safeURL); ++ mimeData->setUrls(safeURLList); ++ QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); ++ ++ mimeData = new QMimeData; ++// mimeData->setImageData(view()->contextMenuResult().pixmap()); ++ mimeData->setUrls(safeURLList); ++ QApplication::clipboard()->setMimeData(mimeData, QClipboard::Selection); ++#endif ++} ++ ++void WebBrowserExtension::slotViewImage() ++{ ++#if QTWEBKIT_VERSION >= QT_VERSION_CHECK(5, 602, 3) ++ if (view()) ++ emit createNewWindow(view()->contextMenuResult().mediaUrl()); ++#endif ++} ++ ++void WebBrowserExtension::slotBlockImage() ++{ ++#if QTWEBKIT_VERSION >= QT_VERSION_CHECK(5, 602, 3) ++ if (!view()) ++ return; ++ ++ bool ok = false; ++ const QString url = QInputDialog::getText(view(), i18n("Add URL to Filter"), ++ i18n("Enter the URL:"), QLineEdit::Normal, ++ view()->contextMenuResult().mediaUrl().toString(), ++ &ok); ++ if (ok) { ++ WebSettings::self()->addAdFilter(url); ++ reparseConfiguration(); ++ } ++#endif ++} ++ ++void WebBrowserExtension::slotBlockHost() ++{ ++ if (!view()) ++ return; ++ ++ QUrl url; // (view()->contextMenuResult().imageUrl()); ++ url.setPath(QL1S("/*")); ++ WebSettings::self()->addAdFilter(url.toString(QUrl::RemoveUserInfo | QUrl::RemovePort)); ++ reparseConfiguration(); ++} ++ ++void WebBrowserExtension::slotCopyLinkURL() ++{ ++ if (view()) ++ view()->triggerPageAction(QWebPage::CopyLinkToClipboard); ++} ++ ++void WebBrowserExtension::slotCopyLinkText() ++{ ++#if QTWEBKIT_VERSION >= QT_VERSION_CHECK(5, 602, 3) ++ if (view()) { ++ QMimeData* data = new QMimeData; ++ data->setText(view()->contextMenuResult().linkText()); ++ QApplication::clipboard()->setMimeData(data, QClipboard::Clipboard); ++ } ++#endif ++} ++ ++void WebBrowserExtension::slotCopyEmailAddress() ++{ ++#if QTWEBKIT_VERSION >= QT_VERSION_CHECK(5, 602, 3) ++ if (view()) { ++ QMimeData* data = new QMimeData; ++ const QUrl url(view()->contextMenuResult().linkUrl()); ++ data->setText(url.path()); ++ QApplication::clipboard()->setMimeData(data, QClipboard::Clipboard); ++ } ++#endif ++} ++ ++void WebBrowserExtension::slotSaveLinkAs() ++{ ++ if (view()) ++ view()->triggerPageAction(QWebPage::DownloadLinkToDisk); ++} ++ ++void WebBrowserExtension::slotViewDocumentSource() ++{ ++ if (!view()) ++ return; ++ ++ const QUrl pageUrl (view()->url()); ++ if (pageUrl.isLocalFile()) { ++ KRun::runUrl(pageUrl, QL1S("text/plain"), view(), false); ++ } else { ++ view()->page()->toHtml([this](const QString& html) { ++ QTemporaryFile tempFile; ++ tempFile.setFileTemplate(tempFile.fileTemplate() + QL1S(".html")); ++ tempFile.setAutoRemove(false); ++ if (tempFile.open()) { ++ tempFile.write(html.toUtf8()); ++ KRun::runUrl(QUrl::fromLocalFile(tempFile.fileName()), QL1S("text/plain"), view(), true, false); ++ } ++ }); ++ } ++} ++ ++#if QTWEBKIT_VERSION >= QT_VERSION_CHECK(5, 602, 3) ++static bool isMultimediaElement(QWebContextMenuData::MediaType mediaType) ++{ ++ switch(mediaType) ++ { ++ case QWebContextMenuData::MediaTypeVideo: ++ case QWebContextMenuData::MediaTypeAudio: ++ return true; ++ default: ++ return false; ++ } ++} ++#endif ++ ++void WebBrowserExtension::slotLoopMedia() ++{ ++#if QTWEBKIT_VERSION >= QT_VERSION_CHECK(5, 602, 3) ++ if (!view()) ++ return; ++ ++ QWebContextMenuData data = view()->contextMenuResult(); ++ if (!isMultimediaElement( data.mediaType())) ++ return; ++ view()->page()->triggerAction(QWebPage::ToggleMediaLoop); ++#endif ++} ++ ++void WebBrowserExtension::slotMuteMedia() ++{ ++#if QTWEBKIT_VERSION >= QT_VERSION_CHECK(5, 602, 3) ++ if (!view()) ++ return; ++ ++ QWebContextMenuData data = view()->contextMenuResult(); ++ if (!isMultimediaElement( data.mediaType())) ++ return; ++ view()->page()->triggerAction(QWebPage::ToggleMediaMute); ++#endif ++} ++ ++void WebBrowserExtension::slotPlayMedia() ++{ ++#if QTWEBKIT_VERSION >= QT_VERSION_CHECK(5, 602, 3) ++ if (!view()) ++ return; ++ ++ QWebContextMenuData data = view()->contextMenuResult(); ++ if (!isMultimediaElement( data.mediaType())) ++ return; ++ view()->page()->triggerAction(QWebPage::ToggleMediaPlayPause); ++#endif ++} ++ ++void WebBrowserExtension::slotShowMediaControls() ++{ ++#if QTWEBKIT_VERSION >= QT_VERSION_CHECK(5, 602, 3) ++ if (!view()) ++ return; ++ ++ QWebContextMenuData data = view()->contextMenuResult(); ++ if (!isMultimediaElement( data.mediaType())) ++ return; ++ view()->page()->triggerAction(QWebPage::ToggleMediaControls); ++#endif ++} ++ ++#if 0 ++static QUrl mediaUrlFrom(QWebElement& element) ++{ ++ QWebFrame* frame = element.webFrame(); ++ QString src = frame ? element.attribute(QL1S("src")) : QString(); ++ if (src.isEmpty()) ++ src = frame ? element.evaluateJavaScript(QL1S("this.src")).toString() : QString(); ++ ++ if (src.isEmpty()) ++ return QUrl(); ++ ++ return QUrl(frame->baseUrl().resolved(QUrl::fromEncoded(QUrl::toPercentEncoding(src), QUrl::StrictMode))); ++} ++#endif ++ ++void WebBrowserExtension::slotSaveMedia() ++{ ++#if QTWEBKIT_VERSION >= QT_VERSION_CHECK(5, 602, 3) ++ if (!view()) ++ return; ++ ++ QWebContextMenuData data = view()->contextMenuResult(); ++ if (!isMultimediaElement( data.mediaType())) ++ return; ++ emit saveUrl(data.mediaUrl()); ++#endif ++} ++ ++void WebBrowserExtension::slotCopyMedia() ++{ ++#if QTWEBKIT_VERSION >= QT_VERSION_CHECK(5, 602, 3) ++ if (!view()) ++ return; ++ QWebContextMenuData data = view()->contextMenuResult(); ++ if (!isMultimediaElement( data.mediaType())) ++ return; ++ ++ QUrl safeURL(data.mediaUrl()); ++ if (!safeURL.isValid()) ++ return; ++ ++ safeURL.setPassword(QString()); ++ // Set it in both the mouse selection and in the clipboard ++ QMimeData* mimeData = new QMimeData; ++//TODO: Porting: test ++ QList<QUrl> safeURLList; ++ safeURLList.append(safeURL); ++ mimeData->setUrls(safeURLList); ++ QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard); ++ ++ mimeData = new QMimeData; ++ mimeData->setUrls(safeURLList); ++ QApplication::clipboard()->setMimeData(mimeData, QClipboard::Selection); ++#endif ++} ++ ++void WebBrowserExtension::slotTextDirectionChanged() ++{ ++ QAction* action = qobject_cast<QAction*>(sender()); ++ if (action) { ++ bool ok = false; ++ const int value = action->data().toInt(&ok); ++ if (ok) { ++ view()->triggerPageAction(static_cast<QWebPage::WebAction>(value)); ++ } ++ } ++} ++ ++static QVariant execJScript(WebView* view, const QString& script) ++{ ++#if 0 ++ QWebElement element (view->contextMenuResult().element()); ++ if (element.isNull()) ++ return QVariant(); ++ return element.evaluateJavaScript(script); ++#endif ++ return QVariant(); ++} ++ ++void WebBrowserExtension::slotCheckSpelling() ++{ ++ const QString text (execJScript(view(), QL1S("this.value")).toString()); ++ ++ if ( text.isEmpty() ) { ++ return; ++ } ++ ++ m_spellTextSelectionStart = 0; ++ m_spellTextSelectionEnd = 0; ++ ++ Sonnet::BackgroundChecker *backgroundSpellCheck = new Sonnet::BackgroundChecker; ++ Sonnet::Dialog* spellDialog = new Sonnet::Dialog(backgroundSpellCheck, view()); ++ backgroundSpellCheck->setParent(spellDialog); ++ spellDialog->setAttribute(Qt::WA_DeleteOnClose, true); ++ spellDialog->showSpellCheckCompletionMessage(true); ++ connect(spellDialog, SIGNAL(replace(QString,int,QString)), this, SLOT(spellCheckerCorrected(QString,int,QString))); ++ connect(spellDialog, SIGNAL(misspelling(QString,int)), this, SLOT(spellCheckerMisspelling(QString,int))); ++ spellDialog->setBuffer(text); ++ spellDialog->show(); ++} ++ ++void WebBrowserExtension::slotSpellCheckSelection() ++{ ++ QString text (execJScript(view(), QL1S("this.value")).toString()); ++ ++ if ( text.isEmpty() ) { ++ return; ++ } ++ ++ m_spellTextSelectionStart = qMax(0, execJScript(view(), QL1S("this.selectionStart")).toInt()); ++ m_spellTextSelectionEnd = qMax(0, execJScript(view(), QL1S("this.selectionEnd")).toInt()); ++ // kDebug() << "selection start:" << m_spellTextSelectionStart << "end:" << m_spellTextSelectionEnd; ++ ++ Sonnet::BackgroundChecker *backgroundSpellCheck = new Sonnet::BackgroundChecker; ++ Sonnet::Dialog* spellDialog = new Sonnet::Dialog(backgroundSpellCheck, view()); ++ backgroundSpellCheck->setParent(spellDialog); ++ spellDialog->setAttribute(Qt::WA_DeleteOnClose, true); ++ spellDialog->showSpellCheckCompletionMessage(true); ++ connect(spellDialog, SIGNAL(replace(QString,int,QString)), this, SLOT(spellCheckerCorrected(QString,int,QString))); ++ connect(spellDialog, SIGNAL(misspelling(QString,int)), this, SLOT(spellCheckerMisspelling(QString,int))); ++ connect(spellDialog, SIGNAL(done(QString)), this, SLOT(slotSpellCheckDone(QString))); ++ spellDialog->setBuffer(text.mid(m_spellTextSelectionStart, (m_spellTextSelectionEnd - m_spellTextSelectionStart))); ++ spellDialog->show(); ++} ++ ++void WebBrowserExtension::spellCheckerCorrected(const QString& original, int pos, const QString& replacement) ++{ ++ // Adjust the selection end... ++ if (m_spellTextSelectionEnd > 0) { ++ m_spellTextSelectionEnd += qMax (0, (replacement.length() - original.length())); ++ } ++ ++ const int index = pos + m_spellTextSelectionStart; ++ QString script(QL1S("this.value=this.value.substring(0,")); ++ script += QString::number(index); ++ script += QL1S(") + \""); ++ script += replacement; ++ script += QL1S("\" + this.value.substring("); ++ script += QString::number(index + original.length()); ++ script += QL1S(")"); ++ ++ //kDebug() << "**** script:" << script; ++ execJScript(view(), script); ++} ++ ++void WebBrowserExtension::spellCheckerMisspelling(const QString& text, int pos) ++{ ++ // kDebug() << text << pos; ++ QString selectionScript (QL1S("this.setSelectionRange(")); ++ selectionScript += QString::number(pos + m_spellTextSelectionStart); ++ selectionScript += QL1C(','); ++ selectionScript += QString::number(pos + text.length() + m_spellTextSelectionStart); ++ selectionScript += QL1C(')'); ++ execJScript(view(), selectionScript); ++} ++ ++void WebBrowserExtension::slotSpellCheckDone(const QString&) ++{ ++ // Restore the text selection if one was present before we started the ++ // spell check. ++ if (m_spellTextSelectionStart > 0 || m_spellTextSelectionEnd > 0) { ++ QString script (QL1S("; this.setSelectionRange(")); ++ script += QString::number(m_spellTextSelectionStart); ++ script += QL1C(','); ++ script += QString::number(m_spellTextSelectionEnd); ++ script += QL1C(')'); ++ execJScript(view(), script); ++ } ++} ++ ++ ++void WebBrowserExtension::saveHistory() ++{ ++ QWebHistory* history = (view() ? view()->history() : 0); ++ ++ if (history && history->count() > 0) { ++ //kDebug() << "Current history: index=" << history->currentItemIndex() << "url=" << history->currentItem().url(); ++ QByteArray histData; ++ QBuffer buff (&histData); ++ m_historyData.clear(); ++ if (buff.open(QIODevice::WriteOnly)) { ++ QDataStream stream (&buff); ++ stream << *history; ++ m_historyData = qCompress(histData, 9); ++ } ++ QWidget* mainWidget = m_part ? m_part->widget() : 0; ++ QWidget* frameWidget = mainWidget ? mainWidget->parentWidget() : 0; ++ if (frameWidget) { ++ emit saveHistory(frameWidget, m_historyData); ++ // kDebug() << "# of items:" << history->count() << "current item:" << history->currentItemIndex() << "url:" << history->currentItem().url(); ++ } ++ } else { ++ Q_ASSERT(false); // should never happen!!! ++ } ++} ++ ++void WebBrowserExtension::slotPrintPreview() ++{ ++#if 0 ++ // Make it non-modal, in case a redirection deletes the part ++ QPointer<QPrintPreviewDialog> dlg (new QPrintPreviewDialog(view())); ++ connect(dlg.data(), SIGNAL(paintRequested(QPrinter*)), ++ view()->page()->currentFrame(), SLOT(print(QPrinter*))); ++ dlg->exec(); ++ delete dlg; ++#endif ++} ++ ++void WebBrowserExtension::slotOpenSelection() ++{ ++ QAction *action = qobject_cast<QAction*>(sender()); ++ if (action) { ++ KParts::BrowserArguments browserArgs; ++ browserArgs.frameName = QStringLiteral("_blank"); ++ emit openUrlRequest(QUrl(action->data().toUrl()), KParts::OpenUrlArguments(), browserArgs); ++ } ++} ++ ++void WebBrowserExtension::slotLinkInTop() ++{ ++#if QTWEBKIT_VERSION >= QT_VERSION_CHECK(5, 602, 3) ++ if (!view()) ++ return; ++ ++ KParts::OpenUrlArguments uargs; ++ uargs.setActionRequestedByUser(true); ++ ++ KParts::BrowserArguments bargs; ++ bargs.frameName = QL1S("_top"); ++ ++ const QUrl url(view()->contextMenuResult().linkUrl()); ++ ++ emit openUrlRequest(url, uargs, bargs); ++#endif ++} ++ ++//// ++ ++WebTextExtension::WebTextExtension(WebKitPart* part) ++ : KParts::TextExtension(part) ++{ ++ connect(part->view(), SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged())); ++} ++ ++WebKitPart* WebTextExtension::part() const ++{ ++ return static_cast<WebKitPart*>(parent()); ++} ++ ++bool WebTextExtension::hasSelection() const ++{ ++ return part()->view()->hasSelection(); ++} ++ ++QString WebTextExtension::selectedText(Format format) const ++{ ++ switch(format) { ++ case PlainText: ++ return part()->view()->selectedText(); ++ case HTML: ++ // PORTING_TODO selectedText might not be html ++ return part()->view()->selectedText(); ++ } ++ return QString(); ++} ++ ++QString WebTextExtension::completeText(Format format) const ++{ ++ // TODO David will hunt me down with a rusty spork if he sees this ++ QEventLoop ev; ++ QString str; ++ switch(format) { ++ case PlainText: ++ part()->view()->page()->toPlainText([&ev,&str](const QString& data) { ++ str = data; ++ ev.quit(); ++ }); ++ case HTML: ++ part()->view()->page()->toHtml([&ev,&str](const QString& data) { ++ str = data; ++ ev.quit(); ++ }); ++ } ++ ev.exec(); ++ return QString(); ++} ++ ++//// ++ ++WebHtmlExtension::WebHtmlExtension(WebKitPart* part) ++ : KParts::HtmlExtension(part) ++{ ++} ++ ++ ++QUrl WebHtmlExtension::baseUrl() const ++{ ++ return part()->view()->page()->url(); ++} ++ ++bool WebHtmlExtension::hasSelection() const ++{ ++ return part()->view()->hasSelection(); ++} ++ ++KParts::SelectorInterface::QueryMethods WebHtmlExtension::supportedQueryMethods() const ++{ ++ return (KParts::SelectorInterface::EntireContent ++ | KParts::SelectorInterface::SelectedContent); ++} ++ ++#if 0 ++static KParts::SelectorInterface::Element convertWebElement(const QWebElement& webElem) ++{ ++ KParts::SelectorInterface::Element element; ++ element.setTagName(webElem.tagName()); ++ Q_FOREACH(const QString &attr, webElem.attributeNames()) { ++ element.setAttribute(attr, webElem.attribute(attr)); ++ } ++ return element; ++} ++#endif ++ ++static QString queryOne(const QString& query) ++{ ++ QString jsQuery = QL1S("(function(query) { var element; var selectedElement = window.getSelection().getRangeAt(0).cloneContents().querySelector(\""); ++ jsQuery += query; ++ jsQuery += QL1S("\"); if (selectedElement && selectedElement.length > 0) { element = new Object; " ++ "element.tagName = String(selectedElements[0].tagName); element.href = String(selectedElements[0].href); } " ++ "return element; }())"); ++ return jsQuery; ++} ++ ++static QString queryAll(const QString& query) ++{ ++ QString jsQuery = QL1S("(function(query) { var elements = []; var selectedElements = window.getSelection().getRangeAt(0).cloneContents().querySelectorAll(\""); ++ jsQuery += query; ++ jsQuery += QL1S("\"); var numSelectedElements = (selectedElements ? selectedElements.length : 0);" ++ "for (var i = 0; i < numSelectedElements; ++i) { var element = new Object; " ++ "element.tagName = String(selectedElements[i].tagName); element.href = String(selectedElements[i].href);" ++ "elements.push(element); } return elements; } ())"); ++ return jsQuery; ++} ++ ++static KParts::SelectorInterface::Element convertSelectionElement(const QVariant& variant) ++{ ++ KParts::SelectorInterface::Element element; ++ if (!variant.isNull() && variant.type() == QVariant::Map) { ++ const QVariantMap elementMap (variant.toMap()); ++ element.setTagName(elementMap.value(QL1S("tagName")).toString()); ++ element.setAttribute(QL1S("href"), elementMap.value(QL1S("href")).toString()); ++ } ++ return element; ++} ++ ++static QList<KParts::SelectorInterface::Element> convertSelectionElements(const QVariant& variant) ++{ ++ QList<KParts::SelectorInterface::Element> elements; ++ const QVariantList resultList (variant.toList()); ++ Q_FOREACH(const QVariant& result, resultList) { ++ const QVariantMap elementMap = result.toMap(); ++ KParts::SelectorInterface::Element element; ++ element.setTagName(elementMap.value(QL1S("tagName")).toString()); ++ element.setAttribute(QL1S("href"), elementMap.value(QL1S("href")).toString()); ++ elements.append(element); ++ } ++ return elements; ++} ++ ++KParts::SelectorInterface::Element WebHtmlExtension::querySelector(const QString& query, KParts::SelectorInterface::QueryMethod method) const ++{ ++ KParts::SelectorInterface::Element element; ++ ++ // If the specified method is None, return an empty list... ++ if (method == KParts::SelectorInterface::None) ++ return element; ++ ++ // If the specified method is not supported, return an empty list... ++ if (!(supportedQueryMethods() & method)) ++ return element; ++ ++#if 0 ++ switch (method) { ++ case KParts::SelectorInterface::EntireContent: { ++ const QWebFrame* webFrame = part()->view()->page()->mainFrame(); ++ element = convertWebElement(webFrame->findFirstElement(query)); ++ break; ++ } ++ case KParts::SelectorInterface::SelectedContent: { ++ QWebFrame* webFrame = part()->view()->page()->mainFrame(); ++ element = convertSelectionElement(webFrame->evaluateJavaScript(queryOne(query))); ++ break; ++ } ++ default: ++ break; ++ } ++#endif ++ ++ return element; ++} ++ ++QList<KParts::SelectorInterface::Element> WebHtmlExtension::querySelectorAll(const QString& query, KParts::SelectorInterface::QueryMethod method) const ++{ ++ QList<KParts::SelectorInterface::Element> elements; ++ ++ // If the specified method is None, return an empty list... ++ if (method == KParts::SelectorInterface::None) ++ return elements; ++ ++ // If the specified method is not supported, return an empty list... ++ if (!(supportedQueryMethods() & method)) ++ return elements; ++#if 0 ++ switch (method) { ++ case KParts::SelectorInterface::EntireContent: { ++ const QWebFrame* webFrame = part()->view()->page()->mainFrame(); ++ const QWebElementCollection collection = webFrame->findAllElements(query); ++ elements.reserve(collection.count()); ++ Q_FOREACH(const QWebElement& element, collection) ++ elements.append(convertWebElement(element)); ++ break; ++ } ++ case KParts::SelectorInterface::SelectedContent: { ++ QWebFrame* webFrame = part()->view()->page()->mainFrame(); ++ elements = convertSelectionElements(webFrame->evaluateJavaScript(queryAll(query))); ++ break; ++ } ++ default: ++ break; ++ } ++#endif ++ return elements; ++} ++ ++QVariant WebHtmlExtension::htmlSettingsProperty(KParts::HtmlSettingsInterface::HtmlSettingsType type) const ++{ ++ QWebView* view = part() ? part()->view() : 0; ++ QWebPage* page = view ? view->page() : 0; ++ QWebSettings* settings = page ? page->settings() : 0; ++ ++ if (settings) { ++ switch (type) { ++ case KParts::HtmlSettingsInterface::AutoLoadImages: ++ return settings->testAttribute(QWebSettings::AutoLoadImages); ++ case KParts::HtmlSettingsInterface::JavaEnabled: ++ return false; // settings->testAttribute(QWebSettings::JavaEnabled); ++ case KParts::HtmlSettingsInterface::JavascriptEnabled: ++ return settings->testAttribute(QWebSettings::JavascriptEnabled); ++ case KParts::HtmlSettingsInterface::PluginsEnabled: ++ return settings->testAttribute(QWebSettings::PluginsEnabled); ++ case KParts::HtmlSettingsInterface::DnsPrefetchEnabled: ++ return false; //settings->testAttribute(QWebSettings::DnsPrefetchEnabled); ++ case KParts::HtmlSettingsInterface::MetaRefreshEnabled: ++ return view->pageAction(QWebPage::Stop)->isEnabled(); ++ case KParts::HtmlSettingsInterface::LocalStorageEnabled: ++ return settings->testAttribute(QWebSettings::LocalStorageEnabled); ++ case KParts::HtmlSettingsInterface::OfflineStorageDatabaseEnabled: ++ return false; //settings->testAttribute(QWebSettings::OfflineStorageDatabaseEnabled); ++ case KParts::HtmlSettingsInterface::OfflineWebApplicationCacheEnabled: ++ return false ;//settings->testAttribute(QWebSettings::OfflineWebApplicationCacheEnabled); ++ case KParts::HtmlSettingsInterface::PrivateBrowsingEnabled: ++ return false; //settings->testAttribute(QWebSettings::PrivateBrowsingEnabled); ++ case KParts::HtmlSettingsInterface::UserDefinedStyleSheetURL: ++ return false; //settings->userStyleSheetUrl(); ++ default: ++ break; ++ } ++ } ++ ++ return QVariant(); ++} ++ ++bool WebHtmlExtension::setHtmlSettingsProperty(KParts::HtmlSettingsInterface::HtmlSettingsType type, const QVariant& value) ++{ ++ QWebView* view = part() ? part()->view() : 0; ++ QWebPage* page = view ? view->page() : 0; ++ QWebSettings* settings = page ? page->settings() : 0; ++ ++ if (settings) { ++ switch (type) { ++ case KParts::HtmlSettingsInterface::AutoLoadImages: ++ settings->setAttribute(QWebSettings::AutoLoadImages, value.toBool()); ++ return true; ++ case KParts::HtmlSettingsInterface::JavaEnabled: ++ //settings->setAttribute(QWebESettings::JavaEnabled, value.toBool()); ++ return false; ++ case KParts::HtmlSettingsInterface::JavascriptEnabled: ++ settings->setAttribute(QWebSettings::JavascriptEnabled, value.toBool()); ++ return true; ++ case KParts::HtmlSettingsInterface::PluginsEnabled: ++ settings->setAttribute(QWebSettings::PluginsEnabled, value.toBool()); ++ return true; ++ case KParts::HtmlSettingsInterface::DnsPrefetchEnabled: ++// settings->setAttribute(QWebSettings::DnsPrefetchEnabled, value.toBool()); ++ return false; ++ case KParts::HtmlSettingsInterface::MetaRefreshEnabled: ++ view->triggerPageAction(QWebPage::Stop); ++ return true; ++ case KParts::HtmlSettingsInterface::LocalStorageEnabled: ++ settings->setAttribute(QWebSettings::LocalStorageEnabled, value.toBool()); ++ return false; ++ case KParts::HtmlSettingsInterface::OfflineStorageDatabaseEnabled: ++ //settings->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, value.toBool()); ++ return false; ++ case KParts::HtmlSettingsInterface::OfflineWebApplicationCacheEnabled: ++ //settings->setAttribute(QWebSettings::OfflineWebApplicationCacheEnabled, value.toBool()); ++ return false; ++ case KParts::HtmlSettingsInterface::PrivateBrowsingEnabled: ++ //settings->setAttribute(QWebEnngineSettings::PrivateBrowsingEnabled, value.toBool()); ++ return false; ++ case KParts::HtmlSettingsInterface::UserDefinedStyleSheetURL: ++ //kDebug() << "Setting user style sheet for" << page << "to" << value.toUrl(); ++ // settings->setUserStyleSheetUrl(value.toUrl()); ++ return false; ++ default: ++ break; ++ } ++ } ++ ++ return false; ++} ++ ++WebKitPart* WebHtmlExtension::part() const ++{ ++ return static_cast<WebKitPart*>(parent()); ++} ++ ++WebScriptableExtension::WebScriptableExtension(WebKitPart* part) ++ : ScriptableExtension(part) ++{ ++} ++ ++QVariant WebScriptableExtension::rootObject() ++{ ++ return QVariant::fromValue(KParts::ScriptableExtension::Object(this, reinterpret_cast<quint64>(this))); ++} ++ ++bool WebScriptableExtension::setException (KParts::ScriptableExtension* callerPrincipal, const QString& message) ++{ ++ return KParts::ScriptableExtension::setException (callerPrincipal, message); ++} ++ ++QVariant WebScriptableExtension::get (KParts::ScriptableExtension* callerPrincipal, quint64 objId, const QString& propName) ++{ ++ //kDebug() << "caller:" << callerPrincipal << "id:" << objId << "propName:" << propName; ++ return callerPrincipal->get (0, objId, propName); ++} ++ ++bool WebScriptableExtension::put (KParts::ScriptableExtension* callerPrincipal, quint64 objId, const QString& propName, const QVariant& value) ++{ ++ return KParts::ScriptableExtension::put (callerPrincipal, objId, propName, value); ++} ++ ++static QVariant exception(const char* msg) ++{ ++ qWarning() << msg; ++ return QVariant::fromValue(KParts::ScriptableExtension::Exception(QString::fromLatin1(msg))); ++} ++ ++QVariant WebScriptableExtension::evaluateScript (KParts::ScriptableExtension* callerPrincipal, ++ quint64 contextObjectId, ++ const QString& code, ++ KParts::ScriptableExtension::ScriptLanguage lang) ++{ ++ Q_UNUSED(contextObjectId); ++ Q_UNUSED(code) ++ //kDebug() << "principal:" << callerPrincipal << "id:" << contextObjectId << "language:" << lang << "code:" << code; ++ ++ if (lang != ECMAScript) ++ return exception("unsupported language"); ++ ++ ++ KParts::ReadOnlyPart* part = callerPrincipal ? qobject_cast<KParts::ReadOnlyPart*>(callerPrincipal->parent()) : 0; ++ // QWebFrame* frame = part ? qobject_cast<QWebFrame*>(part->parent()) : 0; ++ // if (!frame) ++ return exception("failed to resolve principal"); ++#if 0 ++ QVariant result (frame->evaluateJavaScript(code)); ++ ++ if (result.type() == QVariant::Map) { ++ const QVariantMap map (result.toMap()); ++ for (QVariantMap::const_iterator it = map.constBegin(), itEnd = map.constEnd(); it != itEnd; ++it) { ++ callerPrincipal->put(callerPrincipal, 0, it.key(), it.value()); ++ } ++ } else { ++ const QString propName(code.contains(QLatin1String("__nsplugin")) ? QLatin1String("__nsplugin") : QString()); ++ callerPrincipal->put(callerPrincipal, 0, propName, result.toString()); ++ } ++ ++ return QVariant::fromValue(ScriptableExtension::Null()); ++#endif ++} ++ ++bool WebScriptableExtension::isScriptLanguageSupported (KParts::ScriptableExtension::ScriptLanguage lang) const ++{ ++ return (lang == KParts::ScriptableExtension::ECMAScript); ++} ++ ++QVariant WebScriptableExtension::encloserForKid (KParts::ScriptableExtension* kid) ++{ ++#if 0 ++ KParts::ReadOnlyPart* part = kid ? qobject_cast<KParts::ReadOnlyPart*>(kid->parent()) : 0; ++ QWebFrame* frame = part ? qobject_cast<QWebFrame*>(part->parent()) : 0; ++ if (frame) { ++ return QVariant::fromValue(KParts::ScriptableExtension::Object(kid, reinterpret_cast<quint64>(kid))); ++ } ++#endif ++ ++ return QVariant::fromValue(ScriptableExtension::Null()); ++} ++ ++WebKitPart* WebScriptableExtension::part() ++{ ++ return qobject_cast<WebKitPart*>(parent()); ++} ++ +diff --git b/webkitpart/src/webkitpart_ext.h b/webkitpart/src/webkitpart_ext.h +new file mode 100644 +index 000000000..b375cede2 +--- /dev/null ++++ b/webkitpart/src/webkitpart_ext.h +@@ -0,0 +1,201 @@ ++/* ++ * This file is part of the KDE project. ++ * ++ * Copyright (C) 2009 Dawit Alemayehu <adawit@kde.org> ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Lesser General Public License as published by the ++ * Free Software Foundation; either version 2.1 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 Lesser General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library. If not, see <http://www.gnu.org/licenses/>. ++ * ++ */ ++ ++#ifndef WEBKITPART_EXT_H ++#define WEBKITPART_EXT_H ++ ++#include "kwebkitpartlib_export.h" ++ ++#include <QPointer> ++ ++#include <KParts/BrowserExtension> ++#include <KParts/TextExtension> ++#include <KParts/HtmlExtension> ++#include <KParts/HtmlSettingsInterface> ++#include <KParts/ScriptableExtension> ++#include <KParts/SelectorInterface> ++ ++class QUrl; ++class WebPart; ++class WebView; ++class QPrinter; ++class KWEBKITPARTLIB_EXPORT WebBrowserExtension : public KParts::BrowserExtension ++{ ++ Q_OBJECT ++ ++public: ++ WebBrowserExtension(WebKitPart *parent, const QByteArray& cachedHistoryData); ++ ~WebBrowserExtension(); ++ ++ virtual int xOffset() override; ++ virtual int yOffset() override; ++ virtual void saveState(QDataStream &) override; ++ virtual void restoreState(QDataStream &) override; ++ void saveHistory(); ++ ++Q_SIGNALS: ++ void saveUrl(const QUrl &); ++ void saveHistory(QObject*, const QByteArray&); ++ ++public Q_SLOTS: ++ void cut(); ++ void copy(); ++ void paste(); ++ void print(); ++ ++ void slotSaveDocument(); ++ void slotSaveFrame(); ++ void searchProvider(); ++ void reparseConfiguration(); ++ void disableScrolling(); ++ ++ void zoomIn(); ++ void zoomOut(); ++ void zoomNormal(); ++ void toogleZoomTextOnly(); ++ void toogleZoomToDPI(); ++ void slotSelectAll(); ++ ++ void slotSaveImageAs(); ++ void slotSendImage(); ++ void slotCopyImageURL(); ++ void slotCopyImage(); ++ void slotViewImage(); ++ void slotBlockImage(); ++ void slotBlockHost(); ++ ++ void slotCopyLinkURL(); ++ void slotCopyLinkText(); ++ void slotSaveLinkAs(); ++ void slotCopyEmailAddress(); ++ ++ void slotViewDocumentSource(); ++ ++ void updateEditActions(); ++ void updateActions(); ++ ++ void slotPlayMedia(); ++ void slotMuteMedia(); ++ void slotLoopMedia(); ++ void slotShowMediaControls(); ++ void slotSaveMedia(); ++ void slotCopyMedia(); ++ void slotTextDirectionChanged(); ++ void slotCheckSpelling(); ++ void slotSpellCheckSelection(); ++ void slotSpellCheckDone(const QString&); ++ void spellCheckerCorrected(const QString&, int, const QString&); ++ void spellCheckerMisspelling(const QString&, int); ++ //void slotPrintRequested(QWebFrame*); ++ void slotPrintPreview(); ++ ++ void slotOpenSelection(); ++ void slotLinkInTop(); ++ ++private Q_SLOTS: ++ void slotHandlePagePrinted(bool result); ++private: ++ WebView* view(); ++ QPointer<WebPart> m_part; ++ QPointer<WebView> m_view; ++ quint32 m_spellTextSelectionStart; ++ quint32 m_spellTextSelectionEnd; ++ QByteArray m_historyData; ++ QPrinter *mCurrentPrinter; ++}; ++ ++/** ++ * @internal ++ * Implements the TextExtension interface ++ */ ++class WebTextExtension : public KParts::TextExtension ++{ ++ Q_OBJECT ++public: ++ WebTextExtension(WebKitPart* part); ++ ++ bool hasSelection() const Q_DECL_OVERRIDE; ++ QString selectedText(Format format) const Q_DECL_OVERRIDE; ++ QString completeText(Format format) const Q_DECL_OVERRIDE; ++ ++private: ++ WebKitPart* part() const; ++}; ++ ++/** ++ * @internal ++ * Implements the HtmlExtension interface ++ */ ++class WebHtmlExtension : public KParts::HtmlExtension, ++ public KParts::SelectorInterface, ++ public KParts::HtmlSettingsInterface ++{ ++ Q_OBJECT ++ Q_INTERFACES(KParts::SelectorInterface) ++ Q_INTERFACES(KParts::HtmlSettingsInterface) ++ ++public: ++ WebHtmlExtension(WebKitPart* part); ++ ++ // HtmlExtension ++ QUrl baseUrl() const Q_DECL_OVERRIDE; ++ bool hasSelection() const Q_DECL_OVERRIDE; ++ ++ // SelectorInterface ++ QueryMethods supportedQueryMethods() const Q_DECL_OVERRIDE; ++ Element querySelector(const QString& query, KParts::SelectorInterface::QueryMethod method) const Q_DECL_OVERRIDE; ++ QList<Element> querySelectorAll(const QString& query, KParts::SelectorInterface::QueryMethod method) const Q_DECL_OVERRIDE; ++ ++ // HtmlSettingsInterface ++ QVariant htmlSettingsProperty(HtmlSettingsType type) const Q_DECL_OVERRIDE; ++ bool setHtmlSettingsProperty(HtmlSettingsType type, const QVariant& value) Q_DECL_OVERRIDE; ++ ++private: ++ WebKitPart* part() const; ++}; ++ ++class WebScriptableExtension : public KParts::ScriptableExtension ++{ ++ Q_OBJECT ++ ++public: ++ WebScriptableExtension(WebKitPart* part); ++ ++ QVariant rootObject() Q_DECL_OVERRIDE; ++ ++ QVariant get(ScriptableExtension* callerPrincipal, quint64 objId, const QString& propName) Q_DECL_OVERRIDE; ++ ++ bool put(ScriptableExtension* callerPrincipal, quint64 objId, const QString& propName, const QVariant& value) Q_DECL_OVERRIDE; ++ ++ bool setException(ScriptableExtension* callerPrincipal, const QString& message) Q_DECL_OVERRIDE; ++ ++ QVariant evaluateScript(ScriptableExtension* callerPrincipal, ++ quint64 contextObjectId, ++ const QString& code, ++ ScriptLanguage language = ECMAScript) Q_DECL_OVERRIDE; ++ ++ bool isScriptLanguageSupported(ScriptLanguage lang) const Q_DECL_OVERRIDE; ++ ++private: ++ QVariant encloserForKid(KParts::ScriptableExtension* kid) Q_DECL_OVERRIDE; ++ WebKitPart* part(); ++}; ++ ++#endif // WEBKITPART_EXT_H +diff --git b/webkitpart/src/webkitpartfactory.cpp b/webkitpart/src/webkitpartfactory.cpp +new file mode 100644 +index 000000000..1156db0e7 +--- /dev/null ++++ b/webkitpart/src/webkitpartfactory.cpp +@@ -0,0 +1,65 @@ ++/* ++ * This file is part of the KDE project. ++ * ++ * Copyright (C) 2008 Laurent Montel <montel@kde.org> ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Lesser General Public License as published by the ++ * Free Software Foundation; either version 2.1 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 Lesser General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library. If not, see <http://www.gnu.org/licenses/>. ++ * ++ */ ++ ++#include "webkitpartfactory.h" ++#include "webkitpart_ext.h" ++#include "webkitpart.h" ++ ++#include <QWidget> ++ ++WebFactory::~WebFactory() ++{ ++ // kDebug() << this; ++} ++ ++QObject *WebFactory::create(const char* iface, QWidget *parentWidget, QObject *parent, const QVariantList &args, const QString& keyword) ++{ ++ Q_UNUSED(iface); ++ Q_UNUSED(keyword); ++ Q_UNUSED(args); ++ ++ qDebug() << parentWidget << parent; ++ connect(parentWidget, SIGNAL(destroyed(QObject*)), this, SLOT(slotDestroyed(QObject*))); ++ ++ // NOTE: The code below is what makes it possible to properly integrate QtWebKit's PORTING_TODO ++ // history management with any KParts based application. ++ QByteArray histData (m_historyBufContainer.value(parentWidget)); ++ if (!histData.isEmpty()) histData = qUncompress(histData); ++ WebKitPart* part = new WebKitPart(parentWidget, parent, histData); ++ WebBrowserExtension* ext = qobject_cast<WebBrowserExtension*>(part->browserExtension()); ++ if (ext) { ++ connect(ext, SIGNAL(saveHistory(QObject*,QByteArray)), this, SLOT(slotSaveHistory(QObject*,QByteArray))); ++ } ++ return part; ++} ++ ++void WebFactory::slotSaveHistory(QObject* widget, const QByteArray& buffer) ++{ ++ // kDebug() << "Caching history data from" << widget; ++ m_historyBufContainer.insert(widget, buffer); ++} ++ ++void WebFactory::slotDestroyed(QObject* object) ++{ ++ // kDebug() << "Removing cached history data of" << object; ++ m_historyBufContainer.remove(object); ++} ++ ++K_EXPORT_PLUGIN(WebFactory) +diff --git b/webkitpart/src/webkitpartfactory.h b/webkitpart/src/webkitpartfactory.h +new file mode 100644 +index 000000000..f53ed41b7 +--- /dev/null ++++ b/webkitpart/src/webkitpartfactory.h +@@ -0,0 +1,47 @@ ++/* ++ * This file is part of the KDE project. ++ * ++ * Copyright (C) 2008 Laurent Montel <montel@kde.org> ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Lesser General Public License as published by the ++ * Free Software Foundation; either version 2.1 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 Lesser General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library. If not, see <http://www.gnu.org/licenses/>. ++ * ++ */ ++ ++#ifndef WEBKITPARTFACTORY ++#define WEBKITPARTFACTORY ++ ++#include <kpluginfactory.h> ++ ++#include <QHash> ++ ++class QWidget; ++ ++class WebFactory : public KPluginFactory ++{ ++ Q_OBJECT ++ Q_PLUGIN_METADATA(IID "org.kde.KPluginFactory" FILE "") ++ Q_INTERFACES(KPluginFactory) ++public: ++ virtual ~WebFactory(); ++ QObject *create(const char* iface, QWidget *parentWidget, QObject *parent, const QVariantList& args, const QString &keyword) Q_DECL_OVERRIDE; ++ ++private Q_SLOTS: ++ void slotDestroyed(QObject* object); ++ void slotSaveHistory(QObject* widget, const QByteArray&); ++ ++private: ++ QHash<QObject*, QByteArray> m_historyBufContainer; ++}; ++ ++#endif // WEBKITPARTFACTORY +diff --git b/webkitpart/src/webkitview.cpp b/webkitpart/src/webkitview.cpp +new file mode 100644 +index 000000000..a106451d2 +--- /dev/null ++++ b/webkitpart/src/webkitview.cpp +@@ -0,0 +1,594 @@ ++/* ++ * This file is part of the KDE project. ++ * ++ * Copyright (C) 2007 Trolltech ASA ++ * Copyright (C) 2008 - 2010 Urs Wolfer <uwolfer @ kde.org> ++ * Copyright (C) 2008 Laurent Montel <montel@kde.org> ++ * Copyright (C) 2009 Dawit Alemayehu <adawit@kde.org> ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Lesser General Public License as published by the ++ * Free Software Foundation; either version 2.1 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 Lesser General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library. If not, see <http://www.gnu.org/licenses/>. ++ * ++ */ ++ ++#include "webkitview.h" ++#include "webkitpage.h" ++#include "webkitpart.h" ++#include "settings/webkitsettings.h" ++ ++#include <kio/global.h> ++#include <KAboutData> ++#include <KActionCollection> ++#include <KConfigGroup> ++#include <KService> ++#include <KUriFilter> ++#include <KActionMenu> ++#include <KIO/AccessManager> ++#include <KStringHandler> ++#include <KLocalizedString> ++ ++#include <QTimer> ++#include <QMimeData> ++#include <QDropEvent> ++#include <QLabel> ++#include <QNetworkRequest> ++#include <QToolTip> ++#include <QCoreApplication> ++#include <unistd.h> ++#include <QMimeType> ++#include <QMimeDatabase> ++ ++#define QL1S(x) QLatin1String(x) ++#define QL1C(x) QLatin1Char(x) ++ ++#define ALTERNATE_DEFAULT_WEB_SHORTCUT QL1S("google") ++#define ALTERNATE_WEB_SHORTCUTS QStringList() << QL1S("google") << QL1S("wikipedia") << QL1S("webster") << QL1S("dmoz") ++ ++WebView::WebView(WebKitPart* part, QWidget* parent) ++ :QWebView(parent), ++ m_actionCollection(new KActionCollection(this)), ++ m_part(part), ++ m_autoScrollTimerId(-1), ++ m_verticalAutoScrollSpeed(0), ++ m_horizontalAutoScrollSpeed(0) ++{ ++ setAcceptDrops(true); ++ ++ // Create the custom page... ++ setPage(new WebPage(part, this)); ++ ++ connect(this, SIGNAL(loadStarted()), this, SLOT(slotStopAutoScroll())); ++ ++ if (WebSettings::self()->zoomToDPI()) ++ setZoomFactor(logicalDpiY() / 96.0f); ++ ++#ifndef HAVE_WEBCONTEXTMENUDATA ++ m_result = 0; ++#endif ++} ++ ++WebView::~WebView() ++{ ++ //kDebug(); ++} ++ ++void WebView::loadUrl(const QUrl& url, const KParts::OpenUrlArguments& args, const KParts::BrowserArguments& bargs) ++{ ++ page()->setProperty("NavigationTypeUrlEntered", true); ++ ++ if (args.reload() && url == this->url()) { ++ reload(); ++ return; ++ } ++ ++ QNetworkRequest request(url); ++ if (args.reload()) { ++ request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork); ++ } ++ ++ if (bargs.postData.isEmpty()) { ++ QWebView::load(url); ++ } else { ++ // QWebView::load(url, QNetworkAccessManager::PostOperation, bargs.postData); ++ } ++} ++ ++QWebContextMenuData WebView::contextMenuResult() const ++{ ++ return m_result; ++} ++ ++static void extractMimeTypeFor(const QUrl& url, QString& mimeType) ++{ ++ const QString fname(url.fileName()); ++ ++ if (fname.isEmpty() || url.hasFragment() || url.hasQuery()) ++ return; ++ ++ QMimeType pmt = QMimeDatabase().mimeTypeForFile(fname); ++ ++ // Further check for mime types guessed from the extension which, ++ // on a web page, are more likely to be a script delivering content ++ // of undecidable type. If the mime type from the extension is one ++ // of these, don't use it. Retain the original type 'text/html'. ++ if (pmt.isDefault() || ++ pmt.inherits(QL1S("application/x-perl")) || ++ pmt.inherits(QL1S("application/x-perl-module")) || ++ pmt.inherits(QL1S("application/x-php")) || ++ pmt.inherits(QL1S("application/x-python-bytecode")) || ++ pmt.inherits(QL1S("application/x-python")) || ++ pmt.inherits(QL1S("application/x-shellscript"))) ++ return; ++ ++ mimeType = pmt.name(); ++} ++ ++void WebView::contextMenuEvent(QContextMenuEvent* e) ++{ ++#ifdef HAVE_WEBCONTEXTMENUDATA ++ m_result = page()->contextMenuData(); ++ ++ // Clear the previous collection entries first... ++ m_actionCollection->clear(); ++ ++ KParts::BrowserExtension::PopupFlags flags = KParts::BrowserExtension::DefaultPopupItems; ++ KParts::BrowserExtension::ActionGroupMap mapAction; ++ QString mimeType (QL1S("text/html")); ++ bool forcesNewWindow = false; ++ ++ QUrl emitUrl; ++ ++ if (m_result.isContentEditable()) { ++ flags |= KParts::BrowserExtension::ShowTextSelectionItems; ++ editableContentActionPopupMenu(mapAction); ++ } else if (m_result.mediaType() == QWebContextMenuData::MediaTypeVideo || m_result.mediaType() == QWebContextMenuData::MediaTypeAudio) { ++ multimediaActionPopupMenu(mapAction); ++ } else if (!m_result.linkUrl().isValid()) { ++ if (m_result.mediaType() == QWebContextMenuData::MediaTypeImage) { ++ emitUrl = m_result.mediaUrl(); ++ extractMimeTypeFor(emitUrl, mimeType); ++ } else { ++ flags |= KParts::BrowserExtension::ShowBookmark; ++ emitUrl = m_part->url(); ++ ++ if (!m_result.selectedText().isEmpty()) { ++ flags |= KParts::BrowserExtension::ShowTextSelectionItems; ++ selectActionPopupMenu(mapAction); ++ } ++ } ++ partActionPopupMenu(mapAction); ++ } else { ++ flags |= KParts::BrowserExtension::ShowBookmark; ++ flags |= KParts::BrowserExtension::IsLink; ++ emitUrl = m_result.linkUrl(); ++ linkActionPopupMenu(mapAction); ++ if (emitUrl.isLocalFile()) ++ mimeType = QMimeDatabase().mimeTypeForUrl(emitUrl).name(); ++ else ++ extractMimeTypeFor(emitUrl, mimeType); ++ partActionPopupMenu(mapAction); ++ ++ // Show the OpenInThisWindow context menu item ++// forcesNewWindow = (page()->currentFrame() != m_result.linkTargetFrame()); ++ } ++ ++ if (!mapAction.isEmpty()) { ++ KParts::OpenUrlArguments args; ++ KParts::BrowserArguments bargs; ++ args.setMimeType(mimeType); ++ bargs.setForcesNewWindow(forcesNewWindow); ++ e->accept(); ++ emit m_part->browserExtension()->popupMenu(e->globalPos(), emitUrl, static_cast<mode_t>(-1), args, bargs, flags, mapAction); ++ return; ++ } ++ ++#endif ++ QWebView::contextMenuEvent(e); ++} ++ ++void WebView::keyPressEvent(QKeyEvent* e) ++{ ++ if (e && hasFocus()) { ++ const int key = e->key(); ++ if (e->modifiers() & Qt::ShiftModifier) { ++ switch (key) { ++ case Qt::Key_Up: ++ /* if (!isEditableElement(page()))*/ { ++ m_verticalAutoScrollSpeed--; ++ if (m_autoScrollTimerId == -1) ++ m_autoScrollTimerId = startTimer(100); ++ e->accept(); ++ return; ++ } ++ break; ++ case Qt::Key_Down: ++ /*if (!isEditableElement(page()))*/ { ++ m_verticalAutoScrollSpeed++; ++ if (m_autoScrollTimerId == -1) ++ m_autoScrollTimerId = startTimer(100); ++ e->accept(); ++ return; ++ } ++ break; ++ case Qt::Key_Left: ++ /*if (!isEditableElement(page()))*/ { ++ m_horizontalAutoScrollSpeed--; ++ if (m_autoScrollTimerId == -1) ++ m_autoScrollTimerId = startTimer(100); ++ e->accept(); ++ return; ++ } ++ break; ++ case Qt::Key_Right: ++ /*if (!isEditableElement(page()))*/ { ++ m_horizontalAutoScrollSpeed--; ++ if (m_autoScrollTimerId == -1) ++ m_autoScrollTimerId = startTimer(100); ++ e->accept(); ++ return; ++ } ++ break; ++ default: ++ break; ++ } ++ } else if (m_autoScrollTimerId != -1) { ++ // kDebug() << "scroll timer id:" << m_autoScrollTimerId; ++ slotStopAutoScroll(); ++ e->accept(); ++ return; ++ } ++ } ++ QWebView::keyPressEvent(e); ++} ++ ++void WebView::keyReleaseEvent(QKeyEvent *e) ++{ ++ QWebView::keyReleaseEvent(e); ++} ++ ++void WebView::mouseReleaseEvent(QMouseEvent* e) ++{ ++ QWebView::mouseReleaseEvent(e); ++} ++ ++void WebView::wheelEvent (QWheelEvent* e) ++{ ++ QWebView::wheelEvent(e); ++} ++ ++ ++void WebView::timerEvent(QTimerEvent* e) ++{ ++#if 0 ++ if (e && e->timerId() == m_autoScrollTimerId) { ++ // do the scrolling ++ scroll(m_horizontalAutoScrollSpeed, m_verticalAutoScrollSpeed); ++ // check if we reached the end ++ const int y = page()->scrollPosition().y(); ++ if (y == page()->currentFrame()->scrollBarMinimum(Qt::Vertical) || ++ y == page()->currentFrame()->scrollBarMaximum(Qt::Vertical)) { ++ m_verticalAutoScrollSpeed = 0; ++ } ++ ++ const int x = page()->scrollPosition().x(); ++ if (x == page()->currentFrame()->scrollBarMinimum(Qt::Horizontal) || ++ x == page()->currentFrame()->scrollBarMaximum(Qt::Horizontal)) { ++ m_horizontalAutoScrollSpeed = 0; ++ } ++ ++ // Kill the timer once the max/min scroll limit is reached. ++ if (m_horizontalAutoScrollSpeed == 0 && m_verticalAutoScrollSpeed == 0) { ++ killTimer(m_autoScrollTimerId); ++ m_autoScrollTimerId = -1; ++ } ++ e->accept(); ++ return; ++ } ++#endif ++ QWebView::timerEvent(e); ++} ++ ++void WebView::editableContentActionPopupMenu(KParts::BrowserExtension::ActionGroupMap& partGroupMap) ++{ ++ QList<QAction*> editableContentActions; ++ ++ QActionGroup* group = new QActionGroup(this); ++ group->setExclusive(true); ++ ++ QAction* action = new QAction(m_actionCollection); ++ action->setSeparator(true); ++ editableContentActions.append(action); ++ ++ action = m_actionCollection->addAction(KStandardAction::Copy, QL1S("copy"), m_part->browserExtension(), SLOT(copy())); ++ action->setEnabled(pageAction(QWebPage::Copy)->isEnabled()); ++ editableContentActions.append(action); ++ ++ action = m_actionCollection->addAction(KStandardAction::Cut, QL1S("cut"), m_part->browserExtension(), SLOT(cut())); ++ action->setEnabled(pageAction(QWebPage::Cut)->isEnabled()); ++ editableContentActions.append(action); ++ ++ action = m_actionCollection->addAction(KStandardAction::Paste, QL1S("paste"), m_part->browserExtension(), SLOT(paste())); ++ action->setEnabled(pageAction(QWebPage::Paste)->isEnabled()); ++ editableContentActions.append(action); ++ ++ action = new QAction(m_actionCollection); ++ action->setSeparator(true); ++ editableContentActions.append(action); ++ ++ editableContentActions.append(pageAction(QWebPage::SelectAll)); ++ editableContentActions.append(pageAction(QWebPage::InspectElement)); ++ ++ partGroupMap.insert(QStringLiteral("editactions") , editableContentActions); ++} ++ ++ ++void WebView::partActionPopupMenu(KParts::BrowserExtension::ActionGroupMap& partGroupMap) ++{ ++ QList<QAction*> partActions; ++ ++#ifdef HAVE_WEBCONTEXTMENUDATA ++ if (m_result.mediaUrl().isValid()) { ++ QAction *action; ++ action = new QAction(i18n("Save Image As..."), this); ++ m_actionCollection->addAction(QL1S("saveimageas"), action); ++ connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(slotSaveImageAs())); ++ partActions.append(action); ++ ++ action = new QAction(i18n("Send Image..."), this); ++ m_actionCollection->addAction(QL1S("sendimage"), action); ++ connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(slotSendImage())); ++ partActions.append(action); ++ ++ action = new QAction(i18n("Copy Image URL"), this); ++ m_actionCollection->addAction(QL1S("copyimageurl"), action); ++ connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(slotCopyImageURL())); ++ partActions.append(action); ++ ++#if 0 ++ action = new QAction(i18n("Copy Image"), this); ++ m_actionCollection->addAction(QL1S("copyimage"), action); ++ connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(slotCopyImage())); ++ action->setEnabled(!m_result.pixmap().isNull()); ++ partActions.append(action); ++#endif ++ ++ action = new QAction(i18n("View Image (%1)", QUrl(m_result.mediaUrl()).fileName()), this); ++ m_actionCollection->addAction(QL1S("viewimage"), action); ++ connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(slotViewImage())); ++ partActions.append(action); ++ ++ if (WebSettings::self()->isAdFilterEnabled()) { ++ action = new QAction(i18n("Block Image..."), this); ++ m_actionCollection->addAction(QL1S("blockimage"), action); ++ connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(slotBlockImage())); ++ partActions.append(action); ++ ++ if (!m_result.mediaUrl().host().isEmpty() && ++ !m_result.mediaUrl().scheme().isEmpty()) ++ { ++ action = new QAction(i18n("Block Images From %1" , m_result.mediaUrl().host()), this); ++ m_actionCollection->addAction(QL1S("blockhost"), action); ++ connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(slotBlockHost())); ++ partActions.append(action); ++ } ++ } ++ } ++#endif ++ ++ { ++ QAction *separatorAction = new QAction(m_actionCollection); ++ separatorAction->setSeparator(true); ++ partActions.append(separatorAction); ++ } ++ ++ partActions.append(m_part->actionCollection()->action(QStringLiteral("viewDocumentSource"))); ++ ++ partActions.append(pageAction(QWebPage::InspectElement)); ++ ++ partGroupMap.insert(QStringLiteral("partactions"), partActions); ++} ++ ++void WebView::selectActionPopupMenu(KParts::BrowserExtension::ActionGroupMap& selectGroupMap) ++{ ++ QList<QAction*> selectActions; ++ ++ QAction* copyAction = m_actionCollection->addAction(KStandardAction::Copy, QL1S("copy"), m_part->browserExtension(), SLOT(copy())); ++ copyAction->setText(i18n("&Copy Text")); ++ copyAction->setEnabled(m_part->browserExtension()->isActionEnabled("copy")); ++ selectActions.append(copyAction); ++ ++ addSearchActions(selectActions, this); ++ ++ KUriFilterData data (selectedText().simplified().left(256)); ++ data.setCheckForExecutables(false); ++ if (KUriFilter::self()->filterUri(data, QStringList() << QStringLiteral("kshorturifilter") << QStringLiteral("fixhosturifilter")) && ++ data.uri().isValid() && data.uriType() == KUriFilterData::NetProtocol) { ++ QAction *action = new QAction(QIcon::fromTheme(QStringLiteral("window-new")), i18nc("open selected url", "Open '%1'", ++ KStringHandler::rsqueeze(data.uri().url(), 18)), this); ++ m_actionCollection->addAction(QL1S("openSelection"), action); ++ action->setData(QUrl(data.uri())); ++ connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(slotOpenSelection())); ++ selectActions.append(action); ++ } ++ ++ selectGroupMap.insert(QStringLiteral("editactions"), selectActions); ++} ++ ++void WebView::linkActionPopupMenu(KParts::BrowserExtension::ActionGroupMap& linkGroupMap) ++{ ++#ifdef HAVE_WEBCONTEXTMENUDATA ++ Q_ASSERT(!m_result.linkUrl().isEmpty()); ++ ++ const QUrl url(m_result.linkUrl()); ++#else ++ const QUrl url; ++#endif ++ ++ QList<QAction*> linkActions; ++ ++ QAction* action; ++ ++#ifdef HAVE_WEBCONTEXTMENUDATA ++ if (!m_result.selectedText().isEmpty()) { ++ action = m_actionCollection->addAction(KStandardAction::Copy, QL1S("copy"), m_part->browserExtension(), SLOT(copy())); ++ action->setText(i18n("&Copy Text")); ++ action->setEnabled(m_part->browserExtension()->isActionEnabled("copy")); ++ linkActions.append(action); ++ } ++#endif ++ ++ if (url.scheme() == QLatin1String("mailto")) { ++#ifdef HAVE_WEBCONTEXTMENUDATA ++ action = new QAction(i18n("&Copy Email Address"), this); ++ m_actionCollection->addAction(QL1S("copylinklocation"), action); ++ connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(slotCopyEmailAddress())); ++ linkActions.append(action); ++#endif ++ } else { ++#ifdef HAVE_WEBCONTEXTMENUDATA ++ if (!m_result.linkText().isEmpty()) { ++ action = new QAction(QIcon::fromTheme(QStringLiteral("edit-copy")), i18n("Copy Link &Text"), this); ++ m_actionCollection->addAction(QL1S("copylinktext"), action); ++ connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(slotCopyLinkText())); ++ linkActions.append(action); ++ } ++#endif ++ ++ action = new QAction(i18n("Copy Link &URL"), this); ++ m_actionCollection->addAction(QL1S("copylinkurl"), action); ++ connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(slotCopyLinkURL())); ++ linkActions.append(action); ++ ++ action = new QAction(i18n("&Save Link As..."), this); ++ m_actionCollection->addAction(QL1S("savelinkas"), action); ++ connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(slotSaveLinkAs())); ++ linkActions.append(action); ++ } ++ ++ linkGroupMap.insert(QStringLiteral("linkactions"), linkActions); ++} ++ ++void WebView::multimediaActionPopupMenu(KParts::BrowserExtension::ActionGroupMap& mmGroupMap) ++{ ++#ifdef HAVE_WEBCONTEXTMENUDATA ++ QList<QAction*> multimediaActions; ++ ++ const bool isVideoElement = m_result.mediaType() == QWebContextMenuData::MediaTypeVideo; ++ const bool isAudioElement = m_result.mediaType() == QWebContextMenuData::MediaTypeAudio; ++ ++ QAction* action = new QAction(i18n("&Play/Pause"), this); ++ m_actionCollection->addAction(QL1S("playmultimedia"), action); ++ connect(action, SIGNAL(triggered()), m_part->browserExtension(), SLOT(slotPlayMedia())); ++ multimediaActions.append(action); ++ ++ action = new QAction(i18n("Un&mute/&Mute"), this); ++ m_actionCollection->addAction(QL1S("mutemultimedia"), action); ++ connect(action, SIGNAL(triggered()), m_part->browserExtension(), SLOT(slotMuteMedia())); ++ multimediaActions.append(action); ++ ++ action = new QAction(i18n("Toggle &Loop"), this); ++ m_actionCollection->addAction(QL1S("loopmultimedia"), action); ++ connect(action, SIGNAL(triggered()), m_part->browserExtension(), SLOT(slotLoopMedia())); ++ multimediaActions.append(action); ++ ++ action = new QAction(i18n("Toggle &Controls"), this); ++ m_actionCollection->addAction(QL1S("showmultimediacontrols"), action); ++ connect(action, SIGNAL(triggered()), m_part->browserExtension(), SLOT(slotShowMediaControls())); ++ multimediaActions.append(action); ++ ++ action = new QAction(m_actionCollection); ++ action->setSeparator(true); ++ multimediaActions.append(action); ++ ++ QString saveMediaText, copyMediaText; ++ if (isVideoElement) { ++ saveMediaText = i18n("Sa&ve Video As..."); ++ copyMediaText = i18n("C&opy Video URL"); ++ } else if (isAudioElement) { ++ saveMediaText = i18n("Sa&ve Audio As..."); ++ copyMediaText = i18n("C&opy Audio URL"); ++ } else { ++ saveMediaText = i18n("Sa&ve Media As..."); ++ copyMediaText = i18n("C&opy Media URL"); ++ } ++ ++ action = new QAction(saveMediaText, this); ++ m_actionCollection->addAction(QL1S("savemultimedia"), action); ++ connect(action, SIGNAL(triggered()), m_part->browserExtension(), SLOT(slotSaveMedia())); ++ multimediaActions.append(action); ++ ++ action = new QAction(copyMediaText, this); ++ m_actionCollection->addAction(QL1S("copymultimediaurl"), action); ++ connect(action, SIGNAL(triggered()), m_part->browserExtension(), SLOT(slotCopyMedia())); ++ multimediaActions.append(action); ++ ++ mmGroupMap.insert(QStringLiteral("partactions"), multimediaActions); ++#endif ++} ++ ++void WebView::slotStopAutoScroll() ++{ ++ if (m_autoScrollTimerId == -1) { ++ return; ++ } ++ ++ killTimer(m_autoScrollTimerId); ++ m_autoScrollTimerId = -1; ++ m_verticalAutoScrollSpeed = 0; ++ m_horizontalAutoScrollSpeed = 0; ++ ++} ++ ++void WebView::addSearchActions(QList<QAction*>& selectActions, QWebView* view) ++{ ++ // search text ++ const QString selectedText = view->selectedText().simplified(); ++ if (selectedText.isEmpty()) ++ return; ++ ++ KUriFilterData data; ++ data.setData(selectedText); ++ data.setAlternateDefaultSearchProvider(ALTERNATE_DEFAULT_WEB_SHORTCUT); ++ data.setAlternateSearchProviders(ALTERNATE_WEB_SHORTCUTS); ++ ++ if (KUriFilter::self()->filterSearchUri(data, KUriFilter::NormalTextFilter)) { ++ const QString squeezedText = KStringHandler::rsqueeze(selectedText, 20); ++ QAction *action = new QAction(QIcon::fromTheme(data.iconName()), ++ i18nc("Search \"search provider\" for \"text\"", "Search %1 for '%2'", ++ data.searchProvider(), squeezedText), view); ++ action->setData(QUrl(data.uri())); ++ connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(searchProvider())); ++ m_actionCollection->addAction(QL1S("defaultSearchProvider"), action); ++ selectActions.append(action); ++ ++ ++ const QStringList preferredSearchProviders = data.preferredSearchProviders(); ++ if (!preferredSearchProviders.isEmpty()) { ++ KActionMenu* providerList = new KActionMenu(i18nc("Search for \"text\" with", ++ "Search for '%1' with", squeezedText), view); ++ Q_FOREACH(const QString &searchProvider, preferredSearchProviders) { ++ if (searchProvider == data.searchProvider()) ++ continue; ++ ++ QAction *action = new QAction(QIcon::fromTheme(data.iconNameForPreferredSearchProvider(searchProvider)), searchProvider, view); ++ action->setData(data.queryForPreferredSearchProvider(searchProvider)); ++ m_actionCollection->addAction(searchProvider, action); ++ connect(action, SIGNAL(triggered(bool)), m_part->browserExtension(), SLOT(searchProvider())); ++ ++ providerList->addAction(action); ++ } ++ m_actionCollection->addAction(QL1S("searchProviderList"), providerList); ++ selectActions.append(providerList); ++ } ++ } ++} +diff --git b/webkitpart/src/webkitview.h b/webkitpart/src/webkitview.h +new file mode 100644 +index 000000000..2f846f073 +--- /dev/null ++++ b/webkitpart/src/webkitview.h +@@ -0,0 +1,132 @@ ++/* ++ * This file is part of the KDE project. ++ * ++ * Copyright (C) 2007 Trolltech ASA ++ * Copyright (C) 2008 Urs Wolfer <uwolfer @ kde.org> ++ * Copyright (C) 2008 Laurent Montel <montel@kde.org> ++ * Copyright (C) 2009 Dawit Alemayehu <adawit@kde.org> ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Lesser General Public License as published by the ++ * Free Software Foundation; either version 2.1 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 Lesser General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library. If not, see <http://www.gnu.org/licenses/>. ++ * ++ */ ++#ifndef WEBVIEW_H ++#define WEBVIEW_H ++ ++#include <QPointer> ++#include <KParts/BrowserExtension> ++ ++#include <QWebView> ++#include <QtWebKit/QtWebKitVersion> ++#if QTWEBKIT_VERSION >= QT_VERSION_CHECK(5, 602, 3) ++#define HAVE_WEBCONTEXTMENUDATA ++#include <QWebContextMenuData> ++#else ++typedef void* QWebContextMenuData; ++#endif ++ ++class QUrl; ++class WebKitPart; ++ ++class WebView : public QWebView ++{ ++ Q_OBJECT ++public: ++ WebView(WebKitPart* part, QWidget* parent); ++ ~WebView(); ++ ++ /** ++ * Same as QWebPage::load, but with KParts style arguments instead. ++ * ++ * @see KParts::OpenUrlArguments, KParts::BrowserArguments. ++ * ++ * @param url the url to load. ++ * @param args reference to a OpenUrlArguments object. ++ * @param bargs reference to a BrowserArguments object. ++ */ ++ void loadUrl(const QUrl& url, const KParts::OpenUrlArguments& args, const KParts::BrowserArguments& bargs); ++ ++ QWebContextMenuData contextMenuResult() const; ++ ++protected: ++ /** ++ * Reimplemented for internal reasons, the API is not affected. ++ * ++ * @see QWidget::contextMenuEvent ++ * @internal ++ */ ++ void contextMenuEvent(QContextMenuEvent*) Q_DECL_OVERRIDE; ++ ++ /** ++ * Reimplemented for internal reasons, the API is not affected. ++ * ++ * @see QWidget::keyPressEvent ++ * @internal ++ */ ++ void keyPressEvent(QKeyEvent*) Q_DECL_OVERRIDE; ++ ++ /** ++ * Reimplemented for internal reasons, the API is not affected. ++ * ++ * @see QWidget::keyReleaseEvent ++ * @internal ++ */ ++ void keyReleaseEvent(QKeyEvent*) Q_DECL_OVERRIDE; ++ ++ /** ++ * Reimplemented for internal reasons, the API is not affected. ++ * ++ * @see QWidget::mouseReleaseEvent ++ * @internal ++ */ ++ void mouseReleaseEvent(QMouseEvent*) Q_DECL_OVERRIDE; ++ ++ /** ++ * Reimplemented for internal reasons, the API is not affected. ++ * ++ * @see QObject::timerEvent ++ * @internal ++ */ ++ void timerEvent(QTimerEvent*) Q_DECL_OVERRIDE; ++ ++ /** ++ * Reimplemented for internal reasons, the API is not affected. ++ * ++ * @see QWidget::wheelEvent ++ * @internal ++ */ ++ void wheelEvent(QWheelEvent*) Q_DECL_OVERRIDE; ++ ++private Q_SLOTS: ++ void slotStopAutoScroll(); ++ ++private: ++ void editableContentActionPopupMenu(KParts::BrowserExtension::ActionGroupMap&); ++ void selectActionPopupMenu(KParts::BrowserExtension::ActionGroupMap&); ++ void linkActionPopupMenu(KParts::BrowserExtension::ActionGroupMap&); ++ void partActionPopupMenu(KParts::BrowserExtension::ActionGroupMap &); ++ void multimediaActionPopupMenu(KParts::BrowserExtension::ActionGroupMap&); ++ void addSearchActions(QList<QAction*>& selectActions, QWebView*); ++ ++ KActionCollection* m_actionCollection; ++ QWebContextMenuData m_result; ++ QPointer<WebKitPart> m_part; ++ ++ qint32 m_autoScrollTimerId; ++ qint32 m_verticalAutoScrollSpeed; ++ qint32 m_horizontalAutoScrollSpeed; ++ ++ QHash<QString, QChar> m_duplicateLinkElements; ++}; ++ ++#endif // WEBVIEW_H +diff --git b/webkitpart/src/websslinfo.cpp b/webkitpart/src/websslinfo.cpp +new file mode 100644 +index 000000000..7960007d0 +--- /dev/null ++++ b/webkitpart/src/websslinfo.cpp +@@ -0,0 +1,224 @@ ++/* ++ * This file is part of the KDE project. ++ * ++ * Copyright (C) 2009 Dawit Alemayehu <adawit@kde.org> ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Lesser General Public License as published by the ++ * Free Software Foundation; either version 2.1 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 Lesser General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library. If not, see <http://www.gnu.org/licenses/>. ++ * ++ */ ++ ++#include "websslinfo.h" ++ ++#include <QVariant> ++ ++ ++class WebSslInfo::WebSslInfoPrivate ++{ ++public: ++ WebSslInfoPrivate() ++ : usedCipherBits(0), supportedCipherBits(0) {} ++ ++ QUrl url; ++ QString ciphers; ++ QString protocol; ++ QString certErrors; ++ QHostAddress peerAddress; ++ QHostAddress parentAddress; ++ QList<QSslCertificate> certificateChain; ++ ++ int usedCipherBits; ++ int supportedCipherBits; ++}; ++ ++WebSslInfo::WebSslInfo() ++ :d(new WebSslInfo::WebSslInfoPrivate) ++{ ++} ++ ++WebSslInfo::WebSslInfo(const WebSslInfo& other) ++ :d(new WebSslInfo::WebSslInfoPrivate) ++{ ++ *this = other; ++} ++ ++WebSslInfo::~WebSslInfo() ++{ ++ delete d; ++ d = 0; ++} ++ ++bool WebSslInfo::isValid() const ++{ ++ return (d ? !d->peerAddress.isNull() : false); ++} ++ ++QUrl WebSslInfo::url() const ++{ ++ return (d ? d->url : QUrl()); ++} ++ ++QHostAddress WebSslInfo::parentAddress() const ++{ ++ return (d ? d->parentAddress : QHostAddress()); ++} ++ ++QHostAddress WebSslInfo::peerAddress() const ++{ ++ return (d ? d->peerAddress : QHostAddress()); ++} ++ ++QString WebSslInfo::protocol() const ++{ ++ return (d ? d->protocol : QString()); ++} ++ ++QString WebSslInfo::ciphers() const ++{ ++ return (d ? d->ciphers : QString()); ++} ++ ++QString WebSslInfo::certificateErrors() const ++{ ++ return (d ? d->certErrors : QString()); ++} ++ ++int WebSslInfo::supportedChiperBits () const ++{ ++ return (d ? d->supportedCipherBits : 0); ++} ++ ++int WebSslInfo::usedChiperBits () const ++{ ++ return (d ? d->usedCipherBits : 0); ++} ++ ++QList<QSslCertificate> WebSslInfo::certificateChain() const ++{ ++ return (d ? d->certificateChain : QList<QSslCertificate>()); ++} ++ ++WebSslInfo& WebSslInfo::operator=(const WebSslInfo& other) ++{ ++ if (d) { ++ d->ciphers = other.d->ciphers; ++ d->protocol = other.d->protocol; ++ d->certErrors = other.d->certErrors; ++ d->peerAddress = other.d->peerAddress; ++ d->parentAddress = other.d->parentAddress; ++ d->certificateChain = other.d->certificateChain; ++ ++ d->usedCipherBits = other.d->usedCipherBits; ++ d->supportedCipherBits = other.d->supportedCipherBits; ++ d->url = other.d->url; ++ } ++ ++ return *this; ++} ++ ++bool WebSslInfo::saveTo(QMap<QString, QVariant>& data) const ++{ ++ const bool ok = isValid(); ++ if (ok) { ++ data.insert(QStringLiteral("ssl_in_use"), true); ++ data.insert(QStringLiteral("ssl_peer_ip"), d->peerAddress.toString()); ++ data.insert(QStringLiteral("ssl_parent_ip"), d->parentAddress.toString()); ++ data.insert(QStringLiteral("ssl_protocol_version"), d->protocol); ++ data.insert(QStringLiteral("ssl_cipher"), d->ciphers); ++ data.insert(QStringLiteral("ssl_cert_errors"), d->certErrors); ++ data.insert(QStringLiteral("ssl_cipher_used_bits"), d->usedCipherBits); ++ data.insert(QStringLiteral("ssl_cipher_bits"), d->supportedCipherBits); ++ QByteArray certChain; ++ Q_FOREACH(const QSslCertificate& cert, d->certificateChain) ++ certChain += cert.toPem(); ++ data.insert(QStringLiteral("ssl_peer_chain"), certChain); ++ } ++ ++ return ok; ++} ++ ++void WebSslInfo::restoreFrom(const QVariant& value, const QUrl& url, bool reset) ++{ ++ if (reset) { ++ *this = WebSslInfo(); ++ } ++ ++ if (value.isValid() && value.type() == QVariant::Map) { ++ QMap<QString,QVariant> metaData = value.toMap(); ++ if (metaData.value(QStringLiteral("ssl_in_use"), false).toBool()) { ++ setCertificateChain(metaData.value(QStringLiteral("ssl_peer_chain")).toByteArray()); ++ setPeerAddress(metaData.value(QStringLiteral("ssl_peer_ip")).toString()); ++ setParentAddress(metaData.value(QStringLiteral("ssl_parent_ip")).toString()); ++ setProtocol(metaData.value(QStringLiteral("ssl_protocol_version")).toString()); ++ setCiphers(metaData.value(QStringLiteral("ssl_cipher")).toString()); ++ setCertificateErrors(metaData.value(QStringLiteral("ssl_cert_errors")).toString()); ++ setUsedCipherBits(metaData.value(QStringLiteral("ssl_cipher_used_bits")).toString()); ++ setSupportedCipherBits(metaData.value(QStringLiteral("ssl_cipher_bits")).toString()); ++ setUrl(url); ++ } ++ } ++} ++ ++void WebSslInfo::setUrl (const QUrl &url) ++{ ++ if (d) ++ d->url = url; ++} ++ ++void WebSslInfo::setPeerAddress(const QString& address) ++{ ++ if (d) ++ d->peerAddress = address; ++} ++ ++void WebSslInfo::setParentAddress(const QString& address) ++{ ++ if (d) ++ d->parentAddress = address; ++} ++ ++void WebSslInfo::setProtocol(const QString& protocol) ++{ ++ if (d) ++ d->protocol = protocol; ++} ++ ++void WebSslInfo::setCertificateChain(const QByteArray& chain) ++{ ++ if (d) ++ d->certificateChain = QSslCertificate::fromData(chain); ++} ++ ++void WebSslInfo::setCiphers(const QString& ciphers) ++{ ++ if (d) ++ d->ciphers = ciphers; ++} ++ ++void WebSslInfo::setUsedCipherBits(const QString& bits) ++{ ++ if (d) ++ d->usedCipherBits = bits.toInt(); ++} ++ ++void WebSslInfo::setSupportedCipherBits(const QString& bits) ++{ ++ if (d) ++ d->supportedCipherBits = bits.toInt(); ++} ++ ++void WebSslInfo::setCertificateErrors(const QString& certErrors) ++{ ++ if (d) ++ d->certErrors = certErrors; ++} +diff --git b/webkitpart/src/websslinfo.h b/webkitpart/src/websslinfo.h +new file mode 100644 +index 000000000..7c7d09ca7 +--- /dev/null ++++ b/webkitpart/src/websslinfo.h +@@ -0,0 +1,70 @@ ++/* ++ * This file is part of the KDE project. ++ * ++ * Copyright (C) 2009 Dawit Alemayehu <adawit@kde.org> ++ * ++ * This library is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Lesser General Public License as published by the ++ * Free Software Foundation; either version 2.1 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 Lesser General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library. If not, see <http://www.gnu.org/licenses/>. ++ * ++ */ ++#ifndef WEBSSLINFO_H ++#define WEBSSLINFO_H ++ ++//#include <kdemacros.h> ++ ++#include <QUrl> ++#include <QList> ++#include <QString> ++#include <QHostAddress> ++#include <QSslCertificate> ++ ++class WebSslInfo ++{ ++public: ++ WebSslInfo(); ++ WebSslInfo(const WebSslInfo&); ++ virtual ~WebSslInfo(); ++ ++ bool isValid() const; ++ QUrl url() const; ++ QHostAddress peerAddress() const; ++ QHostAddress parentAddress() const; ++ QString ciphers() const; ++ QString protocol() const; ++ QString certificateErrors() const; ++ int supportedChiperBits () const; ++ int usedChiperBits () const; ++ QList<QSslCertificate> certificateChain() const; ++ ++ bool saveTo(QMap<QString, QVariant>&) const; ++ void restoreFrom(const QVariant &, const QUrl& = QUrl(), bool reset = false); ++ ++ void setUrl (const QUrl &url); ++ WebSslInfo& operator = (const WebSslInfo&); ++ ++protected: ++ void setCiphers(const QString& ciphers); ++ void setProtocol(const QString& protocol); ++ void setPeerAddress(const QString& address); ++ void setParentAddress(const QString& address); ++ void setCertificateChain(const QByteArray& chain); ++ void setCertificateErrors(const QString& certErrors); ++ void setUsedCipherBits(const QString& bits); ++ void setSupportedCipherBits(const QString& bits); ++ ++private: ++ class WebSslInfoPrivate; ++ WebSslInfoPrivate* d; ++}; ++ ++#endif // WEBSSLINFO_H +diff --git b/webkitpart/testfiles/embed_tag_test.html b/webkitpart/testfiles/embed_tag_test.html +new file mode 100644 +index 000000000..8afe2d611 +--- /dev/null ++++ b/webkitpart/testfiles/embed_tag_test.html +@@ -0,0 +1,20 @@ ++<html> ++<head> ++ <title> <EMBED> tests</title> ++</head> ++<body> ++ <h1>KDE e.V. Report 2011 Q2</h1> ++ <center> ++ <embed type="application/pdf" src="http://ev.kde.org/reports/ev-quarterly-2011_Q2.pdf" width="75%" height="400"/> ++ </center> ++ <p/> ++ <h1>KDE e.V. Report 2011 Q1</h1> ++ <center> ++ <embed type="application/pdf" src="http://ev.kde.org/reports/ev-quarterly-2011_Q1.pdf" width="75%" height="400"/> ++ </center> ++ <p/> ++ <center> ++ <video src="http://blip.tv/file/get/Sebasje-ThePlasmaDesktopShellInKDE42312.ogv" controls="controls" width="75%" height="450"/> ++ </center> ++</body> ++</html> +diff --git b/webkitpart/testfiles/form_save_restore_test.html b/webkitpart/testfiles/form_save_restore_test.html +new file mode 100644 +index 000000000..d1adaeb76 +--- /dev/null ++++ b/webkitpart/testfiles/form_save_restore_test.html +@@ -0,0 +1,68 @@ ++<html> ++<head> ++ <title>Form save restore test</title> ++</head> ++<body> ++ ++<form name="testform"> ++<label for="testedit">Enter text:</label> ++<input type="text" name="testinputtext" id="testedit"> ++<br> ++<label>Check this box</label> ++<input type="checkbox" name="testinputcheckbox" value="checked"> ++<br> ++<label>File to upload:</label> ++<input type="file" name="testinputfile"> ++<br> ++<input type="radio" name="testinputradio" value="one">One</input> ++<br> ++<input type="radio" name="testinputradio" value="two">Two</input> ++<br> ++<input type="radio" name="testinputradio" value="three">Three</input> ++<br> ++</form> ++ ++<p> ++Enter some text in the box below:<br/> ++<textarea name="testtextarea"></textarea> ++</p> ++ ++<p> ++Disabled text area:<br/> ++<textarea name="testtextarea" disabled></textarea> ++</p> ++ ++<p> ++Read only text area:<br/> ++<textarea name="testtextarea" readonly>This is a read only text area.</textarea> ++</p> ++ ++<p> ++Text area with spell check disabled:<br/> ++<textarea name="testtextarea" spellcheck="false"></textarea> ++</p> ++ ++<p> ++Choose one: ++<select name="testcombobox"> ++<option>First</option> ++<option>Second</option> ++<option>Third</option> ++<option>Fourth</option> ++<option>Fifth</option> ++</select> ++</p><p/> ++ ++<p> ++Select one or more items:<br/> ++<select name="testlist" multiple> ++<option>One</option> ++<option>Two</option> ++<option>Three</option> ++<option>Four</option> ++<option>Five</option> ++</select> ++</p> ++ ++</body> ++</html> +diff --git b/webkitpart/testfiles/frameset_test.html b/webkitpart/testfiles/frameset_test.html +new file mode 100644 +index 000000000..25a295937 +--- /dev/null ++++ b/webkitpart/testfiles/frameset_test.html +@@ -0,0 +1,9 @@ ++<html> ++<head> ++<title><FRAMESET> test</title> ++</head> ++<frameset cols="120,*"> ++ <frame src="frametest/frame_navigation.html" /> ++ <frame src="frametest/frame_a.html" name="showframe" /> ++</frameset> ++</html> +diff --git b/webkitpart/testfiles/frametest/frame_a.html b/webkitpart/testfiles/frametest/frame_a.html +new file mode 100644 +index 000000000..0ea08f3f6 +--- /dev/null ++++ b/webkitpart/testfiles/frametest/frame_a.html +@@ -0,0 +1,7 @@ ++<html> ++<body bgcolor="#8F8FBD"> ++ ++<h3>Frame A</h3> ++ ++</body> ++</html> +diff --git b/webkitpart/testfiles/frametest/frame_b.html b/webkitpart/testfiles/frametest/frame_b.html +new file mode 100644 +index 000000000..fe36a8d98 +--- /dev/null ++++ b/webkitpart/testfiles/frametest/frame_b.html +@@ -0,0 +1,7 @@ ++<html> ++<body bgcolor="#EBC79E"> ++ ++<h3>Frame B</h3> ++ ++</body> ++</html> +\ No newline at end of file +diff --git b/webkitpart/testfiles/frametest/frame_c.html b/webkitpart/testfiles/frametest/frame_c.html +new file mode 100644 +index 000000000..3ed0e0e67 +--- /dev/null ++++ b/webkitpart/testfiles/frametest/frame_c.html +@@ -0,0 +1,7 @@ ++<html> ++<body bgcolor="#FFFFCC"> ++ ++<h3>Frame C</h3> ++<a href="http://www.kde.org">Go to KDE website</a> ++</body> ++</html> +\ No newline at end of file +diff --git b/webkitpart/testfiles/frametest/frame_navigation.html b/webkitpart/testfiles/frametest/frame_navigation.html +new file mode 100644 +index 000000000..3632a0d8b +--- /dev/null ++++ b/webkitpart/testfiles/frametest/frame_navigation.html +@@ -0,0 +1,9 @@ ++<html> ++<body> ++<a href ="frame_a.html" target ="showframe">Frame a</a><br/> ++<a href ="frame_b.html" target ="showframe">Frame b</a><br/> ++<a href ="frame_c.html" target ="showframe">Frame c</a><br/> ++<a href ="frame_d.html" target ="showframe">Invalid frame</a><br/> ++<a href ="https://bugs.kde.org" target ="showframe">bugs.kde.org</a> ++</body> ++</html> +\ No newline at end of file +diff --git b/webkitpart/testfiles/js.html b/webkitpart/testfiles/js.html +new file mode 100644 +index 000000000..4c03c3473 +--- /dev/null ++++ b/webkitpart/testfiles/js.html +@@ -0,0 +1,52 @@ ++<html> ++<head> ++<title>Javascript Link Tests</title> ++<script type="text/javascript"> ++function resize() ++{ ++ window.resizeTo(580, 420); ++} ++ ++function move() ++{ ++ window.moveTo(180, 120); ++} ++ ++function promptAndAlertMessage() ++{ ++ var message = prompt("Enter a message.", ""); ++ alert(message); ++} ++ ++function statusMessage() ++{ ++ window.status = 'A new status message.'; ++} ++ ++function openWindow() ++{ ++ window.open("about:blank", "NewWindowTest1", "width=300, height=400"); ++} ++ ++function openWindowFrameTest() ++{ ++ var new_window = window.open('about:blank','testpage','width=800,height=600'); ++ new_window.location="frameset_test.html"; ++} ++ ++</script> ++</head> ++<body> ++<script type="text/javascript"> ++document.writeln("navigator.appName: " + navigator.appName + "<br />"); ++document.writeln("navigator.appVersion: " + navigator.appVersion + "<br />"); ++</script> ++<h1>Javascript Link Tests</h1> ++<a href="javascript:resize()">resizeTo</a><br /> ++<a href="javascript:move()">moveTo</a><br /> ++<a href="javascript:promptAndAlertMessage()">promptAndAlertMessage</a><br /> ++<a href="javascript:statusMessage()">status</a><br /> ++<a href="javascript:window.open('about:blank', 'NewWindowTest1', 'width=300, height=400')">JS open new window</a><br /> ++<a href="javascript:openWindowFrameTest()">JS open new frameset</a><br /> ++</body> ++</html> +diff --git b/webkitpart/testfiles/link_tests.html b/webkitpart/testfiles/link_tests.html +new file mode 100644 +index 000000000..f2d73007a +--- /dev/null ++++ b/webkitpart/testfiles/link_tests.html +@@ -0,0 +1,136 @@ ++<html> ++<head> ++ <title>Link Tests</title> ++</head> ++<script type="text/javascript"> ++ function delayedRedirect() { ++ setTimeout(window.open("http://kde-look.org/CONTENT/content-files/52338-kÃy.jpg"), 3000) ++ } ++ function openWin(url,name,features) { ++ url = url || '' ++ name = name || '' ++ features = features || 'width=200,height=100' ++ var myWindow = window.open(url,name,features); ++ if (!url) { ++ myWindow.document.write("<p>This is 'myWindow'</p>"); ++ myWindow.focus(); ++ } ++ } ++</script> ++<body> ++<h2>MAILTO Link Tests</h2> ++ <a href="mailto:joe@xyz.com&CC=bob@xyz.com&BCC=bob@xyz.com&attach=%2Fetc%2Fpasswd&subject=hello&body=hello">Email link #1</a> ++ <br/> ++ <a href="mailto:joe@xyz.com">Email link #2</a> ++ <br/> ++<h2>FTP Link Tests</h2> ++ <a href="ftp://ftp.kde.org" target="_blank">FTP link #1 (new window)</a> ++ <br/> ++ <a href="ftp://ftp.kde.org/pub" target="_blank">FTP link #2 (new window)</a> ++ <br/> ++ <a href="ftp://upload.kde.org">FTP link #3</a> ++ <br/> ++ <a href="ftp://ftp.kde.org/pub/kde/README_UPLOAD">Text File Link</a> ++ <br/> ++ <a href="#fragments" target="_top">Anchor test</a> ++ <br/> ++ <a href="#fragments" target="_blank">Anchor test (new window)</a> ++ <br/> ++<h2>HTTP Link Tests</h2> ++ <a href="http://www.kde.org" target="_blank">Web site link (new window)</a> ++ <br/> ++ <a href="http://foo@www.kde.org">Web site link with bogus username</a> ++ <br/> ++ <a href="http://bar@www.kde.org">Web site link with different bogus username</a> ++ <br/> ++ <a href="http://ev.kde.org/reports/ev-quarterly-2012_Q1.pdf">PDF link</a> ++ <br/> ++ <a href="http://ev.kde.org/reports/ev-quarterly-2012_Q1.pdf" target="_blank">PDF link (new window)</a> ++ <br/> ++ <a href="http://ev.kde.org/reports/ev-quarterly-2012_Q1.pdf" target="_blank">Duplicate PDF link (new window)</a> ++ <br/> ++ <a href="http://blip.tv/file/get/Sebasje-WindowManagingFeaturesInKDEPlasma44222.ogg">Movie link</a> ++ <br/> ++ <a href="http://blip.tv/file/get/Sebasje-WindowManagingFeaturesInKDEPlasma44222.ogg" target="_blank">Movie link (new window)</a> ++ <br/> ++ <a href="http://www.ietf.org/rfc/rfc2344.txt">Text Document Link</a> ++ <br/> ++ <a href="http://www.microsoft.com%26item%3Dq209354rexsddiuyjkiuylkuryt2583453453fsesfsdfsfasfdfdsf@www.kde.org/">Bogus link</a> ++ <br/> ++<h2>Javascript Link Tests</h2> ++ <a href="javascript:openWin('http://www.kde.org','', 'width=600,height=600,statusbar=no,toolbar=no')">Open dialog like window link #1</a> ++ <br/> ++ <a href="javascript:openWin('file:///usr/local/src/KDE/git/extragear/kwebkitpart/tests/link_tests.html','','dialog','width=600,height=600,statusbar=no,toolbar=no')">Open dialog like window link #2</a> ++ <br/> ++ <a href="javascript:openWin('http://www.kde.org','', 'width=0,height=0')">Open new window link #2 (might be opened as Tab)</a> ++ <br/> ++ <a href="javascript:openWin('http://ev.kde.org/reports/ev-quarterly-2009Q1.pdf', '_blank', 'width=600,height=600,statusbar=no,toolbar=no')">Open PDF Document (new window)</a> ++ <br/> ++ <a href='empty.html' onclick="openWin('empty.html', 'dz_orders','toolbar=false,height=100,width=100,resizable=1,scrollbars=1')" target='dz_orders'>Javscript + Target test</a> ++ <br/> ++ <a href="javascript:window.close">Close window</a> ++ <br/> ++ <a href="" onmouseover="openWin()">On mouse over open window test</a> ++ <br/> ++ <a href="javascript:setTimeout(delayedRedirect(), 3000)" target="_blank">Redirect test</a> ++ <br/> ++<h2>KDE specific URL Tests</h2> ++ <a href="applications:/Internet/">Text Document Link</a> ++ <br/> ++<h2>Form Tests</h2> ++ <form action="mailto:someone@example.com?CC='bob@example.com&attach=%2fetc%2fpasswd&body=" method="post" enctype="application/x-www-form-urlencoded"> ++ Choose file to upload:<br /> ++ <input type="file" name="upload_file" size="20" /><br/> ++ <input type="submit" value="Send" /> ++ <input type="reset" value="Reset" /> ++ </form> ++ <br/> ++ <a name="fragments"><h2>URL Fragment Test</h2></a> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++ <br/> ++</body> ++</html> +diff --git b/webkitpart/testfiles/meta_tag_refresh_test.html b/webkitpart/testfiles/meta_tag_refresh_test.html +new file mode 100644 +index 000000000..4ea95a59c +--- /dev/null ++++ b/webkitpart/testfiles/meta_tag_refresh_test.html +@@ -0,0 +1,14 @@ ++<html> ++<head> ++ <title>Meta redirect test</title> ++ <meta HTTP-EQUIV="Refresh" CONTENT="10;URL=http://kde.org"> ++</head> ++<body> ++You will be redirected to <a href="http://www.kde.org">kde.org</a> in 10 seconds.<br/> ++<p> ++If the stop button is active (not disabled) after the page has completely loaded, it ++means the rendering engine allows you to cancel <META> based redirect requests. ++Otherwise, you are not able to stop redirects or refresh requests set by web pages. ++</p> ++</body> ++</html> +\ No newline at end of file +diff --git b/webkitpart/tests/CMakeLists.txt b/webkitpart/tests/CMakeLists.txt +new file mode 100644 +index 000000000..85d8f12c6 +--- /dev/null ++++ b/webkitpart/tests/CMakeLists.txt +@@ -0,0 +1,2 @@ ++add_executable(webkitpart_tester webkitpart_tester.cpp) ++target_link_libraries(webkitpart_tester kwebkitpartlib Qt5::Core Qt5::Gui Qt5::Widgets Qt5::WebKitWidgets KF5::I18n KF5::KDELibs4Support) +diff --git b/webkitpart/tests/webkitpart_tester.cpp b/webkitpart/tests/webkitpart_tester.cpp +new file mode 100644 +index 000000000..e4c1e45f6 +--- /dev/null ++++ b/webkitpart/tests/webkitpart_tester.cpp +@@ -0,0 +1,437 @@ ++/* ++ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) ++ * Copyright (C) 2006 George Staikos <staikos@kde.org> ++ * Copyright (C) 2006 Dirk Mueller <mueller@kde.org> ++ * Copyright (C) 2006 Zack Rusin <zack@kde.org> ++ * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org> ++ * ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY ++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR ++ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR ++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY ++ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include <KApplication> ++#include <KAboutData> ++#include <KCmdLineArgs> ++#include <KDebug> ++#include <KIO/AccessManager> ++#include <KUriFilter> ++#include <KInputDialog> ++#include <KLineEdit> ++#include <webkitpart.h> ++ ++#include <QInputDialog> ++ ++//#include <QUiLoader> ++//#include <QWebPage> ++#include <QWebView> ++//#include <QWebFrame> ++#include <QWebSettings> ++//#include <QWebElement> ++//#include <QWebElementCollection> ++ ++#if !defined(QT_NO_PRINTER) ++#include <QPrintPreviewDialog> ++#endif ++ ++#include <QAction> ++#include <QCompleter> ++#include <QMainWindow> ++#include <QMenu> ++#include <QMenuBar> ++#include <QProgressBar> ++#include <QStatusBar> ++#include <QStringListModel> ++#include <QToolBar> ++#include <QToolTip> ++#include <QDir> ++#include <QFile> ++#include <QVector> ++#include <QTextStream> ++#include <QApplication> ++#include <KAboutData> ++#include <KLocalizedString> ++#include <QCommandLineParser> ++ ++ ++class MainWindow : public QMainWindow ++{ ++ Q_OBJECT ++public: ++ MainWindow(const QString& url = QString()): currentZoom(100) { ++ view = new WebKitPart(this); ++ setCentralWidget(view->widget()); ++ ++ connect(view->view(), &QWebView::loadFinished, ++ this, &MainWindow::loadFinished); ++ connect(view->view(), SIGNAL(titleChanged(QString)), ++ this, SLOT(setWindowTitle(QString))); ++ connect(view->view()->page(), SIGNAL(linkHovered(QString)), ++ this, SLOT(showLinkHover(QString))); ++ connect(view->view()->page(), SIGNAL(windowCloseRequested()), this, SLOT(deleteLater())); ++ ++ setupUI(); ++ ++ QUrl qurl(KUriFilter::self()->filteredUri(url, QStringList() << QStringLiteral("kshorturifilter"))); ++ if (qurl.isValid()) { ++ urlEdit->setText(qurl.toEncoded()); ++ view->openUrl(qurl); ++ ++ // the zoom values are chosen to be like in Mozilla Firefox 3 ++ zoomLevels << 30 << 50 << 67 << 80 << 90; ++ zoomLevels << 100; ++ zoomLevels << 110 << 120 << 133 << 150 << 170 << 200 << 240 << 300; ++ } ++ } ++ ++ QWebPage* webPage() const { ++ return view->view()->page(); ++ } ++ ++ QWebView* webView() const { ++ return view->view(); ++ } ++ ++protected slots: ++ ++ void changeLocation() { ++ QUrl url (KUriFilter::self()->filteredUri(urlEdit->text(), QStringList() << QStringLiteral("kshorturifilter"))); ++ view->openUrl(url); ++ view->view()->setFocus(Qt::OtherFocusReason); ++ } ++ ++ void loadFinished() { ++ urlEdit->setText(view->url().toString()); ++ ++ QUrl::FormattingOptions opts; ++ opts |= QUrl::RemoveScheme; ++ opts |= QUrl::RemoveUserInfo; ++ opts |= QUrl::StripTrailingSlash; ++ QString s = view->url().toString(opts); ++ s = s.mid(2); ++ if (s.isEmpty()) ++ return; ++ ++ if (!urlList.contains(s)) ++ urlList += s; ++ urlModel.setStringList(urlList); ++ } ++ ++ void showLinkHover(const QString &link) { ++ statusBar()->showMessage(link); ++ } ++ ++ void zoomIn() { ++ int i = zoomLevels.indexOf(currentZoom); ++ Q_ASSERT(i >= 0); ++ if (i < zoomLevels.count() - 1) ++ currentZoom = zoomLevels[i + 1]; ++ ++ view->view()->setZoomFactor(qreal(currentZoom)/100.0); ++ } ++ ++ void zoomOut() { ++ int i = zoomLevels.indexOf(currentZoom); ++ Q_ASSERT(i >= 0); ++ if (i > 0) ++ currentZoom = zoomLevels[i - 1]; ++ ++ view->view()->setZoomFactor(qreal(currentZoom)/100.0); ++ } ++ ++ void resetZoom() ++ { ++ currentZoom = 100; ++ view->view()->setZoomFactor(1.0); ++ } ++ ++ void toggleZoomTextOnly(bool b) ++ { ++// view->view()->page()->settings()->setAttribute(QWebSettings::ZoomTextOnly, b); ++ } ++ ++ void print() { ++#if !defined(QT_NO_PRINTER) ++ QScopedPointer<QPrintPreviewDialog> dlg (new QPrintPreviewDialog(this)); ++ connect(dlg.data(), SIGNAL(paintRequested(QPrinter*)), ++ view, SLOT(print(QPrinter*))); ++ dlg->exec(); ++#endif ++ } ++ ++ void setEditable(bool on) { ++// view->view()->page()->setContentEditable(on); ++ formatMenuAction->setVisible(on); ++ } ++ ++ void dumpHtml() { ++ view->view()->page()->toHtml([](const QString& text) { ++ kDebug() << "HTML: " << text; ++ }); ++ } ++ ++ void selectElements() { ++ bool ok; ++ QString str = QInputDialog::getText(this, i18nc("input dialog window title for selecting html elements", "Select elements"), ++ i18nc("input dialog text for selecting html elements", "Choose elements"), QLineEdit::Normal, ++ QStringLiteral("a"), &ok); ++ if (ok && !str.isEmpty()) { ++ //QWebElementCollection collection = view->page()->mainFrame()->findAllElements(str); ++ //const int count = collection.count(); ++ //for (int i=0; i < count; i++) ++ // collection.at(i).setStyleProperty("background-color", "yellow"); ++ //statusBar()->showMessage(i18np("%1 element selected", "%1 elements selected", count), 5000); ++ } ++ } ++ ++public slots: ++ ++ void newWindow(const QString &url = QString()) { ++ MainWindow *mw = new MainWindow(url); ++ mw->show(); ++ } ++ ++private: ++ ++ QVector<int> zoomLevels; ++ int currentZoom; ++ ++ // create the status bar, tool bar & menu ++ void setupUI() { ++ progress = new QProgressBar(this); ++ progress->setRange(0, 100); ++ progress->setMinimumSize(100, 20); ++ progress->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); ++ progress->hide(); ++ statusBar()->addPermanentWidget(progress); ++ ++ connect(view->view(), SIGNAL(loadProgress(int)), progress, SLOT(show())); ++ connect(view->view(), SIGNAL(loadProgress(int)), progress, SLOT(setValue(int))); ++ connect(view->view(), SIGNAL(loadFinished(bool)), progress, SLOT(hide())); ++ ++ urlEdit = new KLineEdit(this); ++ urlEdit->setSizePolicy(QSizePolicy::Expanding, urlEdit->sizePolicy().verticalPolicy()); ++ connect(urlEdit, SIGNAL(returnPressed()), ++ SLOT(changeLocation())); ++ QCompleter *completer = new QCompleter(this); ++ urlEdit->setCompleter(completer); ++ completer->setModel(&urlModel); ++ ++ QToolBar *bar = addToolBar(QStringLiteral("Navigation")); ++ bar->addAction(view->view()->pageAction(QWebPage::Back)); ++ bar->addAction(view->view()->pageAction(QWebPage::Forward)); ++ bar->addAction(view->view()->pageAction(QWebPage::Reload)); ++ bar->addAction(view->view()->pageAction(QWebPage::Stop)); ++ bar->addWidget(urlEdit); ++ ++ QMenu *fileMenu = menuBar()->addMenu(i18n("&File")); ++ QAction *newWindow = fileMenu->addAction(i18n("New Window"), this, SLOT(newWindow())); ++ ++ fileMenu->addAction(i18n("Print"), this, SLOT(print())); ++ fileMenu->addAction(i18n("Close"), this, SLOT(close())); ++ ++ QMenu *editMenu = menuBar()->addMenu(i18n("&Edit")); ++ editMenu->addAction(view->view()->pageAction(QWebPage::Undo)); ++ editMenu->addAction(view->view()->pageAction(QWebPage::Redo)); ++ editMenu->addSeparator(); ++ editMenu->addAction(view->view()->pageAction(QWebPage::Cut)); ++ editMenu->addAction(view->view()->pageAction(QWebPage::Copy)); ++ editMenu->addAction(view->view()->pageAction(QWebPage::Paste)); ++ editMenu->addSeparator(); ++ QAction *setEditable = editMenu->addAction(i18n("Set Editable"), this, SLOT(setEditable(bool))); ++ setEditable->setCheckable(true); ++ ++ QMenu *viewMenu = menuBar()->addMenu(i18n("&View")); ++ viewMenu->addAction(view->view()->pageAction(QWebPage::Stop)); ++ viewMenu->addAction(view->view()->pageAction(QWebPage::Reload)); ++ viewMenu->addSeparator(); ++ QAction *zoomIn = viewMenu->addAction(i18n("Zoom &In"), this, SLOT(zoomIn())); ++ QAction *zoomOut = viewMenu->addAction(i18n("Zoom &Out"), this, SLOT(zoomOut())); ++ QAction *resetZoom = viewMenu->addAction(i18n("Reset Zoom"), this, SLOT(resetZoom())); ++ QAction *zoomTextOnly = viewMenu->addAction(i18n("Zoom Text Only"), this, SLOT(toggleZoomTextOnly(bool))); ++ zoomTextOnly->setCheckable(true); ++ zoomTextOnly->setChecked(false); ++ viewMenu->addSeparator(); ++ viewMenu->addAction(i18n("Dump HTML"), this, SLOT(dumpHtml())); ++ ++#if 0 ++ QMenu *formatMenu = new QMenu(i18n("F&ormat")); ++ formatMenuAction = menuBar()->addMenu(formatMenu); ++ formatMenuAction->setVisible(false); ++ formatMenu->addAction(view->view()->pageAction(QWebPage::ToggleBold)); ++ formatMenu->addAction(view->view()->pageAction(QWebPage::ToggleItalic)); ++ formatMenu->addAction(view->view()->pageAction(QWebPage::ToggleUnderline)); ++ QMenu *writingMenu = formatMenu->addMenu(i18n("Writing Direction")); ++ writingMenu->addAction(view->view()->pageAction(QWebPage::SetTextDirectionDefault)); ++ writingMenu->addAction(view->view()->pageAction(QWebPage::SetTextDirectionLeftToRight)); ++ writingMenu->addAction(view->view()->pageAction(QWebPage::SetTextDirectionRightToLeft)); ++#endif ++ newWindow->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_N)); ++ view->view()->pageAction(QWebPage::Back)->setShortcut(QKeySequence::Back); ++ view->view()->pageAction(QWebPage::Stop)->setShortcut(Qt::Key_Escape); ++ view->view()->pageAction(QWebPage::Forward)->setShortcut(QKeySequence::Forward); ++ view->view()->pageAction(QWebPage::Reload)->setShortcut(QKeySequence::Refresh); ++ view->view()->pageAction(QWebPage::Undo)->setShortcut(QKeySequence::Undo); ++ view->view()->pageAction(QWebPage::Redo)->setShortcut(QKeySequence::Redo); ++ view->view()->pageAction(QWebPage::Cut)->setShortcut(QKeySequence::Cut); ++ view->view()->pageAction(QWebPage::Copy)->setShortcut(QKeySequence::Copy); ++ view->view()->pageAction(QWebPage::Paste)->setShortcut(QKeySequence::Paste); ++ zoomIn->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Plus)); ++ zoomOut->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Minus)); ++ resetZoom->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_0)); ++// view->view()->pageAction(QWebPage::ToggleBold)->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_B)); ++// view->view()->pageAction(QWebPage::ToggleItalic)->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_I)); ++// view->view()->pageAction(QWebPage::ToggleUnderline)->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_U)); ++ ++ QMenu *toolsMenu = menuBar()->addMenu(i18n("&Tools")); ++ toolsMenu->addAction(i18n("Select elements..."), this, SLOT(selectElements())); ++ ++ } ++ ++ WebKitPart *view; ++ KLineEdit *urlEdit; ++ QProgressBar *progress; ++ ++ QAction *formatMenuAction; ++ ++ QStringList urlList; ++ QStringListModel urlModel; ++}; ++ ++class URLLoader : public QObject ++{ ++ Q_OBJECT ++public: ++ URLLoader(QWebView* view, const QString& inputFileName) ++ : m_view(view) ++ , m_stdOut(stdout) ++ { ++ init(inputFileName); ++ } ++ ++public slots: ++ void loadNext() ++ { ++ QString qstr; ++ if (getUrl(qstr)) { ++ QUrl url(qstr, QUrl::StrictMode); ++ if (url.isValid()) { ++ m_stdOut << "Loading " << qstr << " ......" << endl; ++ m_view->load(url); ++ } else ++ loadNext(); ++ } else ++ disconnect(m_view, 0, this, 0); ++ } ++ ++private: ++ void init(const QString& inputFileName) ++ { ++ QFile inputFile(inputFileName); ++ if (inputFile.open(QIODevice::ReadOnly | QIODevice::Text)) { ++ QTextStream stream(&inputFile); ++ QString line; ++ while (true) { ++ line = stream.readLine(); ++ if (line.isNull()) ++ break; ++ m_urls.append(line); ++ } ++ } else { ++ kDebug() << "Can't open list file"; ++ exit(0); ++ } ++ m_index = 0; ++ inputFile.close(); ++ } ++ ++ bool getUrl(QString& qstr) ++ { ++ if (m_index == m_urls.size()) ++ return false; ++ ++ qstr = m_urls[m_index++]; ++ return true; ++ } ++ ++private: ++ QVector<QString> m_urls; ++ int m_index; ++ QWebView* m_view; ++ QTextStream m_stdOut; ++}; ++ ++ ++int main(int argc, char **argv) ++{ ++ KAboutData about(QStringLiteral("KDELauncher"), i18n("KDELauncher"), QStringLiteral("0.0000013")); ++ QApplication app(argc, argv); ++ QCommandLineParser parser; ++ KAboutData::setApplicationData(about); ++ parser.addVersionOption(); ++ parser.addHelpOption(); ++ //PORTING SCRIPT: adapt aboutdata variable if necessary ++ about.setupCommandLine(&parser); ++ parser.process(app); ++ about.processCommandLine(&parser); ++ ++ QString url = QStringLiteral("%1/%2").arg(QDir::homePath()).arg(QStringLiteral("index.html")); ++ ++// QWebSettings::globalSettings()->setMaximumPagesInCache(4); ++ ++// QWebSettings::setObjectCacheCapacities((16*1024*1024) / 8, (16*1024*1024) / 8, 16*1024*1024); ++ ++ QWebSettings::globalSettings()->setAttribute(QWebSettings::PluginsEnabled, true); ++// QWebSettings::globalSettings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true); ++ ++ const QStringList args = app.arguments(); ++ ++ if (args.contains(QStringLiteral("-r"))) { ++ // robotized ++ QString listFile = args.at(2); ++ if (!(args.count() == 3) && QFile::exists(listFile)) { ++ kDebug() << "Usage: KDELauncher -r listfile"; ++ exit(0); ++ } ++ MainWindow window; ++ QWebView *view = window.webView(); ++ URLLoader loader(view, listFile); ++ QObject::connect(view, SIGNAL(loadFinished(bool)), &loader, SLOT(loadNext())); ++ loader.loadNext(); ++ window.show(); ++ return app.exec(); ++ } else { ++ if (args.count() > 1) ++ url = args.at(1); ++ ++ MainWindow window(url); ++ ++ // Opens every given urls in new windows ++ for (int i = 2; i < args.count(); i++) ++ window.newWindow(args.at(i)); ++ ++ window.show(); ++ return app.exec(); ++ } ++} ++ ++#include "webkitpart_tester.moc" +diff --git b/webkitpart/webkitpart.lsm b/webkitpart/webkitpart.lsm +new file mode 100644 +index 000000000..1b94c5a24 +--- /dev/null ++++ b/webkitpart/webkitpart.lsm +@@ -0,0 +1,18 @@ ++Begin3 ++Title: webkitpart ++Version: 1.2.0 ++Entered-date: 06APR2011 ++Description: A WebKit browser component for KDE (KPart) ++Keywords: webkit, webkitpart ++Author: Trolltech ASA ++ Urs Wolfer <uwolfer @ kde.org> ++ Laurent Montel <montel@kde.org> ++ Dawit Alemayehu <adawit@kde.org> ++ Sune Vuorela <sune@kde.org> ++Maintained-by: Sune Vuorela <sune@kde.org> ++Primary-site: ++Home-Page: ++Original-site: None ++Platforms: KF5 and higher ++Copying-policy: LGPL ++End |