summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/webtab/clicktoflash.cpp135
-rw-r--r--src/webtab/clicktoflash.h65
-rw-r--r--src/webtab/messagebar.cpp71
-rw-r--r--src/webtab/messagebar.h54
-rw-r--r--src/webtab/networkaccessmanager.cpp120
-rw-r--r--src/webtab/networkaccessmanager.h59
-rw-r--r--src/webtab/previewselectorbar.cpp132
-rw-r--r--src/webtab/previewselectorbar.h67
-rw-r--r--src/webtab/protocolhandler.cpp386
-rw-r--r--src/webtab/protocolhandler.h83
-rw-r--r--src/webtab/searchenginebar.cpp93
-rw-r--r--src/webtab/searchenginebar.h55
-rw-r--r--src/webtab/sslinfo.ui392
-rw-r--r--src/webtab/sslinfodialog.cpp176
-rw-r--r--src/webtab/sslinfodialog.h79
-rw-r--r--src/webtab/walletbar.cpp103
-rw-r--r--src/webtab/walletbar.h66
-rw-r--r--src/webtab/webpage.cpp777
-rw-r--r--src/webtab/webpage.h114
-rw-r--r--src/webtab/webpluginfactory.cpp93
-rw-r--r--src/webtab/webpluginfactory.h65
-rw-r--r--src/webtab/websslinfo.cpp232
-rw-r--r--src/webtab/websslinfo.h78
-rw-r--r--src/webtab/webtab.cpp419
-rw-r--r--src/webtab/webtab.h131
-rw-r--r--src/webtab/webview.cpp1273
-rw-r--r--src/webtab/webview.h159
27 files changed, 5477 insertions, 0 deletions
diff --git a/src/webtab/clicktoflash.cpp b/src/webtab/clicktoflash.cpp
new file mode 100644
index 00000000..baa61367
--- /dev/null
+++ b/src/webtab/clicktoflash.cpp
@@ -0,0 +1,135 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009 by Benjamin C. Meyer <ben@meyerhome.net>
+* Copyright (C) 2010-2011 by Matthieu Gicquel <matgic78@gmail.com>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "clicktoflash.h"
+#include "clicktoflash.moc"
+
+// KDE Includes
+#include <KLocalizedString>
+
+// Qt Includes
+#include <QHBoxLayout>
+#include <QToolButton>
+
+#include <QWebElement>
+#include <QWebFrame>
+#include <QWebView>
+
+
+ClickToFlash::ClickToFlash(const QUrl &pluginUrl, QWidget *parent)
+ : QWidget(parent)
+ , m_url(pluginUrl)
+{
+ QHBoxLayout *l = new QHBoxLayout(this);
+ setLayout(l);
+
+ QToolButton *button = new QToolButton(this);
+ button->setPopupMode(QToolButton::InstantPopup);
+ button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ button->setText(i18n("Load Plugin"));
+ button->setAutoRaise(false);
+ layout()->addWidget(button);
+ connect(button, SIGNAL(clicked(bool)), this, SLOT(load()));
+}
+
+
+void ClickToFlash::load()
+{
+ QWidget *parent = parentWidget();
+ QWebView *view = 0;
+ while (parent)
+ {
+ if (QWebView *aView = qobject_cast<QWebView*>(parent))
+ {
+ view = aView;
+ break;
+ }
+ parent = parent->parentWidget();
+ }
+ if (!view)
+ return;
+
+ const QString selector = QL1S("%1[type=\"application/x-shockwave-flash\"]");
+
+ hide();
+
+ QList<QWebFrame*> frames;
+ frames.append(view->page()->mainFrame());
+ while (!frames.isEmpty())
+ {
+ QWebFrame *frame = frames.takeFirst();
+ QWebElement docElement = frame->documentElement();
+
+ QWebElementCollection elements;
+ elements.append(docElement.findAll(selector.arg(QL1S("object"))));
+ elements.append(docElement.findAll(selector.arg(QL1S("embed"))));
+
+ Q_FOREACH(QWebElement element, elements)
+ {
+ if (checkElement(element))
+ {
+ QWebElement substitute = element.clone();
+ emit signalLoadClickToFlash(true);
+ element.replace(substitute);
+ deleteLater();
+ return;
+ }
+ }
+ frames += frame->childFrames();
+ }
+}
+
+
+bool ClickToFlash::checkElement(QWebElement el)
+{
+ QString checkString;
+ QString urlString;
+
+ checkString = QUrl(el.attribute("src")).toString(QUrl::RemoveQuery);
+ urlString = m_url.toString(QUrl::RemoveQuery);
+
+ if (urlString.contains(checkString))
+ return true;
+
+ QWebElementCollection collec = el.findAll("*");
+ int i = 0;
+ while (i < collec.count())
+ {
+ QWebElement el = collec.at(i);
+
+ checkString = QUrl(el.attribute("src")).toString(QUrl::RemoveQuery);
+ urlString = m_url.toString(QUrl::RemoveQuery);
+
+ if (urlString.contains(checkString))
+ return true;
+
+ i++;
+ }
+
+ return false;
+}
diff --git a/src/webtab/clicktoflash.h b/src/webtab/clicktoflash.h
new file mode 100644
index 00000000..fcafea59
--- /dev/null
+++ b/src/webtab/clicktoflash.h
@@ -0,0 +1,65 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009 by Benjamin C. Meyer <ben@meyerhome.net>
+* Copyright (C) 2010-2011 by Matthieu Gicquel <matgic78@gmail.com>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+#ifndef CLICKTOFLASH_H
+#define CLICKTOFLASH_H
+
+
+// Rekonq Includes
+#include "rekonq_defines.h"
+
+// Qt Includes
+#include <QUrl>
+#include <QWidget>
+
+// Forward Declarations
+class QWebElement;
+
+
+class REKONQ_TESTS_EXPORT ClickToFlash : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit ClickToFlash(const QUrl &pluginUrl, QWidget *parent = 0);
+
+Q_SIGNALS:
+ void signalLoadClickToFlash(bool);
+
+private Q_SLOTS:
+ void load();
+
+private:
+ bool checkElement(QWebElement el);
+
+ /**
+ used to find the right QWebElement between the ones of the different plugins
+ */
+ const QUrl m_url;
+};
+
+#endif // CLICKTOFLASH_H
diff --git a/src/webtab/messagebar.cpp b/src/webtab/messagebar.cpp
new file mode 100644
index 00000000..0e89ac56
--- /dev/null
+++ b/src/webtab/messagebar.cpp
@@ -0,0 +1,71 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2010-2011 by Pierre Rossi <pierre dot rossi at gmail dot com>
+* Copyright (C) 2011 by Andrea Diamantini <adjam7 at gmail dot com>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "messagebar.h"
+#include "messagebar.moc"
+
+// KDE Includes
+#include <KIcon>
+#include <KIconLoader>
+#include <KLocalizedString>
+
+// Qt Includes
+#include <QAction>
+
+
+MessageBar::MessageBar(const QString &message, QWidget *parent)
+ : KMessageWidget(parent)
+{
+ connect(this, SIGNAL(accepted()), this, SLOT(hideAndDelete()));
+ connect(this, SIGNAL(rejected()), this, SLOT(hideAndDelete()));
+
+ setMessageType(KMessageWidget::Warning);
+
+ QSize sz = size();
+ sz.setWidth(qobject_cast<QWidget *>(parent)->size().width());
+ resize(sz);
+
+ setCloseButtonVisible(false);
+
+ setText(message);
+
+ QAction *acceptAction = new QAction(i18n("Yes"), this);
+ connect(acceptAction, SIGNAL(triggered(bool)), this, SIGNAL(accepted()));
+ addAction(acceptAction);
+
+ QAction *rejectAction = new QAction(i18n("No"), this);
+ connect(rejectAction, SIGNAL(triggered(bool)), this, SIGNAL(rejected()));
+ addAction(rejectAction);
+}
+
+
+void MessageBar::hideAndDelete()
+{
+ animatedHide();
+ deleteLater();
+}
diff --git a/src/webtab/messagebar.h b/src/webtab/messagebar.h
new file mode 100644
index 00000000..bbf5d5d4
--- /dev/null
+++ b/src/webtab/messagebar.h
@@ -0,0 +1,54 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2010-2011 by Pierre Rossi <pierre dot rossi at gmail dot com>
+* Copyright (C) 2011 by Andrea Diamantini <adjam7 at gmail dot com>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+#ifndef MESSAGEBAR_H
+#define MESSAGEBAR_H
+
+// Rekonq Includes
+#include "rekonq_defines.h"
+
+// KDE Includes
+#include <KMessageWidget>
+
+
+class REKONQ_TESTS_EXPORT MessageBar : public KMessageWidget
+{
+ Q_OBJECT
+
+public:
+ explicit MessageBar(const QString & message, QWidget *parent);
+
+private Q_SLOTS:
+ void hideAndDelete();
+
+Q_SIGNALS:
+ void accepted();
+ void rejected();
+};
+
+
+#endif // MESSAGEBAR_H
diff --git a/src/webtab/networkaccessmanager.cpp b/src/webtab/networkaccessmanager.cpp
new file mode 100644
index 00000000..dc10da1b
--- /dev/null
+++ b/src/webtab/networkaccessmanager.cpp
@@ -0,0 +1,120 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007-2008 Trolltech ASA. All rights reserved
+* Copyright (C) 2008-2012 by Andrea Diamantini <adjam7 at gmail dot com>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+
+// Self Includes
+#include "networkaccessmanager.h"
+#include "networkaccessmanager.moc"
+
+// Local Includes
+#include "adblockmanager.h"
+#include "application.h"
+#include "webpage.h"
+
+// KDE Includes
+#include <KLocale>
+#include <KProtocolManager>
+
+// Qt Includes
+#include <QNetworkReply>
+#include <QTimer>
+
+
+class NullNetworkReply : public QNetworkReply
+{
+public:
+ NullNetworkReply(const QNetworkRequest &req, QObject* parent = 0)
+ : QNetworkReply(parent)
+ {
+ setRequest(req);
+ setUrl(req.url());
+ setHeader(QNetworkRequest::ContentLengthHeader, 0);
+ setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");
+ setError(QNetworkReply::ContentAccessDenied, i18n("Null reply"));
+ setAttribute(QNetworkRequest::User, QNetworkReply::ContentAccessDenied);
+ QTimer::singleShot(0, this, SIGNAL(finished()));
+ }
+
+ virtual void abort() {}
+ virtual qint64 bytesAvailable() const
+ {
+ return 0;
+ }
+
+protected:
+ virtual qint64 readData(char*, qint64)
+ {
+ return -1;
+ }
+};
+
+
+// ----------------------------------------------------------------------------------------------
+
+
+NetworkAccessManager::NetworkAccessManager(QObject *parent)
+ : AccessManager(parent)
+{
+ QString c = KGlobal::locale()->language();
+
+ if (c == QL1S("C"))
+ c = QL1S("en-US");
+ else
+ c = c.replace(QL1C('_') , QL1C('-'));
+
+ c.append(QL1S(", en-US; q=0.8, en; q=0.6"));
+
+ _acceptLanguage = c.toLatin1();
+}
+
+
+QNetworkReply *NetworkAccessManager::createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *outgoingData)
+{
+ WebPage *parentPage = qobject_cast<WebPage *>(parent());
+
+ // NOTE: This to get sure we are NOT serving unused requests
+ if (!parentPage)
+ return new NullNetworkReply(request, this);
+
+ QNetworkReply *reply = 0;
+
+ // set our "nice" accept-language header...
+ QNetworkRequest req = request;
+ req.setRawHeader("Accept-Language", _acceptLanguage);
+
+ // Handle GET operations with AdBlock
+ if (op == QNetworkAccessManager::GetOperation)
+ reply = rApp->adblockManager()->block(req, parentPage);
+
+ if (!reply)
+ reply = AccessManager::createRequest(op, req, outgoingData);
+
+ if (parentPage->hasNetworkAnalyzerEnabled())
+ emit networkData(op, req, reply);
+
+ return reply;
+}
diff --git a/src/webtab/networkaccessmanager.h b/src/webtab/networkaccessmanager.h
new file mode 100644
index 00000000..5c877bdf
--- /dev/null
+++ b/src/webtab/networkaccessmanager.h
@@ -0,0 +1,59 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007-2008 Trolltech ASA. All rights reserved
+* Copyright (C) 2008-2012 by Andrea Diamantini <adjam7 at gmail dot com>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+#ifndef NETWORKACCESSMANAGER_H
+#define NETWORKACCESSMANAGER_H
+
+
+// Rekonq Includes
+#include "rekonq_defines.h"
+
+// KDE Includes
+#include <KIO/AccessManager>
+
+// Qt Includes
+#include <QByteArray>
+
+
+class REKONQ_TESTS_EXPORT NetworkAccessManager : public KIO::Integration::AccessManager
+{
+ Q_OBJECT
+
+public:
+ NetworkAccessManager(QObject *parent);
+
+protected:
+ virtual QNetworkReply *createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *outgoingData = 0);
+
+Q_SIGNALS:
+ void networkData(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QNetworkReply *reply);
+
+private:
+ QByteArray _acceptLanguage;
+};
+
+#endif // NETWORKACCESSMANAGER_H
diff --git a/src/webtab/previewselectorbar.cpp b/src/webtab/previewselectorbar.cpp
new file mode 100644
index 00000000..b743e3c9
--- /dev/null
+++ b/src/webtab/previewselectorbar.cpp
@@ -0,0 +1,132 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2010 by Matthieu Gicquel <matgic78 at gmail dot com>
+* Copyright (C) 2010-2012 by Andrea Diamantini <adjam7 at gmail dot com>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "previewselectorbar.h"
+#include "previewselectorbar.moc"
+
+// Auto Includes
+#include "rekonq.h"
+
+// Local Include
+#include "application.h"
+#include "mainwindow.h"
+#include "webpage.h"
+#include "webtab.h"
+#include "websnap.h"
+
+// KDE Includes
+#include <KIcon>
+#include <KLocalizedString>
+
+// Qt Includes
+#include <QAction>
+
+
+PreviewSelectorBar::PreviewSelectorBar(int index, QWidget* parent)
+ : KMessageWidget(parent)
+ , m_previewIndex(index)
+ , m_insertAction(0)
+{
+ setMessageType(KMessageWidget::Information);
+
+ QSize sz = size();
+ sz.setWidth(qobject_cast<QWidget *>(parent)->size().width());
+ resize(sz);
+
+ setCloseButtonVisible(false);
+
+ setText(i18n("Please open up the webpage you want to add as favorite"));
+
+ m_insertAction = new QAction(KIcon("insert-image"), i18n("Set to This Page"), this);
+ connect(m_insertAction, SIGNAL(triggered(bool)), this, SLOT(clicked()));
+ addAction(m_insertAction);
+}
+
+
+void PreviewSelectorBar::verifyUrl()
+{
+
+ if (rApp->mainWindow()->currentTab()->page()->mainFrame()->url().scheme() != "about")
+ {
+ m_insertAction->setEnabled(true);
+ m_insertAction->setToolTip("");
+ }
+ else
+ {
+ m_insertAction->setEnabled(false);
+ m_insertAction->setToolTip(i18n("You cannot add this webpage as favorite"));
+ }
+}
+
+
+void PreviewSelectorBar::loadProgress()
+{
+ m_insertAction->setEnabled(false);
+ m_insertAction->setToolTip(i18n("Page is loading..."));
+}
+
+
+void PreviewSelectorBar::loadFinished()
+{
+ m_insertAction->setEnabled(true);
+ m_insertAction->setToolTip("");
+
+ verifyUrl();
+}
+
+
+void PreviewSelectorBar::clicked()
+{
+ WebPage *page = rApp->mainWindow()->currentTab()->page();
+
+ if (page)
+ {
+ KUrl url = page->mainFrame()->url();
+ QStringList names = ReKonfig::previewNames();
+ QStringList urls = ReKonfig::previewUrls();
+
+ //cleanup the previous image from the cache (useful to refresh the snapshot)
+ QFile::remove(WebSnap::imagePathFromUrl(urls.at(m_previewIndex)));
+ QPixmap preview = WebSnap::renderPagePreview(*page);
+ preview.save(WebSnap::imagePathFromUrl(url));
+
+ urls.replace(m_previewIndex, url.toMimeDataString());
+ names.replace(m_previewIndex, page->mainFrame()->title());
+
+ ReKonfig::setPreviewNames(names);
+ ReKonfig::setPreviewUrls(urls);
+
+ ReKonfig::self()->writeConfig();
+
+
+ page->mainFrame()->load(KUrl("about:favorites"));
+ }
+
+ animatedHide();
+ deleteLater();
+}
diff --git a/src/webtab/previewselectorbar.h b/src/webtab/previewselectorbar.h
new file mode 100644
index 00000000..fa54303d
--- /dev/null
+++ b/src/webtab/previewselectorbar.h
@@ -0,0 +1,67 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2010 by Matthieu Gicquel <matgic78 at gmail dot com>
+* Copyright (C) 2010-2012 by Andrea Diamantini <adjam7 at gmail dot com>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+#ifndef PREVIEWSELECTORBAR_H
+#define PREVIEWSELECTORBAR_H
+
+
+// Rekonq Includes
+#include "rekonq_defines.h"
+
+// KDE Includes
+#include <KMessageWidget>
+
+// Forward Declarations
+class QAction;
+
+
+class REKONQ_TESTS_EXPORT PreviewSelectorBar : public KMessageWidget
+{
+ Q_OBJECT
+
+public:
+ PreviewSelectorBar(int index, QWidget *parent);
+
+ inline void setIndex(int index)
+ {
+ m_previewIndex = index;
+ }
+
+private Q_SLOTS:
+ void clicked();
+
+ void loadProgress();
+ void loadFinished();
+
+ void verifyUrl();
+
+private:
+ int m_previewIndex;
+ QAction *m_insertAction;
+};
+
+#endif // PREVIEWSELECTORBAR_H
diff --git a/src/webtab/protocolhandler.cpp b/src/webtab/protocolhandler.cpp
new file mode 100644
index 00000000..186b93d3
--- /dev/null
+++ b/src/webtab/protocolhandler.cpp
@@ -0,0 +1,386 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2010-2012 by Andrea Diamantini <adjam7 at gmail dot com>
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "protocolhandler.h"
+#include "protocolhandler.moc"
+
+// Auto Includes
+#include "rekonq.h"
+
+// Local Includes
+#include "application.h"
+#include "historymanager.h"
+#include "mainview.h"
+#include "mainwindow.h"
+#include "newtabpage.h"
+#include "urlbar.h"
+#include "webpage.h"
+#include "webtab.h"
+
+// KDE Includes
+#include <KIO/Job>
+#include <KDirLister>
+#include <KLocale>
+#include <KLocalizedString>
+#include <KMessageBox>
+#include <KProcess>
+#include <KStandardDirs>
+#include <KToolInvocation>
+#include <KProtocolInfo>
+#include <KRun>
+
+// Qt Includes
+#include <QNetworkRequest>
+#include <QWebFrame>
+#include <QTextDocument>
+
+
+static bool fileItemListLessThan(const KFileItem &s1, const KFileItem &s2)
+{
+ return s1.name().toLower() < s2.name().toLower();
+}
+
+
+static KFileItemList sortFileList(const KFileItemList &list)
+{
+ KFileItemList orderedList, dirList, fileList;
+
+ // order dirs before files..
+ Q_FOREACH(const KFileItem & item, list)
+ {
+ if (item.isDir())
+ dirList << item;
+ else
+ fileList << item;
+ }
+ qStableSort(dirList.begin(), dirList.end(), fileItemListLessThan);
+ qStableSort(fileList.begin(), fileList.end(), fileItemListLessThan);
+
+ orderedList << dirList;
+ orderedList << fileList;
+
+ return orderedList;
+}
+
+
+// -------------------------------------------------------------------------------------------
+
+
+ProtocolHandler::ProtocolHandler(QObject *parent)
+ : QObject(parent)
+ , _lister(new KDirLister(this))
+ , _frame(0)
+{
+ _lister->setMainWindow(rApp->mainWindow());
+}
+
+
+bool ProtocolHandler::preHandling(const QNetworkRequest &request, QWebFrame *frame)
+{
+ _url = request.url();
+ _frame = frame;
+
+ // javascript handling
+ if (_url.protocol() == QL1S("javascript"))
+ {
+ QString scriptSource = _url.authority();
+ if (scriptSource.isEmpty())
+ {
+ // if javascript:<code here> then authority() returns
+ // an empty string. Extract the source manually
+ // Use the prettyUrl() since that is unencoded
+
+ // 11 is length of 'javascript:'
+ // fromPercentEncoding() is used to decode all the % encoded
+ // characters to normal, so that it is treated as valid javascript
+ scriptSource = QUrl::fromPercentEncoding(_url.url().mid(11).toAscii());
+ if (scriptSource.isEmpty())
+ return false;
+ }
+
+ QVariant result = frame->evaluateJavaScript(scriptSource);
+ return true;
+ }
+
+ // "about" handling
+ if (_url.protocol() == QL1S("about"))
+ {
+ QByteArray encodedUrl = _url.toEncoded();
+ // let webkit manage the about:blank url...
+ if (encodedUrl.startsWith(QByteArray("about:blank")))
+ {
+ return false;
+ }
+
+ if (encodedUrl == QByteArray("about:home"))
+ {
+ switch (ReKonfig::newTabStartPage())
+ {
+ case 0: // favorites
+ _url = KUrl("about:favorites");
+ break;
+ case 1: // closed tabs
+ _url = KUrl("about:closedTabs");
+ break;
+ case 2: // bookmarks
+ _url = KUrl("about:bookmarks");
+ break;
+ case 3: // history
+ _url = KUrl("about:history");
+ break;
+ case 4: // downloads
+ _url = KUrl("about:downloads");
+ break;
+ case 5: // tabs
+ _url = KUrl("about:tabs");
+ default: // unuseful
+ break;
+ }
+ }
+
+ WebPage *page = qobject_cast<WebPage *>(frame->page());
+ page->setIsOnRekonqPage(true);
+
+ NewTabPage p(frame);
+ p.generate(_url);
+
+ return true;
+ }
+
+ // "mailto" handling: It needs to be handled both in preHandling (mail url launched)
+ // and in postHandling (mail links clicked)
+ if (_url.protocol() == QL1S("mailto"))
+ {
+ KToolInvocation::invokeMailer(_url);
+ return true;
+ }
+
+ // "apt" handling
+ // NOTE: this is a stupid workaround to ensure apt protocol works
+ if (_url.protocol() == QL1S("apt"))
+ {
+ kDebug() << "APT URL: " << _url;
+ (void)new KRun(_url, rApp->mainWindow(), 0, _url.isLocalFile());
+ return true;
+ }
+
+ // let webkit try to load a known (or missing) protocol...
+ if (KProtocolInfo::isKnownProtocol(_url))
+ return false;
+
+ // Error Message, for those protocols we cannot handle
+ KMessageBox::error(rApp->mainWindow(), i18nc("@info", "rekonq does not know how to handle this protocol: %1", _url.protocol()));
+
+ return true;
+}
+
+
+bool ProtocolHandler::postHandling(const QNetworkRequest &request, QWebFrame *frame)
+{
+ _url = request.url();
+ _frame = frame;
+
+ // "http(s)" (fast) handling
+ if (_url.protocol() == QL1S("http") || _url.protocol() == QL1S("https"))
+ return false;
+
+ // "mailto" handling: It needs to be handled both here(mail links clicked)
+ // and in prehandling (mail url launched)
+ if (_url.protocol() == QL1S("mailto"))
+ {
+ KToolInvocation::invokeMailer(_url);
+ return true;
+ }
+
+ // "ftp" handling. A little bit "hard" handling this. Hope I found
+ // the best solution.
+ // My idea is: webkit cannot handle in any way ftp. So we have surely to return true here.
+ // We start trying to guess what the url represent: it's a dir? show its contents (and download them).
+ // it's a file? download it. It's another thing? beat me, but I don't know what to do...
+ if (_url.protocol() == QL1S("ftp"))
+ {
+ KIO::StatJob *job = KIO::stat(_url);
+ connect(job, SIGNAL(result(KJob*)), this, SLOT(slotMostLocalUrlResult(KJob*)));
+ return true;
+ }
+
+ // "file" handling. This is quite trivial :)
+ if (_url.protocol() == QL1S("file"))
+ {
+ QFileInfo fileInfo(_url.path());
+ if (fileInfo.isDir())
+ {
+ connect(_lister, SIGNAL(newItems(KFileItemList)), this, SLOT(showResults(KFileItemList)));
+ _lister->openUrl(_url);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ // we cannot handle this protocol in any way.
+ // Try KRunning it...
+ if (KProtocolInfo::isKnownProtocol(_url))
+ {
+ (void)new KRun(_url, rApp->mainWindow(), 0, _url.isLocalFile());
+ return true;
+ }
+
+ return false;
+}
+
+
+// ---------------------------------------------------------------------------------------------------------------------------
+
+
+void ProtocolHandler::showResults(const KFileItemList &list)
+{
+ if (!_lister->rootItem().isNull() && _lister->rootItem().isReadable() && _lister->rootItem().isFile())
+ {
+ emit downloadUrl(_lister->rootItem().url());
+ }
+ else
+ {
+ QString html = dirHandling(list);
+ _frame->setHtml(html);
+ qobject_cast<WebPage *>(_frame->page())->setIsOnRekonqPage(true);
+
+ rApp->mainWindow()->mainView()->currentUrlBar()->setQUrl(_url);
+ rApp->mainWindow()->currentTab()->setFocus();
+ rApp->historyManager()->addHistoryEntry(_url, _url.prettyUrl());
+ }
+}
+
+
+QString ProtocolHandler::dirHandling(const KFileItemList &list)
+{
+ if (!_lister)
+ {
+ return QString("rekonq error, sorry :(");
+ }
+
+ // let me modify it..
+ KUrl rootUrl = _url;
+
+ // display "rekonq info" page
+ QString infoFilePath = KStandardDirs::locate("data", "rekonq/htmls/rekonqinfo.html");
+ QFile file(infoFilePath);
+
+ bool isOpened = file.open(QIODevice::ReadOnly);
+ if (!isOpened)
+ {
+ return QString("rekonq error, sorry :(");
+ }
+
+ // 1. default data path
+ QString dataPath = QL1S("file://") + infoFilePath;
+ dataPath.remove(QL1S("/htmls/rekonqinfo.html"));
+
+ // 2. title
+ QString title = _url.prettyUrl();
+
+ // 3. main content
+ QString msg = i18nc("%1=an URL", "<h2>Index of %1</h2>", _url.prettyUrl());
+
+
+ if (rootUrl.cd(".."))
+ {
+ QString path = rootUrl.prettyUrl();
+ QString uparrow = KIconLoader::global()->iconPath("arrow-up", KIconLoader::Small);
+ msg += "<img src=\"file://" + uparrow + "\" alt=\"up-arrow\" />";
+ msg += "<a href=\"" + path + "\">" + i18n("Up to higher level directory") + "</a><br /><br />";
+ }
+
+ msg += QL1S("<table width=\"95%\" align=\"center\">");
+ msg += QL1S("<tr>");
+ msg += QL1S("<th align=\"left\">") + i18n("Name") + QL1S("</th>");
+ msg += QL1S("<th align=\"center\">") + i18n("Size") + QL1S("</th>");
+ msg += QL1S("<th align=\"right\">") + i18n("Last Modified") + QL1S("</th>");
+ msg += QL1S("</tr>");
+
+ KFileItemList orderedList = sortFileList(list);
+ Q_FOREACH(const KFileItem & item, orderedList)
+ {
+ msg += QL1S("<tr>");
+ QString fullPath = Qt::escape(item.url().prettyUrl());
+
+ QString iconName = item.iconName();
+ QString icon = QString("file://") + KIconLoader::global()->iconPath(iconName, KIconLoader::Small);
+
+ msg += QL1S("<td width=\"70%\">");
+ msg += QL1S("<img src=\"") + icon + QL1S("\" alt=\"") + iconName + QL1S("\" /> ");
+ msg += QL1S("<a href=\"") + fullPath + QL1S("\">") + Qt::escape(item.name()) + QL1S("</a>");
+ msg += QL1S("</td>");
+
+ msg += QL1S("<td align=\"right\">");
+ if (item.isFile())
+ {
+ msg += KGlobal::locale()->formatByteSize(item.size(), 1);
+ }
+ msg += QL1S("</td>");
+
+ msg += QL1S("<td align=\"right\">");
+ msg += item.timeString();
+ msg += QL1S("</td>");
+
+ msg += QL1S("</tr>");
+ }
+ msg += QL1S("</table>");
+
+ // done. Replace variables and show it
+ QString html = QL1S(file.readAll());
+
+ html.replace(QL1S("$DEFAULT_PATH"), dataPath);
+ html.replace(QL1S("$PAGE_TITLE"), title);
+ html.replace(QL1S("$MAIN_CONTENT"), msg);
+
+ return html;
+}
+
+
+void ProtocolHandler::slotMostLocalUrlResult(KJob *job)
+{
+ if (job->error())
+ {
+ kDebug() << "JOB ERROR: " << job->errorString();
+ // TODO
+ }
+ else
+ {
+ KIO::StatJob *statJob = static_cast<KIO::StatJob*>(job);
+ KIO::UDSEntry entry = statJob->statResult();
+ if (entry.isDir())
+ {
+ connect(_lister, SIGNAL(newItems(KFileItemList)), this, SLOT(showResults(KFileItemList)));
+ _lister->openUrl(_url);
+ }
+ else
+ {
+ emit downloadUrl(_url);
+ }
+ }
+}
diff --git a/src/webtab/protocolhandler.h b/src/webtab/protocolhandler.h
new file mode 100644
index 00000000..f35fdcc6
--- /dev/null
+++ b/src/webtab/protocolhandler.h
@@ -0,0 +1,83 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2010-2012 by Andrea Diamantini <adjam7 at gmail dot com>
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+
+#ifndef PROTOCOL_HANDLER_H
+#define PROTOCOL_HANDLER_H
+
+
+// Rekonq Includes
+#include "rekonq_defines.h"
+
+// KDE Includes
+#include <KUrl>
+
+// Qt Includes
+#include <QObject>
+
+// Forward Declarations
+class KDirLister;
+class KFileItemList;
+class KJob;
+
+class QNetworkRequest;
+class QWebFrame;
+
+
+class REKONQ_TESTS_EXPORT ProtocolHandler : public QObject
+{
+ Q_OBJECT
+
+public:
+ ProtocolHandler(QObject *parent = 0);
+
+ /**
+ * This function handles all the protocols that have to be handled before
+ * WebKit does
+ */
+ bool preHandling(const QNetworkRequest &request, QWebFrame *frame);
+
+ /**
+ * This function handles all the protocols that have to be handled after
+ * WebKit tried to
+ */
+ bool postHandling(const QNetworkRequest &request, QWebFrame *frame);
+
+Q_SIGNALS:
+ void downloadUrl(const KUrl &);
+
+private Q_SLOTS:
+ void showResults(const KFileItemList &);
+ void slotMostLocalUrlResult(KJob *);
+
+private:
+ QString dirHandling(const KFileItemList &list);
+
+ KDirLister *_lister;
+ QWebFrame *_frame;
+ KUrl _url;
+};
+
+#endif // PROTOCOL_HANDLER_H
diff --git a/src/webtab/searchenginebar.cpp b/src/webtab/searchenginebar.cpp
new file mode 100644
index 00000000..441facf7
--- /dev/null
+++ b/src/webtab/searchenginebar.cpp
@@ -0,0 +1,93 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2012 by Andrea Diamantini <adjam7 at gmail dot com>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "searchenginebar.h"
+#include "searchenginebar.moc"
+
+// Auto Includes
+#include "rekonq.h"
+
+// KDE Includes
+#include <KIcon>
+#include <KIconLoader>
+#include <KAction>
+#include <KLocalizedString>
+
+// Qt Includes
+#include <QProcess>
+
+
+SearchEngineBar::SearchEngineBar(QWidget *parent)
+ : KMessageWidget(parent)
+{
+ connect(this, SIGNAL(accepted()), this, SLOT(hideAndDelete()));
+ connect(this, SIGNAL(accepted()), this, SLOT(slotAccepted()));
+
+ connect(this, SIGNAL(rejected()), this, SLOT(hideAndDelete()));
+ connect(this, SIGNAL(rejected()), this, SLOT(slotRejected()));
+
+ setMessageType(KMessageWidget::Information);
+
+ QSize sz = size();
+ sz.setWidth(qobject_cast<QWidget *>(parent)->size().width());
+ resize(sz);
+
+ setCloseButtonVisible(false);
+
+ setText(i18n("You don't have a default search engine set. Without it, rekonq will not show proper url suggestions."));
+
+ KAction *acceptAction = new KAction(i18n("Set it"), this);
+ connect(acceptAction, SIGNAL(triggered(bool)), this, SIGNAL(accepted()));
+ addAction(acceptAction);
+
+ KAction *rejectAction = new KAction(i18n("Ignore"), this);
+ connect(rejectAction, SIGNAL(triggered(bool)), this, SIGNAL(rejected()));
+ addAction(rejectAction);
+}
+
+
+void SearchEngineBar::hideAndDelete()
+{
+ animatedHide();
+ deleteLater();
+}
+
+
+void SearchEngineBar::slotAccepted()
+{
+ QProcess *proc = new QProcess(parent());
+ QStringList args;
+ args << QL1S("ebrowsing");
+ proc->start(QL1S("kcmshell4"), args);
+}
+
+
+void SearchEngineBar::slotRejected()
+{
+ // Remember users choice
+ ReKonfig::setCheckDefaultSearchEngine(false);
+}
diff --git a/src/webtab/searchenginebar.h b/src/webtab/searchenginebar.h
new file mode 100644
index 00000000..7ee1f90c
--- /dev/null
+++ b/src/webtab/searchenginebar.h
@@ -0,0 +1,55 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2012 by Andrea Diamantini <adjam7 at gmail dot com>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+#ifndef SEARCH_ENGINE_BAR_H
+#define SEARCH_ENGINE_BAR_H
+
+// Rekonq Includes
+#include "rekonq_defines.h"
+
+// KDE Includes
+#include <KMessageWidget>
+
+
+class REKONQ_TESTS_EXPORT SearchEngineBar : public KMessageWidget
+{
+ Q_OBJECT
+
+public:
+ explicit SearchEngineBar(QWidget *parent);
+
+private Q_SLOTS:
+ void hideAndDelete();
+ void slotAccepted();
+ void slotRejected();
+
+Q_SIGNALS:
+ void accepted();
+ void rejected();
+};
+
+
+#endif // SEARCH_ENGINE_BAR_H
diff --git a/src/webtab/sslinfo.ui b/src/webtab/sslinfo.ui
new file mode 100644
index 00000000..c1c67b47
--- /dev/null
+++ b/src/webtab/sslinfo.ui
@@ -0,0 +1,392 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SslInfo</class>
+ <widget class="QWidget" name="SslInfo">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>539</width>
+ <height>459</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;h2&gt;Certificate Information&lt;/h2&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_6">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Certificate Chain:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="comboBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="certInfoLabel">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string/>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="label_20">
+ <property name="text">
+ <string>&lt;h4&gt;Issued To:&lt;/h4&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_6">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>160</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Common Name (CN):</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="subjectCN">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_8">
+ <property name="text">
+ <string>Organization (O):</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="subjectO">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Organizational Unit (OU):</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLabel" name="subjectOU">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Serial Number:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLabel" name="subjectSN">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_21">
+ <property name="text">
+ <string>&lt;h4&gt;Issued By:&lt;/h4&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_10">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>160</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Common Name (CN):</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="issuerCN">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_12">
+ <property name="text">
+ <string>Organization (O):</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_16">
+ <property name="text">
+ <string>Organizational Unit (OU):</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLabel" name="issuerOU">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="issuerO">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_22">
+ <property name="text">
+ <string>&lt;h4&gt;Validity Period:&lt;/h4&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_14">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>160</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Issued on:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="issuedOn">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_18">
+ <property name="text">
+ <string>Expires on:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="expiresOn">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_23">
+ <property name="text">
+ <string>&lt;h4&gt;Digests:&lt;/h4&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QGridLayout" name="gridLayout_5">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_36">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>160</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Md5:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="md5">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_38">
+ <property name="text">
+ <string>SHA-1:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="sha1">
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/webtab/sslinfodialog.cpp b/src/webtab/sslinfodialog.cpp
new file mode 100644
index 00000000..2f0b44e4
--- /dev/null
+++ b/src/webtab/sslinfodialog.cpp
@@ -0,0 +1,176 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2011-2012 by Andrea Diamantini <adjam7 at gmail dot com>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "sslinfodialog.h"
+#include "sslinfodialog.moc"
+
+// KDE Includes
+#include <KFileDialog>
+
+#include <kglobal.h>
+#include <klocale.h>
+#include <ktcpsocket.h>
+
+// Qt Includes
+#include <QDate>
+#include <QFile>
+
+#include <QLabel>
+#include <QTextDocument>
+
+#include <QSslCertificate>
+
+
+SslInfoDialog::SslInfoDialog(const QString &host, const WebSslInfo &info, QWidget *parent)
+ : KDialog(parent)
+ , m_host(host)
+ , m_info(info)
+{
+ setCaption(i18n("Rekonq SSL Information"));
+ setAttribute(Qt::WA_DeleteOnClose);
+
+ setMinimumWidth(300);
+
+ setButtons(KDialog::User1 | KDialog::Close);
+
+ setButtonGuiItem(User1, KGuiItem(i18n("Export"), QL1S("view-certificate-export")));
+ connect(this, SIGNAL(user1Clicked()), this, SLOT(exportCert()));
+
+ ui.setupUi(mainWidget());
+
+ // ------------------------------------------------
+ QList<QSslCertificate> caList = m_info.certificateChain();
+
+ Q_FOREACH(const QSslCertificate & cert, caList)
+ {
+ QString name = cert.subjectInfo(QSslCertificate::CommonName);
+ if (name.isEmpty())
+ name = cert.subjectInfo(QSslCertificate::Organization);
+ if (name.isEmpty())
+ name = cert.serialNumber();
+ ui.comboBox->addItem(name);
+ }
+ connect(ui.comboBox, SIGNAL(activated(int)), this, SLOT(displayFromChain(int)));
+
+ displayFromChain(0);
+}
+
+
+void SslInfoDialog::showCertificateInfo(QSslCertificate subjectCert, const QStringList &certErrors)
+{
+ QStringList sl = certErrors;
+ QString c = sl.takeFirst();
+ c += QL1S("<ul>");
+ Q_FOREACH(const QString & s, sl)
+ {
+ c += QL1S("<li>") + s + QL1S("</li>");
+ }
+ c += QL1S("</ul>");
+ ui.certInfoLabel->setText(c);
+
+ ui.subjectCN->setText(Qt::escape(subjectCert.subjectInfo(QSslCertificate::CommonName)));
+ ui.subjectO->setText(Qt::escape(subjectCert.subjectInfo(QSslCertificate::Organization)));
+ ui.subjectOU->setText(Qt::escape(subjectCert.subjectInfo(QSslCertificate::OrganizationalUnitName)));
+ ui.subjectSN->setText(Qt::escape(subjectCert.serialNumber()));
+
+ ui.issuerCN->setText(Qt::escape(subjectCert.issuerInfo(QSslCertificate::CommonName)));
+ ui.issuerO->setText(Qt::escape(subjectCert.issuerInfo(QSslCertificate::Organization)));
+ ui.issuerOU->setText(Qt::escape(subjectCert.issuerInfo(QSslCertificate::OrganizationalUnitName)));
+
+ ui.issuedOn->setText(Qt::escape(subjectCert.effectiveDate().date().toString(Qt::SystemLocaleShortDate)));
+ ui.expiresOn->setText(Qt::escape(subjectCert.expiryDate().date().toString(Qt::SystemLocaleShortDate)));
+
+ ui.md5->setText(Qt::escape(subjectCert.digest(QCryptographicHash::Md5).toHex()));
+ ui.sha1->setText(Qt::escape(subjectCert.digest(QCryptographicHash::Sha1).toHex()));
+}
+
+
+void SslInfoDialog::displayFromChain(int i)
+{
+ QList<QSslCertificate> caList = m_info.certificateChain();
+ QSslCertificate cert = caList.at(i);
+
+ QStringList errors = SslInfoDialog::errorsFromString(m_info.certificateErrors()).at(i);
+
+ if (cert.isValid() && errors.isEmpty())
+ {
+ QStringList certInfo;
+ certInfo << i18n("The Certificate is Valid!");
+ showCertificateInfo(cert, certInfo);
+ }
+ else
+ {
+ errors.prepend(i18n("The certificate for this site is NOT valid for the following reasons:"));
+ showCertificateInfo(cert, errors);
+ }
+}
+
+
+void SslInfoDialog::exportCert()
+{
+ QSslCertificate cert = m_info.certificateChain().at(ui.comboBox->currentIndex());
+
+ if (cert.isNull())
+ return;
+
+ QString name = m_host + QL1S(".pem");
+
+ QString certPath = KFileDialog::getSaveFileName(name, QString(), this);
+
+ QFile file(certPath);
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
+ return;
+
+ QTextStream out(&file);
+ out << cert.toPem();
+}
+
+
+// static -------------------------------------------------------------------------------------------
+QList<QStringList> SslInfoDialog::errorsFromString(const QString &s)
+{
+ QList<QStringList> resultList;
+
+ QStringList sl1 = s.split('\n', QString::KeepEmptyParts);
+
+ Q_FOREACH(const QString & certErrors, sl1)
+ {
+ QStringList errors;
+ QStringList sl = certErrors.split('\t', QString::SkipEmptyParts);
+ Q_FOREACH(const QString & s, sl)
+ {
+ bool didConvert;
+ KSslError::Error error = static_cast<KSslError::Error>(s.trimmed().toInt(&didConvert));
+ if (didConvert)
+ {
+ errors << KSslError(error).errorString();
+ }
+ }
+ resultList << errors;
+ }
+ return resultList;
+}
diff --git a/src/webtab/sslinfodialog.h b/src/webtab/sslinfodialog.h
new file mode 100644
index 00000000..94f610c6
--- /dev/null
+++ b/src/webtab/sslinfodialog.h
@@ -0,0 +1,79 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2011-2012 by Andrea Diamantini <adjam7 at gmail dot com>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+#ifndef SSL_INFO_DIALOG_H
+#define SSL_INFO_DIALOG_H
+
+
+// Rekonq Includes
+#include "rekonq_defines.h"
+
+// Local Includes
+#include "websslinfo.h"
+
+// Ui Includes
+#include "ui_sslinfo.h"
+
+// KDE Includes
+#include <KDialog>
+
+// Qt Includes
+#include <QString>
+
+// Forward Declarations
+class QSslCertificate;
+
+
+/**
+ * Rekonq SSL Information Dialog
+ *
+ * This class creates a dialog that can be used to display information about
+ * an SSL session.
+ *
+ */
+class SslInfoDialog : public KDialog
+{
+ Q_OBJECT
+
+public:
+ explicit SslInfoDialog(const QString &host, const WebSslInfo &info, QWidget *parent = 0);
+
+ static QList<QStringList> errorsFromString(const QString &s);
+
+private Q_SLOTS:
+ void displayFromChain(int);
+ void exportCert();
+
+private:
+ void showCertificateInfo(QSslCertificate, const QStringList &certErrors);
+
+ QString m_host;
+ WebSslInfo m_info;
+
+ Ui::SslInfo ui;
+};
+
+#endif // SSL_INFO_DIALOG_H
diff --git a/src/webtab/walletbar.cpp b/src/webtab/walletbar.cpp
new file mode 100644
index 00000000..01a6d658
--- /dev/null
+++ b/src/webtab/walletbar.cpp
@@ -0,0 +1,103 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009-2011 by Andrea Diamantini <adjam7 at gmail dot com>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "walletbar.h"
+#include "walletbar.moc"
+
+// Auto Includes
+#include "rekonq.h"
+
+// KDE Includes
+#include <KIcon>
+#include <KLocalizedString>
+
+// Qt Includes
+#include <QAction>
+
+
+WalletBar::WalletBar(QWidget *parent)
+ : KMessageWidget(parent)
+{
+ setMessageType(KMessageWidget::Warning);
+
+ QSize sz = size();
+ sz.setWidth(qobject_cast<QWidget *>(parent)->size().width());
+ resize(sz);
+
+ setCloseButtonVisible(false);
+
+ QAction *rememberAction = new QAction(KIcon("document-save"), i18n("Remember"), this);
+ connect(rememberAction, SIGNAL(triggered(bool)), this, SLOT(rememberData()));
+ addAction(rememberAction);
+
+ QAction *neverHereAction = new QAction(KIcon("process-stop"), i18n("Never for This Site"), this);
+ connect(neverHereAction, SIGNAL(triggered(bool)), this, SLOT(neverRememberData()));
+ addAction(neverHereAction);
+
+ QAction *notNowAction = new QAction(KIcon("dialog-cancel"), i18n("Not Now"), this);
+ connect(notNowAction, SIGNAL(triggered(bool)), this, SLOT(notNowRememberData()));
+ addAction(notNowAction);
+}
+
+
+void WalletBar::rememberData()
+{
+ emit saveFormDataAccepted(m_key);
+
+ animatedHide();
+ deleteLater();
+}
+
+
+void WalletBar::neverRememberData()
+{
+ // add url to the blacklist
+ QStringList list = ReKonfig::walletBlackList();
+ list << m_url.toString();
+ ReKonfig::setWalletBlackList(list);
+
+ notNowRememberData();
+}
+
+
+void WalletBar::notNowRememberData()
+{
+ emit saveFormDataRejected(m_key);
+
+ animatedHide();
+ deleteLater();
+}
+
+
+
+void WalletBar::onSaveFormData(const QString &key, const QUrl &url)
+{
+ setText(i18n("Do you want rekonq to remember the password on %1?", url.host()));
+
+ m_key = key;
+ m_url = url;
+}
diff --git a/src/webtab/walletbar.h b/src/webtab/walletbar.h
new file mode 100644
index 00000000..f1bbd2cb
--- /dev/null
+++ b/src/webtab/walletbar.h
@@ -0,0 +1,66 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009-2011 by Andrea Diamantini <adjam7 at gmail dot com>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+#ifndef WALLET_BAR_H
+#define WALLET_BAR_H
+
+
+// Rekonq Includes
+#include "rekonq_defines.h"
+
+// KDE Includes
+#include <KMessageWidget>
+
+// Qt Includes
+#include <QUrl>
+#include <QString>
+
+
+class REKONQ_TESTS_EXPORT WalletBar : public KMessageWidget
+{
+ Q_OBJECT
+
+public:
+ WalletBar(QWidget *parent);
+
+private Q_SLOTS:
+ void rememberData();
+ void neverRememberData();
+ void notNowRememberData();
+
+public Q_SLOTS:
+ void onSaveFormData(const QString &, const QUrl &);
+
+Q_SIGNALS:
+ void saveFormDataAccepted(const QString &);
+ void saveFormDataRejected(const QString &);
+
+private:
+ QString m_key;
+ QUrl m_url;
+};
+
+#endif // WALLET_BAR_H
diff --git a/src/webtab/webpage.cpp b/src/webtab/webpage.cpp
new file mode 100644
index 00000000..59262862
--- /dev/null
+++ b/src/webtab/webpage.cpp
@@ -0,0 +1,777 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2008 Benjamin C. Meyer <ben@meyerhome.net>
+* Copyright (C) 2008 Dirk Mueller <mueller@kde.org>
+* Copyright (C) 2008 Urs Wolfer <uwolfer @ kde.org>
+* Copyright (C) 2008 Michael Howell <mhowell123@gmail.com>
+* Copyright (C) 2008-2012 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2010 by Matthieu Gicquel <matgic78 at gmail dot com>
+* Copyright (C) 2009-2010 Dawit Alemayehu <adawit at kde dot org>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "webpage.h"
+#include "webpage.moc"
+
+// Auto Includes
+#include "rekonq.h"
+
+// Local Includes
+#include "adblockmanager.h"
+#include "application.h"
+#include "downloadmanager.h"
+#include "historymanager.h"
+#include "iconmanager.h"
+#include "mainview.h"
+#include "mainwindow.h"
+#include "networkaccessmanager.h"
+#include "urlbar.h"
+#include "webpluginfactory.h"
+#include "websnap.h"
+#include "webtab.h"
+#include "searchengine.h"
+#include "sslwidget.h"
+#include "sslinfodialog.h"
+
+// KDE Includes
+#include <KTemporaryFile>
+#include <KStandardDirs>
+#include <KJobUiDelegate>
+#include <KLocalizedString>
+#include <KMessageBox>
+#include <KMimeTypeTrader>
+#include <KService>
+#include <KWebWallet>
+#include <KProtocolInfo>
+#include <KRun>
+
+#include <KIO/JobUiDelegate>
+
+#include <kparts/browseropenorsavequestion.h>
+
+// Qt Includes
+#include <QTextDocument>
+#include <QFileInfo>
+#include <QNetworkReply>
+
+
+// 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);
+}
+
+
+static void extractMimeType(const QNetworkReply* reply, QString& mimeType)
+{
+ mimeType.clear();
+ const KIO::MetaData& metaData = reply->attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::MetaData)).toMap();
+ if (metaData.contains(QL1S("content-type")))
+ mimeType = metaData.value(QL1S("content-type"));
+
+ if (!mimeType.isEmpty())
+ return;
+
+ if (!reply->hasRawHeader("Content-Type"))
+ return;
+
+ const QString value(QL1S(reply->rawHeader("Content-Type").simplified().constData()));
+ const int index = value.indexOf(QL1C(';'));
+ if (index == -1)
+ mimeType = value;
+ else
+ mimeType = value.left(index);
+}
+
+
+// ---------------------------------------------------------------------------------
+
+
+WebPage::WebPage(QWidget *parent)
+ : KWebPage(parent, KWalletIntegration)
+ , _networkAnalyzer(false)
+ , _isOnRekonqPage(false)
+{
+ // handling unsupported content...
+ setForwardUnsupportedContent(true);
+ connect(this, SIGNAL(unsupportedContent(QNetworkReply*)), this, SLOT(handleUnsupportedContent(QNetworkReply*)));
+
+ // rekonq Network Manager
+ NetworkAccessManager *manager = new NetworkAccessManager(this);
+
+ // set network reply object to emit readyRead when it receives meta data
+ manager->setEmitReadyReadOnMetaDataChange(true);
+
+ // disable QtWebKit cache to just use KIO one..
+ manager->setCache(0);
+
+ // set cookieJar window..
+ if (parent && parent->window())
+ manager->setWindow(parent->window());
+
+ setNetworkAccessManager(manager);
+
+ // activate ssl warnings
+ setSessionMetaData(QL1S("ssl_activate_warnings"), QL1S("TRUE"));
+
+ // ----- Web Plugin Factory
+ setPluginFactory(new WebPluginFactory(this));
+
+ // ----- last stuffs
+ connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(manageNetworkErrors(QNetworkReply*)));
+
+ connect(this, SIGNAL(downloadRequested(QNetworkRequest)), this, SLOT(downloadRequest(QNetworkRequest)));
+ connect(this, SIGNAL(loadStarted()), this, SLOT(loadStarted()));
+ connect(this, SIGNAL(loadFinished(bool)), this, SLOT(loadFinished(bool)));
+
+ // protocol handler signals
+ connect(&_protHandler, SIGNAL(downloadUrl(KUrl)), this, SLOT(downloadUrl(KUrl)));
+
+ connect(rApp->iconManager(), SIGNAL(iconChanged()), mainFrame(), SIGNAL(iconChanged()));
+}
+
+
+WebPage::~WebPage()
+{
+ disconnect();
+
+ QPixmap preview = WebSnap::renderPagePreview(*this);
+ QString path = WebSnap::imagePathFromUrl(mainFrame()->url().toString());
+ QFile::remove(path);
+ preview.save(path);
+}
+
+
+bool WebPage::hasNetworkAnalyzerEnabled() const
+{
+ return _networkAnalyzer;
+};
+
+
+void WebPage::enableNetworkAnalyzer(bool b)
+{
+ _networkAnalyzer = b;
+};
+
+
+bool WebPage::isOnRekonqPage() const
+{
+ return _isOnRekonqPage;
+};
+
+
+void WebPage::setIsOnRekonqPage(bool b)
+{
+ _isOnRekonqPage = b;
+};
+
+
+KUrl WebPage::loadingUrl()
+{
+ return _loadingUrl;
+};
+
+
+QString WebPage::suggestedFileName()
+{
+ return _suggestedFileName;
+};
+
+
+bool WebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, NavigationType type)
+{
+ if (_isOnRekonqPage)
+ {
+ WebView *view = qobject_cast<WebView *>(parent());
+ WebTab *tab = qobject_cast<WebTab *>(view->parent());
+ _isOnRekonqPage = false;
+ tab->setPart(0, KUrl()); // re-enable the view page
+ }
+
+ // reset webpage values
+ _suggestedFileName.clear();
+ _loadingUrl = request.url();
+
+ const bool isMainFrameRequest = (frame == mainFrame());
+
+ if (frame)
+ {
+ if (_protHandler.preHandling(request, frame))
+ {
+ return false;
+ }
+
+ switch (type)
+ {
+ case QWebPage::NavigationTypeLinkClicked:
+ if (_sslInfo.isValid())
+ {
+ setRequestMetaData("ssl_was_in_use", "TRUE");
+ }
+ break;
+
+ case QWebPage::NavigationTypeFormSubmitted:
+ break;
+
+ case QWebPage::NavigationTypeFormResubmitted:
+ if (KMessageBox::warningContinueCancel(view(),
+ i18n("Are you sure you want to send your data again?"),
+ i18n("Resend form data")
+ )
+ == KMessageBox::Cancel)
+ {
+ return false;
+ }
+ break;
+
+ case QWebPage::NavigationTypeReload:
+ setRequestMetaData(QL1S("cache"), QL1S("reload"));
+ break;
+
+ case QWebPage::NavigationTypeBackOrForward:
+ case QWebPage::NavigationTypeOther:
+ break;
+
+ default:
+ ASSERT_NOT_REACHED(unknown NavigationType);
+ break;
+ }
+ }
+
+ // Get the SSL information sent, if any...
+ KIO::AccessManager *manager = qobject_cast<KIO::AccessManager*>(networkAccessManager());
+ KIO::MetaData metaData = manager->requestMetaData();
+ if (metaData.contains(QL1S("ssl_in_use")))
+ {
+ WebSslInfo info;
+ info.restoreFrom(metaData.toVariant(), request.url());
+ info.setUrl(request.url());
+ _sslInfo = info;
+ }
+
+ if (isMainFrameRequest)
+ {
+ setRequestMetaData(QL1S("main_frame_request"), QL1S("TRUE"));
+ if (_sslInfo.isValid() && !domainSchemeMatch(request.url(), _sslInfo.url()))
+ {
+ _sslInfo = WebSslInfo();
+ }
+ }
+ else
+ {
+ setRequestMetaData(QL1S("main_frame_request"), QL1S("FALSE"));
+ }
+
+ return KWebPage::acceptNavigationRequest(frame, request, type);
+}
+
+
+WebPage *WebPage::createWindow(QWebPage::WebWindowType type)
+{
+ // added to manage web modal dialogs
+ if (type == QWebPage::WebModalDialog)
+ kDebug() << "Modal Dialog";
+
+ WebTab *w = 0;
+ if (ReKonfig::openLinksInNewWindow())
+ {
+ w = rApp->newMainWindow()->mainView()->currentWebTab();
+ }
+ else
+ {
+ w = rApp->mainWindow()->mainView()->newWebTab(!ReKonfig::openNewTabsInBackground());
+ }
+ return w->page();
+}
+
+
+void WebPage::handleUnsupportedContent(QNetworkReply *reply)
+{
+ Q_ASSERT(reply);
+
+ if (!reply)
+ return;
+
+ // handle protocols WebKit cannot handle...
+ if (_protHandler.postHandling(reply->request(), mainFrame()))
+ {
+ return;
+ }
+
+ if (reply->error() != QNetworkReply::NoError)
+ return;
+
+ KIO::Integration::AccessManager::putReplyOnHold(reply);
+
+ // Get mimeType...
+ extractMimeType(reply, _mimeType);
+
+ // Convert executable text files to plain text...
+ if (KParts::BrowserRun::isTextExecutable(_mimeType))
+ _mimeType = QL1S("text/plain");
+
+ // Get suggested file name...
+ const KIO::MetaData& data = reply->attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::MetaData)).toMap();
+ _suggestedFileName = data.value(QL1S("content-disposition-filename"));
+
+ kDebug() << "Detected MimeType = " << _mimeType;
+ kDebug() << "Suggested File Name = " << _suggestedFileName;
+ // ------------------------------------------------
+
+ KService::Ptr appService = KMimeTypeTrader::self()->preferredService(_mimeType);
+
+ KUrl replyUrl = reply->url();
+ bool isLocal = replyUrl.isLocalFile();
+
+ if (appService.isNull()) // no service can handle this. We can just download it..
+ {
+ isLocal
+ ? KMessageBox::sorry(view(), i18n("No service can handle this file."))
+ : downloadUrl(reply->url());
+
+ return;
+ }
+
+ // NOTE
+ // This is needed in case rekonq has been associated with something it cannot
+ // properly handle (eg: xbel files, see BUG:299056). This way we break an eventual
+ // "recall" loop.
+ if (appService->exec().trimmed().startsWith(QL1S("rekonq")))
+ {
+ isLocal
+ ? KMessageBox::sorry(view(), i18n("rekonq cannot properly handle this, sorry"))
+ : downloadUrl(reply->url());
+
+ return;
+ }
+
+ if (isLocal)
+ {
+ // Load outside local files
+ KRun::run(*appService, replyUrl, 0, false, _suggestedFileName);
+ }
+ else
+ {
+ KParts::BrowserOpenOrSaveQuestion dlg(rApp->mainWindow(), replyUrl, _mimeType);
+
+ if (!_suggestedFileName.isEmpty())
+ dlg.setSuggestedFileName(_suggestedFileName);
+
+ // read askEmbedOrSave preferences. If we don't have to show dialog and rekonq settings are
+ // to automatically choose download dir, we won't show local dir choose dialog
+ KConfigGroup cg = KConfigGroup(KSharedConfig::openConfig("filetypesrc", KConfig::NoGlobals), QL1S("Notification Messages"));
+ bool hideDialog = cg.readEntry(QL1S("askEmbedOrSave") + _mimeType, false);
+
+ kDebug() << "Hide dialog for " << _mimeType << "? " << hideDialog;
+
+ switch (dlg.askEmbedOrSave())
+ {
+ case KParts::BrowserOpenOrSaveQuestion::Save:
+ rApp->downloadManager()->downloadResource(reply->url(), KIO::MetaData(), view(), !hideDialog, _suggestedFileName);
+ return;
+
+ case KParts::BrowserOpenOrSaveQuestion::Cancel:
+ return;
+
+ default: // Can happen when "Open with.." is set and "don't ask again" is checked
+ break;
+ }
+ }
+
+ // Handle Post operations that return content...
+ if (reply->operation() == QNetworkAccessManager::PostOperation)
+ {
+ kDebug() << "POST OPERATION: downloading file...";
+ QFileInfo finfo(_suggestedFileName.isEmpty() ? _loadingUrl.fileName() : _suggestedFileName);
+ KTemporaryFile tempFile;
+ tempFile.setSuffix(QL1C('.') + finfo.suffix());
+ tempFile.setAutoRemove(false);
+ tempFile.open();
+ KUrl destUrl;
+ destUrl.setPath(tempFile.fileName());
+ KIO::Job *job = KIO::file_copy(_loadingUrl, destUrl, 0600, KIO::Overwrite);
+ job->ui()->setWindow(rApp->mainWindow());
+ connect(job, SIGNAL(result(KJob*)), this, SLOT(copyToTempFileResult(KJob*)));
+ return;
+ }
+
+ // case KParts::BrowserRun::Embed
+ KParts::ReadOnlyPart *pa = KMimeTypeTrader::createPartInstanceFromQuery<KParts::ReadOnlyPart>(_mimeType, view(), this, QString());
+ if (pa)
+ {
+ _isOnRekonqPage = true;
+
+ WebView *view = qobject_cast<WebView *>(parent());
+ WebTab *tab = qobject_cast<WebTab *>(view->parent());
+ tab->setPart(pa, replyUrl);
+
+ UrlBar *bar = tab->urlBar();
+ bar->setQUrl(replyUrl);
+
+ rApp->mainWindow()->updateHistoryActions();
+ }
+ else
+ {
+ // No parts, just app services. Load it!
+ // If the app is a KDE one, publish the slave on hold to let it use it.
+ // Otherwise, run the app and remove it (the io slave...)
+ KRun::run(*appService, replyUrl, 0, false, _suggestedFileName);
+ }
+
+ return;
+}
+
+
+void WebPage::loadStarted()
+{
+ _hasAdBlockedElements = false;
+ rApp->adblockManager()->clearElementsLists();
+
+ // set zoom factor
+ QString val;
+ KSharedConfig::Ptr config = KGlobal::config();
+ KConfigGroup group(config, "Zoom");
+ val = group.readEntry(_loadingUrl.host(), QString("10"));
+
+ int value = val.toInt();
+ if (value != 10)
+ mainFrame()->setZoomFactor(QVariant(value).toReal() / 10); // Don't allox max +1 values
+}
+
+
+void WebPage::loadFinished(bool ok)
+{
+ Q_UNUSED(ok);
+
+ // Provide site icon. Can this be moved to loadStarted??
+ rApp->iconManager()->provideIcon(mainFrame(), _loadingUrl);
+
+ // Apply adblock manager hiding rules
+ rApp->adblockManager()->applyHidingRules(this);
+
+ // KWallet Integration
+ QStringList list = ReKonfig::walletBlackList();
+ if (wallet()
+ && !list.contains(mainFrame()->url().toString())
+ )
+ {
+ wallet()->fillFormData(mainFrame());
+ }
+}
+
+
+void WebPage::manageNetworkErrors(QNetworkReply *reply)
+{
+ Q_ASSERT(reply);
+
+ QWebFrame* frame = qobject_cast<QWebFrame *>(reply->request().originatingObject());
+ if (!frame)
+ return;
+
+ const bool isMainFrameRequest = (frame == mainFrame());
+
+ // Only deal with non-redirect responses...
+ const QVariant redirectVar = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
+ if (redirectVar.isValid())
+ {
+ _sslInfo.restoreFrom(reply->attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::MetaData)), reply->url());
+ return;
+ }
+
+ // We are just managing loading URLs errors
+ if (reply->request().url() != _loadingUrl)
+ return;
+
+ // NOTE: These are not all networkreply errors,
+ // but just that supported directly by KIO
+ switch (reply->error())
+ {
+
+ case QNetworkReply::NoError: // no error. Simple :)
+ if (isMainFrameRequest)
+ {
+ // Obtain and set the SSL information if any...
+ _sslInfo.restoreFrom(reply->attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::MetaData)), reply->url());
+ _sslInfo.setUrl(reply->url());
+ }
+ break;
+
+ case QNetworkReply::OperationCanceledError: // operation canceled via abort() or close() calls
+ // ignore this..
+ return;
+
+ // WARNING: This is also typical adblocked element error: IGNORE THIS!
+ case QNetworkReply::ContentAccessDenied: // access to remote content denied
+ break;
+
+ case QNetworkReply::UnknownNetworkError: // unknown network-related error detected
+ // last chance for the strange things (eg: FTP, custom schemes, etc...)
+ if (_protHandler.postHandling(reply->request(), mainFrame()))
+ return;
+
+ case QNetworkReply::ConnectionRefusedError: // remote server refused connection
+ case QNetworkReply::HostNotFoundError: // invalid hostname
+ case QNetworkReply::TimeoutError: // connection time out
+ case QNetworkReply::ProxyNotFoundError: // invalid proxy hostname
+ case QNetworkReply::ContentOperationNotPermittedError: // operation requested on remote content not permitted
+ case QNetworkReply::ContentNotFoundError: // remote content not found on server (similar to HTTP error 404)
+ case QNetworkReply::ProtocolUnknownError: // Unknown protocol
+ case QNetworkReply::ProtocolInvalidOperationError: // requested operation is invalid for this protocol
+ default:
+ kDebug() << "ERROR " << reply->error() << ": " << reply->errorString();
+ if (reply->url() == _loadingUrl)
+ {
+ frame->setHtml(errorPage(reply));
+ if (isMainFrameRequest)
+ {
+ _isOnRekonqPage = true;
+
+ WebView *view = qobject_cast<WebView *>(parent());
+ WebTab *tab = qobject_cast<WebTab *>(view->parent());
+ UrlBar *bar = tab->urlBar();
+ bar->setQUrl(_loadingUrl);
+
+ rApp->mainWindow()->updateHistoryActions();
+ }
+ }
+ break;
+
+ }
+}
+
+
+QString WebPage::errorPage(QNetworkReply *reply)
+{
+ // display "not found" page
+ QString notfoundFilePath = KStandardDirs::locate("data", "rekonq/htmls/rekonqinfo.html");
+ QFile file(notfoundFilePath);
+
+ bool isOpened = file.open(QIODevice::ReadOnly);
+ if (!isOpened)
+ {
+ return QString("Couldn't open the rekonqinfo.html file");
+ }
+
+ // NOTE:
+ // this, to take care about XSS (see BUG 217464)...
+ QString urlString = Qt::escape(reply->url().toString());
+
+ // 1. data path
+ QString dataPath = QL1S("file://") + notfoundFilePath;
+ dataPath.remove(QL1S("/htmls/rekonqinfo.html"));
+
+ // 2. title
+ QString title = i18n("There was a problem while loading the page");
+
+ // 3. main content
+ QString msg;
+
+ msg += i18n("<h1>Oops! Rekonq cannot load <em>%1</em></h1>", urlString);
+
+
+ msg += i18n("<h2>Wrongly typed?</h2>");
+
+ msg += QL1S("<table>");
+ msg += QL1S("<tr><td>");
+
+ msg += QL1S("<p>");
+
+ msg += i18n("We tried to load url: %1.<br />", urlString);
+ msg += i18n("Check your address for errors like <em>ww.kde.org</em> instead of <em>www.kde.org</em>.<br />");
+ msg += i18n("If you spelled right, just try to <a href=\"%1\">reload it</a>.<br />", urlString);
+ msg += i18n("Otherwise, just be careful the next time around.");
+
+ msg += QL1S("</p>");
+
+ QString laughIconPath = QString("file://") + KIconLoader::global()->iconPath("face-laugh" , -KIconLoader::SizeHuge, false);
+ msg += QL1S("</td><td>");
+ msg += QL1S("<img src=\"") + laughIconPath + QL1S("\" />");
+ msg += QL1S("</td></tr></table>");
+
+
+ msg += i18n("<h2>Network problems?</h2>");
+
+ QString faceIconPath = QString("file://") + KIconLoader::global()->iconPath("face-surprise" , -KIconLoader::SizeHuge, false);
+ msg += QL1S("<table>");
+ msg += QL1S("<tr><td width=\"100px\">");
+ msg += QL1S("<img src=\"") + faceIconPath + QL1S("\" />");
+ msg += QL1S("</td><td>");
+
+ msg += QL1S("<p>");
+
+ msg += i18n("Maybe you are having problems with your network.<br />");
+ msg += i18n("Try checking your <a href=\"%1\">network connections</a>", QL1S("about:settings/network"));
+ msg += i18n(", your <a href=\"%1\">proxy settings</a> ", QL1S("about:settings/proxy"));
+ msg += i18n("and your <a href=\"%1\">firewall</a>.<br />", QL1S("about:settings/firewall"));
+ msg += i18n("Then try again.<br />");
+
+ msg += QL1S("</p>");
+
+ msg += QL1S("</td></tr></table>");
+
+
+ msg += i18n("<h2>Suggestions</h2>");
+
+ msg += QL1S("<table>");
+ msg += QL1S("<tr><td>");
+
+ msg += QL1S("<p>");
+
+ // Default SearchEngine
+ KService::Ptr defaultEngine = SearchEngine::defaultEngine();
+
+ if (defaultEngine)
+ {
+ msg += i18n("Consult your default search engine about:");
+ msg += QL1S(" <a href=\"") + SearchEngine::buildQuery(defaultEngine, urlString) + QL1S("\">");
+ msg += i18n("search with %1", defaultEngine->name());
+ msg += QL1S("</a>!<br />");
+ }
+ else
+ {
+ msg += i18n("You don't have a default search engine set. We won't suggest you one.");
+ }
+
+ msg += i18n("At least, you can consult a cached snapshot of the site: <br />");
+ msg += i18n("Try checking the <a href=\"%1\">Wayback Machine</a>", QL1S("http://wayback.archive.org/web/*/") + urlString);
+ msg += i18n(" or the <a href=\"%1\">Google Cache</a>.", QL1S("http://google.com/search?q=cache:") + urlString);
+
+ msg += QL1S("</p>");
+
+ QString winkIconPath = QString("file://") + KIconLoader::global()->iconPath("face-wink" , -KIconLoader::SizeHuge, false);
+ msg += QL1S("</td><td>");
+ msg += QL1S("<img src=\"") + winkIconPath + QL1S("\" />");
+ msg += QL1S("</td></tr></table>");
+
+ // done. Replace variables and show it
+ QString html = QL1S(file.readAll());
+
+ html.replace(QL1S("$DEFAULT_PATH"), dataPath);
+ html.replace(QL1S("$PAGE_TITLE"), title);
+ html.replace(QL1S("$MAIN_CONTENT"), msg);
+
+ return html;
+}
+
+
+void WebPage::downloadRequest(const QNetworkRequest &request)
+{
+ rApp->downloadManager()->downloadResource(request.url(),
+ request.attribute(static_cast<QNetworkRequest::Attribute>(KIO::AccessManager::MetaData)).toMap(),
+ view());
+}
+
+
+void WebPage::downloadUrl(const KUrl &url)
+{
+ rApp->downloadManager()->downloadResource(url, KIO::MetaData(), view());
+}
+
+
+void WebPage::downloadAllContentsWithKGet()
+{
+ QSet<QString> contents;
+ KUrl baseUrl(currentFrame()->url());
+ KUrl relativeUrl;
+
+ QWebElementCollection images = mainFrame()->documentElement().findAll("img");
+ Q_FOREACH(const QWebElement & img, images)
+ {
+ relativeUrl.setEncodedUrl(img.attribute("src").toUtf8(), KUrl::TolerantMode);
+ contents << baseUrl.resolved(relativeUrl).toString();
+ }
+
+ QWebElementCollection links = mainFrame()->documentElement().findAll("a");
+ Q_FOREACH(const QWebElement & link, links)
+ {
+ relativeUrl.setEncodedUrl(link.attribute("href").toUtf8(), KUrl::TolerantMode);
+ contents << baseUrl.resolved(relativeUrl).toString();
+ }
+
+ rApp->downloadManager()->downloadLinksWithKGet(QVariant(contents.toList()));
+}
+
+
+void WebPage::showSSLInfo(QPoint pos)
+{
+ if (mainFrame()->url().scheme() == QL1S("https"))
+ {
+ SSLWidget *widget = new SSLWidget(mainFrame()->url(), _sslInfo, view());
+ widget->showAt(pos);
+ }
+ else
+ {
+ KMessageBox::information(view(),
+ i18n("This site does not contain SSL information."),
+ i18nc("Secure Sockets Layer", "SSL")
+ );
+ }
+}
+
+
+void WebPage::copyToTempFileResult(KJob* job)
+{
+ if (job->error())
+ job->uiDelegate()->showErrorMessage();
+ else
+ (void)KRun::runUrl(static_cast<KIO::FileCopyJob *>(job)->destUrl(), _mimeType, rApp->mainWindow());
+}
+
+
+bool WebPage::hasSslValid() const
+{
+ QList<QSslCertificate> certList = _sslInfo.certificateChain();
+
+ if (certList.isEmpty())
+ return false;
+
+ const QSslCertificate cert = certList.at(0);
+ if (!cert.isValid())
+ return false;
+
+ QList<QStringList> errorList = SslInfoDialog::errorsFromString(_sslInfo.certificateErrors());
+ if (!errorList.isEmpty())
+ {
+ QStringList list = errorList.at(0);
+ if (!list.isEmpty())
+ return false;
+ }
+
+ return true;
+}
diff --git a/src/webtab/webpage.h b/src/webtab/webpage.h
new file mode 100644
index 00000000..abc9f64c
--- /dev/null
+++ b/src/webtab/webpage.h
@@ -0,0 +1,114 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2008 Benjamin C. Meyer <ben@meyerhome.net>
+* Copyright (C) 2008 Dirk Mueller <mueller@kde.org>
+* Copyright (C) 2008 Urs Wolfer <uwolfer @ kde.org>
+* Copyright (C) 2008 Michael Howell <mhowell123@gmail.com>
+* Copyright (C) 2008-2012 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2010 by Matthieu Gicquel <matgic78 at gmail dot com>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+#ifndef WEBPAGE_H
+#define WEBPAGE_H
+
+
+// Rekonq Includes
+#include "rekonq_defines.h"
+
+// Local Includes
+#include "protocolhandler.h"
+#include "websslinfo.h"
+
+// KDE Includes
+#include <KWebPage>
+
+
+class REKONQ_TESTS_EXPORT WebPage : public KWebPage
+{
+ Q_OBJECT
+
+public:
+ explicit WebPage(QWidget *parent = 0);
+ ~WebPage();
+
+ bool hasNetworkAnalyzerEnabled() const;
+ void enableNetworkAnalyzer(bool b);
+
+ bool isOnRekonqPage() const;
+ void setIsOnRekonqPage(bool b);
+
+ KUrl loadingUrl();
+
+ QString suggestedFileName();
+
+ inline bool hasAdBlockedElements() const
+ {
+ return _hasAdBlockedElements;
+ };
+
+ inline void setHasAdBlockedElements(bool b)
+ {
+ _hasAdBlockedElements = b;
+ };
+
+ bool hasSslValid() const;
+
+public Q_SLOTS:
+ void downloadAllContentsWithKGet();
+
+ virtual void downloadRequest(const QNetworkRequest &request);
+ virtual void downloadUrl(const KUrl &url);
+
+protected:
+ WebPage *createWindow(WebWindowType type);
+
+ virtual bool acceptNavigationRequest(QWebFrame *frame,
+ const QNetworkRequest &request,
+ NavigationType type);
+
+private Q_SLOTS:
+ void handleUnsupportedContent(QNetworkReply *reply);
+ void manageNetworkErrors(QNetworkReply *reply);
+ void loadStarted();
+ void loadFinished(bool);
+ void showSSLInfo(QPoint);
+
+ void copyToTempFileResult(KJob*);
+
+private:
+ QString errorPage(QNetworkReply *reply);
+ KUrl _loadingUrl;
+
+ ProtocolHandler _protHandler;
+ WebSslInfo _sslInfo;
+
+ QString _mimeType;
+ QString _suggestedFileName;
+
+ bool _networkAnalyzer;
+ bool _isOnRekonqPage;
+ bool _hasAdBlockedElements;
+};
+
+#endif
diff --git a/src/webtab/webpluginfactory.cpp b/src/webtab/webpluginfactory.cpp
new file mode 100644
index 00000000..b62af1c8
--- /dev/null
+++ b/src/webtab/webpluginfactory.cpp
@@ -0,0 +1,93 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009-2012 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2010 by Matthieu Gicquel <matgic78 at gmail dot com>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "webpluginfactory.h"
+#include "webpluginfactory.moc"
+
+// Auto Includes
+#include "rekonq.h"
+
+// Local Includes
+#include "clicktoflash.h"
+
+
+WebPluginFactory::WebPluginFactory(QObject *parent)
+ : KWebPluginFactory(parent)
+ , _loadClickToFlash(false)
+{
+ connect(this, SIGNAL(signalLoadClickToFlash(bool)), SLOT(setLoadClickToFlash(bool)));
+}
+
+
+void WebPluginFactory::setLoadClickToFlash(bool load)
+{
+ _loadClickToFlash = load;
+}
+
+
+QObject *WebPluginFactory::create(const QString &mimeType,
+ const QUrl &url,
+ const QStringList &argumentNames,
+ const QStringList &argumentValues) const
+{
+ kDebug() << "loading mimeType: " << mimeType;
+
+ switch (ReKonfig::pluginsEnabled())
+ {
+ case 0:
+ kDebug() << "No plugins found for" << mimeType << ". Falling back to KDEWebKit ones...";
+ return KWebPluginFactory::create(mimeType, url, argumentNames, argumentValues);
+
+ case 1:
+ if (mimeType != QString("application/x-shockwave-flash")
+ && mimeType != QString("application/futuresplash"))
+ break;
+
+ if (_loadClickToFlash)
+ {
+ emit signalLoadClickToFlash(false);
+ return KWebPluginFactory::create(mimeType, url, argumentNames, argumentValues);
+ }
+ else
+ {
+ ClickToFlash* ctf = new ClickToFlash(url);
+ connect(ctf, SIGNAL(signalLoadClickToFlash(bool)), this, SLOT(setLoadClickToFlash(bool)));
+ return ctf;
+ }
+ break;
+
+ case 2:
+ return 0;
+
+ default:
+ ASSERT_NOT_REACHED("oh oh.. this should NEVER happen..");
+ break;
+ }
+
+ return KWebPluginFactory::create(mimeType, url, argumentNames, argumentValues);
+}
diff --git a/src/webtab/webpluginfactory.h b/src/webtab/webpluginfactory.h
new file mode 100644
index 00000000..b1bcd967
--- /dev/null
+++ b/src/webtab/webpluginfactory.h
@@ -0,0 +1,65 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009-2012 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2010 by Matthieu Gicquel <matgic78 at gmail dot com>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+#ifndef WEB_PLUGIN_FACTORY_H
+#define WEB_PLUGIN_FACTORY_H
+
+
+// Rekonq Includes
+#include "rekonq_defines.h"
+
+// KDE Includes
+#include <KWebPluginFactory>
+
+
+class REKONQ_TESTS_EXPORT WebPluginFactory : public KWebPluginFactory
+{
+ Q_OBJECT
+
+public:
+ WebPluginFactory(QObject *parent);
+
+ virtual QObject *create(const QString &mimeType,
+ const QUrl &url,
+ const QStringList &argumentNames,
+ const QStringList &argumentValues) const;
+
+Q_SIGNALS:
+ void signalLoadClickToFlash(bool) const;
+
+public Q_SLOTS:
+ void setLoadClickToFlash(bool load);
+
+private:
+ /**
+ When true, force loading of next flash animation (don't show clicktoflash)
+ We use signals/slots to set this property because QWebPluginFactory::create is const
+ */
+ bool _loadClickToFlash;
+};
+
+#endif // WEB_PLUGIN_FACTORY_H
diff --git a/src/webtab/websslinfo.cpp b/src/webtab/websslinfo.cpp
new file mode 100644
index 00000000..adbf64f5
--- /dev/null
+++ b/src/webtab/websslinfo.cpp
@@ -0,0 +1,232 @@
+/* ============================================================
+*
+* This file is a part of the KDE project
+*
+* Copyright (C) 2009-2011 by Dawit Alemayehu <adawit@kde.org>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "websslinfo.h"
+
+// Qt Includes
+#include <QtCore/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("ssl_in_use", true);
+ data.insert("ssl_peer_ip", d->peerAddress.toString());
+ data.insert("ssl_parent_ip", d->parentAddress.toString());
+ data.insert("ssl_protocol_version", d->protocol);
+ data.insert("ssl_cipher", d->ciphers);
+ data.insert("ssl_cert_errors", d->certErrors);
+ data.insert("ssl_cipher_used_bits", d->usedCipherBits);
+ data.insert("ssl_cipher_bits", d->supportedCipherBits);
+ QByteArray certChain;
+ Q_FOREACH(const QSslCertificate & cert, d->certificateChain)
+ certChain += cert.toPem();
+ data.insert("ssl_peer_chain", certChain);
+ }
+
+ return ok;
+}
+
+void WebSslInfo::restoreFrom(const QVariant& value, const QUrl& url)
+{
+ if (value.isValid() && value.type() == QVariant::Map)
+ {
+ QMap<QString, QVariant> metaData = value.toMap();
+ if (metaData.value("ssl_in_use", false).toBool())
+ {
+ setCertificateChain(metaData.value("ssl_peer_chain").toByteArray());
+ setPeerAddress(metaData.value("ssl_peer_ip").toString());
+ setParentAddress(metaData.value("ssl_parent_ip").toString());
+ setProtocol(metaData.value("ssl_protocol_version").toString());
+ setCiphers(metaData.value("ssl_cipher").toString());
+ setCertificateErrors(metaData.value("ssl_cert_errors").toString());
+ setUsedCipherBits(metaData.value("ssl_cipher_used_bits").toString());
+ setSupportedCipherBits(metaData.value("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/src/webtab/websslinfo.h b/src/webtab/websslinfo.h
new file mode 100644
index 00000000..6d47b4c8
--- /dev/null
+++ b/src/webtab/websslinfo.h
@@ -0,0 +1,78 @@
+/* ============================================================
+*
+* This file is a part of the KDE project
+*
+* Copyright (C) 2009-2011 by Dawit Alemayehu <adawit@kde.org>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+#ifndef WEBSSLINFO_H
+#define WEBSSLINFO_H
+
+#include <kdemacros.h>
+
+#include <QtCore/QUrl>
+#include <QtCore/QList>
+#include <QtCore/QString>
+#include <QtNetwork/QHostAddress>
+#include <QtNetwork/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());
+
+ 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/src/webtab/webtab.cpp b/src/webtab/webtab.cpp
new file mode 100644
index 00000000..457e9006
--- /dev/null
+++ b/src/webtab/webtab.cpp
@@ -0,0 +1,419 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2008-2012 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009-2011 by Lionel Chauvin <megabigbug@yahoo.fr>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "webtab.h"
+#include "webtab.moc"
+
+// Auto Includes
+#include "rekonq.h"
+
+// Local Includes
+#include "application.h"
+#include "historymanager.h"
+#include "messagebar.h"
+#include "opensearchmanager.h"
+#include "previewselectorbar.h"
+#include "rsswidget.h"
+#include "searchenginebar.h"
+#include "sessionmanager.h"
+#include "syncmanager.h"
+#include "urlbar.h"
+#include "walletbar.h"
+#include "webpage.h"
+#include "websnap.h"
+#include "webshortcutwidget.h"
+
+// KDE Includes
+#include <KWebWallet>
+#include <KStandardShortcut>
+#include <KMenu>
+#include <KActionMenu>
+#include <KWebView>
+#include <KDebug>
+#include <KBuildSycocaProgressDialog>
+
+// Qt Includes
+#include <QVBoxLayout>
+
+
+WebTab::WebTab(QWidget *parent)
+ : QWidget(parent)
+ , m_webView(0)
+ , m_urlBar(new UrlBar(this))
+ , m_progress(0)
+ , m_part(0)
+{
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+
+ QVBoxLayout *l = new QVBoxLayout(this);
+ l->setMargin(0);
+ l->setSpacing(0);
+
+ l->addWidget(view());
+ view()->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+
+ // fix focus handling
+ setFocusProxy(view());
+
+ KWebWallet *wallet = page()->wallet();
+
+ if (wallet)
+ {
+ connect(wallet, SIGNAL(saveFormDataRequested(QString, QUrl)),
+ this, SLOT(createWalletBar(QString, QUrl)));
+ }
+
+ connect(view(), SIGNAL(loadProgress(int)), this, SLOT(updateProgress(int)));
+ connect(view(), SIGNAL(loadStarted()), this, SLOT(resetProgress()));
+ connect(view(), SIGNAL(titleChanged(QString)), this, SIGNAL(titleChanged(QString)));
+ connect(view(), SIGNAL(loadFinished(bool)), this, SLOT(loadFinished()));
+
+ // Session Manager
+ connect(view(), SIGNAL(loadFinished(bool)), rApp->sessionManager(), SLOT(saveSession()));
+}
+
+
+WebTab::~WebTab()
+{
+ m_walletBar.clear();
+ m_previewSelectorBar.clear();
+
+ // NOTE:
+ // Urlbar is reparented when inserted in StackedUrlBar, so we need
+ // to get sure it will be deleted. Deleting it later to ensure everything
+ // will be finished before ;)
+ m_urlBar->deleteLater();
+
+ // Get sure m_part will be deleted
+ delete m_part;
+}
+
+
+WebView *WebTab::view()
+{
+ if (!m_webView)
+ {
+ m_webView = new WebView(this);
+ }
+ return m_webView;
+}
+
+
+WebPage *WebTab::page()
+{
+ if (view())
+ return view()->page();
+
+ return 0;
+}
+
+
+KUrl WebTab::url()
+{
+ if (page() && page()->isOnRekonqPage())
+ {
+ return page()->loadingUrl();
+ }
+
+ if (view())
+ return view()->url();
+
+ kDebug() << "OOPS... NO web classes survived! Returning an empty url...";
+ return KUrl();
+}
+
+
+void WebTab::updateProgress(int p)
+{
+ m_progress = p;
+ emit loadProgressing();
+}
+
+
+void WebTab::resetProgress()
+{
+ m_progress = 1;
+}
+
+
+bool WebTab::isPageLoading()
+{
+ return m_progress != 0 && m_progress != 100;
+}
+
+
+void WebTab::createWalletBar(const QString &key, const QUrl &url)
+{
+ // check if the url is in the wallet blacklist
+ QString urlString = url.toString();
+ QStringList blackList = ReKonfig::walletBlackList();
+ if (blackList.contains(urlString))
+ return;
+
+ KWebWallet *wallet = page()->wallet();
+
+ if (!ReKonfig::passwordSavingEnabled())
+ {
+ wallet->rejectSaveFormDataRequest(key);
+ return;
+ }
+
+ if (m_walletBar.isNull())
+ {
+ m_walletBar = new WalletBar(this);
+ m_walletBar.data()->onSaveFormData(key, url);
+ qobject_cast<QVBoxLayout *>(layout())->insertWidget(0, m_walletBar.data());
+ m_walletBar.data()->animatedShow();
+ }
+ else
+ {
+ disconnect(wallet);
+ qobject_cast<QVBoxLayout *>(layout())->insertWidget(0, m_walletBar.data());
+ m_walletBar.data()->animatedShow();
+ }
+
+ connect(m_walletBar.data(), SIGNAL(saveFormDataAccepted(QString)),
+ wallet, SLOT(acceptSaveFormDataRequest(QString)), Qt::UniqueConnection);
+ connect(m_walletBar.data(), SIGNAL(saveFormDataRejected(QString)),
+ wallet, SLOT(rejectSaveFormDataRequest(QString)), Qt::UniqueConnection);
+
+ // sync passwords
+ connect(m_walletBar.data(), SIGNAL(saveFormDataAccepted(QString)),
+ rApp->syncManager(), SLOT(syncPasswords()), Qt::UniqueConnection);
+}
+
+
+void WebTab::createPreviewSelectorBar(int index)
+{
+ if (m_previewSelectorBar.isNull())
+ {
+ m_previewSelectorBar = new PreviewSelectorBar(index, this);
+ qobject_cast<QVBoxLayout *>(layout())->insertWidget(0, m_previewSelectorBar.data());
+ m_previewSelectorBar.data()->animatedShow();
+ }
+ else
+ {
+ disconnect(m_previewSelectorBar.data());
+ m_previewSelectorBar.data()->setIndex(index);
+ m_previewSelectorBar.data()->animatedHide();
+ }
+
+ connect(page(), SIGNAL(loadStarted()), m_previewSelectorBar.data(), SLOT(loadProgress()), Qt::UniqueConnection);
+ connect(page(), SIGNAL(loadProgress(int)), m_previewSelectorBar.data(), SLOT(loadProgress()), Qt::UniqueConnection);
+ connect(page(), SIGNAL(loadFinished(bool)), m_previewSelectorBar.data(), SLOT(loadFinished()), Qt::UniqueConnection);
+ connect(page()->mainFrame(), SIGNAL(urlChanged(QUrl)), m_previewSelectorBar.data(), SLOT(verifyUrl()), Qt::UniqueConnection);
+}
+
+
+bool WebTab::hasRSSInfo()
+{
+ QWebElementCollection col = page()->mainFrame()->findAllElements("link[type=\"application/rss+xml\"]");
+ col.append(page()->mainFrame()->findAllElements("link[type=\"application/atom+xml\"]"));
+ if (col.count() != 0)
+ return true;
+
+ return false;
+}
+
+
+void WebTab::showRSSInfo(const QPoint &pos)
+{
+ QWebElementCollection col = page()->mainFrame()->findAllElements("link[type=\"application/rss+xml\"]");
+ col.append(page()->mainFrame()->findAllElements("link[type=\"application/atom+xml\"]"));
+
+ QMap<KUrl, QString> map;
+
+ Q_FOREACH(const QWebElement & el, col)
+ {
+ QString urlString;
+ if (el.attribute("href").startsWith(QL1S("http")))
+ urlString = el.attribute("href");
+ else
+ {
+ KUrl u = url();
+ // NOTE
+ // cd() is probably better than setPath() here,
+ // for all those url sites just having a path
+ if (u.cd(el.attribute("href")))
+ urlString = u.toMimeDataString();
+ }
+
+ QString title = el.attribute("title");
+ if (title.isEmpty())
+ title = el.attribute("href");
+
+ map.insert(KUrl(urlString), title);
+ }
+
+ RSSWidget *widget = new RSSWidget(map, window());
+ widget->showAt(pos);
+}
+
+
+void WebTab::hideSelectorBar()
+{
+ m_previewSelectorBar.data()->animatedHide();
+}
+
+
+void WebTab::setPart(KParts::ReadOnlyPart *p, const KUrl &u)
+{
+ if (p)
+ {
+ // Ok, part exists. Insert & show it..
+ m_part = p;
+ qobject_cast<QVBoxLayout *>(layout())->insertWidget(1, p->widget());
+ p->openUrl(u);
+ m_webView->hide();
+
+ emit titleChanged(u.url());
+ return;
+ }
+
+ if (!m_part)
+ return;
+
+ // Part NO more exists. Let's clean up from webtab
+ m_webView->show();
+ qobject_cast<QVBoxLayout *>(layout())->removeWidget(m_part->widget());
+ delete m_part;
+ m_part = 0;
+}
+
+
+KUrl WebTab::extractOpensearchUrl(QWebElement e)
+{
+ QString href = e.attribute(QL1S("href"));
+ KUrl url = KUrl(href);
+ if (!href.contains(":"))
+ {
+ KUrl docUrl = m_webView->url();
+ QString host = docUrl.scheme() + "://" + docUrl.host();
+ if (docUrl.port() != -1)
+ {
+ host += QL1C(':') + QString::number(docUrl.port());
+ }
+ url = KUrl(docUrl, href);
+ }
+ return url;
+}
+
+
+bool WebTab::hasNewSearchEngine()
+{
+ QWebElement e = page()->mainFrame()->findFirstElement(QL1S("head >link[rel=\"search\"][ type=\"application/opensearchdescription+xml\"]"));
+ return !e.isNull() && !rApp->opensearchManager()->engineExists(extractOpensearchUrl(e));
+}
+
+
+void WebTab::showSearchEngine(const QPoint &pos)
+{
+ QWebElement e = page()->mainFrame()->findFirstElement(QL1S("head >link[rel=\"search\"][ type=\"application/opensearchdescription+xml\"]"));
+ QString title = e.attribute(QL1S("title"));
+ if (!title.isEmpty())
+ {
+ WebShortcutWidget *widget = new WebShortcutWidget(window());
+ widget->setWindowFlags(Qt::Popup);
+
+ connect(widget, SIGNAL(webShortcutSet(KUrl, QString, QString)),
+ rApp->opensearchManager(), SLOT(addOpenSearchEngine(KUrl, QString, QString)));
+ connect(rApp->opensearchManager(), SIGNAL(openSearchEngineAdded(QString)),
+ this, SLOT(openSearchEngineAdded()));
+
+ widget->show(extractOpensearchUrl(e), title, pos);
+ }
+}
+
+
+void WebTab::openSearchEngineAdded()
+{
+ // If the providers changed, tell sycoca to rebuild its database...
+ KBuildSycocaProgressDialog::rebuildKSycoca(this);
+
+ disconnect(rApp->opensearchManager(), SIGNAL(openSearchEngineAdded(QString, QString, QString)),
+ this, SLOT(openSearchEngineAdded()));
+}
+
+
+void WebTab::showMessageBar()
+{
+ MessageBar *msgBar = new MessageBar(i18n("It seems rekonq was not closed properly. Do you want "
+ "to restore the last saved session?"), this);
+
+ qobject_cast<QVBoxLayout *>(layout())->insertWidget(0, msgBar);
+ msgBar->animatedShow();
+
+ connect(msgBar, SIGNAL(accepted()), rApp->sessionManager(), SLOT(restoreCrashedSession()));
+}
+
+
+bool WebTab::hasAdBlockedElements()
+{
+ return page()->hasAdBlockedElements();
+}
+
+
+QPixmap WebTab::tabPreview(int width, int height)
+{
+ if (isPageLoading())
+ {
+ // no previews during load
+ return QPixmap();
+ }
+
+ if (!part())
+ {
+ return WebSnap::renderPagePreview(*page(), width, height);
+ }
+ else
+ {
+ QWidget *partWidget = part()->widget();
+ QPixmap partThumb(partWidget->size());
+
+ partWidget->render(&partThumb);
+
+ return partThumb.scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ }
+}
+
+
+void WebTab::loadFinished()
+{
+ // add page to history
+ QString pageTitle = (page() && page()->isOnRekonqPage()) ? url().url() : m_webView->title();
+ rApp->historyManager()->addHistoryEntry(url(), pageTitle);
+}
+
+
+void WebTab::showSearchEngineBar()
+{
+ SearchEngineBar *seBar = new SearchEngineBar(this);
+
+ qobject_cast<QVBoxLayout *>(layout())->insertWidget(0, seBar);
+ seBar->animatedShow();
+}
diff --git a/src/webtab/webtab.h b/src/webtab/webtab.h
new file mode 100644
index 00000000..39c23fb9
--- /dev/null
+++ b/src/webtab/webtab.h
@@ -0,0 +1,131 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2008-2012 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009-2011 by Lionel Chauvin <megabigbug@yahoo.fr>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+#ifndef WEBTAB_H
+#define WEBTAB_H
+
+
+// Rekonq Includes
+#include "rekonq_defines.h"
+
+// Local Includes
+#include "webview.h"
+
+// KDE Includes
+#include <KParts/Part>
+
+// Qt Includes
+#include <QWidget>
+
+// Forward Declarations
+class NotificationBar;
+class PreviewSelectorBar;
+class QPoint;
+class UrlBar;
+class WalletBar;
+class WebPage;
+
+
+class REKONQ_TESTS_EXPORT WebTab : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit WebTab(QWidget *parent = 0);
+ ~WebTab();
+
+ WebView *view();
+ WebPage *page();
+
+ inline UrlBar *urlBar() const
+ {
+ return m_urlBar;
+ }
+
+ inline int progress() const
+ {
+ return m_progress;
+ }
+
+ KUrl url();
+
+ void createPreviewSelectorBar(int index);
+
+ void hideSelectorBar();
+
+ bool hasRSSInfo();
+
+ bool isPageLoading();
+
+ bool hasNewSearchEngine();
+
+ KParts::ReadOnlyPart *part()
+ {
+ return m_part;
+ }
+
+ void setPart(KParts::ReadOnlyPart *p, const KUrl &u);
+
+ bool hasAdBlockedElements();
+
+ QPixmap tabPreview(int width, int height);
+
+private Q_SLOTS:
+ void updateProgress(int progress);
+ void resetProgress();
+
+ void createWalletBar(const QString &, const QUrl &);
+ void showRSSInfo(const QPoint &pos);
+ void showSearchEngine(const QPoint &pos);
+ void openSearchEngineAdded();
+
+ void showMessageBar();
+ void loadFinished();
+
+ void showSearchEngineBar();
+
+private:
+ KUrl extractOpensearchUrl(QWebElement e);
+
+Q_SIGNALS:
+ void loadProgressing();
+ void titleChanged(const QString &);
+
+private:
+ WebView *m_webView;
+
+ UrlBar *m_urlBar;
+
+ int m_progress;
+
+ QWeakPointer<WalletBar> m_walletBar;
+ QWeakPointer<PreviewSelectorBar> m_previewSelectorBar;
+
+ KParts::ReadOnlyPart *m_part;
+};
+
+#endif
diff --git a/src/webtab/webview.cpp b/src/webtab/webview.cpp
new file mode 100644
index 00000000..00112d61
--- /dev/null
+++ b/src/webtab/webview.cpp
@@ -0,0 +1,1273 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2008-2012 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009-2011 by Lionel Chauvin <megabigbug@yahoo.fr>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "webview.h"
+#include "webview.moc"
+
+// Auto Includes
+#include "rekonq.h"
+
+// Local Includes
+#include "application.h"
+#include "adblockmanager.h"
+#include "bookmarkmanager.h"
+#include "iconmanager.h"
+#include "mainview.h"
+#include "mainwindow.h"
+#include "searchengine.h"
+#include "urlbar.h"
+#include "webpage.h"
+#include "webtab.h"
+
+// KDE Includes
+#include <KAction>
+#include <KActionMenu>
+#include <KLocalizedString>
+#include <KMenu>
+#include <KStandardAction>
+#include <KStandardDirs>
+#include <KToolInvocation>
+
+// Qt Includes
+#include <QFile>
+#include <QTimer>
+
+#include <QClipboard>
+#include <QContextMenuEvent>
+#include <QLabel>
+
+#include <QWebFrame>
+#include <QWebHistory>
+#include <QNetworkRequest>
+
+
+WebView::WebView(QWidget* parent)
+ : KWebView(parent, false)
+ , m_page(0)
+ , m_autoScrollTimer(new QTimer(this))
+ , m_verticalAutoScrollSpeed(0)
+ , m_horizontalAutoScrollSpeed(0)
+ , m_isViewAutoScrolling(false)
+ , m_autoScrollIndicator(QPixmap(KStandardDirs::locate("appdata" , "pics/autoscroll.png")))
+ , m_smoothScrollTimer(new QTimer(this))
+ , m_dy(0)
+ , m_smoothScrollSteps(0)
+ , m_isViewSmoothScrolling(false)
+ , m_accessKeysPressed(false)
+ , m_accessKeysActive(false)
+{
+ // loadUrl signal
+ connect(this, SIGNAL(loadUrl(KUrl, Rekonq::OpenType)), rApp, SLOT(loadUrl(KUrl, Rekonq::OpenType)));
+
+ // Auto scroll timer
+ connect(m_autoScrollTimer, SIGNAL(timeout()), this, SLOT(scrollFrameChanged()));
+ m_autoScrollTimer->setInterval(100);
+
+ // Smooth scroll timer
+ connect(m_smoothScrollTimer, SIGNAL(timeout()), this, SLOT(scrollTick()));
+ m_smoothScrollTimer->setInterval(16);
+
+ connect(this, SIGNAL(iconChanged()), this, SLOT(changeWindowIcon()));
+ connect(this, SIGNAL(loadStarted()), this, SLOT(loadStarted()));
+}
+
+
+WebView::~WebView()
+{
+ if (m_isViewSmoothScrolling)
+ stopSmoothScrolling();
+}
+
+
+void WebView::load(const QUrl &url)
+{
+ load(QNetworkRequest(url));
+}
+
+
+void WebView::load(const QNetworkRequest &req, QNetworkAccessManager::Operation op, const QByteArray &body)
+{
+ QNetworkRequest request = req;
+ const QUrl &reqUrl = request.url();
+ if (reqUrl.host() == url().host())
+ {
+ request.setRawHeader(QByteArray("Referer"), url().toEncoded());
+ }
+
+ KWebView::load(request, op, body);
+}
+
+
+void WebView::loadStarted()
+{
+ hideAccessKeys();
+}
+
+
+void WebView::changeWindowIcon()
+{
+ if (ReKonfig::useFavicon())
+ {
+ MainWindow *const mainWindow = rApp->mainWindow();
+ if (url() == mainWindow->currentTab()->url())
+ {
+ const int index = mainWindow->mainView()->currentIndex();
+ mainWindow->changeWindowIcon(index);
+ }
+ }
+}
+
+
+WebPage *WebView::page()
+{
+ if (!m_page)
+ {
+ m_page = new WebPage(this);
+ setPage(m_page);
+ }
+ return m_page;
+}
+
+
+void WebView::contextMenuEvent(QContextMenuEvent *event)
+{
+ QWebHitTestResult result = page()->mainFrame()->hitTestContent(event->pos());
+ MainWindow *mainwindow = rApp->mainWindow();
+
+ KMenu menu(this);
+ QAction *a;
+
+ KAction *inspectAction = new KAction(KIcon("layer-visible-on"), i18n("Inspect Element"), this);
+ connect(inspectAction, SIGNAL(triggered(bool)), this, SLOT(inspect()));
+
+ KAction *sendByMailAction = new KAction(this);
+ sendByMailAction->setIcon(KIcon("mail-send"));
+ connect(sendByMailAction, SIGNAL(triggered(bool)), this, SLOT(sendByMail()));
+
+ // Choose right context
+ int resultHit = 0;
+ if (result.linkUrl().isEmpty())
+ resultHit = WebView::EmptySelection;
+ else
+ resultHit = WebView::LinkSelection;
+
+ if (!result.pixmap().isNull())
+ resultHit |= WebView::ImageSelection;
+
+ if (result.isContentSelected())
+ resultHit = WebView::TextSelection;
+
+ // --------------------------------------------------------------------------------
+ // Ok, let's start filling up the menu...
+
+ // is content editable? Add PASTE
+ if (result.isContentEditable())
+ {
+ menu.addAction(pageAction(KWebPage::Paste));
+ menu.addSeparator();
+ }
+
+ // EMPTY PAGE ACTIONS -------------------------------------------------------------
+ if (resultHit == WebView::EmptySelection)
+ {
+ // send by mail: page url
+ sendByMailAction->setData(page()->currentFrame()->url());
+ sendByMailAction->setText(i18n("Share page url"));
+
+ // navigation
+ QWebHistory *history = page()->history();
+ if (history->canGoBack())
+ {
+ menu.addAction(pageAction(KWebPage::Back));
+ }
+
+ if (history->canGoForward())
+ {
+ menu.addAction(pageAction(KWebPage::Forward));
+ }
+
+ menu.addAction(mainwindow->actionByName("view_redisplay"));
+
+ menu.addSeparator();
+
+ //Frame
+ KActionMenu *frameMenu = new KActionMenu(i18n("Current Frame"), this);
+ frameMenu->addAction(pageAction(KWebPage::OpenFrameInNewWindow));
+
+ a = new KAction(KIcon("document-print-frame"), i18n("Print Frame"), this);
+ connect(a, SIGNAL(triggered()), this, SLOT(printFrame()));
+ frameMenu->addAction(a);
+
+ menu.addAction(frameMenu);
+
+ menu.addSeparator();
+
+ // Page Actions
+ menu.addAction(pageAction(KWebPage::SelectAll));
+
+ menu.addAction(mainwindow->actionByName(KStandardAction::name(KStandardAction::SaveAs)));
+
+ if (!KStandardDirs::findExe("kget").isNull() && ReKonfig::kgetList())
+ {
+ a = new KAction(KIcon("kget"), i18n("List All Links"), this);
+ connect(a, SIGNAL(triggered(bool)), page(), SLOT(downloadAllContentsWithKGet()));
+ menu.addAction(a);
+ }
+
+ menu.addAction(mainwindow->actionByName("page_source"));
+ menu.addAction(inspectAction);
+
+ if (mainwindow->isFullScreen())
+ {
+ menu.addSeparator();
+ menu.addAction(mainwindow->actionByName("fullscreen"));
+ }
+ }
+
+ // LINK ACTIONS -------------------------------------------------------------------
+ if (resultHit & WebView::LinkSelection)
+ {
+ // send by mail: link url
+ sendByMailAction->setData(result.linkUrl());
+ sendByMailAction->setText(i18n("Share link"));
+
+ a = new KAction(KIcon("tab-new"), i18n("Open in New &Tab"), this);
+ a->setData(result.linkUrl());
+ connect(a, SIGNAL(triggered(bool)), this, SLOT(openLinkInNewTab()));
+ menu.addAction(a);
+
+ a = new KAction(KIcon("window-new"), i18n("Open in New &Window"), this);
+ a->setData(result.linkUrl());
+ connect(a, SIGNAL(triggered(bool)), this, SLOT(openLinkInNewWindow()));
+ menu.addAction(a);
+
+ menu.addSeparator();
+
+ // Don't show dots if we are NOT going to ask for download path
+ a = pageAction(KWebPage::DownloadLinkToDisk);
+ if (ReKonfig::askDownloadPath())
+ a->setText(i18n("Save Link..."));
+ else
+ a->setText(i18n("Save Link"));
+
+ menu.addAction(a);
+ menu.addAction(pageAction(KWebPage::CopyLinkToClipboard));
+ }
+
+ // IMAGE ACTIONS ------------------------------------------------------------------
+ if (resultHit & WebView::ImageSelection)
+ {
+ // send by mail: image url
+ sendByMailAction->setData(result.imageUrl());
+ sendByMailAction->setText(i18n("Share image link"));
+
+ menu.addSeparator();
+
+ a = new KAction(KIcon("view-preview"), i18n("&View Image"), this);
+ a->setData(result.imageUrl());
+ connect(a, SIGNAL(triggered(Qt::MouseButtons, Qt::KeyboardModifiers)),
+ this, SLOT(viewImage(Qt::MouseButtons, Qt::KeyboardModifiers)));
+ menu.addAction(a);
+
+ menu.addAction(pageAction(KWebPage::DownloadImageToDisk));
+
+ a = new KAction(KIcon("view-media-visualization"), i18n("&Copy Image Location"), this);
+ a->setData(result.imageUrl());
+ connect(a, SIGNAL(triggered(Qt::MouseButtons, Qt::KeyboardModifiers)), this, SLOT(slotCopyImageLocation()));
+ menu.addAction(a);
+
+ if (rApp->adblockManager()->isEnabled())
+ {
+ a = new KAction(KIcon("preferences-web-browser-adblock"), i18n("Block image"), this);
+ a->setData(result.imageUrl());
+ connect(a, SIGNAL(triggered(Qt::MouseButtons, Qt::KeyboardModifiers)), this, SLOT(blockImage()));
+ menu.addAction(a);
+ }
+ }
+
+ // ACTIONS FOR TEXT SELECTION -----------------------------------------------------
+ if (resultHit & WebView::TextSelection)
+ {
+ // send by mail: text
+ sendByMailAction->setData(selectedText());
+ sendByMailAction->setText(i18n("Share selected text"));
+
+ if (result.isContentEditable())
+ {
+ // actions for text selected in field
+ menu.addAction(pageAction(KWebPage::Cut));
+ }
+
+ a = pageAction(KWebPage::Copy);
+ if (!result.linkUrl().isEmpty())
+ a->setText(i18n("Copy Text")); //for link
+ else
+ a->setText(i18n("Copy"));
+ menu.addAction(a);
+
+ if (selectedText().contains('.') && selectedText().indexOf('.') < selectedText().length()
+ && !selectedText().trimmed().contains(" ")
+ )
+ {
+ QString text = selectedText();
+ text = text.trimmed();
+ KUrl urlLikeText(text);
+ if (urlLikeText.isValid())
+ {
+ QString truncatedUrl = text;
+ const int maxTextSize = 18;
+ if (truncatedUrl.length() > maxTextSize)
+ {
+ const int truncateSize = 15;
+ truncatedUrl.truncate(truncateSize);
+ truncatedUrl += QL1S("...");
+ }
+ //open selected text url in a new tab
+ QAction * const openInNewTabAction = new KAction(KIcon("tab-new"), i18n("Open '%1' in New Tab", truncatedUrl), this);
+ openInNewTabAction->setData(QUrl(urlLikeText));
+ connect(openInNewTabAction, SIGNAL(triggered(bool)), this, SLOT(openLinkInNewTab()));
+ menu.addAction(openInNewTabAction);
+ //open selected text url in a new window
+ QAction * const openInNewWindowAction = new KAction(KIcon("window-new"), i18n("Open '%1' in New Window", truncatedUrl), this);
+ openInNewWindowAction->setData(QUrl(urlLikeText));
+ connect(openInNewWindowAction, SIGNAL(triggered(bool)), this, SLOT(openLinkInNewWindow()));
+ menu.addAction(openInNewWindowAction);
+ menu.addSeparator();
+ }
+ }
+
+ //Default SearchEngine
+ KService::Ptr defaultEngine = SearchEngine::defaultEngine();
+ if (defaultEngine) // check if a default engine is set
+ {
+ a = new KAction(i18nc("Search selected text with the default search engine", "Search with %1", defaultEngine->name()), this);
+ a->setIcon(rApp->iconManager()->iconForUrl(SearchEngine::buildQuery(defaultEngine, "")));
+ a->setData(defaultEngine->entryPath());
+ connect(a, SIGNAL(triggered(bool)), this, SLOT(search()));
+ menu.addAction(a);
+ }
+
+ //All favourite ones
+ KActionMenu *searchMenu = new KActionMenu(KIcon("edit-find"), i18nc("@title:menu", "Search"), this);
+
+ Q_FOREACH(const KService::Ptr & engine, SearchEngine::favorites())
+ {
+ a = new KAction(i18nc("@item:inmenu Search, %1 = search engine", "With %1", engine->name()), this);
+ a->setIcon(rApp->iconManager()->iconForUrl(SearchEngine::buildQuery(engine, "")));
+ a->setData(engine->entryPath());
+ connect(a, SIGNAL(triggered(bool)), this, SLOT(search()));
+ searchMenu->addAction(a);
+ }
+
+ a = new KAction(KIcon("edit-find"), i18n("On Current Page"), this);
+ connect(a, SIGNAL(triggered()), rApp->mainWindow(), SLOT(findSelectedText()));
+ searchMenu->addAction(a);
+
+ if (!searchMenu->menu()->isEmpty())
+ {
+ menu.addAction(searchMenu);
+ }
+ }
+
+ // DEFAULT ACTIONs (on the bottom) ------------------------------------------------
+ menu.addSeparator();
+ if (resultHit & WebView::LinkSelection)
+ {
+ a = new KAction(KIcon("bookmark-new"), i18n("&Bookmark link"), this);
+ a->setData(result.linkUrl());
+ connect(a, SIGNAL(triggered(bool)), this, SLOT(bookmarkLink()));
+ menu.addAction(a);
+ }
+ else
+ {
+ a = mainwindow->actionByName(KStandardAction::name(KStandardAction::AddBookmark));
+ menu.addAction(a);
+ }
+ menu.addAction(sendByMailAction);
+ menu.addAction(inspectAction);
+
+ // finally launch the menu...
+ menu.exec(mapToGlobal(event->pos()));
+}
+
+
+void WebView::mousePressEvent(QMouseEvent *event)
+{
+ if (m_isViewAutoScrolling)
+ {
+ m_verticalAutoScrollSpeed = 0;
+ m_horizontalAutoScrollSpeed = 0;
+ m_autoScrollTimer->stop();
+ m_isViewAutoScrolling = false;
+ update();
+ return;
+ }
+
+ QWebHitTestResult result = page()->mainFrame()->hitTestContent(event->pos());
+ bool weCanDoMiddleClickActions = !result.isContentEditable() && result.linkUrl().isEmpty();
+
+ switch (event->button())
+ {
+ case Qt::XButton1:
+ triggerPageAction(KWebPage::Back);
+ break;
+
+ case Qt::XButton2:
+ triggerPageAction(KWebPage::Forward);
+ break;
+
+ case Qt::MidButton:
+ switch (ReKonfig::middleClickAction())
+ {
+ case 0: // AutoScroll
+ if (weCanDoMiddleClickActions
+ && !m_isViewAutoScrolling
+ && !page()->currentFrame()->scrollBarGeometry(Qt::Horizontal).contains(event->pos())
+ && !page()->currentFrame()->scrollBarGeometry(Qt::Vertical).contains(event->pos()))
+ {
+ if (!page()->currentFrame()->scrollBarGeometry(Qt::Horizontal).isNull()
+ || !page()->currentFrame()->scrollBarGeometry(Qt::Vertical).isNull())
+ {
+ m_clickPos = event->pos();
+ m_isViewAutoScrolling = true;
+ update();
+ }
+ }
+ break;
+
+ case 1: // Load Clipboard URL
+ if (weCanDoMiddleClickActions)
+ {
+ const QString clipboardContent = rApp->clipboard()->text();
+
+ if (clipboardContent.isEmpty())
+ break;
+
+ if (QUrl::fromUserInput(clipboardContent).isValid())
+ loadUrl(clipboardContent, Rekonq::CurrentTab);
+ else // Search with default Engine
+ {
+ KService::Ptr defaultEngine = SearchEngine::defaultEngine();
+ if (defaultEngine) // check if a default engine is set
+ loadUrl(KUrl(SearchEngine::buildQuery(defaultEngine, clipboardContent)), Rekonq::CurrentTab);
+ }
+ }
+ break;
+
+ default: // Do Nothing
+ break;
+ }
+ break;
+
+ default:
+ break;
+ };
+
+ KWebView::mousePressEvent(event);
+}
+
+
+void WebView::mouseMoveEvent(QMouseEvent *event)
+{
+ QPoint mousePos = event->pos();
+
+ if (m_isViewAutoScrolling)
+ {
+ QPoint r = mousePos - m_clickPos;
+ m_horizontalAutoScrollSpeed = r.x() / 2; // you are too fast..
+ m_verticalAutoScrollSpeed = r.y() / 2;
+ if (!m_autoScrollTimer->isActive())
+ m_autoScrollTimer->start();
+
+ return;
+ }
+
+ MainWindow *w = rApp->mainWindow();
+ if (w->isFullScreen())
+ {
+ if (event->pos().y() >= 0 && event->pos().y() <= 4)
+ {
+ w->setWidgetsVisible(true);
+ }
+ else
+ {
+ if (!w->mainView()->currentUrlBar()->hasFocus())
+ w->setWidgetsVisible(false);
+ }
+ }
+ KWebView::mouseMoveEvent(event);
+}
+
+
+void WebView::dropEvent(QDropEvent *event)
+{
+ bool isEditable = page()->frameAt(event->pos())->hitTestContent(event->pos()).isContentEditable();
+ if (event->mimeData()->hasFormat(BookmarkManager::bookmark_mime_type()))
+ {
+ QByteArray addresses = event->mimeData()->data(BookmarkManager::bookmark_mime_type());
+ KBookmark bookmark = rApp->bookmarkManager()->findByAddress(QString::fromLatin1(addresses.data()));
+ if (bookmark.isGroup())
+ {
+ rApp->bookmarkManager()->openFolderinTabs(bookmark.toGroup());
+ }
+ else
+ {
+ emit loadUrl(bookmark.url(), Rekonq::CurrentTab);
+ }
+ }
+ else if (event->mimeData()->hasUrls() && event->source() != this && !isEditable) //dropped links
+ {
+ Q_FOREACH(const QUrl & url, event->mimeData()->urls())
+ {
+ emit loadUrl(url, Rekonq::NewFocusedTab);
+ }
+ }
+ else if (event->mimeData()->hasFormat("text/plain") && event->source() != this && !isEditable) //dropped plain text with url format
+ {
+ QUrl url = QUrl::fromUserInput(event->mimeData()->data("text/plain"));
+
+ if (url.isValid())
+ emit loadUrl(url, Rekonq::NewFocusedTab);
+ }
+ else
+ {
+ KWebView::dropEvent(event);
+ }
+}
+
+
+void WebView::paintEvent(QPaintEvent* event)
+{
+ KWebView::paintEvent(event);
+
+ if (m_isViewAutoScrolling)
+ {
+ QPoint centeredPoint = m_clickPos;
+ centeredPoint.setX(centeredPoint.x() - m_autoScrollIndicator.width() / 2);
+ centeredPoint.setY(centeredPoint.y() - m_autoScrollIndicator.height() / 2);
+
+ QPainter painter(this);
+ painter.setOpacity(0.8);
+ painter.drawPixmap(centeredPoint, m_autoScrollIndicator);
+ }
+}
+
+
+void WebView::search()
+{
+ KAction *a = qobject_cast<KAction*>(sender());
+ KService::Ptr engine = KService::serviceByDesktopPath(a->data().toString());
+ KUrl urlSearch = KUrl(SearchEngine::buildQuery(engine, selectedText()));
+
+ emit loadUrl(urlSearch, Rekonq::NewTab);
+}
+
+
+void WebView::printFrame()
+{
+ rApp->mainWindow()->printRequested(page()->currentFrame());
+}
+
+
+void WebView::viewImage(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
+{
+ KAction *a = qobject_cast<KAction*>(sender());
+ KUrl url(a->data().toUrl());
+
+ if (modifiers & Qt::ControlModifier || buttons == Qt::MidButton)
+ {
+ emit loadUrl(url, Rekonq::NewTab);
+ }
+ else
+ {
+ emit loadUrl(url, Rekonq::CurrentTab);
+ }
+}
+
+
+void WebView::slotCopyImageLocation()
+{
+ KAction *a = qobject_cast<KAction*>(sender());
+ KUrl imageUrl(a->data().toUrl());
+#ifndef QT_NO_MIMECLIPBOARD
+ // Set it in both the mouse selection and in the clipboard
+ QMimeData* mimeData = new QMimeData;
+ imageUrl.populateMimeData(mimeData);
+ QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
+ mimeData = new QMimeData;
+ imageUrl.populateMimeData(mimeData);
+ QApplication::clipboard()->setMimeData(mimeData, QClipboard::Selection);
+#else
+ QApplication::clipboard()->setText(imageUrl.url());
+#endif
+}
+
+
+void WebView::openLinkInNewWindow()
+{
+ KAction *a = qobject_cast<KAction*>(sender());
+ KUrl url(a->data().toUrl());
+
+ emit loadUrl(url, Rekonq::NewWindow);
+}
+
+
+void WebView::openLinkInNewTab()
+{
+ KAction *a = qobject_cast<KAction*>(sender());
+ KUrl url(a->data().toUrl());
+
+ emit loadUrl(url, Rekonq::NewTab);
+}
+
+
+void WebView::bookmarkLink()
+{
+ KAction *a = qobject_cast<KAction*>(sender());
+ KUrl url(a->data().toUrl());
+
+ rApp->bookmarkManager()->rootGroup().addBookmark(url.prettyUrl(), url);
+ rApp->bookmarkManager()->emitChanged();
+}
+
+
+void WebView::keyPressEvent(QKeyEvent *event)
+{
+ // If CTRL was hit, be prepared for access keys
+ if (ReKonfig::accessKeysEnabled()
+ && !m_accessKeysActive
+ && event->key() == Qt::Key_Control
+ && !(event->modifiers() & ~Qt::ControlModifier)
+ )
+ {
+ m_accessKeysPressed = true;
+ event->accept();
+ return;
+ }
+
+ const QString tagName = page()->mainFrame()->evaluateJavaScript("document.activeElement.tagName").toString();
+
+ if (event->modifiers() == Qt::ControlModifier)
+ {
+ if (event->key() == Qt::Key_C)
+ {
+ triggerPageAction(KWebPage::Copy);
+ event->accept();
+ return;
+ }
+
+ if (event->key() == Qt::Key_A)
+ {
+ triggerPageAction(KWebPage::SelectAll);
+ event->accept();
+ return;
+ }
+
+ // CTRL + RETURN: open link into another tab
+ if (event->key() == Qt::Key_Return && tagName == QL1S("A"))
+ {
+ KUrl u = KUrl(page()->mainFrame()->evaluateJavaScript("document.activeElement.attributes[\"href\"].value").toString());
+ emit loadUrl(u, Rekonq::NewTab);
+ event->accept();
+ return;
+ }
+ }
+
+ // Auto Scrolling
+ if (event->modifiers() == Qt::ShiftModifier
+ && tagName != QL1S("INPUT")
+ && tagName != QL1S("TEXTAREA")
+ )
+ {
+ // NOTE and FIXME
+ // This check is doabled because it presents strange behavior: QtWebKit check works well in pages like gmail
+ // and fails on sites like g+. The opposite is true for javascript check.
+ // Please, help me finding the right way to check this EVERY TIME.
+ bool isContentEditableQW = page()->mainFrame()->hitTestContent(QCursor::pos()).isContentEditable();
+ bool isContentEditableJS = page()->mainFrame()->evaluateJavaScript("document.activeElement.isContentEditable").toBool();
+
+ if (!isContentEditableQW && !isContentEditableJS)
+ {
+ if (event->key() == Qt::Key_Up)
+ {
+ m_verticalAutoScrollSpeed--;
+ if (!m_autoScrollTimer->isActive())
+ m_autoScrollTimer->start();
+
+ event->accept();
+ return;
+ }
+
+ if (event->key() == Qt::Key_Down)
+ {
+ m_verticalAutoScrollSpeed++;
+ if (!m_autoScrollTimer->isActive())
+ m_autoScrollTimer->start();
+
+ event->accept();
+ return;
+ }
+
+ if (event->key() == Qt::Key_Right)
+ {
+ m_horizontalAutoScrollSpeed++;
+ if (!m_autoScrollTimer->isActive())
+ m_autoScrollTimer->start();
+
+ event->accept();
+ return;
+ }
+
+ if (event->key() == Qt::Key_Left)
+ {
+ m_horizontalAutoScrollSpeed--;
+ if (!m_autoScrollTimer->isActive())
+ m_autoScrollTimer->start();
+
+ event->accept();
+ return;
+ }
+
+ if (m_autoScrollTimer->isActive())
+ {
+ m_autoScrollTimer->stop();
+ event->accept();
+ return;
+ }
+ else
+ {
+ if (m_verticalAutoScrollSpeed || m_horizontalAutoScrollSpeed)
+ {
+ m_autoScrollTimer->start();
+ event->accept();
+ return;
+ }
+ }
+ }
+
+ // if you arrived here, I hope it means SHIFT has been pressed NOT for autoscroll management...
+ }
+
+ if (ReKonfig::accessKeysEnabled() && m_accessKeysActive)
+ {
+ hideAccessKeys();
+ event->accept();
+ return;
+ }
+
+ // vi-like navigation
+ if (ReKonfig::enableViShortcuts())
+ {
+ if (event->modifiers() == Qt::NoModifier
+ && tagName != QL1S("INPUT")
+ && tagName != QL1S("TEXTAREA")
+ )
+ {
+ // See note up!
+ bool isContentEditableQW = page()->mainFrame()->hitTestContent(QCursor::pos()).isContentEditable();
+ bool isContentEditableJS = page()->mainFrame()->evaluateJavaScript("document.activeElement.isContentEditable").toBool();
+
+ if (!isContentEditableQW && !isContentEditableJS)
+ {
+ switch (event->key())
+ {
+ case Qt::Key_J:
+ event->accept();
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier);
+ break;
+ case Qt::Key_K:
+ event->accept();
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier);
+ break;
+ case Qt::Key_L:
+ event->accept();
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier);
+ break;
+ case Qt::Key_H:
+ event->accept();
+ event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ KWebView::keyPressEvent(event);
+}
+
+
+void WebView::keyReleaseEvent(QKeyEvent *event)
+{
+ // access keys management
+ if (ReKonfig::accessKeysEnabled())
+ {
+ if (m_accessKeysPressed && event->key() != Qt::Key_Control)
+ m_accessKeysPressed = false;
+
+ if (m_accessKeysPressed && !(event->modifiers() & Qt::ControlModifier))
+ {
+ kDebug() << "Shotting access keys";
+ QTimer::singleShot(200, this, SLOT(accessKeyShortcut()));
+ event->accept();
+ return;
+ }
+ else
+ {
+ checkForAccessKey(event);
+ kDebug() << "Hiding access keys";
+ hideAccessKeys();
+ event->accept();
+ return;
+ }
+ }
+
+ KWebView::keyReleaseEvent(event);
+}
+
+
+void WebView::wheelEvent(QWheelEvent *event)
+{
+ if (event->orientation() == Qt::Vertical || !ReKonfig::hScrollWheelHistory())
+ {
+ // To let some websites (eg: google maps) to handle wheel events
+ int prevPos = page()->currentFrame()->scrollPosition().y();
+ KWebView::wheelEvent(event);
+ int newPos = page()->currentFrame()->scrollPosition().y();
+
+ // Sync with the zoom slider
+ if (event->modifiers() == Qt::ControlModifier)
+ {
+ // Limits of the slider
+ if (zoomFactor() > 1.9)
+ setZoomFactor(1.9);
+ else if (zoomFactor() < 0.1)
+ setZoomFactor(0.1);
+
+ // Round the factor (Fix slider's end value)
+ int newFactor = zoomFactor() * 10;
+ if ((zoomFactor() * 10 - newFactor) > 0.5)
+ newFactor++;
+
+ emit zoomChanged(newFactor);
+ }
+ else if (ReKonfig::smoothScrolling() && prevPos != newPos)
+ {
+ page()->currentFrame()->setScrollPosition(QPoint(page()->currentFrame()->scrollPosition().x(), prevPos));
+
+ if ((event->delta() > 0) != !m_smoothScrollBottomReached)
+ stopSmoothScrolling();
+
+ if (event->delta() > 0)
+ m_smoothScrollBottomReached = false;
+ else
+ m_smoothScrollBottomReached = true;
+
+
+ setupSmoothScrolling(abs(newPos - prevPos));
+ }
+ }
+ // use horizontal wheel events to go back and forward in tab history
+ else
+ {
+ // left -> go to previous page
+ if (event->delta() > 0)
+ {
+ emit openPreviousInHistory();
+ }
+ // right -> go to next page
+ if (event->delta() < 0)
+ {
+ emit openNextInHistory();
+ }
+ }
+}
+
+
+void WebView::inspect()
+{
+ QAction *a = rApp->mainWindow()->actionByName("web_inspector");
+ if (a && !a->isChecked())
+ a->trigger();
+ pageAction(QWebPage::InspectElement)->trigger();
+}
+
+
+void WebView::scrollFrameChanged()
+{
+ // do the scrolling
+ page()->currentFrame()->scroll(m_horizontalAutoScrollSpeed, m_verticalAutoScrollSpeed);
+
+ // check if we reached the end
+ int y = page()->currentFrame()->scrollPosition().y();
+ if (y == 0 || y == page()->currentFrame()->scrollBarMaximum(Qt::Vertical))
+ m_verticalAutoScrollSpeed = 0;
+
+ int x = page()->currentFrame()->scrollPosition().x();
+ if (x == 0 || x == page()->currentFrame()->scrollBarMaximum(Qt::Horizontal))
+ m_horizontalAutoScrollSpeed = 0;
+}
+
+
+void WebView::setupSmoothScrolling(int posY)
+{
+ int ddy = qMax(m_smoothScrollSteps ? abs(m_dy) / m_smoothScrollSteps : 0, 3);
+
+ m_dy += posY;
+
+ if (m_dy <= 0)
+ {
+ stopSmoothScrolling();
+ return;
+ }
+
+ m_smoothScrollSteps = 8;
+
+ if (m_dy / m_smoothScrollSteps < ddy)
+ {
+ m_smoothScrollSteps = (abs(m_dy) + ddy - 1) / ddy;
+ if (m_smoothScrollSteps < 1)
+ m_smoothScrollSteps = 1;
+ }
+
+ m_smoothScrollTime.start();
+
+ if (!m_isViewSmoothScrolling)
+ {
+ m_isViewSmoothScrolling = true;
+ m_smoothScrollTimer->start();
+ scrollTick();
+ }
+}
+
+
+void WebView::scrollTick()
+{
+ if (m_dy == 0)
+ {
+ stopSmoothScrolling();
+ return;
+ }
+
+ if (m_smoothScrollSteps < 1)
+ m_smoothScrollSteps = 1;
+
+ int takesteps = m_smoothScrollTime.restart() / 16;
+ int scroll_y = 0;
+
+ if (takesteps < 1)
+ takesteps = 1;
+
+ if (takesteps > m_smoothScrollSteps)
+ takesteps = m_smoothScrollSteps;
+
+ for (int i = 0; i < takesteps; i++)
+ {
+ int ddy = (m_dy / (m_smoothScrollSteps + 1)) * 2;
+
+ // limit step to requested scrolling distance
+ if (abs(ddy) > abs(m_dy))
+ ddy = m_dy;
+
+ // update remaining scroll
+ m_dy -= ddy;
+ scroll_y += ddy;
+ m_smoothScrollSteps--;
+ }
+
+ if (m_smoothScrollBottomReached)
+ page()->currentFrame()->scroll(0, scroll_y);
+ else
+ page()->currentFrame()->scroll(0, -scroll_y);
+}
+
+
+void WebView::stopSmoothScrolling()
+{
+ m_smoothScrollTimer->stop();
+ m_dy = 0;
+ m_isViewSmoothScrolling = false;
+}
+
+
+void WebView::dragEnterEvent(QDragEnterEvent *event)
+{
+ if (event->mimeData()->hasUrls() || event->mimeData()->hasText())
+ event->acceptProposedAction();
+ else
+ KWebView::dragEnterEvent(event);
+}
+
+
+void WebView::dragMoveEvent(QDragMoveEvent *event)
+{
+ if (event->mimeData()->hasUrls() || event->mimeData()->hasText())
+ event->acceptProposedAction();
+ else
+ KWebView::dragMoveEvent(event);
+}
+
+
+void WebView::hideAccessKeys()
+{
+ if (!m_accessKeyLabels.isEmpty())
+ {
+ for (int i = 0; i < m_accessKeyLabels.count(); ++i)
+ {
+ QLabel *label = m_accessKeyLabels[i];
+ label->hide();
+ label->deleteLater();
+ }
+ m_accessKeyLabels.clear();
+ m_accessKeyNodes.clear();
+ update();
+ }
+}
+
+
+void WebView::showAccessKeys()
+{
+ QStringList supportedElement;
+ supportedElement << QLatin1String("a")
+ << QLatin1String("input")
+ << QLatin1String("area")
+ << QLatin1String("button")
+ << QLatin1String("label")
+ << QLatin1String("legend")
+ << QLatin1String("textarea");
+
+ QList<QChar> unusedKeys;
+ for (char c = 'A'; c <= 'Z'; ++c)
+ unusedKeys << QLatin1Char(c);
+ for (char c = '0'; c <= '9'; ++c)
+ unusedKeys << QLatin1Char(c);
+
+ QRect viewport = QRect(page()->mainFrame()->scrollPosition(), page()->viewportSize());
+ // Priority first goes to elements with accesskey attributes
+ QList<QWebElement> alreadyLabeled;
+ Q_FOREACH(const QString & elementType, supportedElement)
+ {
+ QList<QWebElement> result = page()->mainFrame()->findAllElements(elementType).toList();
+ Q_FOREACH(const QWebElement & element, result)
+ {
+ const QRect geometry = element.geometry();
+ if (geometry.size().isEmpty()
+ || !viewport.contains(geometry.topLeft()))
+ {
+ continue;
+ }
+ QString accessKeyAttribute = element.attribute(QLatin1String("accesskey")).toUpper();
+ if (accessKeyAttribute.isEmpty())
+ continue;
+ QChar accessKey;
+ for (int i = 0; i < accessKeyAttribute.count(); i += 2)
+ {
+ const QChar &possibleAccessKey = accessKeyAttribute[i];
+ if (unusedKeys.contains(possibleAccessKey))
+ {
+ accessKey = possibleAccessKey;
+ break;
+ }
+ }
+ if (accessKey.isNull())
+ {
+ continue;
+ }
+ unusedKeys.removeOne(accessKey);
+ makeAccessKeyLabel(accessKey, element);
+ alreadyLabeled.append(element);
+ }
+ }
+
+ // Pick an access key first from the letters in the text and then from the
+ // list of unused access keys
+ Q_FOREACH(const QString & elementType, supportedElement)
+ {
+ QWebElementCollection result = page()->mainFrame()->findAllElements(elementType);
+ Q_FOREACH(const QWebElement & element, result)
+ {
+ const QRect geometry = element.geometry();
+ if (unusedKeys.isEmpty()
+ || alreadyLabeled.contains(element)
+ || geometry.size().isEmpty()
+ || !viewport.contains(geometry.topLeft()))
+ {
+ continue;
+ }
+ QChar accessKey;
+ QString text = element.toPlainText().toUpper();
+ for (int i = 0; i < text.count(); ++i)
+ {
+ const QChar &c = text.at(i);
+ if (unusedKeys.contains(c))
+ {
+ accessKey = c;
+ break;
+ }
+ }
+ if (accessKey.isNull())
+ accessKey = unusedKeys.takeFirst();
+ unusedKeys.removeOne(accessKey);
+ makeAccessKeyLabel(accessKey, element);
+ }
+ }
+}
+
+
+void WebView::makeAccessKeyLabel(const QChar &accessKey, const QWebElement &element)
+{
+ QLabel *label = new QLabel(this);
+ label->setText(QString(QLatin1String("<qt><b>%1</b>")).arg(accessKey));
+
+ label->setAutoFillBackground(true);
+ label->setFrameStyle(QFrame::Box | QFrame::Plain);
+ QPoint point = element.geometry().center();
+ point -= page()->mainFrame()->scrollPosition();
+ label->move(point);
+ label->show();
+ point.setX(point.x() - label->width() / 2);
+ label->move(point);
+ m_accessKeyLabels.append(label);
+ m_accessKeyNodes[accessKey] = element;
+}
+
+
+bool WebView::checkForAccessKey(QKeyEvent *event)
+{
+ if (m_accessKeyLabels.isEmpty())
+ return false;
+
+ QString text = event->text();
+ if (text.isEmpty())
+ return false;
+ QChar key = text.at(0).toUpper();
+ bool handled = false;
+ if (m_accessKeyNodes.contains(key))
+ {
+ QWebElement element = m_accessKeyNodes[key];
+ QPoint p = element.geometry().center();
+ QWebFrame *frame = element.webFrame();
+ Q_ASSERT(frame);
+ do
+ {
+ p -= frame->scrollPosition();
+ frame = frame->parentFrame();
+ }
+ while (frame && frame != page()->mainFrame());
+ QMouseEvent pevent(QEvent::MouseButtonPress, p, Qt::LeftButton, 0, 0);
+ rApp->sendEvent(this, &pevent);
+ QMouseEvent revent(QEvent::MouseButtonRelease, p, Qt::LeftButton, 0, 0);
+ rApp->sendEvent(this, &revent);
+ handled = true;
+ }
+
+ kDebug() << "checking for access keys: " << handled;
+ return handled;
+}
+
+
+void WebView::accessKeyShortcut()
+{
+ if (!hasFocus()
+ || !m_accessKeysPressed
+ || !ReKonfig::accessKeysEnabled())
+ return;
+ if (m_accessKeyLabels.isEmpty())
+ {
+ showAccessKeys();
+ }
+ else
+ {
+ hideAccessKeys();
+ }
+ m_accessKeysPressed = false;
+}
+
+
+void WebView::sendByMail()
+{
+ KAction *a = qobject_cast<KAction*>(sender());
+ QString url = a->data().toString();
+
+ KToolInvocation::invokeMailer("", "", "", "", url);
+}
+
+
+void WebView::blockImage()
+{
+ QAction *action = qobject_cast<QAction*>(sender());
+ if (!action)
+ return;
+
+ QString imageUrl = action->data().toString();
+ rApp->adblockManager()->addCustomRule(imageUrl);
+}
+
+
+void WebView::mouseReleaseEvent(QMouseEvent *event)
+{
+ QWebHitTestResult hitTest = page()->mainFrame()->hitTestContent(event->pos());
+ const QUrl url = hitTest.linkUrl();
+
+ if (!url.isEmpty())
+ {
+ if (event->button() & Qt::MidButton)
+ {
+ if (event->modifiers() & Qt::ShiftModifier)
+ {
+ if (ReKonfig::openNewTabsInBackground())
+ emit loadUrl(url, Rekonq::NewFocusedTab);
+ else
+ emit loadUrl(url, Rekonq::NewBackGroundTab);
+ event->accept();
+ return;
+ }
+
+ emit loadUrl(url, Rekonq::NewTab);
+ event->accept();
+ return;
+ }
+
+ if ((event->button() & Qt::LeftButton) && (event->modifiers() & Qt::ControlModifier))
+ {
+ emit loadUrl(url, Rekonq::NewTab);
+ event->accept();
+ return;
+ }
+
+ if ((event->button() & Qt::LeftButton) && (event->modifiers() & Qt::ShiftModifier))
+ {
+ page()->downloadUrl(url);
+ event->accept();
+ return;
+ }
+ }
+
+ QWebView::mouseReleaseEvent(event);
+}
diff --git a/src/webtab/webview.h b/src/webtab/webview.h
new file mode 100644
index 00000000..0141925c
--- /dev/null
+++ b/src/webtab/webview.h
@@ -0,0 +1,159 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2008-2012 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009-2011 by Lionel Chauvin <megabigbug@yahoo.fr>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+#ifndef WEBVIEW_H
+#define WEBVIEW_H
+
+
+// Rekonq Includes
+#include "rekonq_defines.h"
+
+// KDE Includes
+#include <KWebView>
+
+// Qt Includes
+#include <QTime>
+#include <QPoint>
+#include <QPixmap>
+
+// Forward Declarations
+class WebPage;
+
+class QLabel;
+class QTimer;
+
+
+class REKONQ_TESTS_EXPORT WebView : public KWebView
+{
+ Q_OBJECT
+
+public:
+
+ enum ContextType
+ {
+ EmptySelection = 0x00000000,
+ LinkSelection = 0x00000001,
+ ImageSelection = 0x00000010,
+ TextSelection = 0x00000100
+ };
+
+ explicit WebView(QWidget *parent);
+ ~WebView();
+
+ WebPage *page();
+
+ void load(const QUrl &url);
+ void load(const QNetworkRequest &req,
+ QNetworkAccessManager::Operation op = QNetworkAccessManager::GetOperation,
+ const QByteArray & body = QByteArray());
+
+protected:
+ void contextMenuEvent(QContextMenuEvent *event);
+
+ void mouseMoveEvent(QMouseEvent *event);
+ void mousePressEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *event);
+
+ void keyPressEvent(QKeyEvent *event);
+ void keyReleaseEvent(QKeyEvent *event);
+
+ void wheelEvent(QWheelEvent *event);
+
+ void dropEvent(QDropEvent *event);
+ void dragEnterEvent(QDragEnterEvent *event);
+ void dragMoveEvent(QDragMoveEvent * event);
+
+ void paintEvent(QPaintEvent *event);
+
+private Q_SLOTS:
+ void search();
+
+ void printFrame();
+
+ void openLinkInNewWindow();
+ void openLinkInNewTab();
+ void bookmarkLink();
+ void sendByMail();
+
+ void viewImage(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers);
+ void slotCopyImageLocation();
+ void inspect();
+
+ void scrollFrameChanged();
+ void scrollTick();
+
+ void setupSmoothScrolling(int posY);
+
+ void stopSmoothScrolling();
+ void changeWindowIcon();
+
+ void accessKeyShortcut();
+ void hideAccessKeys();
+
+ void loadStarted();
+
+ void blockImage();
+
+
+Q_SIGNALS:
+ void loadUrl(const KUrl &, const Rekonq::OpenType &);
+ void zoomChanged(int);
+ void openPreviousInHistory();
+ void openNextInHistory();
+
+private:
+ bool checkForAccessKey(QKeyEvent *event);
+ void showAccessKeys();
+ void makeAccessKeyLabel(const QChar &accessKey, const QWebElement &element);
+
+private:
+ WebPage *m_page;
+ QPoint m_clickPos;
+
+ // Auto Scroll
+ QTimer *const m_autoScrollTimer;
+ int m_verticalAutoScrollSpeed;
+ int m_horizontalAutoScrollSpeed;
+ bool m_isViewAutoScrolling;
+ QPixmap m_autoScrollIndicator;
+
+ // Smooth Scroll
+ QTimer *const m_smoothScrollTimer;
+ QTime m_smoothScrollTime;
+ bool m_smoothScrollBottomReached;
+ int m_dy;
+ int m_smoothScrollSteps;
+ bool m_isViewSmoothScrolling;
+
+ // Access Keys
+ QList<QLabel*> m_accessKeyLabels;
+ QHash<QChar, QWebElement> m_accessKeyNodes;
+ bool m_accessKeysPressed;
+ bool m_accessKeysActive;
+};
+
+#endif