summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt63
-rw-r--r--src/application.cpp206
-rw-r--r--src/application.h115
-rw-r--r--src/autosaver.cpp90
-rw-r--r--src/autosaver.h55
-rw-r--r--src/bookmarks.cpp278
-rw-r--r--src/bookmarks.h238
-rw-r--r--src/cookiejar.cpp841
-rw-r--r--src/cookiejar.h200
-rw-r--r--src/cookies.ui107
-rw-r--r--src/cookiesexceptions.ui179
-rw-r--r--src/download.cpp224
-rw-r--r--src/download.h141
-rw-r--r--src/edittableview.cpp61
-rw-r--r--src/edittableview.h42
-rw-r--r--src/edittreeview.cpp61
-rw-r--r--src/edittreeview.h41
-rw-r--r--src/findbar.cpp137
-rw-r--r--src/findbar.h61
-rw-r--r--src/history.cpp1459
-rw-r--r--src/history.h402
-rw-r--r--src/history.ui101
-rw-r--r--src/lineedit.cpp85
-rw-r--r--src/lineedit.h50
-rw-r--r--src/main.cpp98
-rw-r--r--src/mainview.cpp716
-rw-r--r--src/mainview.h198
-rw-r--r--src/mainwindow.cpp930
-rw-r--r--src/mainwindow.h153
-rw-r--r--src/modelmenu.cpp228
-rw-r--r--src/modelmenu.h92
-rw-r--r--src/networkaccessmanager.cpp165
-rw-r--r--src/networkaccessmanager.h47
-rw-r--r--src/panelhistory.cpp95
-rw-r--r--src/panelhistory.h55
-rw-r--r--src/password.ui69
-rw-r--r--src/proxy.ui62
-rw-r--r--src/rekonq.kcfg119
-rw-r--r--src/rekonq.kcfgc5
-rw-r--r--src/rekonqui.rc104
-rw-r--r--src/searchbar.cpp129
-rw-r--r--src/searchbar.h67
-rw-r--r--src/settings.cpp212
-rw-r--r--src/settings.h55
-rw-r--r--src/settings_fonts.ui97
-rw-r--r--src/settings_general.ui142
-rw-r--r--src/settings_privacy.ui168
-rw-r--r--src/settings_proxy.ui152
-rw-r--r--src/settings_webkit.ui134
-rw-r--r--src/sidepanel.cpp53
-rw-r--r--src/sidepanel.h50
-rw-r--r--src/stackedurlbar.cpp152
-rw-r--r--src/stackedurlbar.h64
-rw-r--r--src/tabbar.cpp145
-rw-r--r--src/tabbar.h78
-rw-r--r--src/urlbar.cpp240
-rw-r--r--src/urlbar.h99
-rw-r--r--src/webview.cpp504
-rw-r--r--src/webview.h155
59 files changed, 11069 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 00000000..a64cc747
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,63 @@
+SET( rekonq_SRCS
+ autosaver.cpp
+ application.cpp
+ mainwindow.cpp
+ mainview.cpp
+ tabbar.cpp
+ cookiejar.cpp
+ edittableview.cpp
+ edittreeview.cpp
+ history.cpp
+ download.cpp
+ bookmarks.cpp
+ modelmenu.cpp
+ networkaccessmanager.cpp
+ urlbar.cpp
+ findbar.cpp
+ searchbar.cpp
+ settings.cpp
+ webview.cpp
+ main.cpp
+ sidepanel.cpp
+ panelhistory.cpp
+ lineedit.cpp
+ stackedurlbar.cpp
+)
+
+KDE4_ADD_UI_FILES( rekonq_SRCS
+ cookies.ui
+ cookiesexceptions.ui
+ history.ui
+ password.ui
+ proxy.ui
+ settings_general.ui
+ settings_fonts.ui
+ settings_privacy.ui
+ settings_proxy.ui
+ settings_webkit.ui
+ )
+
+KDE4_ADD_KCFG_FILES( rekonq_SRCS rekonq.kcfgc )
+
+### ------------------------------------------
+
+ADD_DEFINITIONS( ${KDE4_DEFINITIONS} )
+
+KDE4_ADD_EXECUTABLE( rekonq ${rekonq_SRCS} )
+
+TARGET_LINK_LIBRARIES( rekonq
+ ${QT_LIBRARIES}
+ ${QT_QTNETWORK_LIBRARY}
+ ${QT_QTWEBKIT_LIBRARY}
+ ${QT_QTUITOOLS_LIBRARY}
+ ${KDE4_KUTILS_LIBS}
+ ${KDE4_KDEUI_LIBS}
+ ${KDE4_KIO_LIBS}
+)
+
+INSTALL( TARGETS rekonq ${INSTALL_TARGETS_DEFAULT_ARGS} )
+
+########### install files ###############
+
+INSTALL( FILES rekonq.kcfg DESTINATION ${KCFG_INSTALL_DIR} )
+INSTALL( FILES rekonqui.rc DESTINATION ${DATA_INSTALL_DIR}/rekonq )
diff --git a/src/application.cpp b/src/application.cpp
new file mode 100644
index 00000000..ec24691e
--- /dev/null
+++ b/src/application.cpp
@@ -0,0 +1,206 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2008 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009 by Paweł Prażak <pawelprazak 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+
+// Self Includes
+#include "application.h"
+#include "application.moc"
+
+// Auto Includes
+#include "rekonq.h"
+
+// Local Includes
+#include "mainwindow.h"
+#include "cookiejar.h"
+#include "history.h"
+#include "networkaccessmanager.h"
+#include "mainview.h"
+#include "webview.h"
+#include "download.h"
+
+// KDE Includes
+#include <KCmdLineArgs>
+#include <KAboutData>
+#include <KStandardDirs>
+#include <KConfig>
+#include <kio/job.h>
+#include <kio/jobclasses.h>
+
+// Qt Includes
+#include <QtCore>
+#include <QtWebKit>
+
+
+QPointer<HistoryManager> Application::s_historyManager;
+QPointer<NetworkAccessManager> Application::s_networkAccessManager;
+QPointer<DownloadManager> Application::s_downloadManager;
+QPointer<BookmarkProvider> Application::s_bookmarkProvider;
+
+
+
+Application::Application()
+ : KUniqueApplication()
+{
+}
+
+
+Application::~Application()
+{
+ delete m_mainWindow;
+ delete s_bookmarkProvider;
+ delete s_networkAccessManager;
+ delete s_historyManager;
+}
+
+
+int Application::newInstance()
+{
+ KCmdLineArgs::setCwd(QDir::currentPath().toUtf8());
+ KCmdLineArgs* args = KCmdLineArgs::parsedArgs();
+
+ if (!m_mainWindow)
+ {
+ m_mainWindow = new MainWindow();
+
+ m_mainWindow->setObjectName("MainWindow");
+ setWindowIcon(KIcon("rekonq"));
+
+ m_mainWindow->show();
+
+ QTimer::singleShot(0, this, SLOT(postLaunch()));
+ }
+
+ if (args->count() > 0)
+ {
+ for (int i = 0; i < args->count(); ++i)
+ {
+ KUrl url = MainWindow::guessUrlFromString(args->arg(i));
+ newWebView();
+ mainWindow()->loadUrl(url);
+ }
+ args->clear();
+ }
+ else
+ {
+ newWebView();
+ mainWindow()->slotHome();
+ }
+
+ return 0;
+}
+
+
+Application *Application::instance()
+{
+ return (static_cast<Application *>(QCoreApplication::instance()));
+}
+
+
+void Application::postLaunch()
+{
+ // set Icon Database Path to store "favicons" associated with web sites
+ QString directory = KStandardDirs::locateLocal("cache" , "" , true);
+ if (directory.isEmpty())
+ {
+ directory = QDir::homePath() + QLatin1String("/.") + QCoreApplication::applicationName();
+ }
+ QWebSettings::setIconDatabasePath(directory);
+
+ Application::historyManager();
+}
+
+
+
+void Application::slotSaveConfiguration() const
+{
+ ReKonfig::self()->writeConfig();
+}
+
+
+MainWindow *Application::mainWindow()
+{
+ return m_mainWindow;
+}
+
+
+WebView *Application::newWebView(Rekonq::OpenType type)
+{
+ return m_mainWindow->mainView()->newWebView(type);
+}
+
+
+CookieJar *Application::cookieJar()
+{
+ return (CookieJar*)networkAccessManager()->cookieJar();
+}
+
+
+NetworkAccessManager *Application::networkAccessManager()
+{
+ if (!s_networkAccessManager)
+ {
+ s_networkAccessManager = new NetworkAccessManager();
+ s_networkAccessManager->setCookieJar(new CookieJar);
+ }
+ return s_networkAccessManager;
+}
+
+
+HistoryManager *Application::historyManager()
+{
+ if (!s_historyManager)
+ {
+ s_historyManager = new HistoryManager();
+ QWebHistoryInterface::setDefaultInterface(s_historyManager);
+ }
+ return s_historyManager;
+}
+
+
+DownloadManager *Application::downloadManager()
+{
+ if (!s_downloadManager)
+ {
+ s_downloadManager = new DownloadManager();
+ }
+ return s_downloadManager;
+}
+
+
+BookmarkProvider *Application::bookmarkProvider()
+{
+ if (!s_bookmarkProvider)
+ {
+ s_bookmarkProvider = new BookmarkProvider();
+ }
+ return s_bookmarkProvider;
+}
+
+
+KIcon Application::icon(const KUrl &url) const
+{
+ KIcon icon = KIcon(QWebSettings::iconForUrl(url));
+ if (icon.isNull())
+ {
+ icon = KIcon("kde");
+ }
+ return icon;
+}
diff --git a/src/application.h b/src/application.h
new file mode 100644
index 00000000..61f4af81
--- /dev/null
+++ b/src/application.h
@@ -0,0 +1,115 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2008 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009 by Paweł Prażak <pawelprazak 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+
+#ifndef APPLICATION_H
+#define APPLICATION_H
+
+// Qt Includes
+#include <QPointer>
+
+// KDE Includes
+#include <KUniqueApplication>
+#include <KCmdLineArgs>
+#include <KIcon>
+#include <KUrl>
+#include <KJob>
+#include <kio/job.h>
+#include <kio/jobclasses.h>
+
+
+// Forward Declarations
+class KIcon;
+class KUrl;
+class BookmarkProvider;
+class CookieJar;
+class DownloadManager;
+class HistoryManager;
+class MainWindow;
+class NetworkAccessManager;
+class WebView;
+
+
+namespace Rekonq
+{
+ /**
+ * @short Open link options
+ * Different modes of opening new tab
+ */
+ enum OpenType
+ {
+ Default, ///< open url according to users settings
+ New, ///< open url in new tab and make it current
+ Background ///< open url in new tab in background
+ };
+}
+
+
+/**
+ *
+ */
+class Application : public KUniqueApplication
+{
+ Q_OBJECT
+
+public:
+ Application();
+ ~Application();
+ int newInstance();
+ static Application *instance();
+
+ MainWindow *mainWindow();
+ WebView* newWebView(Rekonq::OpenType type = Rekonq::Default);
+
+ KIcon icon(const KUrl &url) const;
+
+ static HistoryManager *historyManager();
+ static CookieJar *cookieJar();
+ static NetworkAccessManager *networkAccessManager();
+ static DownloadManager *downloadManager();
+ static BookmarkProvider *bookmarkProvider();
+
+public slots:
+ /**
+ * Save application's configuration
+ * @see ReKonfig::self()->writeConfig();
+ */
+ void slotSaveConfiguration() const;
+
+
+private slots:
+
+ /**
+ * Any actions that can be delayed until the window is visible
+ */
+ void postLaunch();
+
+
+private:
+ static QPointer<HistoryManager> s_historyManager;
+ static QPointer<NetworkAccessManager> s_networkAccessManager;
+ static QPointer<DownloadManager> s_downloadManager;
+ static QPointer<BookmarkProvider> s_bookmarkProvider;
+
+ QPointer<MainWindow> m_mainWindow;
+};
+
+#endif // APPLICATION_H
diff --git a/src/autosaver.cpp b/src/autosaver.cpp
new file mode 100644
index 00000000..25bf9016
--- /dev/null
+++ b/src/autosaver.cpp
@@ -0,0 +1,90 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007-2008 Trolltech ASA. All rights reserved
+* Copyright (C) 2008-2009 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+
+// Local Includes
+#include "autosaver.h"
+
+// KDE Includes
+#include <KDebug>
+
+// Qt Includes
+#include <QtCore>
+
+
+#define AUTOSAVE_IN 1000 * 3 // seconds
+#define MAXWAIT 1000 * 15 // seconds
+
+
+AutoSaver::AutoSaver(QObject *parent) : QObject(parent)
+{
+ Q_ASSERT(parent);
+}
+
+
+AutoSaver::~AutoSaver()
+{
+ if (m_timer.isActive())
+ kWarning() << "AutoSaver: still active when destroyed, changes not saved.";
+}
+
+
+void AutoSaver::changeOccurred()
+{
+ if (m_firstChange.isNull())
+ m_firstChange.start();
+
+ if (m_firstChange.elapsed() > MAXWAIT)
+ {
+ saveIfNeccessary();
+ }
+ else
+ {
+ m_timer.start(AUTOSAVE_IN, this);
+ }
+}
+
+
+void AutoSaver::timerEvent(QTimerEvent *event)
+{
+ if (event->timerId() == m_timer.timerId())
+ {
+ saveIfNeccessary();
+ }
+ else
+ {
+ QObject::timerEvent(event);
+ }
+}
+
+
+void AutoSaver::saveIfNeccessary()
+{
+ if (!m_timer.isActive())
+ return;
+ m_timer.stop();
+ m_firstChange = QTime();
+ if (!QMetaObject::invokeMethod(parent(), "save", Qt::DirectConnection))
+ {
+ kWarning() << "AutoSaver: error invoking slot save() on parent";
+ }
+}
+
diff --git a/src/autosaver.h b/src/autosaver.h
new file mode 100644
index 00000000..8931da13
--- /dev/null
+++ b/src/autosaver.h
@@ -0,0 +1,55 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007-2008 Trolltech ASA. All rights reserved
+* Copyright (C) 2008-2009 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+
+#ifndef AUTOSAVER_H
+#define AUTOSAVER_H
+
+#include <QtCore>
+
+/*
+ This class will call the save() slot on the parent object when the parent changes.
+ It will wait several seconds after changed() to combining multiple changes and
+ prevent continuous writing to disk.
+ */
+class AutoSaver : public QObject
+{
+ Q_OBJECT
+
+public:
+ AutoSaver(QObject *parent);
+ ~AutoSaver();
+ void saveIfNeccessary();
+
+public slots:
+ void changeOccurred();
+
+protected:
+ void timerEvent(QTimerEvent *event);
+
+private:
+ QBasicTimer m_timer;
+ QTime m_firstChange;
+
+};
+
+#endif // AUTOSAVER_H
+
diff --git a/src/bookmarks.cpp b/src/bookmarks.cpp
new file mode 100644
index 00000000..c7f4da98
--- /dev/null
+++ b/src/bookmarks.cpp
@@ -0,0 +1,278 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2008-2009 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009 by Paweł Prażak <pawelprazak 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+
+// Self Includes
+#include "bookmarks.h"
+#include "bookmarks.moc"
+
+// Local Includes
+#include "mainwindow.h"
+#include "webview.h"
+#include "application.h"
+
+// KDE Includes
+#include <KActionCollection>
+#include <KBookmark>
+#include <KBookmarkAction>
+#include <KBookmarkActionMenu>
+#include <KBookmarkGroup>
+#include <KBookmarkMenu>
+#include <KToolBar>
+#include <KDebug>
+#include <KMenu>
+#include <KMimeType>
+#include <KStandardDirs>
+#include <KUrl>
+
+// Qt Includes
+#include <QActionGroup>
+#include <QFile>
+
+
+BookmarkOwner::BookmarkOwner(QObject *parent)
+ : QObject(parent)
+ , KBookmarkOwner()
+{
+}
+
+
+void BookmarkOwner::openBookmark(const KBookmark & bookmark,
+ Qt::MouseButtons mouseButtons,
+ Qt::KeyboardModifiers keyboardModifiers)
+{
+ Q_UNUSED(mouseButtons)
+ Q_UNUSED(keyboardModifiers)
+
+ emit openUrl(bookmark.url());
+}
+
+
+QString BookmarkOwner::currentUrl() const
+{
+ return Application::instance()->mainWindow()->currentTab()->url().url();
+}
+
+
+QString BookmarkOwner::currentTitle() const
+{
+ return Application::instance()->mainWindow()->currentTab()->title();
+}
+
+
+void BookmarkOwner::openFolderinTabs(const KBookmarkGroup &bm)
+{
+ QList<KUrl> urlList = bm.groupUrlList();
+ QList<KUrl>::iterator url;
+ Application* app = Application::instance();
+ for (url = urlList.begin(); url != urlList.end(); ++url)
+ {
+ app->newWebView();
+ app->mainWindow()->loadUrl(*url);
+ }
+}
+
+
+// ------------------------------------------------------------------------------------------------------
+
+
+BookmarkMenu::BookmarkMenu(KBookmarkManager *manager,
+ KBookmarkOwner *owner,
+ KMenu *menu,
+ KActionCollection* actionCollection)
+ : KBookmarkMenu(manager, owner, menu, actionCollection)
+
+{
+ actionCollection->addAction(KStandardAction::AddBookmark,
+ QLatin1String("add_bookmark_payload"),
+ this, SLOT(slotAddBookmark()));
+
+}
+
+BookmarkMenu::~BookmarkMenu()
+{
+}
+
+
+KMenu *BookmarkMenu::viewContextMenu(QAction *action)
+{
+ return contextMenu(action);
+}
+
+
+void BookmarkMenu::slotAddBookmark()
+{
+ KAction *action = qobject_cast<KAction *>(sender());
+ if (action && !action->data().isNull())
+ {
+ KBookmarkGroup parentBookmark = manager()->findByAddress(parentAddress()).toGroup();
+ /// TODO Add bookmark Icon
+ parentBookmark.addBookmark(owner()->currentTitle(), action->data().toUrl());
+ manager()->emitChanged();
+ return;
+ }
+
+ KBookmarkMenu::slotAddBookmark();
+}
+
+
+// ------------------------------------------------------------------------------------------------------
+
+
+BookmarkProvider::BookmarkProvider(QWidget *parent)
+ : QWidget(parent)
+ , m_manager(0)
+ , m_owner(0)
+ , m_menu(new KMenu(this))
+ , m_actionCollection(new KActionCollection(this))
+ , m_bookmarkMenu(0)
+ , m_bookmarkToolBar(0)
+{
+ KUrl bookfile = KUrl("~/.kde/share/apps/konqueror/bookmarks.xml"); // share konqueror bookmarks
+
+ if (!QFile::exists(bookfile.path()))
+ {
+ bookfile = KUrl("~/.kde4/share/apps/konqueror/bookmarks.xml");
+ if (!QFile::exists(bookfile.path()))
+ {
+ QString bookmarksDefaultPath = KStandardDirs::locate("appdata" , "defaultbookmarks.xbel");
+ kWarning() << bookmarksDefaultPath;
+ QFile bkms(bookmarksDefaultPath);
+ QString bookmarksPath = KStandardDirs::locateLocal("appdata", "bookmarks.xml", true);
+ bookmarksPath.replace("rekonq", "konqueror");
+ bkms.copy(bookmarksPath);
+
+ bookfile = KUrl(bookmarksPath);
+ }
+ }
+ m_manager = KBookmarkManager::managerForExternalFile(bookfile.path());
+ connect(m_manager, SIGNAL(changed(const QString &, const QString &)),
+ this, SLOT(slotBookmarksChanged(const QString &, const QString &)));
+
+ // setup menu
+ m_owner = new BookmarkOwner(this);
+ connect(m_owner, SIGNAL(openUrl(const KUrl&)), this, SIGNAL(openUrl(const KUrl&)));
+ m_bookmarkMenu = new BookmarkMenu(m_manager, m_owner, m_menu, m_actionCollection);
+
+ // setup toolbar
+ setupToolBar();
+}
+
+
+BookmarkProvider::~BookmarkProvider()
+{
+ delete m_bookmarkToolBar;
+ delete m_bookmarkMenu;
+ delete m_actionCollection;
+ delete m_menu;
+ delete m_owner;
+ delete m_manager;
+}
+
+
+void BookmarkProvider::setupToolBar()
+{
+ m_bookmarkToolBar = new KToolBar(this);
+ m_bookmarkToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ m_bookmarkToolBar->setIconDimensions(16);
+ m_bookmarkToolBar->setAcceptDrops(true);
+ m_bookmarkToolBar->setContentsMargins(0, 0, 0, 0);
+ m_bookmarkToolBar->setMinimumHeight(16);
+ m_bookmarkToolBar->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(m_bookmarkToolBar, SIGNAL(customContextMenuRequested(const QPoint &)),
+ this, SLOT(contextMenu(const QPoint &)));
+
+ slotBookmarksChanged("", "");
+}
+
+
+void BookmarkProvider::slotBookmarksChanged(const QString &group, const QString &caller)
+{
+ Q_UNUSED(group)
+ Q_UNUSED(caller)
+
+ if (!m_bookmarkToolBar)
+ {
+ kWarning() << "There is no bookmark toolbar";
+ return;
+ }
+
+ KActionCollection bookmarkCollection(this);
+
+ KBookmarkGroup toolBarGroup = m_manager->toolbar();
+ if (toolBarGroup.isNull())
+ return;
+
+ KBookmark bookmark = toolBarGroup.first();
+ while (!bookmark.isNull())
+ {
+ if (!bookmark.isGroup())
+ {
+ KAction *action = new KBookmarkAction(bookmark, m_owner, this);
+ QString text = bookmark.address();
+ bookmarkCollection.addAction(text, action);
+ }
+ bookmark = toolBarGroup.next(bookmark);
+ }
+ m_bookmarkToolBar->clear();
+ m_bookmarkToolBar->addActions(bookmarkCollection.actions());
+}
+
+
+QAction *BookmarkProvider::actionByName(const QString &name)
+{
+ QAction *action = m_actionCollection->action(name);
+ if (action)
+ return action;
+ /* else */
+ kWarning() << "Action named: " << name << " not found, returning empty action.";
+ return new QAction(this); // return empty object instead of NULL pointer
+}
+
+
+void BookmarkProvider::contextMenu(const QPoint &point)
+{
+ KAction* action = dynamic_cast<KAction*>(m_bookmarkToolBar->actionAt(point));
+ if (!action)
+ return;
+ KMenu *menu = m_bookmarkMenu->viewContextMenu(action);
+ menu->popup(m_bookmarkToolBar->mapToGlobal(point));
+}
+
+
+KActionMenu* BookmarkProvider::bookmarkActionMenu()
+{
+ KActionMenu *bookmarkActionMenu = new KActionMenu(this);
+ bookmarkActionMenu->setMenu(m_menu);
+ bookmarkActionMenu->setText(i18n("&Bookmarks"));
+ return bookmarkActionMenu;
+}
+
+
+KAction* BookmarkProvider::bookmarkToolBarAction()
+{
+ KAction *bookmarkToolBarAction = new KAction(this);
+ bookmarkToolBarAction->setDefaultWidget(m_bookmarkToolBar); // The ownership is transferred to action
+ bookmarkToolBarAction->setText(i18n("Bookmarks Bar"));
+ bookmarkToolBarAction->setShortcutConfigurable(false);
+ return bookmarkToolBarAction;
+}
+
diff --git a/src/bookmarks.h b/src/bookmarks.h
new file mode 100644
index 00000000..d7213cb7
--- /dev/null
+++ b/src/bookmarks.h
@@ -0,0 +1,238 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2008-2009 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009 by Paweł Prażak <pawelprazak 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+
+#ifndef BOOKMARKS_H
+#define BOOKMARKS_H
+
+// Qt Includes
+#include <QWidget>
+
+// KDE Includes
+#include <KBookmarkOwner>
+
+// Forward Declarations
+class BookmarkProvider;
+
+class KAction;
+class KActionCollection;
+class KActionMenu;
+class KUrl;
+class KToolBar;
+class KBookmarkManager;
+
+
+/**
+ * Reimplementation of KBookmarkOwner, this class allows to manage
+ * bookmarks as actions
+ *
+ */
+class BookmarkOwner : public QObject , public KBookmarkOwner
+{
+ Q_OBJECT
+
+public:
+
+ /**
+ * @short The class constructor.
+ *
+ * @param parent the pointer parent Bookmark provider. We need it
+ * to get pointer to MainWindow
+ */
+ BookmarkOwner(QObject *parent = 0);
+ virtual ~BookmarkOwner() {}
+
+ /**
+ * This function is called when a bookmark is selected and belongs to
+ * the ancestor class.
+ * This method actually emits signal to load bookmark's url.
+ *
+ * @param bookmark the bookmark to open
+ * @param mouseButtons the mouse buttons clicked to select the bookmark
+ * @param keyboardModifiers the keyboard modifiers pushed when the bookmark was selected
+ */
+ virtual void openBookmark(const KBookmark &bookmark,
+ Qt::MouseButtons mouseButtons,
+ Qt::KeyboardModifiers keyboardModifiers);
+
+
+ /**
+ * this method, from KBookmarkOwner interface, allows to add the current page
+ * to the bookmark list, returning the URL page as QString.
+ *
+ * @return the current page's URL
+ */
+ virtual QString currentUrl() const;
+
+ /**
+ * this method, from KBookmarkOwner interface, allows to add the current page
+ * to the bookmark list, returning the title's page as QString.
+ *
+ * @return the current page's title
+ */
+ virtual QString currentTitle() const;
+
+ /**
+ * This function returns whether the owner supports tabs.
+ */
+ virtual bool supportsTabs() const
+ {
+ return true;
+ }
+
+ /**
+ * Called if the user wants to open every bookmark in this folder in a new tab.
+ * The default implementation does nothing.
+ * This is only called if supportsTabs() returns true
+ */
+ virtual void openFolderinTabs(const KBookmarkGroup &bm);
+
+signals:
+ /**
+ * This signal is emitted when an url has to be loaded
+ *
+ * @param url the URL to load
+ *
+ */
+ void openUrl(const KUrl &);
+
+private:
+
+};
+
+// ------------------------------------------------------------------------------
+
+
+#include <KBookmarkMenu>
+
+
+/**
+ * This class represent the rekonq bookmarks menu.
+ * It's just a simple class inherited from KBookmarkMenu
+ *
+ */
+class BookmarkMenu : public KBookmarkMenu
+{
+ Q_OBJECT
+
+public:
+ BookmarkMenu(KBookmarkManager* manager,
+ KBookmarkOwner* owner,
+ KMenu* menu,
+ KActionCollection* actionCollection);
+ ~BookmarkMenu();
+
+ virtual KMenu *viewContextMenu(QAction* action);
+
+protected slots:
+ void slotAddBookmark();
+
+};
+
+
+// ------------------------------------------------------------------------------
+
+
+/**
+ * This class represent the interface to rekonq bookmarks system.
+ * All rekonq needs (Bookmarks Menu, Bookmarks Toolbar) is provided
+ * from this class.
+ * So it implements code to have each one
+ *
+ *
+ */
+class BookmarkProvider : public QWidget
+{
+ Q_OBJECT
+
+public:
+ /**
+ * @short Class constructor.
+ * Connect BookmarksProvider with bookmarks source
+ * (actually konqueror's bookmarks)
+ * @param parent The MainWindow to provide bookmarks objects
+ *
+ */
+ BookmarkProvider(QWidget* parent = 0);
+ ~BookmarkProvider();
+
+ /**
+ * @short Get the Bookmarks Menu Action
+ * @return the Bookmarks Menu
+ */
+ KActionMenu *bookmarkActionMenu();
+
+
+ /**
+ * @short Get the Bookmarks Toolbar Action
+ * @return the Bookmarks Toolbar Action
+ */
+ KAction *bookmarkToolBarAction();
+
+
+ /**
+ * @short Get action by name
+ * This method returns poiner bookmark action of given name.
+ * @pre m_actionCollection != NULL
+ * @param name Name of action you want to get
+ * @return It returns actions if one exists or empty object
+ */
+ QAction *actionByName(const QString &name);
+
+signals:
+ /**
+ * @short This signal is emitted when an url has to be loaded
+ *
+ * @param url the URL to load
+ */
+ void openUrl(const KUrl &url);
+
+
+public slots:
+ /**
+ * @short Opens the context menu on given position
+ * @param point Point on whitch you want to open this menu
+ */
+ void contextMenu(const QPoint &point);
+
+ /**
+ * @short Waits for signal that the group with the address has been modified by the caller.
+ * Waits for signal that the group (or any of its children) with the address
+ * @p groupAddress (e.g. "/4/5") has been modified by the caller @p caller.
+ *
+ * @param group bookmark group adress
+ * @param caller caller that modified the bookmarks
+ * @see KBookmarkManager::changed
+ */
+ void slotBookmarksChanged(const QString &group, const QString &caller);
+
+private:
+ void setupToolBar();
+
+ KBookmarkManager *m_manager;
+ BookmarkOwner *m_owner;
+ KMenu *m_menu;
+ KActionCollection *m_actionCollection;
+ BookmarkMenu *m_bookmarkMenu;
+ KToolBar *m_bookmarkToolBar;
+};
+
+#endif
diff --git a/src/cookiejar.cpp b/src/cookiejar.cpp
new file mode 100644
index 00000000..de7d7d7e
--- /dev/null
+++ b/src/cookiejar.cpp
@@ -0,0 +1,841 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007-2008 Trolltech ASA. All rights reserved
+* Copyright (C) 2008-2009 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009 by Domrachev Alexandr <alexandr.domrachev@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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+
+// Self Includes
+#include "cookiejar.h"
+#include "cookiejar.moc"
+
+// Auto Includes
+#include "rekonq.h"
+
+// Local Includes
+#include "autosaver.h"
+
+// KDE Includes
+#include <KConfig>
+#include <KStandardDirs>
+#include <KDebug>
+
+// Qt Includes
+#include <QtCore>
+#include <QtGui>
+#include <QtWebKit>
+
+
+static const unsigned int JAR_VERSION = 23;
+
+
+QDataStream &operator<<(QDataStream &stream, const QList<QNetworkCookie> &list)
+{
+ stream << JAR_VERSION;
+ stream << quint32(list.size());
+ for (int i = 0; i < list.size(); ++i)
+ stream << list.at(i).toRawForm();
+ return stream;
+}
+
+
+QDataStream &operator>>(QDataStream &stream, QList<QNetworkCookie> &list)
+{
+ list.clear();
+
+ quint32 version;
+ stream >> version;
+
+ if (version != JAR_VERSION)
+ return stream;
+
+ quint32 count;
+ stream >> count;
+ for (quint32 i = 0; i < count; ++i)
+ {
+ QByteArray value;
+ stream >> value;
+ QList<QNetworkCookie> newCookies = QNetworkCookie::parseCookies(value);
+ if (newCookies.count() == 0 && value.length() != 0)
+ {
+ kWarning() << "CookieJar: Unable to parse saved cookie:" << value;
+ }
+ for (int j = 0; j < newCookies.count(); ++j)
+ list.append(newCookies.at(j));
+ if (stream.atEnd())
+ break;
+ }
+ return stream;
+}
+
+
+CookieJar::CookieJar(QObject *parent)
+ : QNetworkCookieJar(parent)
+ , m_loaded(false)
+ , m_saveTimer(new AutoSaver(this))
+ , m_acceptCookies(AcceptOnlyFromSitesNavigatedTo)
+{
+ load();
+}
+
+
+CookieJar::~CookieJar()
+{
+ if (m_keepCookies == KeepUntilExit)
+ clear();
+ m_saveTimer->saveIfNeccessary();
+}
+
+
+void CookieJar::clear()
+{
+ setAllCookies(QList<QNetworkCookie>());
+ m_saveTimer->changeOccurred();
+ emit cookiesChanged();
+}
+
+
+void CookieJar::load()
+{
+ if (m_loaded)
+ return;
+
+ // load cookies and exceptions
+ QString filepath = KStandardDirs::locateLocal("appdata", "cookies.ini");
+ qRegisterMetaTypeStreamOperators<QList<QNetworkCookie> >("QList<QNetworkCookie>");
+ QSettings cookieSettings(filepath, QSettings::IniFormat);
+ setAllCookies(qvariant_cast<QList<QNetworkCookie> >(cookieSettings.value(QLatin1String("cookies"))));
+ cookieSettings.beginGroup(QLatin1String("Exceptions"));
+ m_exceptions_block = cookieSettings.value(QLatin1String("block")).toStringList();
+ m_exceptions_allow = cookieSettings.value(QLatin1String("allow")).toStringList();
+ m_exceptions_allowForSession = cookieSettings.value(QLatin1String("allowForSession")).toStringList();
+ qSort(m_exceptions_block.begin(), m_exceptions_block.end());
+ qSort(m_exceptions_allow.begin(), m_exceptions_allow.end());
+ qSort(m_exceptions_allowForSession.begin(), m_exceptions_allowForSession.end());
+
+ loadSettings();
+
+ save();
+}
+
+
+void CookieJar::loadSettings()
+{
+ int canAcceptCookies = ReKonfig::acceptCookies();
+
+ switch (canAcceptCookies)
+ {
+ case 0:
+ m_acceptCookies = AcceptAlways;
+ break;
+ case 1:
+ m_acceptCookies = AcceptNever;
+ break;
+ case 2:
+ default:
+ m_acceptCookies = AcceptOnlyFromSitesNavigatedTo;
+ break;
+ }
+
+ int canKeepCookiesUntil = ReKonfig::keepCookiesUntil();
+
+ switch (canKeepCookiesUntil)
+ {
+ default:
+ case 0:
+ m_keepCookies = KeepUntilExpire;
+ break;
+ case 1:
+ m_keepCookies = KeepUntilExit;
+ setAllCookies(QList<QNetworkCookie>());
+ break;
+ case 2:
+ m_keepCookies = KeepUntilTimeLimit;
+ break;
+ }
+
+ m_loaded = true;
+ emit cookiesChanged();
+}
+
+
+void CookieJar::save()
+{
+ if (!m_loaded)
+ return;
+ purgeOldCookies();
+
+ QString filepath = KStandardDirs::locateLocal("appdata", "cookies.ini");
+ QSettings cookieSettings(filepath, QSettings::IniFormat);
+ QList<QNetworkCookie> cookies = allCookies();
+ for (int i = cookies.count() - 1; i >= 0; --i)
+ {
+ if (cookies.at(i).isSessionCookie())
+ cookies.removeAt(i);
+ }
+
+ cookieSettings.setValue(QLatin1String("cookies"), qVariantFromValue<QList<QNetworkCookie> >(cookies));
+ cookieSettings.beginGroup(QLatin1String("Exceptions"));
+ cookieSettings.setValue(QLatin1String("block"), m_exceptions_block);
+ cookieSettings.setValue(QLatin1String("allow"), m_exceptions_allow);
+ cookieSettings.setValue(QLatin1String("allowForSession"), m_exceptions_allowForSession);
+
+ // save cookie settings
+ int n;
+ switch (m_acceptCookies)
+ {
+ case AcceptAlways:
+ n = 0;
+ break;
+ case AcceptNever:
+ n = 1;
+ break;
+ case AcceptOnlyFromSitesNavigatedTo:
+ default:
+ n = 2;
+ break;
+ }
+ ReKonfig::setAcceptCookies(n);
+
+
+ switch (m_keepCookies)
+ {
+ default:
+ case KeepUntilExpire:
+ n = 0;
+ break;
+ case KeepUntilExit:
+ n = 1;
+ break;
+ case KeepUntilTimeLimit:
+ n = 2;
+ break;
+ }
+ ReKonfig::setKeepCookiesUntil(n);
+}
+
+
+void CookieJar::purgeOldCookies()
+{
+ QList<QNetworkCookie> cookies = allCookies();
+ if (cookies.isEmpty())
+ return;
+ int oldCount = cookies.count();
+ QDateTime now = QDateTime::currentDateTime();
+ for (int i = cookies.count() - 1; i >= 0; --i)
+ {
+ if (!cookies.at(i).isSessionCookie() && cookies.at(i).expirationDate() < now)
+ cookies.removeAt(i);
+ }
+ if (oldCount == cookies.count())
+ return;
+ setAllCookies(cookies);
+ emit cookiesChanged();
+}
+
+
+QList<QNetworkCookie> CookieJar::cookiesForUrl(const QUrl &url) const
+{
+ CookieJar *that = const_cast<CookieJar*>(this);
+ if (!m_loaded)
+ that->load();
+
+ QWebSettings *globalSettings = QWebSettings::globalSettings();
+ if (globalSettings->testAttribute(QWebSettings::PrivateBrowsingEnabled))
+ {
+ QList<QNetworkCookie> noCookies;
+ return noCookies;
+ }
+
+ return QNetworkCookieJar::cookiesForUrl(url);
+}
+
+
+bool CookieJar::setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url)
+{
+ if (!m_loaded)
+ load();
+
+ QWebSettings *globalSettings = QWebSettings::globalSettings();
+ if (globalSettings->testAttribute(QWebSettings::PrivateBrowsingEnabled))
+ return false;
+
+ QString host = url.host();
+ bool eBlock = qBinaryFind(m_exceptions_block.begin(), m_exceptions_block.end(), host) != m_exceptions_block.end();
+ bool eAllow = qBinaryFind(m_exceptions_allow.begin(), m_exceptions_allow.end(), host) != m_exceptions_allow.end();
+ bool eAllowSession = qBinaryFind(m_exceptions_allowForSession.begin(), m_exceptions_allowForSession.end(), host) != m_exceptions_allowForSession.end();
+
+ bool addedCookies = false;
+ // pass exceptions
+ bool acceptInitially = (m_acceptCookies != AcceptNever);
+ if ((acceptInitially && !eBlock) || (!acceptInitially && (eAllow || eAllowSession)))
+ {
+ // pass url domain == cookie domain
+ QDateTime soon = QDateTime::currentDateTime();
+ soon = soon.addDays(90);
+ foreach(QNetworkCookie cookie, cookieList)
+ {
+ QList<QNetworkCookie> lst;
+ if (m_keepCookies == KeepUntilTimeLimit
+ && !cookie.isSessionCookie()
+ && cookie.expirationDate() > soon)
+ {
+ cookie.setExpirationDate(soon);
+ }
+ lst += cookie;
+ if (QNetworkCookieJar::setCookiesFromUrl(lst, url))
+ {
+ addedCookies = true;
+ }
+ else
+ {
+ // finally force it in if wanted
+ if (m_acceptCookies == AcceptAlways)
+ {
+ QList<QNetworkCookie> cookies = allCookies();
+ cookies += cookie;
+ setAllCookies(cookies);
+ addedCookies = true;
+ }
+#if 0
+ else
+ kWarning() << "setCookiesFromUrl failed" << url << cookieList.value(0).toRawForm();
+#endif
+ }
+ }
+ }
+
+ if (addedCookies)
+ {
+ m_saveTimer->changeOccurred();
+ emit cookiesChanged();
+ }
+ return addedCookies;
+}
+
+
+CookieJar::AcceptPolicy CookieJar::acceptPolicy() const
+{
+ if (!m_loaded)
+ (const_cast<CookieJar*>(this))->load();
+ return m_acceptCookies;
+}
+
+
+void CookieJar::setAcceptPolicy(AcceptPolicy policy)
+{
+ if (!m_loaded)
+ load();
+ if (policy == m_acceptCookies)
+ return;
+ m_acceptCookies = policy;
+ m_saveTimer->changeOccurred();
+}
+
+
+CookieJar::KeepPolicy CookieJar::keepPolicy() const
+{
+ if (!m_loaded)
+ (const_cast<CookieJar*>(this))->load();
+ return m_keepCookies;
+}
+
+
+void CookieJar::setKeepPolicy(KeepPolicy policy)
+{
+ if (!m_loaded)
+ load();
+ if (policy == m_keepCookies)
+ return;
+ m_keepCookies = policy;
+ m_saveTimer->changeOccurred();
+}
+
+
+QStringList CookieJar::blockedCookies() const
+{
+ if (!m_loaded)
+ (const_cast<CookieJar*>(this))->load();
+ return m_exceptions_block;
+}
+
+
+QStringList CookieJar::allowedCookies() const
+{
+ if (!m_loaded)
+ (const_cast<CookieJar*>(this))->load();
+ return m_exceptions_allow;
+}
+
+
+QStringList CookieJar::allowForSessionCookies() const
+{
+ if (!m_loaded)
+ (const_cast<CookieJar*>(this))->load();
+ return m_exceptions_allowForSession;
+}
+
+
+void CookieJar::setBlockedCookies(const QStringList &list)
+{
+ if (!m_loaded)
+ load();
+ m_exceptions_block = list;
+ qSort(m_exceptions_block.begin(), m_exceptions_block.end());
+ m_saveTimer->changeOccurred();
+}
+
+
+void CookieJar::setAllowedCookies(const QStringList &list)
+{
+ if (!m_loaded)
+ load();
+ m_exceptions_allow = list;
+ qSort(m_exceptions_allow.begin(), m_exceptions_allow.end());
+ m_saveTimer->changeOccurred();
+}
+
+
+void CookieJar::setAllowForSessionCookies(const QStringList &list)
+{
+ if (!m_loaded)
+ load();
+ m_exceptions_allowForSession = list;
+ qSort(m_exceptions_allowForSession.begin(), m_exceptions_allowForSession.end());
+ m_saveTimer->changeOccurred();
+}
+
+
+// -------------------------------------------------------------------------------------------
+
+
+CookieModel::CookieModel(CookieJar *cookieJar, QObject *parent)
+ : QAbstractTableModel(parent)
+ , m_cookieJar(cookieJar)
+{
+ connect(m_cookieJar, SIGNAL(cookiesChanged()), this, SLOT(cookiesChanged()));
+ m_cookieJar->load();
+}
+
+
+QVariant CookieModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (role == Qt::SizeHintRole)
+ {
+ QFont font;
+ font.setPointSize(10);
+ QFontMetrics fm(font);
+ int height = fm.height() + fm.height() / 3;
+ int width = fm.width(headerData(section, orientation, Qt::DisplayRole).toString());
+ return QSize(width, height);
+ }
+
+ if (orientation == Qt::Horizontal)
+ {
+ if (role != Qt::DisplayRole)
+ return QVariant();
+
+ switch (section)
+ {
+ case 0:
+ return i18n("Website");
+ case 1:
+ return i18n("Name");
+ case 2:
+ return i18n("Path");
+ case 3:
+ return i18n("Secure");
+ case 4:
+ return i18n("Expires");
+ case 5:
+ return i18n("Contents");
+ default:
+ return QVariant();
+ }
+ }
+ return QAbstractTableModel::headerData(section, orientation, role);
+}
+
+
+QVariant CookieModel::data(const QModelIndex &index, int role) const
+{
+ QList<QNetworkCookie> lst;
+ if (m_cookieJar)
+ lst = m_cookieJar->allCookies();
+ if (index.row() < 0 || index.row() >= lst.size())
+ return QVariant();
+
+ switch (role)
+ {
+ case Qt::DisplayRole:
+ case Qt::EditRole:
+ {
+ QNetworkCookie cookie = lst.at(index.row());
+ switch (index.column())
+ {
+ case 0:
+ return cookie.domain();
+ case 1:
+ return cookie.name();
+ case 2:
+ return cookie.path();
+ case 3:
+ return cookie.isSecure();
+ case 4:
+ return cookie.expirationDate();
+ case 5:
+ return cookie.value();
+ }
+ }
+ case Qt::FontRole:
+ {
+ QFont font;
+ font.setPointSize(10);
+ return font;
+ }
+ }
+
+ return QVariant();
+}
+
+
+int CookieModel::columnCount(const QModelIndex &parent) const
+{
+ return (parent.isValid()) ? 0 : 6;
+}
+
+
+int CookieModel::rowCount(const QModelIndex &parent) const
+{
+ return (parent.isValid() || !m_cookieJar) ? 0 : m_cookieJar->allCookies().count();
+}
+
+
+bool CookieModel::removeRows(int row, int count, const QModelIndex &parent)
+{
+ if (parent.isValid() || !m_cookieJar)
+ return false;
+ int lastRow = row + count - 1;
+ beginRemoveRows(parent, row, lastRow);
+ QList<QNetworkCookie> lst = m_cookieJar->allCookies();
+ for (int i = lastRow; i >= row; --i)
+ {
+ lst.removeAt(i);
+ }
+ m_cookieJar->setAllCookies(lst);
+ endRemoveRows();
+ return true;
+}
+
+
+void CookieModel::cookiesChanged()
+{
+ reset();
+}
+
+
+
+// ------------------------------------------------------------------------------------------------
+
+
+CookiesDialog::CookiesDialog(CookieJar *cookieJar, QWidget *parent)
+ : QDialog(parent)
+{
+ setupUi(this);
+ setWindowFlags(Qt::Sheet);
+ CookieModel *model = new CookieModel(cookieJar, this);
+ m_proxyModel = new QSortFilterProxyModel(this);
+ connect(search, SIGNAL(textChanged(QString)),
+ m_proxyModel, SLOT(setFilterFixedString(QString)));
+ connect(removeButton, SIGNAL(clicked()), cookiesTable, SLOT(removeOne()));
+ connect(removeAllButton, SIGNAL(clicked()), cookiesTable, SLOT(removeAll()));
+ m_proxyModel->setSourceModel(model);
+ cookiesTable->verticalHeader()->hide();
+ cookiesTable->setSelectionBehavior(QAbstractItemView::SelectRows);
+ cookiesTable->setModel(m_proxyModel);
+ cookiesTable->setAlternatingRowColors(true);
+ cookiesTable->setTextElideMode(Qt::ElideMiddle);
+ cookiesTable->setShowGrid(false);
+ cookiesTable->setSortingEnabled(true);
+ QFont f = font();
+ f.setPointSize(10);
+ QFontMetrics fm(f);
+ int height = fm.height() + fm.height() / 3;
+ cookiesTable->verticalHeader()->setDefaultSectionSize(height);
+ cookiesTable->verticalHeader()->setMinimumSectionSize(-1);
+ for (int i = 0; i < model->columnCount(); ++i)
+ {
+ int header = cookiesTable->horizontalHeader()->sectionSizeHint(i);
+ switch (i)
+ {
+ case 0:
+ header = fm.width(QLatin1String("averagehost.domain.com"));
+ break;
+ case 1:
+ header = fm.width(QLatin1String("_session_id"));
+ break;
+ case 4:
+ header = fm.width(QDateTime::currentDateTime().toString(Qt::LocalDate));
+ break;
+ }
+ int buffer = fm.width(QLatin1String("xx"));
+ header += buffer;
+ cookiesTable->horizontalHeader()->resizeSection(i, header);
+ }
+ cookiesTable->horizontalHeader()->setStretchLastSection(true);
+}
+
+
+// ---------------------------------------------------------------------------------------------------
+
+
+CookieExceptionsModel::CookieExceptionsModel(CookieJar *cookiejar, QObject *parent)
+ : QAbstractTableModel(parent)
+ , m_cookieJar(cookiejar)
+{
+ m_allowedCookies = m_cookieJar->allowedCookies();
+ m_blockedCookies = m_cookieJar->blockedCookies();
+ m_sessionCookies = m_cookieJar->allowForSessionCookies();
+}
+
+
+QVariant CookieExceptionsModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (role == Qt::SizeHintRole)
+ {
+ QFont font;
+ font.setPointSize(10);
+ QFontMetrics fm(font);
+ int height = fm.height() + fm.height() / 3;
+ int width = fm.width(headerData(section, orientation, Qt::DisplayRole).toString());
+ return QSize(width, height);
+ }
+
+ if (orientation == Qt::Horizontal
+ && role == Qt::DisplayRole)
+ {
+ switch (section)
+ {
+ case 0:
+ return i18n("Website");
+ case 1:
+ return i18n("Status");
+ }
+ }
+ return QAbstractTableModel::headerData(section, orientation, role);
+}
+
+
+QVariant CookieExceptionsModel::data(const QModelIndex &index, int role) const
+{
+ if (index.row() < 0 || index.row() >= rowCount())
+ return QVariant();
+
+ switch (role)
+ {
+ case Qt::DisplayRole:
+ case Qt::EditRole:
+ {
+ int row = index.row();
+ if (row < m_allowedCookies.count())
+ {
+ switch (index.column())
+ {
+ case 0:
+ return m_allowedCookies.at(row);
+ case 1:
+ return i18n("Allow");
+ }
+ }
+ row = row - m_allowedCookies.count();
+ if (row < m_blockedCookies.count())
+ {
+ switch (index.column())
+ {
+ case 0:
+ return m_blockedCookies.at(row);
+ case 1:
+ return i18n("Block");
+ }
+ }
+ row = row - m_blockedCookies.count();
+ if (row < m_sessionCookies.count())
+ {
+ switch (index.column())
+ {
+ case 0:
+ return m_sessionCookies.at(row);
+ case 1:
+ return i18n("Allow For Session");
+ }
+ }
+ }
+ case Qt::FontRole:
+ {
+ QFont font;
+ font.setPointSize(10);
+ return font;
+ }
+ }
+ return QVariant();
+}
+
+
+int CookieExceptionsModel::columnCount(const QModelIndex &parent) const
+{
+ return (parent.isValid()) ? 0 : 2;
+}
+
+
+int CookieExceptionsModel::rowCount(const QModelIndex &parent) const
+{
+ return (parent.isValid() || !m_cookieJar) ? 0 : m_allowedCookies.count() + m_blockedCookies.count() + m_sessionCookies.count();
+}
+
+
+bool CookieExceptionsModel::removeRows(int row, int count, const QModelIndex &parent)
+{
+ if (parent.isValid() || !m_cookieJar)
+ return false;
+
+ int lastRow = row + count - 1;
+ beginRemoveRows(parent, row, lastRow);
+ for (int i = lastRow; i >= row; --i)
+ {
+ if (i < m_allowedCookies.count())
+ {
+ m_allowedCookies.removeAt(row);
+ continue;
+ }
+ i = i - m_allowedCookies.count();
+ if (i < m_blockedCookies.count())
+ {
+ m_blockedCookies.removeAt(row);
+ continue;
+ }
+ i = i - m_blockedCookies.count();
+ if (i < m_sessionCookies.count())
+ {
+ m_sessionCookies.removeAt(row);
+ continue;
+ }
+ }
+ m_cookieJar->setAllowedCookies(m_allowedCookies);
+ m_cookieJar->setBlockedCookies(m_blockedCookies);
+ m_cookieJar->setAllowForSessionCookies(m_sessionCookies);
+ endRemoveRows();
+ return true;
+}
+
+
+// ----------------------------------------------------------------------------------------------------------------
+
+
+CookiesExceptionsDialog::CookiesExceptionsDialog(CookieJar *cookieJar, QWidget *parent)
+ : QDialog(parent)
+ , m_cookieJar(cookieJar)
+{
+ setupUi(this);
+ setWindowFlags(Qt::Sheet);
+ connect(removeButton, SIGNAL(clicked()), exceptionTable, SLOT(removeOne()));
+ connect(removeAllButton, SIGNAL(clicked()), exceptionTable, SLOT(removeAll()));
+ exceptionTable->verticalHeader()->hide();
+ exceptionTable->setSelectionBehavior(QAbstractItemView::SelectRows);
+ exceptionTable->setAlternatingRowColors(true);
+ exceptionTable->setTextElideMode(Qt::ElideMiddle);
+ exceptionTable->setShowGrid(false);
+ exceptionTable->setSortingEnabled(true);
+ m_exceptionsModel = new CookieExceptionsModel(cookieJar, this);
+ m_proxyModel = new QSortFilterProxyModel(this);
+ m_proxyModel->setSourceModel(m_exceptionsModel);
+ connect(search, SIGNAL(textChanged(QString)),
+ m_proxyModel, SLOT(setFilterFixedString(QString)));
+ exceptionTable->setModel(m_proxyModel);
+
+ CookieModel *cookieModel = new CookieModel(cookieJar, this);
+ domainLineEdit->setCompleter(new QCompleter(cookieModel, domainLineEdit));
+
+ connect(domainLineEdit, SIGNAL(textChanged(const QString &)),
+ this, SLOT(textChanged(const QString &)));
+ connect(blockButton, SIGNAL(clicked()), this, SLOT(block()));
+ connect(allowButton, SIGNAL(clicked()), this, SLOT(allow()));
+ connect(allowForSessionButton, SIGNAL(clicked()), this, SLOT(allowForSession()));
+
+ QFont f = font();
+ f.setPointSize(10);
+ QFontMetrics fm(f);
+ int height = fm.height() + fm.height() / 3;
+ exceptionTable->verticalHeader()->setDefaultSectionSize(height);
+ exceptionTable->verticalHeader()->setMinimumSectionSize(-1);
+ for (int i = 0; i < m_exceptionsModel->columnCount(); ++i)
+ {
+ int header = exceptionTable->horizontalHeader()->sectionSizeHint(i);
+ switch (i)
+ {
+ case 0:
+ header = fm.width(QLatin1String("averagebiglonghost.domain.com"));
+ break;
+ case 1:
+ header = fm.width(QLatin1String("Allow For Session"));
+ break;
+ }
+ int buffer = fm.width(QLatin1String("xx"));
+ header += buffer;
+ exceptionTable->horizontalHeader()->resizeSection(i, header);
+ }
+}
+
+
+void CookiesExceptionsDialog::textChanged(const QString &text)
+{
+ bool enabled = !text.isEmpty();
+ blockButton->setEnabled(enabled);
+ allowButton->setEnabled(enabled);
+ allowForSessionButton->setEnabled(enabled);
+}
+
+
+void CookiesExceptionsDialog::block()
+{
+ if (domainLineEdit->text().isEmpty())
+ return;
+ m_exceptionsModel->m_blockedCookies.append(domainLineEdit->text());
+ m_cookieJar->setBlockedCookies(m_exceptionsModel->m_blockedCookies);
+ m_exceptionsModel->reset();
+}
+
+
+void CookiesExceptionsDialog::allow()
+{
+ if (domainLineEdit->text().isEmpty())
+ return;
+ m_exceptionsModel->m_allowedCookies.append(domainLineEdit->text());
+ m_cookieJar->setAllowedCookies(m_exceptionsModel->m_allowedCookies);
+ m_exceptionsModel->reset();
+}
+
+
+void CookiesExceptionsDialog::allowForSession()
+{
+ if (domainLineEdit->text().isEmpty())
+ return;
+ m_exceptionsModel->m_sessionCookies.append(domainLineEdit->text());
+ m_cookieJar->setAllowForSessionCookies(m_exceptionsModel->m_sessionCookies);
+ m_exceptionsModel->reset();
+}
diff --git a/src/cookiejar.h b/src/cookiejar.h
new file mode 100644
index 00000000..27071b6d
--- /dev/null
+++ b/src/cookiejar.h
@@ -0,0 +1,200 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007-2008 Trolltech ASA. All rights reserved
+* Copyright (C) 2008-2009 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009 by Domrachev Alexandr <alexandr.domrachev@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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+#ifndef COOKIEJAR_H
+#define COOKIEJAR_H
+
+
+// KDE Includes
+#include <QDialog>
+
+// Qt Includes
+#include <QNetworkCookieJar>
+#include <QAbstractItemModel>
+#include <QStringList>
+#include <QTableView>
+
+// Forward Declarations
+class QSortFilterProxyModel;
+class QKeyEvent;
+class AutoSaver;
+
+
+class CookieJar : public QNetworkCookieJar
+{
+ friend class CookieModel;
+ Q_OBJECT
+ Q_PROPERTY(AcceptPolicy acceptPolicy READ acceptPolicy WRITE setAcceptPolicy)
+ Q_PROPERTY(KeepPolicy keepPolicy READ keepPolicy WRITE setKeepPolicy)
+ Q_PROPERTY(QStringList blockedCookies READ blockedCookies WRITE setBlockedCookies)
+ Q_PROPERTY(QStringList allowedCookies READ allowedCookies WRITE setAllowedCookies)
+ Q_PROPERTY(QStringList allowForSessionCookies READ allowForSessionCookies WRITE setAllowForSessionCookies)
+ Q_ENUMS(KeepPolicy)
+ Q_ENUMS(AcceptPolicy)
+
+signals:
+ void cookiesChanged();
+
+public:
+ enum AcceptPolicy
+ {
+ AcceptAlways,
+ AcceptNever,
+ AcceptOnlyFromSitesNavigatedTo
+ };
+
+ enum KeepPolicy
+ {
+ KeepUntilExpire,
+ KeepUntilExit,
+ KeepUntilTimeLimit
+ };
+
+ CookieJar(QObject *parent = 0);
+ ~CookieJar();
+
+ QList<QNetworkCookie> cookiesForUrl(const QUrl &url) const;
+ bool setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url);
+
+ AcceptPolicy acceptPolicy() const;
+ void setAcceptPolicy(AcceptPolicy policy);
+
+ KeepPolicy keepPolicy() const;
+ void setKeepPolicy(KeepPolicy policy);
+
+ QStringList blockedCookies() const;
+ QStringList allowedCookies() const;
+ QStringList allowForSessionCookies() const;
+
+ void setBlockedCookies(const QStringList &list);
+ void setAllowedCookies(const QStringList &list);
+ void setAllowForSessionCookies(const QStringList &list);
+
+public slots:
+ void clear();
+ void loadSettings();
+
+private slots:
+ void save();
+
+private:
+ void purgeOldCookies();
+ void load();
+ bool m_loaded;
+ AutoSaver *m_saveTimer;
+
+ AcceptPolicy m_acceptCookies;
+ KeepPolicy m_keepCookies;
+
+ QStringList m_exceptions_block;
+ QStringList m_exceptions_allow;
+ QStringList m_exceptions_allowForSession;
+};
+
+
+// -------------------------------------------------------------------------------------------------------------
+
+
+class CookieModel : public QAbstractTableModel
+{
+ Q_OBJECT
+
+public:
+ CookieModel(CookieJar *jar, QObject *parent = 0);
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
+
+private slots:
+ void cookiesChanged();
+
+private:
+ CookieJar *m_cookieJar;
+};
+
+
+// ----------------------------------------------------------------------------------------------------------------------
+
+
+#include "ui_cookies.h"
+
+class CookiesDialog : public QDialog, public Ui_CookiesDialog
+{
+ Q_OBJECT
+
+public:
+ CookiesDialog(CookieJar *cookieJar, QWidget *parent = 0);
+
+private:
+ QSortFilterProxyModel *m_proxyModel;
+};
+
+class CookieExceptionsModel : public QAbstractTableModel
+{
+ Q_OBJECT
+ friend class CookiesExceptionsDialog;
+
+public:
+ CookieExceptionsModel(CookieJar *cookieJar, QObject *parent = 0);
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
+
+private:
+ CookieJar *m_cookieJar;
+
+ // Domains we allow, Domains we block, Domains we allow for this session
+ QStringList m_allowedCookies;
+ QStringList m_blockedCookies;
+ QStringList m_sessionCookies;
+};
+
+
+// -----------------------------------------------------------------------------------------------------------------
+
+
+#include "ui_cookiesexceptions.h"
+
+class CookiesExceptionsDialog : public QDialog, public Ui_CookiesExceptionsDialog
+{
+ Q_OBJECT
+
+public:
+ CookiesExceptionsDialog(CookieJar *cookieJar, QWidget *parent = 0);
+
+private slots:
+ void block();
+ void allow();
+ void allowForSession();
+ void textChanged(const QString &text);
+
+private:
+ CookieExceptionsModel *m_exceptionsModel;
+ QSortFilterProxyModel *m_proxyModel;
+ CookieJar *m_cookieJar;
+};
+
+#endif // COOKIEJAR_H
diff --git a/src/cookies.ui b/src/cookies.ui
new file mode 100644
index 00000000..49ad3a96
--- /dev/null
+++ b/src/cookies.ui
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>CookiesDialog</class>
+ <widget class="QDialog" name="CookiesDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>550</width>
+ <height>370</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Cookies</string>
+ </property>
+ <layout class="QGridLayout">
+ <item row="0" column="0">
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>252</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="1">
+ <widget class="KLineEdit" name="search"/>
+ </item>
+ <item row="1" column="0" colspan="2">
+ <widget class="EditTableView" name="cookiesTable"/>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QPushButton" name="removeButton">
+ <property name="text">
+ <string>&amp;Remove</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="removeAllButton">
+ <property name="text">
+ <string>Remove &amp;All Cookies</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>KLineEdit</class>
+ <extends>QLineEdit</extends>
+ <header>klineedit.h</header>
+ </customwidget>
+ <customwidget>
+ <class>EditTableView</class>
+ <extends>QTableView</extends>
+ <header>edittableview.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>CookiesDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>472</x>
+ <y>329</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>461</x>
+ <y>356</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/cookiesexceptions.ui b/src/cookiesexceptions.ui
new file mode 100644
index 00000000..de59eee0
--- /dev/null
+++ b/src/cookiesexceptions.ui
@@ -0,0 +1,179 @@
+<ui version="4.0" >
+ <class>CookiesExceptionsDialog</class>
+ <widget class="QDialog" name="CookiesExceptionsDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>466</width>
+ <height>446</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Cookie Exceptions</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QGroupBox" name="newExceptionGroupBox" >
+ <property name="title" >
+ <string>New Exception</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>Domain:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="KLineEdit" name="domainLineEdit" />
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="0" >
+ <layout class="QHBoxLayout" >
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>81</width>
+ <height>25</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="blockButton" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="text" >
+ <string>Block</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="allowForSessionButton" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="text" >
+ <string>Allow For Session</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="allowButton" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="text" >
+ <string>Allow</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="ExceptionsGroupBox" >
+ <property name="title" >
+ <string>Exceptions</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" colspan="3" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>252</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="3" >
+ <widget class="KLineEdit" name="search" />
+ </item>
+ <item row="1" column="0" colspan="4" >
+ <widget class="EditTableView" name="exceptionTable" />
+ </item>
+ <item row="2" column="0" >
+ <widget class="QPushButton" name="removeButton" >
+ <property name="text" >
+ <string>&amp;Remove</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QPushButton" name="removeAllButton" >
+ <property name="text" >
+ <string>Remove &amp;All</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2" colspan="2" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>EditTableView</class>
+ <extends>QTableView</extends>
+ <header>edittableview.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>CookiesExceptionsDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>381</x>
+ <y>428</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>336</x>
+ <y>443</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/download.cpp b/src/download.cpp
new file mode 100644
index 00000000..9489b270
--- /dev/null
+++ b/src/download.cpp
@@ -0,0 +1,224 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007 Lukas Appelhans <l.appelhans@gmx.de>
+* Copyright (C) 2008-2009 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009 by Paweł Prażak <pawelprazak at gmail dot com>
+* Copyright (C) 2009 by Domrachev Alexandr <alexandr.domrachev@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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+// local Includes
+#include "download.h"
+#include "download.moc"
+
+// KDE Includes
+#include <KDebug>
+#include <KFileDialog>
+#include <KGlobalSettings>
+#include <KMessageBox>
+#include <KMimeType>
+#include <KStandardDirs>
+
+// Qt Includes
+#include <QFile>
+#include <QFileInfo>
+
+// Local Includes
+#include "application.h"
+#include "mainwindow.h"
+
+
+DownloadManager::DownloadManager()
+ : QObject()
+{
+}
+
+
+DownloadManager::~DownloadManager()
+{
+ foreach(Download *download, m_downloads)
+ {
+ // cancel all unfinished downloads
+ download->cancel();
+ delete download;
+ }
+}
+
+
+void DownloadManager::newDownload(const KUrl &srcUrl, const KUrl &destUrl)
+{
+ KUrl destination = destUrl;
+ Download::DownloadType type;
+
+ KSharedPtr<KMimeType> mimeType = KMimeType::findByPath(srcUrl.prettyUrl());
+
+ QString typeText = KMimeType::extractKnownExtension(srcUrl.fileName());
+ typeText += " (" + mimeType->name() + ")";
+
+ int answer = KMessageBox::questionYesNoCancel(NULL,
+ i18n("Download '%1'?\n""Type: %2", srcUrl.prettyUrl(), typeText),
+ i18n("Download '%1'...", srcUrl.fileName()),
+ KStandardGuiItem::save(),
+ KStandardGuiItem::open(),
+ KStandardGuiItem::cancel(),
+ "showOpenSaveDownloadDialog"
+ );
+
+ switch (answer)
+ {
+ case KMessageBox::Cancel:
+ return;
+ break;
+
+ case KMessageBox::Yes: // ----- SAVE
+ // if destination is empty than ask for download path (if showOpenSaveDownloadDialog setting enabled)
+ if (destination.isEmpty())
+ {
+ destination = downloadDestination(srcUrl.fileName());
+ }
+ type = Download::Save;
+ break;
+
+ case KMessageBox::No: // ----- OPEN
+ // Download file to tmp dir
+ destination.setDirectory(KStandardDirs::locateLocal("tmp", "", true));
+ destination.addPath(srcUrl.fileName());
+ type = Download::Open;
+ break;
+
+ default:
+ // impossible
+ break;
+ };
+
+ // if user canceled download than abort
+ if (destination.isEmpty())
+ return;
+
+ Download *download = new Download(srcUrl, destination, type);
+ connect(download, SIGNAL(downloadFinished(int)), this, SLOT(slotDownloadFinished(int)));
+ m_downloads.append(download);
+}
+
+
+const QList<Download *> &DownloadManager::downloads() const
+{
+ return m_downloads;
+};
+
+
+KUrl DownloadManager::downloadDestination(const QString &filename)
+{
+ KUrl destination = ReKonfig::downloadDir();
+ if (destination.isEmpty())
+ destination = KGlobalSettings::downloadPath();
+ destination.addPath(filename);
+
+ if (!ReKonfig::downloadToDefaultDir())
+ {
+ destination = KFileDialog::getSaveUrl(destination);
+ // if user canceled the download return empty url
+ if (destination.isEmpty())
+ return KUrl();
+ }
+ return destination;
+}
+
+
+void DownloadManager::slotDownloadFinished(int errorCode)
+{
+ Q_UNUSED(errorCode)
+
+ // if sender exists and list contains it - (open and) delete it
+ Download *download = qobject_cast<Download *>(sender());
+ if (download && m_downloads.contains(download))
+ {
+ if (download->type() == Download::Open)
+ {
+ KSharedPtr<KMimeType> mimeType = KMimeType::findByPath(download->destUrl().prettyUrl());
+ KRun::runUrl(download->destUrl(), mimeType->name(), NULL, true);
+ }
+ disconnect(download, SIGNAL(downloadFinished(int)), this, SLOT(slotDownloadFinished(int)));
+ int index = m_downloads.indexOf(download);
+ delete m_downloads.takeAt(index);
+ return;
+ }
+ kWarning() << "Could not find download or invalid sender. Sender:" << sender();
+}
+
+
+//----
+
+#include <KJob>
+#include <KIO/Job>
+#include <KIO/CopyJob>
+
+
+Download::Download(const KUrl &srcUrl, const KUrl &destUrl, DownloadType type)
+ : QObject()
+ , m_srcUrl(srcUrl)
+ , m_destUrl(destUrl)
+ , m_type(type)
+{
+ Q_ASSERT(!m_srcUrl.isEmpty());
+ Q_ASSERT(!m_destUrl.isEmpty());
+ kDebug() << "DownloadFile: " << m_srcUrl.url() << " to dest: " << m_destUrl.url();
+
+ m_copyJob = KIO::file_copy(m_srcUrl, m_destUrl);
+ connect(m_copyJob, SIGNAL(result(KJob *)), SLOT(slotResult(KJob *)));
+}
+
+
+Download::~Download()
+{
+}
+
+
+void Download::cancel()
+{
+ bool result = m_copyJob->kill(KJob::EmitResult);
+ Q_ASSERT(result);
+}
+
+
+void Download::slotResult(KJob *job)
+{
+ switch (job->error())
+ {
+ case 0: //The download has finished
+ {
+ kDebug() << "Downloading successfully finished: " << m_destUrl.url();
+ break;
+ }
+ case KIO::ERR_FILE_ALREADY_EXIST:
+ {
+ kWarning() << "ERROR - File already exists";
+ break;
+ }
+ case KIO::ERR_USER_CANCELED:
+ {
+ kWarning() << "ERROR - User canceled the downlaod";
+ break;
+ }
+ default:
+ kWarning() << "We are sorry to say you, that there were errors while downloading :(";
+ break;
+ }
+
+ // inform the world
+ emit downloadFinished(job->error());
+}
diff --git a/src/download.h b/src/download.h
new file mode 100644
index 00000000..0ad01e69
--- /dev/null
+++ b/src/download.h
@@ -0,0 +1,141 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007 Lukas Appelhans <l.appelhans@gmx.de>
+* Copyright (C) 2008-2009 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009 by Paweł Prażak <pawelprazak at gmail dot com>
+* Copyright (C) 2009 by Domrachev Alexandr <alexandr.domrachev@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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+#ifndef DOWNLOAD_H
+#define DOWNLOAD_H
+
+// Auto Includes
+#include "rekonq.h"
+
+// KDE Includes
+#include <KIO/FileCopyJob>
+
+// Qt Includes
+#include <QObject>
+
+// Forward Declarations
+class KJob;
+
+namespace KIO
+{
+class Job;
+}
+
+
+/**
+ * This class lets rekonq to download an object from the network.
+ * Creating a new object, you can continue downloading a file also
+ * when rekonq is closed.
+ *
+ */
+class Download : public QObject
+{
+ Q_OBJECT
+
+public:
+ enum DownloadType { Save, Open };
+
+ /**
+ * Class constructor. This is the unique method we need to
+ * use this class. In fact Download class needs to know just
+ * "where" catch the file to download and where it has to put it
+ *
+ * @param srcUrl the source url
+ * @param destUrl the destination url
+ *
+ */
+ Download(const KUrl &srcUrl, const KUrl &destUrl, DownloadType type);
+
+ /**
+ * class destructor
+ */
+ ~Download();
+
+ KUrl srcUrl() const
+ {
+ return m_srcUrl;
+ }
+ KUrl destUrl() const
+ {
+ return m_destUrl;
+ }
+ DownloadType type() const
+ {
+ return m_type;
+ }
+ void cancel();
+
+signals:
+ void downloadFinished(int errorCode);
+
+private slots:
+ void slotResult(KJob *job);
+
+private:
+ KIO::FileCopyJob *m_copyJob;
+ KUrl m_srcUrl;
+ KUrl m_destUrl;
+ KUrl m_destFile;
+ QByteArray m_data;
+ DownloadType m_type;
+};
+
+
+// ----------------------
+
+
+class DownloadManager : public QObject
+{
+ Q_OBJECT
+
+public:
+ DownloadManager();
+ ~DownloadManager();
+
+ /**
+ * @short Creates new download job.
+ * This method lets you to download a file from a remote source url
+ * to a local destination url.
+ *
+ * @param srcUrl the source url
+ * @param destUrl the destination url (default value is your default download destination setting)
+ *
+ */
+ void newDownload(const KUrl &srcUrl, const KUrl &destUrl = KUrl());
+
+ const QList<Download *> &downloads() const;
+
+public slots:
+ void slotDownloadFinished(int errorCode);
+
+private:
+ KUrl downloadDestination(const QString &filename);
+
+ QList<Download *> m_downloads;
+};
+
+
+//--
+
+
+#endif
diff --git a/src/edittableview.cpp b/src/edittableview.cpp
new file mode 100644
index 00000000..bf1ef370
--- /dev/null
+++ b/src/edittableview.cpp
@@ -0,0 +1,61 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007-2008 Trolltech ASA. All rights reserved
+* Copyright (C) 2008-2009 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+
+#include "edittableview.h"
+#include <QtGui/QKeyEvent>
+
+EditTableView::EditTableView(QWidget *parent)
+ : QTableView(parent)
+{
+}
+
+void EditTableView::keyPressEvent(QKeyEvent *event)
+{
+ if ((event->key() == Qt::Key_Delete
+ || event->key() == Qt::Key_Backspace)
+ && model())
+ {
+ removeOne();
+ }
+ else
+ {
+ QAbstractItemView::keyPressEvent(event);
+ }
+}
+
+void EditTableView::removeOne()
+{
+ if (!model() || !selectionModel())
+ return;
+ int row = currentIndex().row();
+ model()->removeRow(row, rootIndex());
+ QModelIndex idx = model()->index(row, 0, rootIndex());
+ if (!idx.isValid())
+ idx = model()->index(row - 1, 0, rootIndex());
+ selectionModel()->select(idx, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
+}
+
+void EditTableView::removeAll()
+{
+ if (model())
+ model()->removeRows(0, model()->rowCount(rootIndex()), rootIndex());
+}
diff --git a/src/edittableview.h b/src/edittableview.h
new file mode 100644
index 00000000..dbc9a145
--- /dev/null
+++ b/src/edittableview.h
@@ -0,0 +1,42 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007-2008 Trolltech ASA. All rights reserved
+* Copyright (C) 2008-2009 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+
+#ifndef EDITTABLEVIEW_H
+#define EDITTABLEVIEW_H
+
+#include <QtGui/QTableView>
+
+class EditTableView : public QTableView
+{
+ Q_OBJECT
+
+public:
+ EditTableView(QWidget *parent = 0);
+ void keyPressEvent(QKeyEvent *event);
+
+public slots:
+ void removeOne();
+ void removeAll();
+};
+
+#endif // EDITTABLEVIEW_H
+
diff --git a/src/edittreeview.cpp b/src/edittreeview.cpp
new file mode 100644
index 00000000..49730d67
--- /dev/null
+++ b/src/edittreeview.cpp
@@ -0,0 +1,61 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007-2008 Trolltech ASA. All rights reserved
+* Copyright (C) 2008-2009 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+
+#include "edittreeview.h"
+
+#include <QtGui/QKeyEvent>
+
+EditTreeView::EditTreeView(QWidget *parent)
+ : QTreeView(parent)
+{
+}
+
+void EditTreeView::keyPressEvent(QKeyEvent *event)
+{
+ if ((event->key() == Qt::Key_Delete
+ || event->key() == Qt::Key_Backspace)
+ && model())
+ {
+ removeOne();
+ }
+ else
+ {
+ QAbstractItemView::keyPressEvent(event);
+ }
+}
+
+void EditTreeView::removeOne()
+{
+ if (!model())
+ return;
+ QModelIndex ci = currentIndex();
+ int row = ci.row();
+ model()->removeRow(row, ci.parent());
+}
+
+void EditTreeView::removeAll()
+{
+ if (!model())
+ return;
+ model()->removeRows(0, model()->rowCount(rootIndex()), rootIndex());
+}
+
diff --git a/src/edittreeview.h b/src/edittreeview.h
new file mode 100644
index 00000000..5be0dc45
--- /dev/null
+++ b/src/edittreeview.h
@@ -0,0 +1,41 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007-2008 Trolltech ASA. All rights reserved
+* Copyright (C) 2008-2009 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+#ifndef EDITTREEVIEW_H
+#define EDITTREEVIEW_H
+
+#include <QtGui/QTreeView>
+
+class EditTreeView : public QTreeView
+{
+ Q_OBJECT
+
+public:
+ EditTreeView(QWidget *parent = 0);
+ void keyPressEvent(QKeyEvent *event);
+
+public slots:
+ void removeOne();
+ void removeAll();
+};
+
+#endif // EDITTREEVIEW_H
+
diff --git a/src/findbar.cpp b/src/findbar.cpp
new file mode 100644
index 00000000..11d890c1
--- /dev/null
+++ b/src/findbar.cpp
@@ -0,0 +1,137 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2008-2009 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "findbar.h"
+#include "findbar.moc"
+
+// KDE Includes
+#include <KLineEdit>
+#include <KAction>
+#include <KIcon>
+#include <KPushButton>
+#include <klocalizedstring.h>
+
+// Qt Includes
+#include <QtGui>
+
+
+FindBar::FindBar(KXmlGuiWindow *mainwindow)
+ : QWidget(mainwindow)
+ , m_lineEdit(new KLineEdit(this))
+ , m_matchCase(new QCheckBox(i18n("&Match case"), this))
+{
+ QHBoxLayout *layout = new QHBoxLayout;
+
+ // cosmetic
+ layout->setContentsMargins(2, 0, 2, 0);
+
+ // hide button
+ QToolButton *hideButton = new QToolButton(this);
+ hideButton->setAutoRaise(true);
+ hideButton->setIcon(KIcon("dialog-close"));
+ connect(hideButton, SIGNAL(clicked()), this, SLOT(hide()));
+ layout->addWidget(hideButton);
+ layout->setAlignment(hideButton, Qt::AlignLeft | Qt::AlignTop);
+
+ // label
+ QLabel *label = new QLabel(i18n("Find: "));
+ layout->addWidget(label);
+
+ // lineEdit, focusProxy
+ setFocusProxy(m_lineEdit);
+ m_lineEdit->setMaximumWidth(250);
+ connect(m_lineEdit, SIGNAL(textChanged(const QString &)), mainwindow, SLOT(slotFind(const QString &)));
+ layout->addWidget(m_lineEdit);
+
+ // buttons
+ KPushButton *findNext = new KPushButton(KIcon("go-down"), i18n("&Next"), this);
+ KPushButton *findPrev = new KPushButton(KIcon("go-up"), i18n("&Previous"), this);
+ connect(findNext, SIGNAL(clicked()), mainwindow, SLOT(slotFindNext()));
+ connect(findPrev, SIGNAL(clicked()), mainwindow, SLOT(slotFindPrevious()));
+ layout->addWidget(findNext);
+ layout->addWidget(findPrev);
+
+ // Case sensitivity. Deliberately set so this is off by default.
+ m_matchCase->setCheckState(Qt::Unchecked);
+ m_matchCase->setTristate(false);
+ layout->addWidget(m_matchCase);
+
+ // stretching widget on the left
+ layout->addStretch();
+
+ setLayout(layout);
+
+ // we start off hidden
+ hide();
+}
+
+
+FindBar::~FindBar()
+{
+}
+
+
+KLineEdit *FindBar::lineEdit() const
+{
+ return m_lineEdit;
+}
+
+
+bool FindBar::matchCase() const
+{
+ return m_matchCase->isChecked();
+}
+
+
+void FindBar::clear()
+{
+ m_lineEdit->setText(QString());
+}
+
+
+void FindBar::showFindBar()
+{
+ // show findbar if not visible
+ if (!isVisible())
+ {
+ show();
+ }
+ // set focus to findbar if user select showFindBar shortcut
+ m_lineEdit->setFocus();
+ m_lineEdit->selectAll();
+}
+
+
+void FindBar::keyPressEvent(QKeyEvent* event)
+{
+ if (event->key() == Qt::Key_Escape)
+ {
+ hide();
+ return;
+ }
+ if (event->key() == Qt::Key_Return && !m_lineEdit->text().isEmpty())
+ {
+ emit searchString(m_lineEdit->text());
+ return;
+ }
+ QWidget::keyPressEvent(event);
+}
+
diff --git a/src/findbar.h b/src/findbar.h
new file mode 100644
index 00000000..15a82e1e
--- /dev/null
+++ b/src/findbar.h
@@ -0,0 +1,61 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2008-2009 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+
+#ifndef FINDBAR_H
+#define FINDBAR_H
+
+// KDE Includes
+#include <KLineEdit>
+#include <KToolBar>
+#include <KXmlGuiWindow>
+
+// Qt Includes
+#include <QtCore>
+#include <QtGui>
+
+
+class FindBar : public QWidget
+{
+ Q_OBJECT
+
+public:
+ FindBar(KXmlGuiWindow *mainwindow);
+ ~FindBar();
+ KLineEdit *lineEdit() const;
+ bool matchCase() const;
+
+public slots:
+ void clear();
+ void showFindBar();
+
+protected Q_SLOTS:
+ void keyPressEvent(QKeyEvent* event);
+
+signals:
+ void searchString(const QString &);
+
+private:
+ KLineEdit *m_lineEdit;
+ QCheckBox *m_matchCase;
+};
+
+
+#endif
diff --git a/src/history.cpp b/src/history.cpp
new file mode 100644
index 00000000..afcb477a
--- /dev/null
+++ b/src/history.cpp
@@ -0,0 +1,1459 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007-2008 Trolltech ASA. All rights reserved
+* Copyright (C) 2008 Benjamin C. Meyer <ben@meyerhome.net>
+* Copyright (C) 2008-2009 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "history.h"
+#include "history.moc"
+
+// Auto Includes
+#include "rekonq.h"
+
+// Local Includes
+#include "autosaver.h"
+#include "application.h"
+
+// KDE Includes
+#include <KDebug>
+#include <KStandardDirs>
+
+// Qt Includes
+#include <QtCore>
+#include <QtGui>
+#include <QtWebKit>
+
+#include <QtAlgorithms>
+
+
+static const unsigned int HISTORY_VERSION = 23;
+
+
+HistoryManager::HistoryManager(QObject *parent)
+ : QWebHistoryInterface(parent)
+ , m_saveTimer(new AutoSaver(this))
+ , m_historyLimit(30)
+ , m_historyModel(0)
+ , m_historyFilterModel(0)
+ , m_historyTreeModel(0)
+{
+ m_expiredTimer.setSingleShot(true);
+ connect(&m_expiredTimer, SIGNAL(timeout()), this, SLOT(checkForExpired()));
+ connect(this, SIGNAL(entryAdded(const HistoryItem &)), m_saveTimer, SLOT(changeOccurred()));
+ connect(this, SIGNAL(entryRemoved(const HistoryItem &)), m_saveTimer, SLOT(changeOccurred()));
+ load();
+
+ m_historyModel = new HistoryModel(this, this);
+ m_historyFilterModel = new HistoryFilterModel(m_historyModel, this);
+ m_historyTreeModel = new HistoryTreeModel(m_historyFilterModel, this);
+
+ // QWebHistoryInterface will delete the history manager
+ QWebHistoryInterface::setDefaultInterface(this);
+}
+
+
+HistoryManager::~HistoryManager()
+{
+ m_saveTimer->saveIfNeccessary();
+}
+
+
+QList<HistoryItem> HistoryManager::history() const
+{
+ return m_history;
+}
+
+
+bool HistoryManager::historyContains(const QString &url) const
+{
+ return m_historyFilterModel->historyContains(url);
+}
+
+
+void HistoryManager::addHistoryEntry(const QString &url)
+{
+ QUrl cleanUrl(url);
+ cleanUrl.setPassword(QString());
+ cleanUrl.setHost(cleanUrl.host().toLower());
+ HistoryItem item(cleanUrl.toString(), QDateTime::currentDateTime());
+ addHistoryEntry(item);
+}
+
+
+void HistoryManager::setHistory(const QList<HistoryItem> &history, bool loadedAndSorted)
+{
+ m_history = history;
+
+ // verify that it is sorted by date
+ if (!loadedAndSorted)
+ qSort(m_history.begin(), m_history.end());
+
+ checkForExpired();
+
+ if (loadedAndSorted)
+ {
+ m_lastSavedUrl = m_history.value(0).url;
+ }
+ else
+ {
+ m_lastSavedUrl = QString();
+ m_saveTimer->changeOccurred();
+ }
+ emit historyReset();
+}
+
+
+HistoryModel *HistoryManager::historyModel() const
+{
+ return m_historyModel;
+}
+
+
+HistoryFilterModel *HistoryManager::historyFilterModel() const
+{
+ return m_historyFilterModel;
+}
+
+
+HistoryTreeModel *HistoryManager::historyTreeModel() const
+{
+ return m_historyTreeModel;
+}
+
+
+void HistoryManager::checkForExpired()
+{
+ if (m_historyLimit < 0 || m_history.isEmpty())
+ return;
+
+ QDateTime now = QDateTime::currentDateTime();
+ int nextTimeout = 0;
+
+ while (!m_history.isEmpty())
+ {
+ QDateTime checkForExpired = m_history.last().dateTime;
+ checkForExpired.setDate(checkForExpired.date().addDays(m_historyLimit));
+ if (now.daysTo(checkForExpired) > 7)
+ {
+ // check at most in a week to prevent int overflows on the timer
+ nextTimeout = 7 * 86400;
+ }
+ else
+ {
+ nextTimeout = now.secsTo(checkForExpired);
+ }
+ if (nextTimeout > 0)
+ break;
+ HistoryItem item = m_history.takeLast();
+ // remove from saved file also
+ m_lastSavedUrl = QString();
+ emit entryRemoved(item);
+ }
+
+ if (nextTimeout > 0)
+ m_expiredTimer.start(nextTimeout * 1000);
+}
+
+
+void HistoryManager::addHistoryEntry(const HistoryItem &item)
+{
+ QWebSettings *globalSettings = QWebSettings::globalSettings();
+ if (globalSettings->testAttribute(QWebSettings::PrivateBrowsingEnabled))
+ return;
+
+ m_history.prepend(item);
+ emit entryAdded(item);
+ if (m_history.count() == 1)
+ checkForExpired();
+}
+
+
+void HistoryManager::updateHistoryEntry(const KUrl &url, const QString &title)
+{
+ for (int i = 0; i < m_history.count(); ++i)
+ {
+ if (url == m_history.at(i).url)
+ {
+ m_history[i].title = title;
+ m_saveTimer->changeOccurred();
+ if (m_lastSavedUrl.isEmpty())
+ m_lastSavedUrl = m_history.at(i).url;
+ emit entryUpdated(i);
+ break;
+ }
+ }
+}
+
+
+void HistoryManager::removeHistoryEntry(const HistoryItem &item)
+{
+ m_lastSavedUrl.clear();
+ m_history.removeOne(item);
+ emit entryRemoved(item);
+}
+
+
+void HistoryManager::removeHistoryEntry(const KUrl &url, const QString &title)
+{
+ for (int i = 0; i < m_history.count(); ++i)
+ {
+ if (url == m_history.at(i).url
+ && (title.isEmpty() || title == m_history.at(i).title))
+ {
+ removeHistoryEntry(m_history.at(i));
+ break;
+ }
+ }
+}
+
+
+int HistoryManager::historyLimit() const
+{
+ return m_historyLimit;
+}
+
+
+void HistoryManager::setHistoryLimit(int limit)
+{
+ if (m_historyLimit == limit)
+ return;
+ m_historyLimit = limit;
+ checkForExpired();
+ m_saveTimer->changeOccurred();
+}
+
+
+void HistoryManager::clear()
+{
+ m_history.clear();
+ m_lastSavedUrl = QString();
+ m_saveTimer->changeOccurred();
+ m_saveTimer->saveIfNeccessary();
+ historyReset();
+}
+
+
+void HistoryManager::loadSettings()
+{
+ int historyExpire = ReKonfig::expireHistory();
+ int days;
+ switch (historyExpire)
+ {
+ case 0: days = 1; break;
+ case 1: days = 7; break;
+ case 2: days = 14; break;
+ case 3: days = 30; break;
+ case 4: days = 365; break;
+ case 5: days = -1; break;
+ default: days = -1;
+ }
+ m_historyLimit = days;
+}
+
+
+void HistoryManager::load()
+{
+ loadSettings();
+
+ QString historyFilePath = KStandardDirs::locateLocal("appdata" , "history");
+ QFile historyFile(historyFilePath);
+ if (!historyFile.exists())
+ return;
+ if (!historyFile.open(QFile::ReadOnly))
+ {
+ kWarning() << "Unable to open history file" << historyFile.fileName();
+ return;
+ }
+
+ QList<HistoryItem> list;
+ QDataStream in(&historyFile);
+ // Double check that the history file is sorted as it is read in
+ bool needToSort = false;
+ HistoryItem lastInsertedItem;
+ QByteArray data;
+ QDataStream stream;
+ QBuffer buffer;
+ stream.setDevice(&buffer);
+ while (!historyFile.atEnd())
+ {
+ in >> data;
+ buffer.close();
+ buffer.setBuffer(&data);
+ buffer.open(QIODevice::ReadOnly);
+ quint32 ver;
+ stream >> ver;
+ if (ver != HISTORY_VERSION)
+ continue;
+ HistoryItem item;
+ stream >> item.url;
+ stream >> item.dateTime;
+ stream >> item.title;
+
+ if (!item.dateTime.isValid())
+ continue;
+
+ if (item == lastInsertedItem)
+ {
+ if (lastInsertedItem.title.isEmpty() && !list.isEmpty())
+ list[0].title = item.title;
+ continue;
+ }
+
+ if (!needToSort && !list.isEmpty() && lastInsertedItem < item)
+ needToSort = true;
+
+ list.prepend(item);
+ lastInsertedItem = item;
+ }
+ if (needToSort)
+ qSort(list.begin(), list.end());
+
+ setHistory(list, true);
+
+ // If we had to sort re-write the whole history sorted
+ if (needToSort)
+ {
+ m_lastSavedUrl = QString();
+ m_saveTimer->changeOccurred();
+ }
+}
+
+
+void HistoryManager::save()
+{
+ bool saveAll = m_lastSavedUrl.isEmpty();
+ int first = m_history.count() - 1;
+ if (!saveAll)
+ {
+ // find the first one to save
+ for (int i = 0; i < m_history.count(); ++i)
+ {
+ if (m_history.at(i).url == m_lastSavedUrl)
+ {
+ first = i - 1;
+ break;
+ }
+ }
+ }
+ if (first == m_history.count() - 1)
+ saveAll = true;
+
+ QString historyFilePath = KStandardDirs::locateLocal("appdata" , "history");
+ QFile historyFile(historyFilePath);
+
+ // When saving everything use a temporary file to prevent possible data loss.
+ QTemporaryFile tempFile;
+ tempFile.setAutoRemove(false);
+ bool open = false;
+ if (saveAll)
+ {
+ open = tempFile.open();
+ }
+ else
+ {
+ open = historyFile.open(QFile::Append);
+ }
+
+ if (!open)
+ {
+ kWarning() << "Unable to open history file for saving"
+ << (saveAll ? tempFile.fileName() : historyFile.fileName());
+ return;
+ }
+
+ QDataStream out(saveAll ? &tempFile : &historyFile);
+ for (int i = first; i >= 0; --i)
+ {
+ QByteArray data;
+ QDataStream stream(&data, QIODevice::WriteOnly);
+ HistoryItem item = m_history.at(i);
+ stream << HISTORY_VERSION << item.url << item.dateTime << item.title;
+ out << data;
+ }
+ tempFile.close();
+
+ if (saveAll)
+ {
+ if (historyFile.exists() && !historyFile.remove())
+ kWarning() << "History: error removing old history." << historyFile.errorString();
+ if (!tempFile.rename(historyFile.fileName()))
+ kWarning() << "History: error moving new history over old." << tempFile.errorString() << historyFile.fileName();
+ }
+ m_lastSavedUrl = m_history.value(0).url;
+}
+
+
+// --------------------------------------------------------------------------------------------------------------------------
+
+
+HistoryModel::HistoryModel(HistoryManager *history, QObject *parent)
+ : QAbstractTableModel(parent)
+ , m_history(history)
+{
+ Q_ASSERT(m_history);
+ connect(m_history, SIGNAL(historyReset()), this, SLOT(historyReset()));
+ connect(m_history, SIGNAL(entryRemoved(const HistoryItem &)), this, SLOT(historyReset()));
+ connect(m_history, SIGNAL(entryAdded(const HistoryItem &)), this, SLOT(entryAdded()));
+ connect(m_history, SIGNAL(entryUpdated(int)), this, SLOT(entryUpdated(int)));
+}
+
+
+void HistoryModel::historyReset()
+{
+ reset();
+}
+
+
+void HistoryModel::entryAdded()
+{
+ beginInsertRows(QModelIndex(), 0, 0);
+ endInsertRows();
+}
+
+
+void HistoryModel::entryUpdated(int offset)
+{
+ QModelIndex idx = index(offset, 0);
+ emit dataChanged(idx, idx);
+}
+
+
+QVariant HistoryModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (orientation == Qt::Horizontal
+ && role == Qt::DisplayRole)
+ {
+ switch (section)
+ {
+ case 0: return i18n("Title");
+ case 1: return i18n("Address");
+ }
+ }
+ return QAbstractTableModel::headerData(section, orientation, role);
+}
+
+
+QVariant HistoryModel::data(const QModelIndex &index, int role) const
+{
+ QList<HistoryItem> lst = m_history->history();
+ if (index.row() < 0 || index.row() >= lst.size())
+ return QVariant();
+
+ const HistoryItem &item = lst.at(index.row());
+ switch (role)
+ {
+ case DateTimeRole:
+ return item.dateTime;
+ case DateRole:
+ return item.dateTime.date();
+ case UrlRole:
+ return QUrl(item.url);
+ case UrlStringRole:
+ return item.url;
+ case Qt::DisplayRole:
+ case Qt::EditRole:
+ {
+ switch (index.column())
+ {
+ case 0:
+ // when there is no title try to generate one from the url
+ if (item.title.isEmpty())
+ {
+ QString page = QFileInfo(QUrl(item.url).path()).fileName();
+ if (!page.isEmpty())
+ return page;
+ return item.url;
+ }
+ return item.title;
+ case 1:
+ return item.url;
+ }
+ }
+ case Qt::DecorationRole:
+ if (index.column() == 0)
+ {
+ return Application::instance()->icon(item.url);
+ }
+ }
+ return QVariant();
+}
+
+
+int HistoryModel::columnCount(const QModelIndex &parent) const
+{
+ return (parent.isValid()) ? 0 : 2;
+}
+
+
+int HistoryModel::rowCount(const QModelIndex &parent) const
+{
+ return (parent.isValid()) ? 0 : m_history->history().count();
+}
+
+
+bool HistoryModel::removeRows(int row, int count, const QModelIndex &parent)
+{
+ if (parent.isValid())
+ return false;
+ int lastRow = row + count - 1;
+ beginRemoveRows(parent, row, lastRow);
+ QList<HistoryItem> lst = m_history->history();
+ for (int i = lastRow; i >= row; --i)
+ lst.removeAt(i);
+ disconnect(m_history, SIGNAL(historyReset()), this, SLOT(historyReset()));
+ m_history->setHistory(lst);
+ connect(m_history, SIGNAL(historyReset()), this, SLOT(historyReset()));
+ endRemoveRows();
+ return true;
+}
+
+
+
+// -----------------------------------------------------------------------------------------------
+
+
+#define MOVEDROWS 10
+
+
+/*
+ Maps the first bunch of items of the source model to the root
+*/
+HistoryMenuModel::HistoryMenuModel(HistoryTreeModel *sourceModel, QObject *parent)
+ : QAbstractProxyModel(parent)
+ , m_treeModel(sourceModel)
+{
+ setSourceModel(sourceModel);
+}
+
+
+int HistoryMenuModel::bumpedRows() const
+{
+ QModelIndex first = m_treeModel->index(0, 0);
+ if (!first.isValid())
+ return 0;
+ return qMin(m_treeModel->rowCount(first), MOVEDROWS);
+}
+
+
+int HistoryMenuModel::columnCount(const QModelIndex &parent) const
+{
+ return m_treeModel->columnCount(mapToSource(parent));
+}
+
+
+int HistoryMenuModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.column() > 0)
+ return 0;
+
+ if (!parent.isValid())
+ {
+ int folders = sourceModel()->rowCount();
+ int bumpedItems = bumpedRows();
+ if (bumpedItems <= MOVEDROWS
+ && bumpedItems == sourceModel()->rowCount(sourceModel()->index(0, 0)))
+ --folders;
+ return bumpedItems + folders;
+ }
+
+ if (parent.internalId() == -1)
+ {
+ if (parent.row() < bumpedRows())
+ return 0;
+ }
+
+ QModelIndex idx = mapToSource(parent);
+ int defaultCount = sourceModel()->rowCount(idx);
+ if (idx == sourceModel()->index(0, 0))
+ return defaultCount - bumpedRows();
+ return defaultCount;
+}
+
+
+QModelIndex HistoryMenuModel::mapFromSource(const QModelIndex &sourceIndex) const
+{
+ // currently not used or autotested
+ Q_ASSERT(false);
+ int sr = m_treeModel->mapToSource(sourceIndex).row();
+ return createIndex(sourceIndex.row(), sourceIndex.column(), sr);
+}
+
+
+QModelIndex HistoryMenuModel::mapToSource(const QModelIndex &proxyIndex) const
+{
+ if (!proxyIndex.isValid())
+ return QModelIndex();
+
+ if (proxyIndex.internalId() == -1)
+ {
+ int bumpedItems = bumpedRows();
+ if (proxyIndex.row() < bumpedItems)
+ return m_treeModel->index(proxyIndex.row(), proxyIndex.column(), m_treeModel->index(0, 0));
+ if (bumpedItems <= MOVEDROWS && bumpedItems == sourceModel()->rowCount(m_treeModel->index(0, 0)))
+ --bumpedItems;
+ return m_treeModel->index(proxyIndex.row() - bumpedItems, proxyIndex.column());
+ }
+
+ QModelIndex historyIndex = m_treeModel->sourceModel()->index(proxyIndex.internalId(), proxyIndex.column());
+ QModelIndex treeIndex = m_treeModel->mapFromSource(historyIndex);
+ return treeIndex;
+}
+
+
+QModelIndex HistoryMenuModel::index(int row, int column, const QModelIndex &parent) const
+{
+ if (row < 0
+ || column < 0 || column >= columnCount(parent)
+ || parent.column() > 0)
+ return QModelIndex();
+ if (!parent.isValid())
+ return createIndex(row, column, -1);
+
+ QModelIndex treeIndexParent = mapToSource(parent);
+
+ int bumpedItems = 0;
+ if (treeIndexParent == m_treeModel->index(0, 0))
+ bumpedItems = bumpedRows();
+ QModelIndex treeIndex = m_treeModel->index(row + bumpedItems, column, treeIndexParent);
+ QModelIndex historyIndex = m_treeModel->mapToSource(treeIndex);
+ int historyRow = historyIndex.row();
+ if (historyRow == -1)
+ historyRow = treeIndex.row();
+ return createIndex(row, column, historyRow);
+}
+
+
+QModelIndex HistoryMenuModel::parent(const QModelIndex &index) const
+{
+ int offset = index.internalId();
+ if (offset == -1 || !index.isValid())
+ return QModelIndex();
+
+ QModelIndex historyIndex = m_treeModel->sourceModel()->index(index.internalId(), 0);
+ QModelIndex treeIndex = m_treeModel->mapFromSource(historyIndex);
+ QModelIndex treeIndexParent = treeIndex.parent();
+
+ int sr = m_treeModel->mapToSource(treeIndexParent).row();
+ int bumpedItems = bumpedRows();
+ if (bumpedItems <= MOVEDROWS && bumpedItems == sourceModel()->rowCount(sourceModel()->index(0, 0)))
+ --bumpedItems;
+ return createIndex(bumpedItems + treeIndexParent.row(), treeIndexParent.column(), sr);
+}
+
+
+// -------------------------------------------------------------------------------------------------------------
+
+
+HistoryMenu::HistoryMenu(QWidget *parent)
+ : ModelMenu(parent)
+ , m_history(0)
+{
+ connect(this, SIGNAL(activated(const QModelIndex &)), this, SLOT(activated(const QModelIndex &)));
+ setHoverRole(HistoryModel::UrlStringRole);
+}
+
+
+void HistoryMenu::activated(const QModelIndex &index)
+{
+ emit openUrl(index.data(HistoryModel::UrlRole).toUrl());
+}
+
+
+bool HistoryMenu::prePopulated()
+{
+ if (!m_history)
+ {
+ m_history = Application::historyManager();
+ m_historyMenuModel = new HistoryMenuModel(m_history->historyTreeModel(), this);
+ setModel(m_historyMenuModel);
+ }
+ // initial actions
+ for (int i = 0; i < m_initialActions.count(); ++i)
+ addAction(m_initialActions.at(i));
+ if (!m_initialActions.isEmpty())
+ addSeparator();
+ setFirstSeparator(m_historyMenuModel->bumpedRows());
+
+ return false;
+}
+
+
+void HistoryMenu::postPopulated()
+{
+ if (m_history->history().count() > 0)
+ addSeparator();
+
+ KAction *showAllAction = new KAction(i18n("Show All History"), this);
+ connect(showAllAction, SIGNAL(triggered()), this, SLOT(showHistoryDialog()));
+ addAction(showAllAction);
+
+ KAction *clearAction = new KAction(i18n("Clear History"), this);
+ connect(clearAction, SIGNAL(triggered()), m_history, SLOT(clear()));
+ addAction(clearAction);
+}
+
+
+void HistoryMenu::showHistoryDialog()
+{
+ HistoryDialog *dialog = new HistoryDialog(this);
+ connect(dialog, SIGNAL(openUrl(const KUrl&)), this, SIGNAL(openUrl(const KUrl&)));
+ dialog->show();
+}
+
+
+void HistoryMenu::setInitialActions(QList<QAction*> actions)
+{
+ m_initialActions = actions;
+ for (int i = 0; i < m_initialActions.count(); ++i)
+ addAction(m_initialActions.at(i));
+}
+
+
+// --------------------------------------------------------------------------------------------------------------
+
+
+TreeProxyModel::TreeProxyModel(QObject *parent) : QSortFilterProxyModel(parent)
+{
+ setSortRole(HistoryModel::DateTimeRole);
+ setFilterCaseSensitivity(Qt::CaseInsensitive);
+}
+
+
+bool TreeProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
+{
+ if (!source_parent.isValid())
+ return true;
+ return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
+}
+
+
+// -----------------------------------------------------------------------------------------------------
+
+
+HistoryDialog::HistoryDialog(QWidget *parent, HistoryManager *setHistory) : QDialog(parent)
+{
+ HistoryManager *history = setHistory;
+ if (!history)
+ history = Application::historyManager();
+ setupUi(this);
+ tree->setUniformRowHeights(true);
+ tree->setSelectionBehavior(QAbstractItemView::SelectRows);
+ tree->setTextElideMode(Qt::ElideMiddle);
+ QAbstractItemModel *model = history->historyTreeModel();
+ TreeProxyModel *proxyModel = new TreeProxyModel(this);
+ connect(search, SIGNAL(textChanged(QString)),
+ proxyModel, SLOT(setFilterFixedString(QString)));
+ connect(removeButton, SIGNAL(clicked()), tree, SLOT(removeOne()));
+ connect(removeAllButton, SIGNAL(clicked()), history, SLOT(clear()));
+ proxyModel->setSourceModel(model);
+ tree->setModel(proxyModel);
+ tree->setExpanded(proxyModel->index(0, 0), true);
+ tree->setAlternatingRowColors(true);
+ QFontMetrics fm(font());
+ int header = fm.width(QLatin1Char('m')) * 40;
+ tree->header()->resizeSection(0, header);
+ tree->header()->setStretchLastSection(true);
+ connect(tree, SIGNAL(activated(const QModelIndex&)),
+ this, SLOT(open()));
+ tree->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(tree, SIGNAL(customContextMenuRequested(const QPoint &)),
+ this, SLOT(customContextMenuRequested(const QPoint &)));
+}
+
+
+void HistoryDialog::customContextMenuRequested(const QPoint &pos)
+{
+ QMenu menu;
+ QModelIndex index = tree->indexAt(pos);
+ index = index.sibling(index.row(), 0);
+ if (index.isValid() && !tree->model()->hasChildren(index))
+ {
+ menu.addAction(i18n("Open"), this, SLOT(open()));
+ menu.addSeparator();
+ menu.addAction(i18n("Copy"), this, SLOT(copy()));
+ }
+ menu.addAction(i18n("Delete"), tree, SLOT(removeOne()));
+ menu.exec(QCursor::pos());
+}
+
+
+void HistoryDialog::open()
+{
+ QModelIndex index = tree->currentIndex();
+ if (!index.parent().isValid())
+ return;
+ emit openUrl(index.data(HistoryModel::UrlRole).toUrl());
+}
+
+
+void HistoryDialog::copy()
+{
+ QModelIndex index = tree->currentIndex();
+ if (!index.parent().isValid())
+ return;
+ QString url = index.data(HistoryModel::UrlStringRole).toString();
+
+ QClipboard *clipboard = QApplication::clipboard();
+ clipboard->setText(url);
+}
+
+
+// ---------------------------------------------------------------------------------------------------------------
+
+HistoryFilterModel::HistoryFilterModel(QAbstractItemModel *sourceModel, QObject *parent)
+ : QAbstractProxyModel(parent),
+ m_loaded(false)
+{
+ setSourceModel(sourceModel);
+}
+
+
+int HistoryFilterModel::historyLocation(const QString &url) const
+{
+ load();
+ if (!m_historyHash.contains(url))
+ return 0;
+ return sourceModel()->rowCount() - m_historyHash.value(url);
+}
+
+
+QVariant HistoryFilterModel::data(const QModelIndex &index, int role) const
+{
+ return QAbstractProxyModel::data(index, role);
+}
+
+
+void HistoryFilterModel::setSourceModel(QAbstractItemModel *newSourceModel)
+{
+ if (sourceModel())
+ {
+ disconnect(sourceModel(), SIGNAL(modelReset()), this, SLOT(sourceReset()));
+ disconnect(sourceModel(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
+ this, SLOT(dataChanged(const QModelIndex &, const QModelIndex &)));
+ disconnect(sourceModel(), SIGNAL(rowsInserted(const QModelIndex &, int, int)),
+ this, SLOT(sourceRowsInserted(const QModelIndex &, int, int)));
+ disconnect(sourceModel(), SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
+ this, SLOT(sourceRowsRemoved(const QModelIndex &, int, int)));
+ }
+
+ QAbstractProxyModel::setSourceModel(newSourceModel);
+
+ if (sourceModel())
+ {
+ m_loaded = false;
+ connect(sourceModel(), SIGNAL(modelReset()), this, SLOT(sourceReset()));
+ connect(sourceModel(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
+ this, SLOT(sourceDataChanged(const QModelIndex &, const QModelIndex &)));
+ connect(sourceModel(), SIGNAL(rowsInserted(const QModelIndex &, int, int)),
+ this, SLOT(sourceRowsInserted(const QModelIndex &, int, int)));
+ connect(sourceModel(), SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
+ this, SLOT(sourceRowsRemoved(const QModelIndex &, int, int)));
+ }
+}
+
+
+void HistoryFilterModel::sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
+{
+ emit dataChanged(mapFromSource(topLeft), mapFromSource(bottomRight));
+}
+
+
+QVariant HistoryFilterModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ return sourceModel()->headerData(section, orientation, role);
+}
+
+
+void HistoryFilterModel::sourceReset()
+{
+ m_loaded = false;
+ reset();
+}
+
+
+int HistoryFilterModel::rowCount(const QModelIndex &parent) const
+{
+ load();
+ if (parent.isValid())
+ return 0;
+ return m_historyHash.count();
+}
+
+
+int HistoryFilterModel::columnCount(const QModelIndex &parent) const
+{
+ return (parent.isValid()) ? 0 : 2;
+}
+
+
+QModelIndex HistoryFilterModel::mapToSource(const QModelIndex &proxyIndex) const
+{
+ load();
+ int sourceRow = sourceModel()->rowCount() - proxyIndex.internalId();
+ return sourceModel()->index(sourceRow, proxyIndex.column());
+}
+
+
+QModelIndex HistoryFilterModel::mapFromSource(const QModelIndex &sourceIndex) const
+{
+ load();
+ QString url = sourceIndex.data(HistoryModel::UrlStringRole).toString();
+ if (!m_historyHash.contains(url))
+ return QModelIndex();
+
+ // This can be done in a binary search, but we can't use qBinary find
+ // because it can't take: qBinaryFind(m_sourceRow.end(), m_sourceRow.begin(), v);
+ // so if this is a performance bottlneck then convert to binary search, until then
+ // the cleaner/easier to read code wins the day.
+ int realRow = -1;
+ int sourceModelRow = sourceModel()->rowCount() - sourceIndex.row();
+
+ for (int i = 0; i < m_sourceRow.count(); ++i)
+ {
+ if (m_sourceRow.at(i) == sourceModelRow)
+ {
+ realRow = i;
+ break;
+ }
+ }
+ if (realRow == -1)
+ return QModelIndex();
+
+ return createIndex(realRow, sourceIndex.column(), sourceModel()->rowCount() - sourceIndex.row());
+}
+
+
+QModelIndex HistoryFilterModel::index(int row, int column, const QModelIndex &parent) const
+{
+ load();
+ if (row < 0 || row >= rowCount(parent)
+ || column < 0 || column >= columnCount(parent))
+ return QModelIndex();
+
+ return createIndex(row, column, m_sourceRow[row]);
+}
+
+
+QModelIndex HistoryFilterModel::parent(const QModelIndex &) const
+{
+ return QModelIndex();
+}
+
+
+void HistoryFilterModel::load() const
+{
+ if (m_loaded)
+ return;
+ m_sourceRow.clear();
+ m_historyHash.clear();
+ m_historyHash.reserve(sourceModel()->rowCount());
+ for (int i = 0; i < sourceModel()->rowCount(); ++i)
+ {
+ QModelIndex idx = sourceModel()->index(i, 0);
+ QString url = idx.data(HistoryModel::UrlStringRole).toString();
+ if (!m_historyHash.contains(url))
+ {
+ m_sourceRow.append(sourceModel()->rowCount() - i);
+ m_historyHash[url] = sourceModel()->rowCount() - i;
+ }
+ }
+ m_loaded = true;
+}
+
+
+void HistoryFilterModel::sourceRowsInserted(const QModelIndex &parent, int start, int end)
+{
+ Q_ASSERT(start == end && start == 0);
+ Q_UNUSED(end);
+ if (!m_loaded)
+ return;
+ QModelIndex idx = sourceModel()->index(start, 0, parent);
+ QString url = idx.data(HistoryModel::UrlStringRole).toString();
+ if (m_historyHash.contains(url))
+ {
+ int sourceRow = sourceModel()->rowCount() - m_historyHash[url];
+ int realRow = mapFromSource(sourceModel()->index(sourceRow, 0)).row();
+ beginRemoveRows(QModelIndex(), realRow, realRow);
+ m_sourceRow.removeAt(realRow);
+ m_historyHash.remove(url);
+ endRemoveRows();
+ }
+ beginInsertRows(QModelIndex(), 0, 0);
+ m_historyHash.insert(url, sourceModel()->rowCount() - start);
+ m_sourceRow.insert(0, sourceModel()->rowCount());
+ endInsertRows();
+}
+
+
+void HistoryFilterModel::sourceRowsRemoved(const QModelIndex &, int start, int end)
+{
+ Q_UNUSED(start);
+ Q_UNUSED(end);
+ sourceReset();
+}
+
+
+/*
+ Removing a continuous block of rows will remove filtered rows too as this is
+ the users intention.
+*/
+bool HistoryFilterModel::removeRows(int row, int count, const QModelIndex &parent)
+{
+ if (row < 0 || count <= 0 || row + count > rowCount(parent) || parent.isValid())
+ return false;
+ int lastRow = row + count - 1;
+ disconnect(sourceModel(), SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
+ this, SLOT(sourceRowsRemoved(const QModelIndex &, int, int)));
+ beginRemoveRows(parent, row, lastRow);
+ int oldCount = rowCount();
+ int start = sourceModel()->rowCount() - m_sourceRow.value(row);
+ int end = sourceModel()->rowCount() - m_sourceRow.value(lastRow);
+ sourceModel()->removeRows(start, end - start + 1);
+ endRemoveRows();
+ connect(sourceModel(), SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
+ this, SLOT(sourceRowsRemoved(const QModelIndex &, int, int)));
+ m_loaded = false;
+ if (oldCount - count != rowCount())
+ reset();
+ return true;
+}
+
+
+// ------------------------------------------------------------------------------------------------------
+
+
+HistoryCompletionModel::HistoryCompletionModel(QObject *parent)
+ : QAbstractProxyModel(parent)
+{
+}
+
+
+QVariant HistoryCompletionModel::data(const QModelIndex &index, int role) const
+{
+ if (sourceModel()
+ && (role == Qt::EditRole || role == Qt::DisplayRole)
+ && index.isValid())
+ {
+ QModelIndex idx = mapToSource(index);
+ idx = idx.sibling(idx.row(), 1);
+ QString urlString = idx.data(HistoryModel::UrlStringRole).toString();
+ if (index.row() % 2)
+ {
+ QUrl url = urlString;
+ QString s = url.toString(QUrl::RemoveScheme
+ | QUrl::RemoveUserInfo
+ | QUrl::StripTrailingSlash);
+ return s.mid(2); // strip // from the front
+ }
+ return urlString;
+ }
+ return QAbstractProxyModel::data(index, role);
+}
+
+
+int HistoryCompletionModel::rowCount(const QModelIndex &parent) const
+{
+ return (parent.isValid() || !sourceModel()) ? 0 : sourceModel()->rowCount(parent) * 2;
+}
+
+
+int HistoryCompletionModel::columnCount(const QModelIndex &parent) const
+{
+ return (parent.isValid()) ? 0 : 1;
+}
+
+
+QModelIndex HistoryCompletionModel::mapFromSource(const QModelIndex &sourceIndex) const
+{
+ int row = sourceIndex.row() * 2;
+ return index(row, sourceIndex.column());
+}
+
+
+QModelIndex HistoryCompletionModel::mapToSource(const QModelIndex &proxyIndex) const
+{
+ if (!sourceModel())
+ return QModelIndex();
+ int row = proxyIndex.row() / 2;
+ return sourceModel()->index(row, proxyIndex.column());
+}
+
+
+QModelIndex HistoryCompletionModel::index(int row, int column, const QModelIndex &parent) const
+{
+ if (row < 0 || row >= rowCount(parent)
+ || column < 0 || column >= columnCount(parent))
+ return QModelIndex();
+ return createIndex(row, column, 0);
+}
+
+
+QModelIndex HistoryCompletionModel::parent(const QModelIndex &) const
+{
+ return QModelIndex();
+}
+
+
+void HistoryCompletionModel::setSourceModel(QAbstractItemModel *newSourceModel)
+{
+ if (sourceModel())
+ {
+ disconnect(sourceModel(), SIGNAL(modelReset()), this, SLOT(sourceReset()));
+ disconnect(sourceModel(), SIGNAL(rowsInserted(const QModelIndex &, int, int)),
+ this, SLOT(sourceReset()));
+ disconnect(sourceModel(), SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
+ this, SLOT(sourceReset()));
+ }
+
+ QAbstractProxyModel::setSourceModel(newSourceModel);
+
+ if (newSourceModel)
+ {
+ connect(newSourceModel, SIGNAL(modelReset()), this, SLOT(sourceReset()));
+ connect(sourceModel(), SIGNAL(rowsInserted(const QModelIndex &, int, int)),
+ this, SLOT(sourceReset()));
+ connect(sourceModel(), SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
+ this, SLOT(sourceReset()));
+ }
+
+ reset();
+}
+
+
+void HistoryCompletionModel::sourceReset()
+{
+ reset();
+}
+
+
+// ------------------------------------------------------------------------------------------------------
+
+
+HistoryTreeModel::HistoryTreeModel(QAbstractItemModel *sourceModel, QObject *parent)
+ : QAbstractProxyModel(parent)
+{
+ setSourceModel(sourceModel);
+}
+
+
+QVariant HistoryTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ return sourceModel()->headerData(section, orientation, role);
+}
+
+
+QVariant HistoryTreeModel::data(const QModelIndex &index, int role) const
+{
+ if ((role == Qt::EditRole || role == Qt::DisplayRole))
+ {
+ int start = index.internalId();
+ if (start == 0)
+ {
+ int offset = sourceDateRow(index.row());
+ if (index.column() == 0)
+ {
+ QModelIndex idx = sourceModel()->index(offset, 0);
+ QDate date = idx.data(HistoryModel::DateRole).toDate();
+ if (date == QDate::currentDate())
+ return i18n("Earlier Today");
+ return date.toString(QLatin1String("dddd, MMMM d, yyyy"));
+ }
+ if (index.column() == 1)
+ {
+ return i18np("1 item", "%1 items", rowCount(index.sibling(index.row(), 0)));
+ }
+ }
+ }
+ if (role == Qt::DecorationRole && index.column() == 0 && !index.parent().isValid())
+ return KIcon("view-history");
+ if (role == HistoryModel::DateRole && index.column() == 0 && index.internalId() == 0)
+ {
+ int offset = sourceDateRow(index.row());
+ QModelIndex idx = sourceModel()->index(offset, 0);
+ return idx.data(HistoryModel::DateRole);
+ }
+
+ return QAbstractProxyModel::data(index, role);
+}
+
+
+int HistoryTreeModel::columnCount(const QModelIndex &parent) const
+{
+ return sourceModel()->columnCount(mapToSource(parent));
+}
+
+
+int HistoryTreeModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.internalId() != 0
+ || parent.column() > 0
+ || !sourceModel())
+ return 0;
+
+ // row count OF dates
+ if (!parent.isValid())
+ {
+ if (!m_sourceRowCache.isEmpty())
+ return m_sourceRowCache.count();
+ QDate currentDate;
+ int rows = 0;
+ int totalRows = sourceModel()->rowCount();
+
+ for (int i = 0; i < totalRows; ++i)
+ {
+ QDate rowDate = sourceModel()->index(i, 0).data(HistoryModel::DateRole).toDate();
+ if (rowDate != currentDate)
+ {
+ m_sourceRowCache.append(i);
+ currentDate = rowDate;
+ ++rows;
+ }
+ }
+ Q_ASSERT(m_sourceRowCache.count() == rows);
+ return rows;
+ }
+
+ // row count FOR a date
+ int start = sourceDateRow(parent.row());
+ int end = sourceDateRow(parent.row() + 1);
+ return (end - start);
+}
+
+
+// Translate the top level date row into the offset where that date starts
+int HistoryTreeModel::sourceDateRow(int row) const
+{
+ if (row <= 0)
+ return 0;
+
+ if (m_sourceRowCache.isEmpty())
+ rowCount(QModelIndex());
+
+ if (row >= m_sourceRowCache.count())
+ {
+ if (!sourceModel())
+ return 0;
+ return sourceModel()->rowCount();
+ }
+ return m_sourceRowCache.at(row);
+}
+
+
+QModelIndex HistoryTreeModel::mapToSource(const QModelIndex &proxyIndex) const
+{
+ int offset = proxyIndex.internalId();
+ if (offset == 0)
+ return QModelIndex();
+ int startDateRow = sourceDateRow(offset - 1);
+ return sourceModel()->index(startDateRow + proxyIndex.row(), proxyIndex.column());
+}
+
+
+QModelIndex HistoryTreeModel::index(int row, int column, const QModelIndex &parent) const
+{
+ if (row < 0
+ || column < 0 || column >= columnCount(parent)
+ || parent.column() > 0)
+ return QModelIndex();
+
+ if (!parent.isValid())
+ return createIndex(row, column, 0);
+ return createIndex(row, column, parent.row() + 1);
+}
+
+
+QModelIndex HistoryTreeModel::parent(const QModelIndex &index) const
+{
+ int offset = index.internalId();
+ if (offset == 0 || !index.isValid())
+ return QModelIndex();
+ return createIndex(offset - 1, 0, 0);
+}
+
+
+bool HistoryTreeModel::hasChildren(const QModelIndex &parent) const
+{
+ QModelIndex grandparent = parent.parent();
+ if (!grandparent.isValid())
+ return true;
+ return false;
+}
+
+
+Qt::ItemFlags HistoryTreeModel::flags(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return Qt::NoItemFlags;
+ return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled;
+}
+
+
+bool HistoryTreeModel::removeRows(int row, int count, const QModelIndex &parent)
+{
+ if (row < 0 || count <= 0 || row + count > rowCount(parent))
+ return false;
+
+ if (parent.isValid())
+ {
+ // removing pages
+ int offset = sourceDateRow(parent.row());
+ return sourceModel()->removeRows(offset + row, count);
+ }
+ else
+ {
+ // removing whole dates
+ for (int i = row + count - 1; i >= row; --i)
+ {
+ QModelIndex dateParent = index(i, 0);
+ int offset = sourceDateRow(dateParent.row());
+ if (!sourceModel()->removeRows(offset, rowCount(dateParent)))
+ return false;
+ }
+ }
+ return true;
+}
+
+
+void HistoryTreeModel::setSourceModel(QAbstractItemModel *newSourceModel)
+{
+ if (sourceModel())
+ {
+ disconnect(sourceModel(), SIGNAL(modelReset()), this, SLOT(sourceReset()));
+ disconnect(sourceModel(), SIGNAL(layoutChanged()), this, SLOT(sourceReset()));
+ disconnect(sourceModel(), SIGNAL(rowsInserted(const QModelIndex &, int, int)),
+ this, SLOT(sourceRowsInserted(const QModelIndex &, int, int)));
+ disconnect(sourceModel(), SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
+ this, SLOT(sourceRowsRemoved(const QModelIndex &, int, int)));
+ }
+
+ QAbstractProxyModel::setSourceModel(newSourceModel);
+
+ if (newSourceModel)
+ {
+ connect(sourceModel(), SIGNAL(modelReset()), this, SLOT(sourceReset()));
+ connect(sourceModel(), SIGNAL(layoutChanged()), this, SLOT(sourceReset()));
+ connect(sourceModel(), SIGNAL(rowsInserted(const QModelIndex &, int, int)),
+ this, SLOT(sourceRowsInserted(const QModelIndex &, int, int)));
+ connect(sourceModel(), SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
+ this, SLOT(sourceRowsRemoved(const QModelIndex &, int, int)));
+ }
+
+ reset();
+}
+
+
+void HistoryTreeModel::sourceReset()
+{
+ m_sourceRowCache.clear();
+ reset();
+}
+
+
+void HistoryTreeModel::sourceRowsInserted(const QModelIndex &parent, int start, int end)
+{
+ Q_UNUSED(parent); // Avoid warnings when compiling release
+ Q_ASSERT(!parent.isValid());
+ if (start != 0 || start != end)
+ {
+ m_sourceRowCache.clear();
+ reset();
+ return;
+ }
+
+ m_sourceRowCache.clear();
+ QModelIndex treeIndex = mapFromSource(sourceModel()->index(start, 0));
+ QModelIndex treeParent = treeIndex.parent();
+ if (rowCount(treeParent) == 1)
+ {
+ beginInsertRows(QModelIndex(), 0, 0);
+ endInsertRows();
+ }
+ else
+ {
+ beginInsertRows(treeParent, treeIndex.row(), treeIndex.row());
+ endInsertRows();
+ }
+}
+
+
+QModelIndex HistoryTreeModel::mapFromSource(const QModelIndex &sourceIndex) const
+{
+ if (!sourceIndex.isValid())
+ return QModelIndex();
+
+ if (m_sourceRowCache.isEmpty())
+ rowCount(QModelIndex());
+
+ QList<int>::iterator it;
+ it = qLowerBound(m_sourceRowCache.begin(), m_sourceRowCache.end(), sourceIndex.row());
+ if (*it != sourceIndex.row())
+ --it;
+
+ int dateRow = qMax(0, it - m_sourceRowCache.begin());
+ // FIXME fix crach on history submenu open. BUG:'ASSERT failure in QList<T>::at: "index out of range"'
+ // it crashes when dateRow == 1
+ // kDebug() << m_sourceRowCache << dateRow;
+ int row = sourceIndex.row() - m_sourceRowCache.at(dateRow);
+ return createIndex(row, sourceIndex.column(), dateRow + 1);
+}
+
+
+void HistoryTreeModel::sourceRowsRemoved(const QModelIndex &parent, int start, int end)
+{
+ Q_UNUSED(parent); // Avoid warnings when compiling release
+ Q_ASSERT(!parent.isValid());
+ if (m_sourceRowCache.isEmpty())
+ return;
+ for (int i = end; i >= start;)
+ {
+ QList<int>::iterator it;
+ it = qLowerBound(m_sourceRowCache.begin(), m_sourceRowCache.end(), i);
+ // playing it safe
+ if (it == m_sourceRowCache.end())
+ {
+ m_sourceRowCache.clear();
+ reset();
+ return;
+ }
+
+ if (*it != i)
+ --it;
+ int row = qMax(0, it - m_sourceRowCache.begin());
+ int offset = m_sourceRowCache[row];
+ QModelIndex dateParent = index(row, 0);
+ // If we can remove all the rows in the date do that and skip over them
+ int rc = rowCount(dateParent);
+ if (i - rc + 1 == offset && start <= i - rc + 1)
+ {
+ beginRemoveRows(QModelIndex(), row, row);
+ m_sourceRowCache.removeAt(row);
+ i -= rc + 1;
+ }
+ else
+ {
+ beginRemoveRows(dateParent, i - offset, i - offset);
+ ++row;
+ --i;
+ }
+ for (int j = row; j < m_sourceRowCache.count(); ++j)
+ --m_sourceRowCache[j];
+ endRemoveRows();
+ }
+}
diff --git a/src/history.h b/src/history.h
new file mode 100644
index 00000000..ecae00c3
--- /dev/null
+++ b/src/history.h
@@ -0,0 +1,402 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007-2008 Trolltech ASA. All rights reserved
+* Copyright (C) 2008 Benjamin C. Meyer <ben@meyerhome.net>
+* Copyright (C) 2008-2009 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+#ifndef HISTORY_H
+#define HISTORY_H
+
+// Local Includes
+#include "modelmenu.h"
+
+// KDE Includes
+#include <KAction>
+#include <KUrl>
+
+// Qt Includes
+#include <QDateTime>
+#include <QHash>
+#include <QObject>
+#include <QTimer>
+#include <QSortFilterProxyModel>
+#include <QWebHistoryInterface>
+
+
+/**
+ * Elements in this class represent an history item
+ *
+ */
+
+class HistoryItem
+{
+public:
+ HistoryItem() {}
+ HistoryItem(const QString &u,
+ const QDateTime &d = QDateTime(), const QString &t = QString())
+ : title(t), url(u), dateTime(d) {}
+
+ inline bool operator==(const HistoryItem &other) const
+ {
+ return other.title == title
+ && other.url == url && other.dateTime == dateTime;
+ }
+
+ // history is sorted in reverse
+ inline bool operator <(const HistoryItem &other) const
+ {
+ return dateTime > other.dateTime;
+ }
+
+ QString title;
+ QString url;
+ QDateTime dateTime;
+};
+
+
+
+// ---------------------------------------------------------------------------------------------------------------
+
+
+class AutoSaver;
+class HistoryModel;
+class HistoryFilterModel;
+class HistoryTreeModel;
+
+
+class HistoryManager : public QWebHistoryInterface
+{
+ Q_OBJECT
+ Q_PROPERTY(int historyLimit READ historyLimit WRITE setHistoryLimit)
+
+signals:
+ void historyReset();
+ void entryAdded(const HistoryItem &item);
+ void entryRemoved(const HistoryItem &item);
+ void entryUpdated(int offset);
+
+public:
+ HistoryManager(QObject *parent = 0);
+ ~HistoryManager();
+
+ bool historyContains(const QString &url) const;
+ void addHistoryEntry(const QString &url);
+ void updateHistoryEntry(const KUrl &url, const QString &title);
+ void removeHistoryEntry(const KUrl &url, const QString &title = QString());
+
+ int historyLimit() const;
+ void setHistoryLimit(int limit);
+
+ QList<HistoryItem> history() const;
+ void setHistory(const QList<HistoryItem> &history, bool loadedAndSorted = false);
+
+ // History manager keeps around these models for use by the completer and other classes
+ HistoryModel *historyModel() const;
+ HistoryFilterModel *historyFilterModel() const;
+ HistoryTreeModel *historyTreeModel() const;
+
+public slots:
+ void clear();
+ void loadSettings();
+
+private slots:
+ void save();
+ void checkForExpired();
+
+protected:
+ void addHistoryEntry(const HistoryItem &item);
+ void removeHistoryEntry(const HistoryItem &item);
+
+private:
+ void load();
+
+ AutoSaver *m_saveTimer;
+ int m_historyLimit;
+ QTimer m_expiredTimer;
+ QList<HistoryItem> m_history;
+ QString m_lastSavedUrl;
+
+ HistoryModel *m_historyModel;
+ HistoryFilterModel *m_historyFilterModel;
+ HistoryTreeModel *m_historyTreeModel;
+};
+
+
+// --------------------------------------------------------------------------------------------------------
+
+
+class HistoryModel : public QAbstractTableModel
+{
+ Q_OBJECT
+
+public slots:
+ void historyReset();
+ void entryAdded();
+ void entryUpdated(int offset);
+
+public:
+ enum Roles
+ {
+ DateRole = Qt::UserRole + 1,
+ DateTimeRole = Qt::UserRole + 2,
+ UrlRole = Qt::UserRole + 3,
+ UrlStringRole = Qt::UserRole + 4
+ };
+
+ HistoryModel(HistoryManager *history, QObject *parent = 0);
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
+
+private:
+ HistoryManager *m_history;
+};
+
+
+// ----------------------------------------------------------------------------------------------------
+
+/**
+ * Proxy model that will remove any duplicate entries.
+ * Both m_sourceRow and m_historyHash store their offsets not from
+ * the front of the list, but as offsets from the back.
+ *
+ */
+
+class HistoryFilterModel : public QAbstractProxyModel
+{
+ Q_OBJECT
+
+public:
+ HistoryFilterModel(QAbstractItemModel *sourceModel, QObject *parent = 0);
+
+ inline bool historyContains(const QString &url) const
+ {
+ load(); return m_historyHash.contains(url);
+ }
+ int historyLocation(const QString &url) const;
+
+ QModelIndex mapFromSource(const QModelIndex &sourceIndex) const;
+ QModelIndex mapToSource(const QModelIndex &proxyIndex) const;
+ void setSourceModel(QAbstractItemModel *sourceModel);
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
+ QModelIndex index(int, int, const QModelIndex& = QModelIndex()) const;
+ QModelIndex parent(const QModelIndex& index = QModelIndex()) const;
+ bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+
+private slots:
+ void sourceReset();
+ void sourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
+ void sourceRowsInserted(const QModelIndex &parent, int start, int end);
+ void sourceRowsRemoved(const QModelIndex &, int, int);
+
+private:
+ void load() const;
+
+ mutable QList<int> m_sourceRow;
+ mutable QHash<QString, int> m_historyHash;
+ mutable bool m_loaded;
+};
+
+
+// ----------------------------------------------------------------------------------------------------------------------
+
+/**
+ * The history menu
+ * - Removes the first twenty entries and puts them as children of the top level.
+ * - If there are less then twenty entries then the first folder is also removed.
+ *
+ * The mapping is done by knowing that HistoryTreeModel is over a table
+ * We store that row offset in our index's private data.
+ *
+ */
+
+class HistoryMenuModel : public QAbstractProxyModel
+{
+ Q_OBJECT
+
+public:
+ HistoryMenuModel(HistoryTreeModel *sourceModel, QObject *parent = 0);
+ int columnCount(const QModelIndex &parent) const;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ QModelIndex mapFromSource(const QModelIndex & sourceIndex) const;
+ QModelIndex mapToSource(const QModelIndex & proxyIndex) const;
+ QModelIndex index(int, int, const QModelIndex &parent = QModelIndex()) const;
+ QModelIndex parent(const QModelIndex &index = QModelIndex()) const;
+
+ int bumpedRows() const;
+
+private:
+ HistoryTreeModel *m_treeModel;
+};
+
+
+// ---------------------------------------------------------------------------------------------
+
+/**
+ * Menu that is dynamically populated from the history
+ *
+ */
+
+class HistoryMenu : public ModelMenu
+{
+ Q_OBJECT
+
+signals:
+ void openUrl(const KUrl &url);
+
+public:
+ HistoryMenu(QWidget *parent = 0);
+ void setInitialActions(QList<QAction*> actions);
+
+protected:
+ bool prePopulated();
+ void postPopulated();
+
+private slots:
+ void activated(const QModelIndex &index);
+ void showHistoryDialog();
+
+private:
+ HistoryManager *m_history;
+ HistoryMenuModel *m_historyMenuModel;
+ QList<QAction*> m_initialActions;
+};
+
+
+// ----------------------------------------------------------------------------------------
+
+/**
+ * Proxy model for the history model that
+ * exposes each url http://www.foo.com and
+ * it url starting at the host www.foo.com
+ *
+ */
+
+class HistoryCompletionModel : public QAbstractProxyModel
+{
+ Q_OBJECT
+
+public:
+ HistoryCompletionModel(QObject *parent = 0);
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
+ QModelIndex mapFromSource(const QModelIndex &sourceIndex) const;
+ QModelIndex mapToSource(const QModelIndex &proxyIndex) const;
+ QModelIndex index(int, int, const QModelIndex& = QModelIndex()) const;
+ QModelIndex parent(const QModelIndex& index = QModelIndex()) const;
+ void setSourceModel(QAbstractItemModel *sourceModel);
+
+private slots:
+ void sourceReset();
+
+};
+
+
+// ---------------------------------------------------------------------------------------
+
+/**
+ * Proxy model for the history model that converts the list
+ * into a tree, one top level node per day.
+ * Used in the HistoryDialog.
+ *
+ */
+
+class HistoryTreeModel : public QAbstractProxyModel
+{
+ Q_OBJECT
+
+public:
+ HistoryTreeModel(QAbstractItemModel *sourceModel, QObject *parent = 0);
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ int columnCount(const QModelIndex &parent) const;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ QModelIndex mapFromSource(const QModelIndex &sourceIndex) const;
+ QModelIndex mapToSource(const QModelIndex &proxyIndex) const;
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
+ QModelIndex parent(const QModelIndex &index = QModelIndex()) const;
+ bool hasChildren(const QModelIndex &parent = QModelIndex()) const;
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+ bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
+
+ void setSourceModel(QAbstractItemModel *sourceModel);
+
+private slots:
+ void sourceReset();
+ void sourceRowsInserted(const QModelIndex &parent, int start, int end);
+ void sourceRowsRemoved(const QModelIndex &parent, int start, int end);
+
+private:
+ int sourceDateRow(int row) const;
+ mutable QList<int> m_sourceRowCache;
+
+};
+
+
+// -----------------------------------------------------------------------------------------------------------------
+
+/**
+ * A modified QSortFilterProxyModel that always accepts
+ * the root nodes in the tree
+ * so filtering is only done on the children.
+ * Used in the HistoryDialog.
+ *
+ */
+
+class TreeProxyModel : public QSortFilterProxyModel
+{
+ Q_OBJECT
+
+public:
+ TreeProxyModel(QObject *parent = 0);
+
+protected:
+ bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
+};
+
+
+// ------------------------------------------------------------------------------------------
+
+#include "ui_history.h"
+
+class HistoryDialog : public QDialog, public Ui_HistoryDialog
+{
+ Q_OBJECT
+
+signals:
+ void openUrl(const KUrl &url);
+
+public:
+ HistoryDialog(QWidget *parent = 0, HistoryManager *history = 0);
+
+private slots:
+ void customContextMenuRequested(const QPoint &pos);
+ void open();
+ void copy();
+
+};
+
+#endif // HISTORY_H
+
diff --git a/src/history.ui b/src/history.ui
new file mode 100644
index 00000000..806bc9ad
--- /dev/null
+++ b/src/history.ui
@@ -0,0 +1,101 @@
+<ui version="4.0" >
+ <class>HistoryDialog</class>
+ <widget class="QDialog" name="HistoryDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>758</width>
+ <height>450</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>History</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout" >
+ <item row="0" column="0" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>252</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="1" >
+ <widget class="KLineEdit" name="search" />
+ </item>
+ <item row="1" column="0" colspan="2" >
+ <widget class="EditTreeView" name="tree" />
+ </item>
+ <item row="2" column="0" colspan="2" >
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="QPushButton" name="removeButton" >
+ <property name="text" >
+ <string>&amp;Remove</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="removeAllButton" >
+ <property name="text" >
+ <string>Remove &amp;All</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>EditTreeView</class>
+ <extends>QTreeView</extends>
+ <header>edittreeview.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>HistoryDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>472</x>
+ <y>329</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>461</x>
+ <y>356</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/lineedit.cpp b/src/lineedit.cpp
new file mode 100644
index 00000000..c9df7bfa
--- /dev/null
+++ b/src/lineedit.cpp
@@ -0,0 +1,85 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009 by Paweł Prażak <pawelprazak 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+// Self Includes
+#include "lineedit.h"
+#include "lineedit.moc"
+
+// Qt Includes
+#include <QContextMenuEvent>
+#include <QFocusEvent>
+#include <QKeyEvent>
+
+// KDE Includes
+#include <KDebug>
+
+// Local Includes
+
+LineEdit::LineEdit(QWidget* parent)
+ : KLineEdit(parent)
+{
+ setMinimumWidth(180);
+ setFocusPolicy(Qt::WheelFocus);
+
+ setHandleSignals(true);
+}
+
+
+LineEdit::~LineEdit()
+{
+}
+
+
+void LineEdit::keyPressEvent(QKeyEvent *event)
+{
+ if (event->key() == Qt::Key_Escape)
+ {
+ clearFocus();
+ event->accept();
+ }
+
+ KLineEdit::keyPressEvent(event);
+}
+
+
+void LineEdit::contextMenuEvent(QContextMenuEvent *event)
+{
+ KLineEdit::contextMenuEvent(event);
+}
+
+
+void LineEdit::focusInEvent(QFocusEvent *event)
+{
+ selectAll();
+
+ KLineEdit::focusInEvent(event);
+}
+
+
+void LineEdit::focusOutEvent(QFocusEvent *event)
+{
+ KLineEdit::focusOutEvent(event);
+
+ // reset cursor state and deselect
+ setCursorPosition(0);
+ deselect();
+}
+
+
+
diff --git a/src/lineedit.h b/src/lineedit.h
new file mode 100644
index 00000000..f1bd8f88
--- /dev/null
+++ b/src/lineedit.h
@@ -0,0 +1,50 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009 by Paweł Prażak <pawelprazak 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+#ifndef LINEEDIT_H
+#define LINEEDIT_H
+
+// Qt Includes
+
+// KDE Includes
+#include <KLineEdit>
+
+// Local Includes
+
+class QContextMenuEvent;
+class QFocusEvent;
+class QKeyEvent;
+
+class LineEdit : public KLineEdit
+{
+ Q_OBJECT
+
+public:
+ explicit LineEdit(QWidget *parent = 0);
+ virtual ~LineEdit();
+
+protected:
+ virtual void keyPressEvent(QKeyEvent*);
+ virtual void contextMenuEvent(QContextMenuEvent*);
+ virtual void focusInEvent(QFocusEvent*);
+ virtual void focusOutEvent(QFocusEvent*);
+};
+
+#endif // LINEEDIT_H
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 00000000..5ada94b4
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,98 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2008-2009 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+#include "application.h"
+
+#include <KAboutData>
+#include <KCmdLineArgs>
+#include <KDebug>
+
+
+static const char description[] =
+ I18N_NOOP("KDE Browser Webkit Based");
+
+
+static const char version[] = "0.1alpha";
+
+
+int main(int argc, char **argv)
+{
+ KAboutData about("rekonq",
+ 0,
+ ki18n("rekonq"),
+ version,
+ ki18n(description),
+ KAboutData::License_GPL_V3,
+ ki18n("(C) 2008-2009 Andrea Diamantini"),
+ KLocalizedString(),
+ "http://rekonq.sourceforge.net",
+ "rekonq@kde.org"
+ );
+
+ // about authors
+ about.addAuthor(ki18n("Andrea Diamantini"),
+ ki18n("Project Lead, Developer, Italian translation"),
+ "adjam7@gmail.com",
+ "http://www.adjam.org");
+
+ about.addAuthor(ki18n("Domrachev Alexandr"),
+ ki18n("Developer, Russian translation"),
+ "alexandr.domrachev@gmail.com",
+ "");
+
+ about.addAuthor(ki18n("Pawel Prazak"),
+ ki18n("Developer"),
+ "kojots350@gmail.com",
+ "");
+
+ about.addAuthor(ki18n("Panagiotis Papadopoulos"),
+ ki18n("German translation"),
+ "pano_90@gmx.net",
+ "");
+
+// about.addAuthor(ki18n("your name"),
+// ki18n("your role"),
+// "your mail",
+// "your site");
+
+ // Initialize command line args
+ KCmdLineArgs::init(argc, argv, &about);
+
+ // Define the command line options using KCmdLineOptions
+ KCmdLineOptions options;
+
+ // adding URL option
+ options.add("+[URL]" , ki18n("Location to open"));
+
+ // Register the supported options
+ KCmdLineArgs::addCmdLineOptions(options);
+
+ // Add options from Application class
+ Application::addCmdLineOptions();
+
+ if (!Application::start())
+ {
+ kWarning() << "rekonq is already running!";
+ return 0;
+ }
+
+ Application app;
+ return app.exec();
+}
diff --git a/src/mainview.cpp b/src/mainview.cpp
new file mode 100644
index 00000000..d4edeb19
--- /dev/null
+++ b/src/mainview.cpp
@@ -0,0 +1,716 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2008 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009 by Paweł Prażak <pawelprazak 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+
+// Self Includes
+#include "mainview.h"
+#include "mainview.moc"
+
+// Auto Includes
+#include "rekonq.h"
+
+// Local Includes
+#include "tabbar.h"
+#include "application.h"
+#include "mainwindow.h"
+#include "history.h"
+#include "stackedurlbar.h"
+#include "urlbar.h"
+#include "webview.h"
+
+// KDE Includes
+#include <KUrl>
+#include <KMenu>
+#include <KAction>
+#include <KShortcut>
+#include <KStandardShortcut>
+#include <KMessageBox>
+#include <KActionCollection>
+#include <KDebug>
+#include <KStandardDirs>
+
+// Qt Includes
+#include <QtCore>
+#include <QtGui>
+#include <QtWebKit>
+
+
+
+MainView::MainView(QWidget *parent)
+ : KTabWidget(parent)
+ , m_recentlyClosedTabsAction(0)
+ , m_recentlyClosedTabsMenu(new KMenu(this))
+ , m_urlBars(new StackedUrlBar(this))
+ , m_tabBar(new TabBar(this))
+{
+ // setting tabbar
+ setTabBar(m_tabBar);
+
+ // loading pixmap path
+ m_loadingGitPath = KStandardDirs::locate("appdata" , "pics/loading.gif");
+
+ // connecting tabbar signals
+ connect(m_tabBar, SIGNAL(closeTab(int)), this, SLOT(slotCloseTab(int)));
+ connect(m_tabBar, SIGNAL(cloneTab(int)), this, SLOT(slotCloneTab(int)));
+ connect(m_tabBar, SIGNAL(closeOtherTabs(int)), this, SLOT(slotCloseOtherTabs(int)));
+ connect(m_tabBar, SIGNAL(reloadTab(int)), this, SLOT(slotReloadTab(int)));
+ connect(m_tabBar, SIGNAL(reloadAllTabs()), this, SLOT(slotReloadAllTabs()));
+ connect(m_tabBar, SIGNAL(tabMoved(int, int)), this, SLOT(moveTab(int, int)));
+
+ // current page index changing
+ connect(this, SIGNAL(currentChanged(int)), this, SLOT(slotCurrentChanged(int)));
+
+ setTabsClosable(true);
+ connect(m_tabBar, SIGNAL(tabCloseRequested(int)), this, SLOT(slotCloseTab(int)));
+
+ QTimer::singleShot(0, this, SLOT(postLaunch()));
+}
+
+
+MainView::~MainView()
+{
+}
+
+
+void MainView::postLaunch()
+{
+ // Recently Closed Tab Action
+ connect(m_recentlyClosedTabsMenu, SIGNAL(aboutToShow()), this, SLOT(aboutToShowRecentTabsMenu()));
+ connect(m_recentlyClosedTabsMenu, SIGNAL(triggered(QAction *)), this, SLOT(aboutToShowRecentTriggeredAction(QAction *)));
+ m_recentlyClosedTabsAction = new KAction(i18n("Recently Closed Tabs"), this);
+ m_recentlyClosedTabsAction->setMenu(m_recentlyClosedTabsMenu);
+ m_recentlyClosedTabsAction->setEnabled(false);
+}
+
+void MainView::showTabBar()
+{
+ if (ReKonfig::alwaysShowTabBar())
+ {
+ if (m_tabBar->isHidden())
+ {
+ m_tabBar->show();
+ }
+ return;
+ }
+
+ if (m_tabBar->count() == 1)
+ {
+ m_tabBar->hide();
+ }
+ else
+ {
+ if (m_tabBar->isHidden())
+ {
+ m_tabBar->show();
+ }
+ }
+}
+
+
+void MainView::slotWebReload()
+{
+ WebView *webView = currentWebView();
+ QWebPage *currentParent = webView->webPage();
+ QAction *action = currentParent->action(QWebPage::Reload);
+ action->trigger();
+}
+
+
+void MainView::slotWebStop()
+{
+ WebView *webView = currentWebView();
+ QWebPage *currentParent = webView->webPage();
+ QAction *action = currentParent->action(QWebPage::Stop);
+ action->trigger();
+}
+
+
+void MainView::slotWebBack()
+{
+ WebView *webView = currentWebView();
+ QWebPage *currentParent = webView->webPage();
+ QAction *action = currentParent->action(QWebPage::Back);
+ action->trigger();
+}
+
+
+void MainView::slotWebForward()
+{
+ WebView *webView = currentWebView();
+ QWebPage *currentParent = webView->webPage();
+ QAction *action = currentParent->action(QWebPage::Forward);
+ action->trigger();
+}
+
+
+void MainView::slotWebUndo()
+{
+ WebView *webView = currentWebView();
+ QWebPage *currentParent = webView->webPage();
+ QAction *action = currentParent->action(QWebPage::Undo);
+ action->trigger();
+}
+
+
+void MainView::slotWebRedo()
+{
+ WebView *webView = currentWebView();
+ QWebPage *currentParent = webView->webPage();
+ QAction *action = currentParent->action(QWebPage::Redo);
+ action->trigger();
+}
+
+
+void MainView::slotWebCut()
+{
+ WebView *webView = currentWebView();
+ QWebPage *currentParent = webView->webPage();
+ QAction *action = currentParent->action(QWebPage::Cut);
+ action->trigger();
+}
+
+
+void MainView::slotWebCopy()
+{
+ WebView *webView = currentWebView();
+ QWebPage *currentParent = webView->webPage();
+ QAction *action = currentParent->action(QWebPage::Copy);
+ action->trigger();
+}
+
+
+void MainView::slotWebPaste()
+{
+ WebView *webView = currentWebView();
+ QWebPage *currentParent = webView->webPage();
+ QAction *action = currentParent->action(QWebPage::Paste);
+ action->trigger();
+}
+
+
+void MainView::clear()
+{
+ // clear the recently closed tabs
+ m_recentlyClosedTabs.clear();
+ // clear the line edit history
+ for (int i = 0; i < m_urlBars->count(); ++i)
+ {
+ /// TODO What exacly do we need to clear here?
+ urlBar(i)->clearHistory();
+ urlBar(i)->clear();
+ }
+}
+
+
+// When index is -1 index chooses the current tab
+void MainView::slotReloadTab(int index)
+{
+ if (index < 0)
+ index = currentIndex();
+ if (index < 0 || index >= count())
+ return;
+
+ QWidget *widget = this->widget(index);
+ if (WebView *tab = qobject_cast<WebView*>(widget))
+ tab->reload();
+}
+
+
+void MainView::slotCurrentChanged(int index)
+{
+ WebView *webView = this->webView(index);
+ if (!webView)
+ return;
+
+ Q_ASSERT(m_urlBars->count() == count());
+
+ WebView *oldWebView = this->webView(m_urlBars->currentIndex());
+ if (oldWebView)
+ {
+ disconnect(oldWebView, SIGNAL(statusBarMessage(const QString&)),
+ this, SIGNAL(showStatusBarMessage(const QString&)));
+ disconnect(oldWebView->page(), SIGNAL(linkHovered(const QString&, const QString&, const QString&)),
+ this, SIGNAL(linkHovered(const QString&)));
+ disconnect(oldWebView, SIGNAL(loadProgress(int)),
+ this, SIGNAL(loadProgress(int)));
+ }
+
+ connect(webView, SIGNAL(statusBarMessage(const QString&)), this, SIGNAL(showStatusBarMessage(const QString&)));
+ connect(webView->page(), SIGNAL(linkHovered(const QString&, const QString&, const QString&)), this, SIGNAL(linkHovered(const QString&)));
+ connect(webView, SIGNAL(loadProgress(int)), this, SIGNAL(loadProgress(int)));
+
+ emit setCurrentTitle(webView->title());
+ m_urlBars->setCurrentIndex(index);
+ emit loadProgress(webView->progress());
+ emit showStatusBarMessage(webView->lastStatusBarText());
+
+ // set focus to the current webview
+ webView->setFocus();
+}
+
+
+UrlBar *MainView::urlBar(int index) const
+{
+ if (index == -1)
+ {
+ index = m_urlBars->currentIndex();
+ }
+ UrlBar *urlBar = m_urlBars->urlBar(index);
+ if (urlBar)
+ {
+ return urlBar;
+ }
+ kWarning() << "URL bar with index" << index << "not found. Returning NULL. (line:" << __LINE__ << ")";
+ return NULL;
+}
+
+
+WebView *MainView::webView(int index) const
+{
+ QWidget *widget = this->widget(index);
+ if (WebView *webView = qobject_cast<WebView*>(widget))
+ {
+ return webView;
+ }
+
+ kWarning() << "WebView with index " << index << "not found. Returning NULL." ;
+ return 0;
+}
+
+
+WebView *MainView::newWebView(Rekonq::OpenType type)
+{
+ // line edit
+ UrlBar *urlBar = new UrlBar; // Ownership of widget is passed on to the QStackedWidget (addWidget method).
+ connect(urlBar, SIGNAL(activated(const KUrl&)), this, SLOT(loadUrl(const KUrl&)));
+ m_urlBars->addUrlBar(urlBar);
+
+ WebView *webView = new WebView; // should be deleted on tab close
+
+ // connecting webview with urlbar
+ connect(webView, SIGNAL(loadProgress(int)), urlBar, SLOT(slotUpdateProgress(int)));
+ connect(webView, SIGNAL(loadFinished(bool)), urlBar, SLOT(slotLoadFinished(bool)));
+ connect(webView, SIGNAL(urlChanged(const QUrl &)), urlBar, SLOT(setUrl(const QUrl &)));
+ connect(webView, SIGNAL(iconChanged()), urlBar, SLOT(slotUpdateUrl()));
+
+ // connecting webview with mainview
+ connect(webView, SIGNAL(loadStarted()), this, SLOT(webViewLoadStarted()));
+ connect(webView, SIGNAL(loadProgress(int)), this, SLOT(webViewLoadProgress(int)));
+ connect(webView, SIGNAL(loadFinished(bool)), this, SLOT(webViewLoadFinished(bool)));
+ connect(webView, SIGNAL(iconChanged()), this, SLOT(webViewIconChanged()));
+ connect(webView, SIGNAL(titleChanged(const QString &)), this, SLOT(webViewTitleChanged(const QString &)));
+ connect(webView, SIGNAL(urlChanged(const QUrl &)), this, SLOT(webViewUrlChanged(const QUrl &)));
+
+ connect(webView, SIGNAL(ctrlTabPressed()), this, SLOT(nextTab()));
+ connect(webView, SIGNAL(shiftCtrlTabPressed()), this, SLOT(previousTab()));
+
+ // connecting webPage signals with mainview
+ connect(webView->page(), SIGNAL(windowCloseRequested()),
+ this, SLOT(windowCloseRequested()));
+ connect(webView->page(), SIGNAL(geometryChangeRequested(const QRect &)),
+ this, SIGNAL(geometryChangeRequested(const QRect &)));
+ connect(webView->page(), SIGNAL(printRequested(QWebFrame *)),
+ this, SIGNAL(printRequested(QWebFrame *)));
+ connect(webView->page(), SIGNAL(menuBarVisibilityChangeRequested(bool)),
+ this, SIGNAL(menuBarVisibilityChangeRequested(bool)));
+ connect(webView->page(), SIGNAL(statusBarVisibilityChangeRequested(bool)),
+ this, SIGNAL(statusBarVisibilityChangeRequested(bool)));
+ connect(webView->page(), SIGNAL(toolBarVisibilityChangeRequested(bool)),
+ this, SIGNAL(toolBarVisibilityChangeRequested(bool)));
+
+ addTab(webView, i18n("(Untitled)"));
+
+ switch(type)
+ {
+ case Rekonq::Default:
+ if (!m_makeBackTab)
+ {
+ setCurrentWidget(webView); // this method does NOT take ownership of webView
+ urlBar->setFocus();
+ }
+ break;
+ case Rekonq::New:
+ setCurrentWidget(webView); // this method does NOT take ownership of webView
+ urlBar->setFocus();
+ break;
+ case Rekonq::Background:
+ break;
+ };
+
+ emit tabsChanged();
+
+ showTabBar();
+
+ return webView;
+}
+
+
+void MainView::slotReloadAllTabs()
+{
+ for (int i = 0; i < count(); ++i)
+ {
+ QWidget *tabWidget = widget(i);
+ if (WebView *tab = qobject_cast<WebView*>(tabWidget))
+ {
+ tab->reload();
+ }
+ }
+}
+
+
+void MainView::windowCloseRequested()
+{
+
+ WebPage *webPage = qobject_cast<WebPage*>(sender());
+ WebView *webView = qobject_cast<WebView*>(webPage->view());
+ int index = webViewIndex(webView);
+
+ if (index >= 0)
+ {
+ if (count() == 1)
+ {
+ Application::instance()->mainWindow()->close();
+ }
+ else
+ {
+ slotCloseTab(index);
+ }
+ }
+ else
+ {
+ kWarning() << "Invalid tab index" << "line:" << __LINE__;
+ }
+}
+
+
+void MainView::slotCloseOtherTabs(int index)
+{
+ if (-1 == index)
+ return;
+
+ for (int i = count() - 1; i > index; --i)
+ {
+ slotCloseTab(i);
+ }
+
+ for (int i = index - 1; i >= 0; --i)
+ {
+ slotCloseTab(i);
+ }
+
+ showTabBar();
+}
+
+
+// When index is -1 index chooses the current tab
+void MainView::slotCloneTab(int index)
+{
+ if (index < 0)
+ index = currentIndex();
+ if (index < 0 || index >= count())
+ return;
+ WebView *tab = newWebView();
+ tab->setUrl(webView(index)->url());
+
+ showTabBar();
+}
+
+
+// When index is -1 index chooses the current tab
+void MainView::slotCloseTab(int index)
+{
+ // do nothing if just one tab is opened
+ if (count() == 1)
+ return;
+
+ if (index < 0)
+ index = currentIndex();
+ if (index < 0 || index >= count())
+ return;
+
+ bool hasFocus = false;
+ if (WebView *tab = webView(index))
+ {
+ if (tab->isModified())
+ {
+ int risp = KMessageBox::questionYesNo(this ,
+ i18n("You have modified this page and when closing it you would lose the modification.\n"
+ "Do you really want to close this page?\n"),
+ i18n("Do you really want to close this page?")
+ );
+ if (risp == KMessageBox::No)
+ return;
+ }
+ hasFocus = tab->hasFocus();
+
+ m_recentlyClosedTabsAction->setEnabled(true);
+ m_recentlyClosedTabs.prepend(tab->url());
+
+ // don't add empty urls
+ if (tab->url().isValid())
+ {
+ m_recentlyClosedTabs.prepend(tab->url());
+ }
+
+ if (m_recentlyClosedTabs.size() >= MainView::m_recentlyClosedTabsSize)
+ {
+ m_recentlyClosedTabs.removeLast();
+ }
+ }
+
+ QWidget *urlBar = m_urlBars->urlBar(index);
+ m_urlBars->removeWidget(urlBar);
+ urlBar->deleteLater(); // urlBar is scheduled for deletion.
+
+ QWidget *webView = widget(index);
+ removeTab(index);
+ webView->deleteLater(); // webView is scheduled for deletion.
+
+ emit tabsChanged();
+
+ if (hasFocus && count() > 0)
+ {
+ currentWebView()->setFocus();
+ }
+
+ showTabBar();
+}
+
+
+void MainView::webViewLoadStarted()
+{
+ WebView *webView = qobject_cast<WebView*>(sender());
+ int index = webViewIndex(webView);
+ if (-1 != index)
+ {
+ QLabel *label = animatedLoading(index, true);
+ if (label->movie())
+ {
+ label->movie()->start();
+ }
+ }
+
+ if (index != currentIndex())
+ return;
+
+ emit showStatusBarMessage(i18n("Loading..."));
+}
+
+
+void MainView::webViewLoadProgress(int progress)
+{
+ WebView *webView = qobject_cast<WebView*>(sender());
+ int index = webViewIndex(webView);
+ if (index != currentIndex() || index < 0)
+ {
+ return;
+ }
+
+ double totalBytes = static_cast<double>(webView->webPage()->totalBytes() / 1024);
+
+ QString message = i18n("Loading %1% (%2 %3)...", progress, totalBytes, QLatin1String("kB"));
+ emit showStatusBarMessage(message);
+}
+
+
+void MainView::webViewLoadFinished(bool ok)
+{
+ WebView *webView = qobject_cast<WebView*>(sender());
+ int index = webViewIndex(webView);
+
+ if (-1 != index)
+ {
+ QLabel *label = animatedLoading(index, true);
+ QMovie *movie = label->movie();
+ if (movie)
+ movie->stop();
+ }
+
+ webViewIconChanged();
+
+ // don't display messages for background tabs
+ if (index != currentIndex())
+ {
+ return;
+ }
+
+ if (ok)
+ emit showStatusBarMessage(i18n("Done"));
+ else
+ emit showStatusBarMessage(i18n("Failed to load"));
+}
+
+
+void MainView::webViewIconChanged()
+{
+ WebView *webView = qobject_cast<WebView*>(sender());
+ int index = webViewIndex(webView);
+ if (-1 != index)
+ {
+ QIcon icon = Application::instance()->icon(webView->url());
+ QLabel *label = animatedLoading(index, false);
+ QMovie *movie = label->movie();
+ delete movie;
+ label->setMovie(0);
+ label->setPixmap(icon.pixmap(16, 16));
+ }
+}
+
+
+void MainView::webViewTitleChanged(const QString &title)
+{
+ QString tabTitle = title;
+ if (title.isEmpty())
+ {
+ tabTitle = i18n("(Untitled)");
+ }
+ WebView *webView = qobject_cast<WebView*>(sender());
+ int index = webViewIndex(webView);
+ if (-1 != index)
+ {
+ setTabText(index, tabTitle);
+ }
+ if (currentIndex() == index)
+ {
+ emit setCurrentTitle(tabTitle);
+ }
+ Application::historyManager()->updateHistoryEntry(webView->url(), tabTitle);
+}
+
+
+void MainView::webViewUrlChanged(const QUrl &url)
+{
+ WebView *webView = qobject_cast<WebView*>(sender());
+ int index = webViewIndex(webView);
+ if (-1 != index)
+ {
+ m_tabBar->setTabData(index, url);
+ }
+ emit tabsChanged();
+}
+
+
+void MainView::aboutToShowRecentTabsMenu()
+{
+ m_recentlyClosedTabsMenu->clear();
+ for (int i = 0; i < m_recentlyClosedTabs.count(); ++i)
+ {
+ KAction *action = new KAction(m_recentlyClosedTabsMenu);
+ action->setData(m_recentlyClosedTabs.at(i));
+ QIcon icon = Application::instance()->icon(m_recentlyClosedTabs.at(i));
+ action->setIcon(icon);
+ action->setText(m_recentlyClosedTabs.at(i).prettyUrl());
+ m_recentlyClosedTabsMenu->addAction(action);
+ }
+}
+
+
+void MainView::aboutToShowRecentTriggeredAction(QAction *action)
+{
+ KUrl url = action->data().toUrl();
+ loadUrl(url);
+}
+
+
+void MainView::loadUrl(const KUrl &url)
+{
+ if (url.isEmpty())
+ return;
+
+ currentUrlBar()->setUrl(url.prettyUrl());
+
+ WebView *webView = currentWebView();
+
+ KUrl loadingUrl(url);
+
+ if (loadingUrl.isRelative())
+ {
+ QString fn = loadingUrl.url(KUrl::RemoveTrailingSlash);
+ loadingUrl.setUrl("//" + fn);
+ loadingUrl.setScheme("http");
+ }
+
+ if (webView)
+ {
+ webView->load(loadingUrl);
+ webView->setFocus();
+ }
+}
+
+
+void MainView::nextTab()
+{
+ int next = currentIndex() + 1;
+ if (next == count())
+ next = 0;
+ setCurrentIndex(next);
+}
+
+
+void MainView::previousTab()
+{
+ int next = currentIndex() - 1;
+ if (next < 0)
+ next = count() - 1;
+ setCurrentIndex(next);
+}
+
+
+void MainView::moveTab(int fromIndex, int toIndex)
+{
+ QWidget *lineEdit = m_urlBars->widget(fromIndex);
+ m_urlBars->removeWidget(lineEdit);
+ m_urlBars->insertWidget(toIndex, lineEdit);
+}
+
+
+QLabel *MainView::animatedLoading(int index, bool addMovie)
+{
+ if (index == -1)
+ return 0;
+
+ QLabel *label = qobject_cast<QLabel*>(m_tabBar->tabButton(index, QTabBar::LeftSide));
+ if (!label)
+ {
+ label = new QLabel(this);
+ }
+ if (addMovie && !label->movie())
+ {
+ QMovie *movie = new QMovie(m_loadingGitPath, QByteArray(), label);
+ movie->setSpeed(50);
+ label->setMovie(movie);
+ movie->start();
+ }
+ m_tabBar->setTabButton(index, QTabBar::LeftSide, 0);
+ m_tabBar->setTabButton(index, QTabBar::LeftSide, label);
+ return label;
+}
+
+
+void MainView::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ if (!childAt(event->pos()))
+ {
+ newWebView(Rekonq::New);
+ return;
+ }
+ KTabWidget::mouseDoubleClickEvent(event);
+} \ No newline at end of file
diff --git a/src/mainview.h b/src/mainview.h
new file mode 100644
index 00000000..372902dd
--- /dev/null
+++ b/src/mainview.h
@@ -0,0 +1,198 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2008 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009 by Paweł Prażak <pawelprazak 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+
+
+#ifndef TABWIDGET_H
+#define TABWIDGET_H
+
+// Local Includes
+#include "webview.h"
+#include "application.h"
+
+// KDE Includes
+#include <KTabWidget>
+
+// Forward Declarations
+class QLineEdit;
+class QUrl;
+class QWebFrame;
+class QLabel;
+
+class KAction;
+class KCompletion;
+class KMenu;
+class KUrl;
+
+class HistoryCompletionModel;
+class StackedUrlBar;
+class TabBar;
+class UrlBar;
+
+
+/**
+ * This class represent rekonq Main View. It contains all WebViews and a stack widget
+ * of associated line edits.
+ *
+ */
+
+class MainView : public KTabWidget
+{
+ Q_OBJECT
+
+public:
+ MainView(QWidget *parent = 0);
+ ~MainView();
+
+public:
+
+ UrlBar *urlBar(int index) const;
+ UrlBar *currentUrlBar() const { return urlBar(-1); }
+ WebView *webView(int index) const;
+ QList<WebView *> tabs(); // ?
+
+ // inlines
+ TabBar *tabBar() const { return m_tabBar; }
+ StackedUrlBar *urlBarStack() const { return m_urlBars; }
+ WebView *currentWebView() const { return webView(currentIndex()); }
+ int webViewIndex(WebView *webView) const { return indexOf(webView); }
+ KAction *recentlyClosedTabsAction() const { return m_recentlyClosedTabsAction; }
+ void setMakeBackTab(bool b) { m_makeBackTab = b; }
+
+ /**
+ * show and hide TabBar if user doesn't choose
+ * "Always Show TabBar" option
+ *
+ */
+ void showTabBar();
+ void clear();
+
+
+signals:
+ // tab widget signals
+ void tabsChanged();
+ void lastTabClosed();
+
+ // current tab signals
+ void setCurrentTitle(const QString &url);
+ void showStatusBarMessage(const QString &message);
+ void linkHovered(const QString &link);
+ void loadProgress(int progress);
+
+ void geometryChangeRequested(const QRect &geometry);
+ void menuBarVisibilityChangeRequested(bool visible);
+ void statusBarVisibilityChangeRequested(bool visible);
+ void toolBarVisibilityChangeRequested(bool visible);
+ void printRequested(QWebFrame *frame);
+
+public slots:
+ /**
+ * Core browser slot. This create a new tab with a WebView inside
+ * for browsing.
+ *
+ * @return a pointer to the new WebView
+ */
+ WebView *newWebView(Rekonq::OpenType type = Rekonq::Default);
+
+ /**
+ * Core browser slot. Load an url in a webview
+ *
+ * @param url The url to load
+ */
+ void loadUrl(const KUrl &url);
+ void slotCloneTab(int index = -1);
+ void slotCloseTab(int index = -1);
+ void slotCloseOtherTabs(int index);
+ void slotReloadTab(int index = -1);
+ void slotReloadAllTabs();
+ void nextTab();
+ void previousTab();
+
+ // WEB slot actions
+ void slotWebReload();
+ void slotWebStop();
+ void slotWebBack();
+ void slotWebForward();
+ void slotWebUndo();
+ void slotWebRedo();
+ void slotWebCut();
+ void slotWebCopy();
+ void slotWebPaste();
+
+private slots:
+ void slotCurrentChanged(int index);
+ void aboutToShowRecentTabsMenu();
+ void aboutToShowRecentTriggeredAction(QAction *action); // need QAction!
+
+ void webViewLoadStarted();
+ void webViewLoadProgress(int progress);
+ void webViewLoadFinished(bool ok);
+ void webViewIconChanged();
+ void webViewTitleChanged(const QString &title);
+ void webViewUrlChanged(const QUrl &url);
+
+ void windowCloseRequested();
+
+ /**
+ * This functions move tab informations "from index to index"
+ *
+ * @param fromIndex the index from which we move
+ *
+ * @param toIndex the index to which we move
+ */
+ void moveTab(int fromIndex, int toIndex);
+
+ void postLaunch();
+
+protected:
+
+ virtual void mouseDoubleClickEvent(QMouseEvent *event);
+
+
+private:
+
+ /**
+ * This function creates (if not exists) and returns a QLabel
+ * with a loading QMovie.
+ * Imported from Arora's code.
+ *
+ * @param index the tab index where inserting the animated label
+ * @param addMovie creates or not a loading movie
+ *
+ * @return animated label's pointer
+ */
+ QLabel *animatedLoading(int index, bool addMovie);
+
+ static const int m_recentlyClosedTabsSize = 10;
+ KAction *m_recentlyClosedTabsAction;
+
+ KMenu *m_recentlyClosedTabsMenu;
+ QList<KUrl> m_recentlyClosedTabs;
+
+ StackedUrlBar *m_urlBars;
+ TabBar *m_tabBar;
+
+ QString m_loadingGitPath;
+
+ bool m_makeBackTab;
+};
+
+#endif
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
new file mode 100644
index 00000000..d1ab721f
--- /dev/null
+++ b/src/mainwindow.cpp
@@ -0,0 +1,930 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007-2008 Trolltech ASA. All rights reserved
+* Copyright (C) 2008-2009 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009 by Paweł Prażak <pawelprazak 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "mainwindow.h"
+#include "mainwindow.moc"
+
+// Auto Includes
+#include "rekonq.h"
+
+// Local Includes
+#include "application.h"
+#include "settings.h"
+#include "history.h"
+#include "cookiejar.h"
+#include "networkaccessmanager.h"
+#include "bookmarks.h"
+#include "webview.h"
+#include "mainview.h"
+#include "bookmarks.h"
+#include "download.h"
+#include "findbar.h"
+#include "sidepanel.h"
+#include "urlbar.h"
+#include "stackedurlbar.h"
+
+// KDE Includes
+#include <KUrl>
+#include <KStatusBar>
+#include <KMenuBar>
+#include <KShortcut>
+#include <KStandardAction>
+#include <KAction>
+#include <KToggleFullScreenAction>
+#include <KActionCollection>
+#include <KMessageBox>
+#include <KFileDialog>
+#include <KMenu>
+#include <KGlobalSettings>
+#include <KPushButton>
+#include <KTemporaryFile>
+
+#include <kdeprintdialog.h>
+#include <kprintpreview.h>
+
+
+// Qt Includes
+#include <QtGui>
+#include <QtCore>
+#include <QtWebKit>
+
+
+MainWindow::MainWindow()
+ : KXmlGuiWindow()
+ , m_view(new MainView(this))
+ , m_findBar(new FindBar(this))
+ , m_searchBar(new SearchBar(this))
+ , m_sidePanel(0)
+{
+ // updating rekonq configuration
+ slotUpdateConfiguration();
+
+ // creating a centralWidget containing panel, m_view and the hidden findbar
+ QWidget *centralWidget = new QWidget;
+ centralWidget->setContentsMargins(0, 0, 0, 0);
+
+ // setting layout
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->addWidget(m_view);
+ layout->addWidget(m_findBar);
+ centralWidget->setLayout(layout);
+
+ // central widget
+ setCentralWidget(centralWidget);
+
+ // setting size policies
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+
+ // then, setup our actions
+ setupActions();
+
+ // setting up toolbars: this has to be done BEFORE setupGUI!!
+ setupToolBars();
+
+ // Bookmark Menu
+ KActionMenu *bmMenu = Application::bookmarkProvider()->bookmarkActionMenu();
+ actionCollection()->addAction(QLatin1String("bookmarks"), bmMenu);
+
+ // Side Panel: this has to be done BEFORE setupGUI!!
+ setupSidePanel();
+
+ // a call to KXmlGuiWindow::setupGUI() populates the GUI
+ // with actions, using KXMLGUI.
+ // It also applies the saved mainwindow settings, if any, and ask the
+ // mainwindow to automatically save settings if changed: window size,
+ // toolbar position, icon size, etc.
+ setupGUI();
+
+ QTimer::singleShot(0, this, SLOT(postLaunch()));
+}
+
+
+MainWindow::~MainWindow()
+{
+ delete m_view;
+}
+
+
+void MainWindow::postLaunch()
+{
+ // setup history menu: this has to be done AFTER setupGUI!!
+ setupHistoryMenu();
+
+ // --------- connect signals and slots
+ connect(m_view, SIGNAL(setCurrentTitle(const QString &)), this, SLOT(slotUpdateWindowTitle(const QString &)));
+ connect(m_view, SIGNAL(loadProgress(int)), this, SLOT(slotLoadProgress(int)));
+ connect(m_view, SIGNAL(geometryChangeRequested(const QRect &)), this, SLOT(geometryChangeRequested(const QRect &)));
+ connect(m_view, SIGNAL(printRequested(QWebFrame *)), this, SLOT(printRequested(QWebFrame *)));
+ connect(m_view, SIGNAL(menuBarVisibilityChangeRequested(bool)), menuBar(), SLOT(setVisible(bool)));
+ connect(m_view, SIGNAL(statusBarVisibilityChangeRequested(bool)), statusBar(), SLOT(setVisible(bool)));
+
+ // status bar messages
+ connect(m_view, SIGNAL(showStatusBarMessage(const QString&)), statusBar(), SLOT(showMessage(const QString&)));
+ connect(m_view, SIGNAL(linkHovered(const QString&)), statusBar(), SLOT(showMessage(const QString&)));
+
+ // update toolbar actions signals
+ connect(m_view, SIGNAL(tabsChanged()), this, SLOT(slotUpdateActions()));
+ connect(m_view, SIGNAL(currentChanged(int)), this, SLOT(slotUpdateActions()));
+
+ // Find Bar signal
+ connect(m_findBar, SIGNAL(searchString(const QString &)), this, SLOT(slotFind(const QString &)));
+
+ // bookmarks loading
+ connect(Application::bookmarkProvider(), SIGNAL(openUrl(const KUrl&)), this, SLOT(loadUrl(const KUrl&)));
+
+ // setting up toolbars to NOT have context menu enabled
+ setContextMenuPolicy(Qt::DefaultContextMenu);
+
+ // accept d'n'd
+ setAcceptDrops(true);
+}
+
+
+QSize MainWindow::sizeHint() const
+{
+ QRect desktopRect = QApplication::desktop()->screenGeometry();
+ QSize size = desktopRect.size() * 0.8;
+ return size;
+}
+
+
+void MainWindow::setupToolBars()
+{
+ KAction *a;
+
+ // location bar
+ a = new KAction(i18n("Location Bar"), this);
+ a->setShortcut(KShortcut(Qt::Key_F6));
+ a->setDefaultWidget(m_view->urlBarStack());
+ actionCollection()->addAction(QLatin1String("url_bar"), a);
+
+ // search bar
+ a = new KAction(i18n("Search Bar"), this);
+ a->setShortcut(KShortcut(Qt::CTRL + Qt::Key_K));
+ a->setDefaultWidget(m_searchBar);
+ connect(m_searchBar, SIGNAL(search(const KUrl&)), this, SLOT(loadUrl(const KUrl&)));
+ actionCollection()->addAction(QLatin1String("search_bar"), a);
+
+ // bookmarks bar
+ KAction *bookmarkBarAction = Application::bookmarkProvider()->bookmarkToolBarAction();
+ a = actionCollection()->addAction(QLatin1String("bookmarks_bar"), bookmarkBarAction);
+}
+
+
+void MainWindow::setupActions()
+{
+ KAction *a;
+
+ // Standard Actions
+ KStandardAction::open(this, SLOT(slotFileOpen()), actionCollection());
+ KStandardAction::saveAs(this, SLOT(slotFileSaveAs()), actionCollection());
+ KStandardAction::printPreview(this, SLOT(slotFilePrintPreview()), actionCollection());
+ KStandardAction::print(this, SLOT(slotFilePrint()), actionCollection());
+ KStandardAction::quit(this , SLOT(close()), actionCollection());
+ KStandardAction::find(this, SLOT(slotViewFindBar()) , actionCollection());
+ KStandardAction::findNext(this, SLOT(slotFindNext()) , actionCollection());
+ KStandardAction::findPrev(this, SLOT(slotFindPrevious()) , actionCollection());
+ KStandardAction::fullScreen(this, SLOT(slotViewFullScreen(bool)), this, actionCollection());
+ KStandardAction::home(this, SLOT(slotHome()), actionCollection());
+ KStandardAction::preferences(this, SLOT(slotPreferences()), actionCollection());
+ KStandardAction::showMenubar(this, SLOT(slotShowMenubar(bool)), actionCollection());
+
+ // WEB Actions (NO KStandardActions..)
+ a = KStandardAction::redisplay(m_view, SLOT(slotWebReload()), actionCollection());
+ a->setText(i18n("Reload"));
+ KStandardAction::back(m_view, SLOT(slotWebBack()), actionCollection());
+ KStandardAction::forward(m_view, SLOT(slotWebForward()), actionCollection());
+ KStandardAction::undo(m_view, SLOT(slotWebUndo()), actionCollection());
+ KStandardAction::redo(m_view, SLOT(slotWebRedo()), actionCollection());
+ KStandardAction::cut(m_view, SLOT(slotWebCut()), actionCollection());
+ KStandardAction::copy(m_view, SLOT(slotWebCopy()), actionCollection());
+ KStandardAction::paste(m_view, SLOT(slotWebPaste()), actionCollection());
+
+ a = new KAction(KIcon("process-stop"), i18n("&Stop"), this);
+ a->setShortcut(KShortcut(Qt::CTRL | Qt::Key_Period));
+ actionCollection()->addAction(QLatin1String("stop"), a);
+ connect(a, SIGNAL(triggered(bool)), m_view, SLOT(slotWebStop()));
+
+ // stop reload Action
+ m_stopReloadAction = new KAction(KIcon("view-refresh"), i18n("Reload"), this);
+ actionCollection()->addAction(QLatin1String("stop_reload") , m_stopReloadAction);
+ m_stopReloadAction->setShortcutConfigurable(false);
+
+ // ============== Custom Actions
+ a = new KAction(KIcon("document-open-remote"), i18n("Open Location"), this);
+ a->setShortcut(Qt::CTRL + Qt::Key_L);
+ actionCollection()->addAction(QLatin1String("open_location"), a);
+ connect(a, SIGNAL(triggered(bool)) , this, SLOT(slotOpenLocation()));
+
+ a = new KAction(KIcon("zoom-in"), i18n("&Enlarge Font"), this);
+ a->setShortcut(KShortcut(Qt::CTRL | Qt::Key_Plus));
+ actionCollection()->addAction(QLatin1String("bigger_font"), a);
+ connect(a, SIGNAL(triggered(bool)), this, SLOT(slotViewTextBigger()));
+
+ a = new KAction(KIcon("zoom-original"), i18n("&Normal Font"), this);
+ a->setShortcut(KShortcut(Qt::CTRL | Qt::Key_0));
+ actionCollection()->addAction(QLatin1String("normal_font"), a);
+ connect(a, SIGNAL(triggered(bool)), this, SLOT(slotViewTextNormal()));
+
+ a = new KAction(KIcon("zoom-out"), i18n("&Shrink Font"), this);
+ a->setShortcut(KShortcut(Qt::CTRL | Qt::Key_Minus));
+ actionCollection()->addAction(QLatin1String("smaller_font"), a);
+ connect(a, SIGNAL(triggered(bool)), this, SLOT(slotViewTextSmaller()));
+
+ a = new KAction(i18n("Page S&ource"), this);
+ actionCollection()->addAction(QLatin1String("page_source"), a);
+ connect(a, SIGNAL(triggered(bool)), this, SLOT(slotViewPageSource()));
+
+ // ================ Tools (WebKit) Actions
+ a = new KAction(KIcon("tools-report-bug"), i18n("Web &Inspector"), this);
+ a->setCheckable(true);
+ actionCollection()->addAction(QLatin1String("web_inspector"), a);
+ connect(a, SIGNAL(triggered(bool)), this, SLOT(slotToggleInspector(bool)));
+
+ a = new KAction(KIcon("view-media-artist"), i18n("Private &Browsing"), this);
+ a->setCheckable(true);
+ actionCollection()->addAction(QLatin1String("private_browsing"), a);
+ connect(a, SIGNAL(triggered(bool)) , this, SLOT(slotPrivateBrowsing(bool)));
+
+ // ================ history related actions
+ m_historyBackAction = new KAction(KIcon("go-previous"), i18n("Back"), this);
+ m_historyBackMenu = new KMenu(this);
+ m_historyBackAction->setMenu(m_historyBackMenu);
+ connect(m_historyBackAction, SIGNAL(triggered(bool)), this, SLOT(slotOpenPrevious()));
+ connect(m_historyBackMenu, SIGNAL(aboutToShow()), this, SLOT(slotAboutToShowBackMenu()));
+ connect(m_historyBackMenu, SIGNAL(triggered(QAction *)), this, SLOT(slotOpenActionUrl(QAction *)));
+ actionCollection()->addAction(QLatin1String("history_back"), m_historyBackAction);
+
+ m_historyForwardAction = new KAction(KIcon("go-next"), i18n("Forward"), this);
+ connect(m_historyForwardAction, SIGNAL(triggered(bool)), this, SLOT(slotOpenNext()));
+ actionCollection()->addAction(QLatin1String("history_forward"), m_historyForwardAction);
+
+ // =================== Tab Actions
+ a = new KAction(KIcon("tab-new"), i18n("New &Tab"), this);
+ QList<QKeySequence> newTabShortcutList;
+ newTabShortcutList << QKeySequence(QKeySequence::New);
+ newTabShortcutList << QKeySequence(QKeySequence::AddTab);
+ a->setShortcut(KShortcut(newTabShortcutList));
+ actionCollection()->addAction(QLatin1String("new_tab"), a);
+ connect(a, SIGNAL(triggered(bool)), m_view, SLOT(newWebView()));
+
+ a = new KAction(KIcon("tab-close"), i18n("&Close Tab"), this);
+ a->setShortcut(KShortcut(Qt::CTRL + Qt::Key_W));
+ actionCollection()->addAction(QLatin1String("close_tab"), a);
+ connect(a, SIGNAL(triggered(bool)), m_view, SLOT(slotCloseTab()));
+
+ a = new KAction(i18n("Show Next Tab"), this);
+ a->setShortcuts(QApplication::isRightToLeft() ? KStandardShortcut::tabPrev() : KStandardShortcut::tabNext());
+ actionCollection()->addAction(QLatin1String("show_next_tab"), a);
+ connect(a, SIGNAL(triggered(bool)), m_view, SLOT(nextTab()));
+
+ a = new KAction(i18n("Show Previous Tab"), this);
+ a->setShortcuts(QApplication::isRightToLeft() ? KStandardShortcut::tabNext() : KStandardShortcut::tabPrev());
+ actionCollection()->addAction(QLatin1String("show_prev_tab"), a);
+ connect(a, SIGNAL(triggered(bool)), m_view, SLOT(previousTab()));
+}
+
+
+void MainWindow::setupSidePanel()
+{
+ // Setup history side panel
+ m_sidePanel = new SidePanel(i18n("History"), this);
+ connect(m_sidePanel, SIGNAL(openUrl(const KUrl&)), this, SLOT(loadUrl(const KUrl&)));
+ connect(m_sidePanel, SIGNAL(destroyed()), Application::instance(), SLOT(slotSaveConfiguration()));
+
+ addDockWidget(Qt::LeftDockWidgetArea, m_sidePanel);
+
+ // setup side panel actions
+ KAction* a = new KAction(this);
+ a->setText(i18n("History"));
+ a->setCheckable(true);
+ a->setChecked(ReKonfig::showSideBar());
+ a->setShortcut(KShortcut(Qt::CTRL + Qt::Key_H));
+ actionCollection()->addAction(QLatin1String("show_history_panel"), a);
+
+ // connect to toogle action
+ connect(a, SIGNAL(triggered(bool)), m_sidePanel->toggleViewAction(), SLOT(trigger()));
+}
+
+
+void MainWindow::setupHistoryMenu()
+{
+ HistoryMenu *historyMenu = new HistoryMenu(this);
+ connect(historyMenu, SIGNAL(openUrl(const KUrl&)), this, SLOT(loadUrl(const KUrl&)));
+ connect(historyMenu, SIGNAL(hovered(const QString&)), this, SLOT(slotUpdateStatusbar(const QString&)));
+ historyMenu->setTitle(i18n("&History"));
+
+ // setting history menu position
+ menuBar()->insertMenu(actionCollection()->action("bookmarks"), historyMenu);
+
+ // setting initial actions
+ QList<QAction*> historyActions;
+ historyActions.append(actionCollection()->action("history_back"));
+ historyActions.append(actionCollection()->action("history_forward"));
+ historyActions.append(m_view->recentlyClosedTabsAction());
+ historyMenu->setInitialActions(historyActions);
+}
+
+
+void MainWindow::slotUpdateConfiguration()
+{
+ // ============== General ==================
+ m_homePage = ReKonfig::homePage();
+ mainView()->showTabBar();
+ mainView()->setMakeBackTab( ReKonfig::openTabsBack() );
+
+ // =========== Fonts ==============
+ QWebSettings *defaultSettings = QWebSettings::globalSettings();
+
+ int fnSize = ReKonfig::fontSize();
+
+ QFont standardFont = ReKonfig::standardFont();
+ defaultSettings->setFontFamily(QWebSettings::StandardFont, standardFont.family());
+ defaultSettings->setFontSize(QWebSettings::DefaultFontSize, fnSize);
+
+ QFont fixedFont = ReKonfig::fixedFont();
+ defaultSettings->setFontFamily(QWebSettings::FixedFont, fixedFont.family());
+ defaultSettings->setFontSize(QWebSettings::DefaultFixedFontSize, fnSize);
+
+ // ================ WebKit ============================
+ defaultSettings->setAttribute(QWebSettings::AutoLoadImages, ReKonfig::autoLoadImages());
+ defaultSettings->setAttribute(QWebSettings::JavascriptEnabled, ReKonfig::javascriptEnabled());
+ defaultSettings->setAttribute(QWebSettings::JavaEnabled, ReKonfig::javaEnabled());
+ defaultSettings->setAttribute(QWebSettings::PluginsEnabled, ReKonfig::pluginsEnabled());
+ defaultSettings->setAttribute(QWebSettings::JavascriptCanOpenWindows, ReKonfig::javascriptCanOpenWindows());
+ defaultSettings->setAttribute(QWebSettings::JavascriptCanAccessClipboard, ReKonfig::javascriptCanAccessClipboard());
+ defaultSettings->setAttribute(QWebSettings::LinksIncludedInFocusChain, ReKonfig::linksIncludedInFocusChain());
+ defaultSettings->setAttribute(QWebSettings::ZoomTextOnly, ReKonfig::zoomTextOnly());
+ defaultSettings->setAttribute(QWebSettings::PrintElementBackgrounds, ReKonfig::printElementBackgrounds());
+ defaultSettings->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, ReKonfig::offlineStorageDatabaseEnabled());
+ defaultSettings->setAttribute(QWebSettings::OfflineWebApplicationCacheEnabled, ReKonfig::offlineWebApplicationCacheEnabled());
+ defaultSettings->setAttribute(QWebSettings::LocalStorageDatabaseEnabled, ReKonfig::localStorageDatabaseEnabled());
+
+ // ====== load Settings on main classes
+ Application::networkAccessManager()->loadSettings();
+ Application::cookieJar()->loadSettings();
+ Application::historyManager()->loadSettings();
+}
+
+
+void MainWindow::slotUpdateBrowser()
+{
+ slotUpdateConfiguration();
+ mainView()->slotReloadAllTabs();
+}
+
+
+KUrl MainWindow::guessUrlFromString(const QString &string)
+{
+ QString urlStr = string.trimmed();
+ QRegExp test(QLatin1String("^[a-zA-Z]+\\:.*"));
+
+ // Check if it looks like a qualified URL. Try parsing it and see.
+ bool hasSchema = test.exactMatch(urlStr);
+
+ if (hasSchema)
+ {
+ QUrl qurl(urlStr, QUrl::TolerantMode);
+ KUrl url(qurl);
+
+ if (url.isValid())
+ {
+ return url;
+ }
+ }
+
+ // Might be a file.
+ if (QFile::exists(urlStr))
+ {
+ QFileInfo info(urlStr);
+ return KUrl::fromPath(info.absoluteFilePath());
+ }
+
+ // Might be a shorturl - try to detect the schema.
+ if (!hasSchema)
+ {
+ int dotIndex = urlStr.indexOf(QLatin1Char('.'));
+
+ if (dotIndex != -1)
+ {
+ QString prefix = urlStr.left(dotIndex).toLower();
+ QString schema = (prefix == QLatin1String("ftp")) ? prefix : QLatin1String("http");
+ QUrl qurl(schema + QLatin1String("://") + urlStr, QUrl::TolerantMode);
+ KUrl url(qurl);
+
+ if (url.isValid())
+ {
+ return url;
+ }
+ }
+ }
+
+ // Fall back to QUrl's own tolerant parser.
+ QUrl qurl = QUrl(string, QUrl::TolerantMode);
+ KUrl url(qurl);
+
+ // finally for cases where the user just types in a hostname add http
+ if (qurl.scheme().isEmpty())
+ {
+ qurl = QUrl(QLatin1String("http://") + string, QUrl::TolerantMode);
+ url = KUrl(qurl);
+ }
+ return url;
+}
+
+
+void MainWindow::loadUrl(const KUrl &url)
+{
+ m_view->loadUrl(url);
+}
+
+
+void MainWindow::slotOpenLocation()
+{
+ m_view->currentUrlBar()->selectAll();
+ m_view->currentUrlBar()->setFocus();
+}
+
+
+void MainWindow::slotFileSaveAs()
+{
+ KUrl srcUrl = currentTab()->url();
+ Application::downloadManager()->newDownload(srcUrl);
+}
+
+
+void MainWindow::slotPreferences()
+{
+ // an instance the dialog could be already created and could be cached,
+ // in which case you want to display the cached dialog
+ if (SettingsDialog::showDialog("rekonfig"))
+ return;
+
+ // we didn't find an instance of this dialog, so lets create it
+ SettingsDialog *s = new SettingsDialog(this);
+
+ // keep us informed when the user changes settings
+ connect(s, SIGNAL(settingsChanged(const QString&)), this, SLOT(slotUpdateBrowser()));
+
+ s->exec();
+}
+
+
+void MainWindow::slotUpdateStatusbar(const QString &string)
+{
+ statusBar()->showMessage(string, 2000);
+}
+
+
+void MainWindow::slotUpdateActions()
+{
+ m_historyBackAction->setEnabled(currentTab()->history()->canGoBack());
+ m_historyForwardAction->setEnabled(currentTab()->history()->canGoForward());
+}
+
+
+void MainWindow::slotUpdateWindowTitle(const QString &title)
+{
+ if (title.isEmpty())
+ {
+ setWindowTitle("rekonq");
+ }
+ else
+ {
+ setWindowTitle(title + " - rekonq");
+ }
+}
+
+
+void MainWindow::slotFileOpen()
+{
+ QString filePath = KFileDialog::getOpenFileName(KUrl(),
+ i18n("Web Resources (*.html *.htm *.svg *.png *.gif *.svgz); All files (*.*)"),
+ this,
+ i18n("Open Web Resource")
+ );
+
+ if (filePath.isEmpty())
+ return;
+
+ loadUrl(guessUrlFromString(filePath));
+}
+
+
+void MainWindow::slotFilePrintPreview()
+{
+ if (!currentTab())
+ return;
+
+ QPrinter printer;
+ KPrintPreview previewdlg(&printer, this);
+ currentTab()->print(&printer);
+ previewdlg.exec();
+}
+
+
+void MainWindow::slotFilePrint()
+{
+ if (!currentTab())
+ return;
+ printRequested(currentTab()->page()->mainFrame());
+}
+
+
+void MainWindow::printRequested(QWebFrame *frame)
+{
+ QPrinter printer;
+
+ QPrintDialog *dialog = KdePrint::createPrintDialog(&printer, this);
+ if (dialog->exec() != QDialog::Accepted)
+ return;
+ frame->print(&printer);
+}
+
+
+void MainWindow::slotPrivateBrowsing(bool enable)
+{
+ QWebSettings *settings = QWebSettings::globalSettings();
+ if (enable)
+ {
+ QString title = i18n("Are you sure you want to turn on private browsing?");
+ QString text = "<b>" + title + i18n("</b><br><br>When private browsing in turned on,"
+ " webpages are not added to the history,"
+ " new cookies are not stored, current cookies cannot be accessed," \
+ " site icons will not be stored, session will not be saved, " \
+ " and searches are not addded to the pop-up menu in the Google search box." \
+ " Until you close the window, you can still click the Back and Forward buttons" \
+ " to return to the webpages you have opened.");
+
+ int button = KMessageBox::questionYesNo(this, text, title);
+ if (button == KMessageBox::Ok)
+ {
+ settings->setAttribute(QWebSettings::PrivateBrowsingEnabled, true);
+ }
+ else
+ {
+ actionCollection()->action("private_browsing")->setChecked(false);
+ }
+ }
+ else
+ {
+ settings->setAttribute(QWebSettings::PrivateBrowsingEnabled, false);
+
+ MainWindow* win = Application::instance()->mainWindow();
+ win->m_lastSearch = QString::null;
+ win->mainView()->clear();
+ }
+}
+
+void MainWindow::slotFind(const QString & search)
+{
+ if (!currentTab())
+ return;
+ m_lastSearch = search;
+ slotFindNext();
+}
+
+
+void MainWindow::slotViewFindBar()
+{
+ m_findBar->showFindBar();
+}
+
+
+void MainWindow::slotFindNext()
+{
+ if (!currentTab() && m_lastSearch.isEmpty())
+ return;
+
+ QWebPage::FindFlags options;
+ if (m_findBar->matchCase())
+ {
+ options = QWebPage::FindCaseSensitively | QWebPage::FindWrapsAroundDocument;
+ }
+ else
+ {
+ options = QWebPage::FindWrapsAroundDocument;
+ }
+
+ if (!currentTab()->findText(m_lastSearch, options))
+ {
+ slotUpdateStatusbar(QString(m_lastSearch) + i18n(" not found."));
+ }
+}
+
+
+void MainWindow::slotFindPrevious()
+{
+ if (!currentTab() && m_lastSearch.isEmpty())
+ return;
+
+ QWebPage::FindFlags options;
+ if (m_findBar->matchCase())
+ {
+ options = QWebPage::FindCaseSensitively | QWebPage::FindBackward | QWebPage::FindWrapsAroundDocument;
+ }
+ else
+ {
+ options = QWebPage::FindBackward | QWebPage::FindWrapsAroundDocument;
+ }
+
+ if (!currentTab()->findText(m_lastSearch, options))
+ {
+ slotUpdateStatusbar(QString(m_lastSearch) + i18n(" not found."));
+ }
+}
+
+
+void MainWindow::slotViewTextBigger()
+{
+ if (!currentTab())
+ return;
+ currentTab()->setTextSizeMultiplier(currentTab()->textSizeMultiplier() + 0.1);
+}
+
+
+void MainWindow::slotViewTextNormal()
+{
+ if (!currentTab())
+ return;
+ currentTab()->setTextSizeMultiplier(1.0);
+}
+
+
+void MainWindow::slotViewTextSmaller()
+{
+ if (!currentTab())
+ return;
+ currentTab()->setTextSizeMultiplier(currentTab()->textSizeMultiplier() - 0.1);
+}
+
+
+void MainWindow::slotViewFullScreen(bool makeFullScreen)
+{
+ // state flags
+ static bool menubarFlag;
+ static bool mainToolBarFlag;
+ static bool bookmarksToolBarFlag;
+ static bool statusBarFlag;
+ static bool sidePanelFlag;
+
+ if (makeFullScreen == true)
+ {
+ // save current state
+ menubarFlag = menuBar()->isHidden();
+ mainToolBarFlag = toolBar("mainToolBar")->isHidden();
+ bookmarksToolBarFlag = toolBar("bookmarksToolBar")->isHidden();
+ statusBarFlag = statusBar()->isHidden();
+ sidePanelFlag = sidePanel()->isHidden();
+
+ menuBar()->hide();
+ toolBar("mainToolBar")->hide();
+ toolBar("bookmarksToolBar")->hide();
+ statusBar()->hide();
+ sidePanel()->hide();
+ }
+ else
+ {
+ if (!menubarFlag)
+ menuBar()->show();
+ if (!mainToolBarFlag)
+ toolBar("mainToolBar")->show();
+ if (!bookmarksToolBarFlag)
+ toolBar("bookmarksToolBar")->show();
+ if (!statusBarFlag)
+ statusBar()->show();
+ if (!sidePanelFlag)
+ sidePanel()->show();
+ }
+
+ KToggleFullScreenAction::setFullScreen(this, makeFullScreen);
+}
+
+
+void MainWindow::slotViewPageSource()
+{
+ if (!currentTab())
+ return;
+
+ KUrl url(currentTab()->url());
+ bool isTempFile = false;
+ if (!url.isLocalFile())
+ {
+ KTemporaryFile sourceFile;
+
+ /// TODO: autochoose tempfile suffix
+ sourceFile.setSuffix(QString(".html"));
+ sourceFile.setAutoRemove(false);
+
+ if (sourceFile.open())
+ {
+ QDataStream stream(&sourceFile);
+ stream << currentTab()->page()->mainFrame()->toHtml().toUtf8();
+
+ url = KUrl();
+ url.setPath(sourceFile.fileName());
+ isTempFile = true;
+ }
+ }
+ KRun::runUrl(url, QLatin1String("text/plain"), this, isTempFile);
+}
+
+
+void MainWindow::slotHome()
+{
+ loadUrl(KUrl(m_homePage));
+}
+
+
+void MainWindow::slotToggleInspector(bool enable)
+{
+ QWebSettings::globalSettings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, enable);
+ if (enable)
+ {
+ int result = KMessageBox::questionYesNo(this,
+ i18n("The web inspector will only work correctly for pages that were loaded after enabling.\n"
+ "Do you want to reload all pages?"),
+ i18n("Web Inspector")
+ );
+
+ if (result == KMessageBox::Yes)
+ {
+ m_view->slotReloadAllTabs();
+ }
+ }
+}
+
+
+MainView *MainWindow::mainView() const
+{
+ return m_view;
+}
+
+
+
+WebView *MainWindow::currentTab() const
+{
+ return m_view->currentWebView();
+}
+
+
+void MainWindow::slotLoadProgress(int progress)
+{
+ QAction *stop = actionCollection()->action("stop");
+ QAction *reload = actionCollection()->action("view_redisplay");
+ if (progress < 100 && progress > 0)
+ {
+ disconnect(m_stopReloadAction, SIGNAL(triggered(bool)), reload , SIGNAL(triggered(bool)));
+ m_stopReloadAction->setIcon(KIcon("process-stop"));
+ m_stopReloadAction->setToolTip(i18n("Stop loading the current page"));
+ m_stopReloadAction->setText(i18n("Stop"));
+ connect(m_stopReloadAction, SIGNAL(triggered(bool)), stop, SIGNAL(triggered(bool)));
+ }
+ else
+ {
+ disconnect(m_stopReloadAction, SIGNAL(triggered(bool)), stop , SIGNAL(triggered(bool)));
+ m_stopReloadAction->setIcon(KIcon("view-refresh"));
+ m_stopReloadAction->setToolTip(i18n("Reload the current page"));
+ m_stopReloadAction->setText(i18n("Reload"));
+ connect(m_stopReloadAction, SIGNAL(triggered(bool)), reload, SIGNAL(triggered(bool)));
+
+ }
+}
+
+
+void MainWindow::slotAboutToShowBackMenu()
+{
+ m_historyBackMenu->clear();
+ if (!currentTab())
+ return;
+ QWebHistory *history = currentTab()->history();
+ int historyCount = history->count();
+ for (int i = history->backItems(historyCount).count() - 1; i >= 0; --i)
+ {
+ QWebHistoryItem item = history->backItems(history->count()).at(i);
+ KAction *action = new KAction(this);
+ action->setData(-1*(historyCount - i - 1));
+ QIcon icon = Application::instance()->icon(item.url());
+ action->setIcon(icon);
+ action->setText(item.title());
+ m_historyBackMenu->addAction(action);
+ }
+}
+
+
+void MainWindow::slotOpenActionUrl(QAction *action)
+{
+ int offset = action->data().toInt();
+ QWebHistory *history = currentTab()->history();
+ if (offset < 0)
+ {
+ history->goToItem(history->backItems(-1*offset).first()); // back
+ }
+ else
+ {
+ if (offset > 0)
+ {
+ history->goToItem(history->forwardItems(history->count() - offset + 1).back()); // forward
+ }
+ }
+}
+
+
+void MainWindow::slotOpenPrevious()
+{
+ QWebHistory *history = currentTab()->history();
+ if (history->canGoBack())
+ history->goToItem(history->backItem());
+}
+
+
+void MainWindow::slotOpenNext()
+{
+ QWebHistory *history = currentTab()->history();
+ if (history->canGoForward())
+ history->goToItem(history->forwardItem());
+}
+
+
+void MainWindow::geometryChangeRequested(const QRect &geometry)
+{
+ setGeometry(geometry);
+}
+
+
+void MainWindow::slotShowMenubar(bool enable)
+{
+ if (enable)
+ menuBar()->show();
+ else
+ menuBar()->hide();
+}
+
+
+bool MainWindow::queryClose()
+{
+ if (m_view->count() > 1)
+ {
+
+ int answer = KMessageBox::questionYesNoCancel(
+ this,
+ i18np("Are you sure you want to close the window?\n" "You have 1 tab open","Are you sure you want to close the window?\n" "You have %1 tabs open" , m_view->count()),
+ i18n("Are you sure you want to close the window?"),
+ KStandardGuiItem::quit(),
+ KGuiItem(i18n("C&lose Current Tab"), KIcon("tab-close")),
+ KStandardGuiItem::cancel(),
+ "confirmClosingMultipleTabs"
+ );
+
+ switch (answer)
+ {
+ case KMessageBox::Yes:
+ // Quit
+ return true;
+ break;
+ case KMessageBox::No:
+ // Close only the current tab
+ m_view->slotCloseTab();
+ default:
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+QAction *MainWindow::actionByName(const QString name)
+{
+ QAction *ret = actionCollection()->action(name);
+
+ if (ret)
+ return ret;
+
+ /* else */
+ kWarning() << "Action named: " << name << " not found, returning empty action.";
+
+ return new QAction(this); // return empty object instead of NULL pointer
+}
+
diff --git a/src/mainwindow.h b/src/mainwindow.h
new file mode 100644
index 00000000..cdb7151d
--- /dev/null
+++ b/src/mainwindow.h
@@ -0,0 +1,153 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007-2008 Trolltech ASA. All rights reserved
+* Copyright (C) 2008-2009 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009 by Paweł Prażak <pawelprazak 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+// Local Includes
+#include "searchbar.h"
+#include "bookmarks.h"
+#include "mainview.h"
+#include "webview.h"
+
+// KDE Includes
+#include <KXmlGuiWindow>
+#include <KToolBar>
+
+// Forward Declarations
+class QWebFrame;
+
+class KUrl;
+class KAction;
+class KActionMenu;
+class KIcon;
+class KMenu;
+
+class FindBar;
+class HistoryMenu;
+class SidePanel;
+class WebView;
+
+
+/**
+ * This class serves as the main window for rekonq.
+ * It handles the menus, toolbars, and status bars.
+ *
+ */
+class MainWindow : public KXmlGuiWindow
+{
+ Q_OBJECT
+
+public:
+ MainWindow();
+ ~MainWindow();
+
+ static KUrl guessUrlFromString(const QString &url);
+ MainView *mainView() const;
+ WebView *currentTab() const;
+ QAction *actionByName(const QString name);
+ virtual QSize sizeHint() const;
+
+private:
+ void setupActions();
+ void setupHistoryMenu();
+ void setupToolBars();
+ void setupSidePanel();
+ SidePanel *sidePanel()
+ {
+ return m_sidePanel;
+ }
+
+public slots:
+ void slotHome();
+ void loadUrl(const KUrl &url);
+ void slotUpdateBrowser();
+
+protected:
+ bool queryClose();
+
+private slots:
+ void postLaunch();
+ void slotUpdateConfiguration();
+ void slotLoadProgress(int);
+ void slotUpdateStatusbar(const QString &string);
+ void slotUpdateActions();
+ void slotUpdateWindowTitle(const QString &title = QString());
+ void slotOpenLocation();
+ void slotAboutToShowBackMenu();
+ void geometryChangeRequested(const QRect &geometry);
+
+ // history related
+ void slotOpenActionUrl(QAction *action);
+ void slotOpenPrevious();
+ void slotOpenNext();
+
+ // File Menu slots
+ void slotFileOpen();
+ void slotFilePrintPreview();
+ void slotFilePrint();
+ void slotPrivateBrowsing(bool);
+ void slotFileSaveAs();
+ void printRequested(QWebFrame *frame);
+
+ // Edit Menu slots
+ void slotFind(const QString &);
+ void slotFindNext();
+ void slotFindPrevious();
+
+ // View Menu slots
+ void slotViewTextBigger();
+ void slotViewTextNormal();
+ void slotViewTextSmaller();
+ void slotViewPageSource();
+ void slotViewFullScreen(bool enable);
+ void slotViewFindBar();
+
+ // Tools Menu slots
+ void slotToggleInspector(bool enable);
+
+ // Settings Menu slots
+ void slotShowMenubar(bool enable);
+ void slotPreferences();
+
+private:
+ MainView *m_view;
+ FindBar *m_findBar;
+ SearchBar *m_searchBar;
+ SidePanel *m_sidePanel;
+
+ KMenu *m_historyBackMenu;
+ KMenu *m_windowMenu;
+ KActionMenu *m_historyActionMenu;
+
+ KAction *m_stopReloadAction;
+ KAction *m_stopAction;
+ KAction *m_reloadAction;
+ KAction *m_historyBackAction;
+ KAction *m_historyForwardAction;
+
+ QString m_lastSearch;
+ QString m_homePage;
+};
+
+#endif // MAINWINDOW_H
diff --git a/src/modelmenu.cpp b/src/modelmenu.cpp
new file mode 100644
index 00000000..cc43a3f3
--- /dev/null
+++ b/src/modelmenu.cpp
@@ -0,0 +1,228 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007-2008 Trolltech ASA. All rights reserved
+* Copyright (C) 2008-2009 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+#include "modelmenu.h"
+
+
+ModelMenu::ModelMenu(QWidget * parent)
+ : KMenu(parent)
+ , m_maxRows(7)
+ , m_firstSeparator(-1)
+ , m_maxWidth(-1)
+ , m_hoverRole(0)
+ , m_separatorRole(0)
+ , m_model(0)
+{
+ connect(this, SIGNAL(aboutToShow()), this, SLOT(aboutToShow()));
+}
+
+
+bool ModelMenu::prePopulated()
+{
+ return false;
+}
+
+
+void ModelMenu::postPopulated()
+{
+}
+
+
+void ModelMenu::setModel(QAbstractItemModel *model)
+{
+ m_model = model;
+}
+
+
+QAbstractItemModel *ModelMenu::model() const
+{
+ return m_model;
+}
+
+
+void ModelMenu::setMaxRows(int max)
+{
+ m_maxRows = max;
+}
+
+
+int ModelMenu::maxRows() const
+{
+ return m_maxRows;
+}
+
+
+void ModelMenu::setFirstSeparator(int offset)
+{
+ m_firstSeparator = offset;
+}
+
+
+int ModelMenu::firstSeparator() const
+{
+ return m_firstSeparator;
+}
+
+
+void ModelMenu::setRootIndex(const QModelIndex &index)
+{
+ m_root = index;
+}
+
+
+QModelIndex ModelMenu::rootIndex() const
+{
+ return m_root;
+}
+
+
+void ModelMenu::setHoverRole(int role)
+{
+ m_hoverRole = role;
+}
+
+
+int ModelMenu::hoverRole() const
+{
+ return m_hoverRole;
+}
+
+
+void ModelMenu::setSeparatorRole(int role)
+{
+ m_separatorRole = role;
+}
+
+
+int ModelMenu::separatorRole() const
+{
+ return m_separatorRole;
+}
+
+
+Q_DECLARE_METATYPE(QModelIndex)
+void ModelMenu::aboutToShow()
+{
+ if (QMenu *menu = qobject_cast<QMenu*>(sender()))
+ {
+ QVariant v = menu->menuAction()->data();
+ if (v.canConvert<QModelIndex>())
+ {
+ QModelIndex idx = qvariant_cast<QModelIndex>(v);
+ createMenu(idx, -1, menu, menu);
+ disconnect(menu, SIGNAL(aboutToShow()), this, SLOT(aboutToShow()));
+ return;
+ }
+ }
+
+ clear();
+ if (prePopulated())
+ addSeparator();
+ int max = m_maxRows;
+ if (max != -1)
+ max += m_firstSeparator;
+ createMenu(m_root, max, this, this);
+ postPopulated();
+}
+
+void ModelMenu::createMenu(const QModelIndex &parent, int max, QMenu *parentMenu, QMenu *menu)
+{
+ if (!menu)
+ {
+ QString title = parent.data().toString();
+ menu = new QMenu(title, this);
+ QIcon icon = qvariant_cast<QIcon>(parent.data(Qt::DecorationRole));
+ menu->setIcon(icon);
+ parentMenu->addMenu(menu);
+ QVariant v;
+ v.setValue(parent);
+ menu->menuAction()->setData(v);
+ connect(menu, SIGNAL(aboutToShow()), this, SLOT(aboutToShow()));
+ return;
+ }
+
+ int end = m_model->rowCount(parent);
+ if (max != -1)
+ end = qMin(max, end);
+
+ connect(menu, SIGNAL(triggered(QAction*)), this, SLOT(triggered(QAction*)));
+ connect(menu, SIGNAL(hovered(QAction*)), this, SLOT(hovered(QAction*)));
+
+ for (int i = 0; i < end; ++i)
+ {
+ QModelIndex idx = m_model->index(i, 0, parent);
+ if (m_model->hasChildren(idx))
+ {
+ createMenu(idx, -1, menu);
+ }
+ else
+ {
+ if (m_separatorRole != 0
+ && idx.data(m_separatorRole).toBool())
+ addSeparator();
+ else
+ menu->addAction(makeAction(idx));
+ }
+ if (menu == this && i == m_firstSeparator - 1)
+ addSeparator();
+ }
+}
+
+KAction *ModelMenu::makeAction(const QModelIndex &index)
+{
+ QIcon icon = qvariant_cast<QIcon>(index.data(Qt::DecorationRole));
+ KAction *action = (KAction *) makeAction(KIcon(icon), index.data().toString(), this);
+ QVariant v;
+ v.setValue(index);
+ action->setData(v);
+ return action;
+}
+
+KAction *ModelMenu::makeAction(const KIcon &icon, const QString &text, QObject *parent)
+{
+ QFontMetrics fm(font());
+ if (-1 == m_maxWidth)
+ m_maxWidth = fm.width(QLatin1Char('m')) * 30;
+ QString smallText = fm.elidedText(text, Qt::ElideMiddle, m_maxWidth);
+ return new KAction(icon, smallText, parent);
+}
+
+void ModelMenu::triggered(QAction *action)
+{
+ QVariant v = action->data();
+ if (v.canConvert<QModelIndex>())
+ {
+ QModelIndex idx = qvariant_cast<QModelIndex>(v);
+ emit activated(idx);
+ }
+}
+
+void ModelMenu::hovered(QAction *action)
+{
+ QVariant v = action->data();
+ if (v.canConvert<QModelIndex>())
+ {
+ QModelIndex idx = qvariant_cast<QModelIndex>(v);
+ QString hoveredString = idx.data(m_hoverRole).toString();
+ if (!hoveredString.isEmpty())
+ emit hovered(hoveredString);
+ }
+}
diff --git a/src/modelmenu.h b/src/modelmenu.h
new file mode 100644
index 00000000..3cc657b3
--- /dev/null
+++ b/src/modelmenu.h
@@ -0,0 +1,92 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007-2008 Trolltech ASA. All rights reserved
+* Copyright (C) 2008-2009 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+
+#ifndef MODELMENU_H
+#define MODELMENU_H
+
+// Qt Includes
+#include <QtGui>
+#include <QtCore>
+
+// KDE Includes
+#include <KIcon>
+#include <KAction>
+#include <KMenu>
+
+// A QMenu that is dynamically populated from a QAbstractItemModel
+class ModelMenu : public KMenu
+{
+ Q_OBJECT
+
+signals:
+ void activated(const QModelIndex &index);
+ void hovered(const QString &text);
+
+public:
+ ModelMenu(QWidget *parent = 0);
+
+ void setModel(QAbstractItemModel *model);
+ QAbstractItemModel *model() const;
+
+ void setMaxRows(int max);
+ int maxRows() const;
+
+ void setFirstSeparator(int offset);
+ int firstSeparator() const;
+
+ void setRootIndex(const QModelIndex &index);
+ QModelIndex rootIndex() const;
+
+ void setHoverRole(int role);
+ int hoverRole() const;
+
+ void setSeparatorRole(int role);
+ int separatorRole() const;
+
+ KAction *makeAction(const KIcon &icon, const QString &text, QObject *parent);
+
+protected:
+ // add any actions before the tree, return true if any actions are added.
+ virtual bool prePopulated();
+ // add any actions after the tree
+ virtual void postPopulated();
+ // put all of the children of parent into menu up to max
+ void createMenu(const QModelIndex &parent, int max, QMenu *parentMenu = 0, QMenu *menu = 0);
+
+private slots:
+ void aboutToShow();
+ void triggered(QAction *action);
+ void hovered(QAction *action);
+
+private:
+ KAction *makeAction(const QModelIndex &index);
+ int m_maxRows;
+ int m_firstSeparator;
+ int m_maxWidth;
+ int m_hoverRole;
+ int m_separatorRole;
+ QAbstractItemModel *m_model;
+ QPersistentModelIndex m_root;
+};
+
+#endif // MODELMENU_H
+
diff --git a/src/networkaccessmanager.cpp b/src/networkaccessmanager.cpp
new file mode 100644
index 00000000..d92edbd6
--- /dev/null
+++ b/src/networkaccessmanager.cpp
@@ -0,0 +1,165 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007-2008 Trolltech ASA. All rights reserved
+* Copyright (C) 2008-2009 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "networkaccessmanager.h"
+#include "networkaccessmanager.moc"
+
+// Local Includes
+#include "application.h"
+#include "mainwindow.h"
+
+// Auto Includes
+#include "rekonq.h"
+
+// Ui Includes
+#include "ui_password.h"
+#include "ui_proxy.h"
+
+// KDE Includes
+#include <KMessageBox>
+#include <KStandardDirs>
+
+// Qt Includes
+#include <QDialog>
+#include <QStyle>
+#include <QTextDocument>
+#include <QAuthenticator>
+#include <QNetworkProxy>
+#include <QNetworkReply>
+#include <QSslError>
+
+
+NetworkAccessManager::NetworkAccessManager(QObject *parent)
+ : QNetworkAccessManager(parent)
+{
+ connect(this, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)),
+ SLOT(authenticationRequired(QNetworkReply*, QAuthenticator*)));
+ connect(this, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)),
+ SLOT(proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)));
+
+#ifndef QT_NO_OPENSSL
+ connect(this, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>&)),
+ SLOT(sslErrors(QNetworkReply*, const QList<QSslError>&)));
+#endif
+
+ loadSettings();
+
+ QNetworkDiskCache *diskCache = new QNetworkDiskCache(this);
+ QString location = KStandardDirs::locateLocal("cache", "", true);
+ diskCache->setCacheDirectory(location);
+ setCache(diskCache);
+}
+
+
+void NetworkAccessManager::loadSettings()
+{
+ QNetworkProxy proxy;
+ if (ReKonfig::isProxyEnabled())
+ {
+ if (ReKonfig::proxyType() == 0)
+ {
+ proxy.setType(QNetworkProxy::Socks5Proxy);
+ }
+ else
+ {
+ proxy.setType(QNetworkProxy::HttpProxy);
+ }
+ proxy.setHostName(ReKonfig::proxyHostName());
+ proxy.setPort(ReKonfig::proxyPort());
+ proxy.setUser(ReKonfig::proxyUserName());
+ proxy.setPassword(ReKonfig::proxyPassword());
+ }
+ setProxy(proxy);
+}
+
+
+
+void NetworkAccessManager::authenticationRequired(QNetworkReply *reply, QAuthenticator *auth)
+{
+ MainWindow *mainWindow = Application::instance()->mainWindow();
+
+ KDialog dialog(mainWindow, Qt::Sheet);
+ dialog.setButtons(KDialog::Ok | KDialog::Cancel);
+
+ Ui::passwordWidget passwordWidget;
+ QWidget widget;
+ passwordWidget.setupUi(&widget);
+
+ dialog.setMainWidget(&widget);
+
+ passwordWidget.iconLabel->setText(QString());
+ passwordWidget.iconLabel->setPixmap(mainWindow->style()->standardIcon(QStyle::SP_MessageBoxQuestion, 0, mainWindow).pixmap(32, 32));
+
+ QString introMessage = i18n("<qt>Enter username and password for ") +
+ Qt::escape(reply->url().toString()) + i18n(" at ") + Qt::escape(reply->url().toString()) + "</qt>";
+ passwordWidget.introLabel->setText(introMessage);
+ passwordWidget.introLabel->setWordWrap(true);
+
+ if (dialog.exec() == QDialog::Accepted)
+ {
+ auth->setUser(passwordWidget.userNameLineEdit->text());
+ auth->setPassword(passwordWidget.passwordLineEdit->text());
+ }
+}
+
+void NetworkAccessManager::proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth)
+{
+ MainWindow *mainWindow = Application::instance()->mainWindow();
+
+ KDialog dialog(mainWindow, Qt::Sheet);
+ dialog.setButtons(KDialog::Ok | KDialog::Cancel);
+
+ Ui::proxyWidget proxyWdg;
+ QWidget widget;
+ proxyWdg.setupUi(&widget);
+
+ dialog.setMainWidget(&widget);
+
+ proxyWdg.iconLabel->setText(QString());
+ proxyWdg.iconLabel->setPixmap(mainWindow->style()->standardIcon(QStyle::SP_MessageBoxQuestion, 0, mainWindow).pixmap(32, 32));
+
+ QString introMessage = i18n("<qt>Connect to proxy ") + Qt::escape(proxy.hostName()) + i18n(" using:</qt>");
+ proxyWdg.introLabel->setText(introMessage);
+ proxyWdg.introLabel->setWordWrap(true);
+
+ if (dialog.exec() == QDialog::Accepted)
+ {
+ auth->setUser(proxyWdg.userNameLineEdit->text());
+ auth->setPassword(proxyWdg.passwordLineEdit->text());
+ }
+}
+
+#ifndef QT_NO_OPENSSL
+void NetworkAccessManager::sslErrors(QNetworkReply *reply, const QList<QSslError> &error)
+{
+ MainWindow *mainWindow = Application::instance()->mainWindow();
+
+ QStringList errorStrings;
+ for (int i = 0; i < error.count(); ++i)
+ errorStrings += error.at(i).errorString();
+ QString errors = errorStrings.join(QLatin1String("\n"));
+ int ret = KMessageBox::warningYesNo(mainWindow, i18n("SSL Errors:\n\n") + reply->url().toString() + "\n\n" + QString(errors) + "\n\n");
+ if (ret == KMessageBox::Yes)
+ reply->ignoreSslErrors();
+}
+#endif
+
diff --git a/src/networkaccessmanager.h b/src/networkaccessmanager.h
new file mode 100644
index 00000000..ebcd952d
--- /dev/null
+++ b/src/networkaccessmanager.h
@@ -0,0 +1,47 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007-2008 Trolltech ASA. All rights reserved
+* Copyright (C) 2008-2009 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+#ifndef NETWORKACCESSMANAGER_H
+#define NETWORKACCESSMANAGER_H
+
+
+#include <QNetworkAccessManager>
+
+
+class NetworkAccessManager : public QNetworkAccessManager
+{
+ Q_OBJECT
+
+public:
+ NetworkAccessManager(QObject *parent = 0);
+
+public slots:
+ void loadSettings();
+
+private slots:
+ void authenticationRequired(QNetworkReply *reply, QAuthenticator *auth);
+ void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth);
+#ifndef QT_NO_OPENSSL
+ void sslErrors(QNetworkReply *reply, const QList<QSslError> &error);
+#endif
+};
+
+#endif // NETWORKACCESSMANAGER_H
diff --git a/src/panelhistory.cpp b/src/panelhistory.cpp
new file mode 100644
index 00000000..72507663
--- /dev/null
+++ b/src/panelhistory.cpp
@@ -0,0 +1,95 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009 by Domrachev Alexandr <alexandr.domrachev@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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "panelhistory.h"
+#include "panelhistory.moc"
+
+// QT Includes
+#include <QLabel>
+
+// KDE Includes
+#include <KLocalizedString>
+#include <KLineEdit>
+#include <KUrl>
+
+// Local Includes
+#include "history.h"
+
+
+PanelHistory::PanelHistory(QWidget *parent)
+ : QWidget(parent)
+ , m_historyTreeView(new QTreeView)
+ , m_treeProxyModel(new TreeProxyModel(this))
+{
+ m_historyTreeView->setUniformRowHeights(true);
+ m_historyTreeView->setSelectionBehavior(QAbstractItemView::SelectRows);
+ m_historyTreeView->setTextElideMode(Qt::ElideMiddle);
+ m_historyTreeView->setAlternatingRowColors(true);
+
+ // add search bar
+ QHBoxLayout *hBoxLayout = new QHBoxLayout;
+ hBoxLayout->setContentsMargins(5, 0, 0, 0);
+ QLabel *searchLabel = new QLabel(i18n("Search: "));
+ hBoxLayout->addWidget(searchLabel);
+ KLineEdit *search = new KLineEdit;
+ hBoxLayout->addWidget(search);
+ QWidget *searchBar = new QWidget;
+ searchBar->setLayout(hBoxLayout);
+
+ // setup view
+ QVBoxLayout *vBoxLayout = new QVBoxLayout;
+ vBoxLayout->setContentsMargins(0, 0, 0, 0);
+ vBoxLayout->addWidget(searchBar);
+ vBoxLayout->addWidget(m_historyTreeView);
+ setLayout(vBoxLayout);
+
+ //-
+ HistoryManager *historyManager = Application::historyManager();
+ QAbstractItemModel *model = historyManager->historyTreeModel();
+
+ m_treeProxyModel->setSourceModel(model);
+ m_historyTreeView->setModel(m_treeProxyModel);
+ m_historyTreeView->setExpanded(m_treeProxyModel->index(0, 0), true);
+ m_historyTreeView->header()->hideSection(1);
+ QFontMetrics fm(font());
+ int header = fm.width(QLatin1Char('m')) * 40;
+ m_historyTreeView->header()->resizeSection(0, header);
+
+ connect(search, SIGNAL(textChanged(QString)), m_treeProxyModel, SLOT(setFilterFixedString(QString)));
+ connect(m_historyTreeView, SIGNAL(activated(const QModelIndex&)), this, SLOT(open()));
+}
+
+
+PanelHistory::~PanelHistory()
+{
+ delete m_treeProxyModel;
+ delete m_historyTreeView;
+}
+
+
+void PanelHistory::open()
+{
+ QModelIndex index = m_historyTreeView->currentIndex();
+ if (!index.parent().isValid())
+ return;
+ emit openUrl(index.data(HistoryModel::UrlRole).toUrl());
+}
+
diff --git a/src/panelhistory.h b/src/panelhistory.h
new file mode 100644
index 00000000..89759a84
--- /dev/null
+++ b/src/panelhistory.h
@@ -0,0 +1,55 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009 by Domrachev Alexandr <alexandr.domrachev@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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+#ifndef PANELHISTORY_H
+#define PANELHISTORY_H
+
+// Qt Includes
+#include <QWidget>
+
+// Local Includes
+#include "application.h"
+
+class QTreeView;
+class KUrl;
+class TreeProxyModel;
+
+
+class PanelHistory : public QWidget
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(PanelHistory)
+
+public:
+ explicit PanelHistory(QWidget *parent = 0);
+ virtual ~PanelHistory();
+
+signals:
+ void openUrl(const KUrl &);
+
+private slots:
+ void open();
+
+private:
+ QTreeView *m_historyTreeView;
+ TreeProxyModel *m_treeProxyModel;
+
+};
+
+#endif // PANELHISTORY_H
diff --git a/src/password.ui b/src/password.ui
new file mode 100644
index 00000000..028e1683
--- /dev/null
+++ b/src/password.ui
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>passwordWidget</class>
+ <widget class="QWidget" name="passwordWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>343</width>
+ <height>193</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0" colspan="2">
+ <layout class="QHBoxLayout">
+ <item>
+ <widget class="QLabel" name="iconLabel">
+ <property name="text">
+ <string>DUMMY ICON</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="introLabel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>INTRO TEXT DUMMY</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Username:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="userNameLineEdit"/>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="lblPassword">
+ <property name="text">
+ <string>Password:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLineEdit" name="passwordLineEdit">
+ <property name="echoMode">
+ <enum>QLineEdit::Password</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/proxy.ui b/src/proxy.ui
new file mode 100644
index 00000000..e7440862
--- /dev/null
+++ b/src/proxy.ui
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>proxyWidget</class>
+ <widget class="QWidget" name="proxyWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>264</width>
+ <height>153</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="iconLabel">
+ <property name="text">
+ <string>ICON</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" colspan="2">
+ <widget class="QLabel" name="introLabel">
+ <property name="text">
+ <string>Connect to proxy</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="2">
+ <widget class="QLabel" name="usernameLabel">
+ <property name="text">
+ <string>Username:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QLineEdit" name="userNameLineEdit"/>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <widget class="QLabel" name="passwordLabel">
+ <property name="text">
+ <string>Password:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QLineEdit" name="passwordLineEdit">
+ <property name="echoMode">
+ <enum>QLineEdit::Password</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/rekonq.kcfg b/src/rekonq.kcfg
new file mode 100644
index 00000000..499258d2
--- /dev/null
+++ b/src/rekonq.kcfg
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="rekonqrc"/>
+
+<!-- Includes -->
+<include>QtWebKit</include>
+<include>KUrl</include>
+
+<!-- General Settings -->
+ <group name="General">
+ <entry name="homePage" type="String">
+ <default>http://www.kde.org/</default>
+ </entry>
+ <entry name="downloadDir" type="Path">
+ <default>$HOME</default>
+ </entry>
+ <entry name="downloadToDefaultDir" type="Bool">
+ <default>false</default>
+ </entry>
+ <entry name="alwaysShowTabBar" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="showSideBar" type="Bool">
+ <default>false</default>
+ </entry>
+ <entry name="openTabsBack" type="Bool">
+ <default>false</default>
+ </entry>
+ </group>
+
+<!-- Fonts Settings -->
+ <group name="Fonts">
+ <entry name="standardFont" type="Font">
+ <default code="true">QFont(QWebSettings::globalSettings()->fontFamily(QWebSettings::StandardFont))</default>
+ </entry>
+ <entry name="fixedFont" type="Font">
+ <default code="true">QFont(QWebSettings::globalSettings()->fontFamily(QWebSettings::FixedFont))</default>
+ </entry>
+ <entry name="fontSize" type="Int">
+ <default>12</default>
+ </entry>
+ </group>
+
+<!-- Privacy Settings -->
+ <group name="Privacy">
+ <entry name="expireHistory" type="Int">
+ <default>1</default>
+ </entry>
+ <entry name="acceptCookies" type="Int">
+ <default>2</default>
+ </entry>
+ <entry name="keepCookiesUntil" type="Int">
+ <default>0</default>
+ </entry>
+ </group>
+
+<!-- Proxy Settings -->
+ <group name="Proxy">
+ <entry name="isProxyEnabled" type="Bool">
+ <default>false</default>
+ </entry>
+ <entry name="proxyType" type="Int">
+ <default>0</default>
+ </entry>
+ <entry name="proxyHostName" type="String">
+ </entry>
+ <entry name="proxyPort" type="Int">
+ <default>8080</default>
+ </entry>
+ <entry name="proxyUserName" type="String">
+ </entry>
+ <entry name="proxyPassword" type="Password">
+ </entry>
+ </group>
+
+<!-- WebKit Settings -->
+ <group name="Webkit">
+ <entry name="autoLoadImages" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="javascriptEnabled" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="javaEnabled" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="pluginsEnabled" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="javascriptCanOpenWindows" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="javascriptCanAccessClipboard" type="Bool">
+ <default>false</default>
+ </entry>
+ <entry name="linksIncludedInFocusChain" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="zoomTextOnly" type="Bool">
+ <default>false</default>
+ </entry>
+ <entry name="printElementBackgrounds" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="offlineStorageDatabaseEnabled" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="offlineWebApplicationCacheEnabled" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="localStorageDatabaseEnabled" type="Bool">
+ <default>true</default>
+ </entry>
+ </group>
+
+</kcfg>
diff --git a/src/rekonq.kcfgc b/src/rekonq.kcfgc
new file mode 100644
index 00000000..50a9817d
--- /dev/null
+++ b/src/rekonq.kcfgc
@@ -0,0 +1,5 @@
+File=rekonq.kcfg
+ClassName=ReKonfig
+Singleton=true
+Mutators=true
+UseEnumTypes=true
diff --git a/src/rekonqui.rc b/src/rekonqui.rc
new file mode 100644
index 00000000..aa372538
--- /dev/null
+++ b/src/rekonqui.rc
@@ -0,0 +1,104 @@
+<?xml version="1.0"?>
+<!DOCTYPE gui SYSTEM "kpartgui.dtd">
+<gui name="rekonq" version="40">
+
+<MenuBar>
+
+<!-- ============ FILE menu =========== -->
+<Menu name="file" noMerge="1"><text>&amp;File</text>
+ <Action name="file_open" />
+ <Action name="open_location" />
+ <Separator/>
+ <Action name="new_tab" />
+ <Action name="close_tab" />
+ <Separator/>
+ <Action name="file_save_as" />
+ <Separator/>
+ <Action name="file_print_preview" />
+ <Action name="file_print" />
+ <Separator/>
+ <Action name="file_quit" />
+</Menu>
+
+<!-- ============ EDIT menu =========== -->
+<Menu name="edit" noMerge="1"><text>&amp;Edit</text>
+ <Action name="edit_undo" />
+ <Action name="edit_redo" />
+ <Separator/>
+ <Action name="edit_cut" />
+ <Action name="edit_copy" />
+ <Action name="edit_paste" />
+ <Separator/>
+ <Action name="edit_find" />
+ <Action name="edit_find_next" />
+ <Action name="edit_find_prev" />
+</Menu>
+
+<!-- ============ VIEW menu =========== -->
+<Menu name="view" noMerge="1"><text>&amp;View</text>
+ <Action name="stop_reload" />
+ <Action name="go_home" />
+ <Separator/>
+ <Action name="bigger_font" />
+ <Action name="normal_font" />
+ <Action name="smaller_font" />
+ <Separator/>
+ <Action name="page_source" />
+</Menu>
+
+<!-- ============ GO menu =========== -->
+<Menu name="go" deleted="true">
+</Menu>
+
+<!-- ============ HISTORY menu =========== -->
+<Action name="history" ><text>Hi&amp;story</text>
+</Action>
+
+<!-- ============ BOOKMARKS menu =========== -->
+<Action name="bookmarks" ><text>&amp;Bookmarks</text>
+</Action>
+
+<!-- ============ TOOLS menu =========== -->
+<Menu name="tools" noMerge="1"><text>&amp;Tools</text>
+ <Action name="web_inspector" />
+ <Action name="private_browsing" />
+</Menu>
+
+<!-- ============ SETTINGS menu =========== -->
+<Menu name="settings" noMerge="1"><text>&amp;Settings</text>
+ <Action name="options_show_menubar" />
+ <Action name="options_show_statusbar" />
+ <Merge name="StandardToolBarMenuHandler" />
+ <Merge/>
+ <Menu name="side_panels"><text>Side &amp;Panels</text>
+ <Action name="show_history_panel" />
+ </Menu>
+ <Separator/>
+ <Action name="fullscreen" />
+ <Separator/>
+ <Action name="options_configure_keybinding" />
+ <Action name="options_configure_toolbars" />
+ <Action name="options_configure" />
+</Menu>
+
+</MenuBar>
+
+<!-- ============ Main ToolBar =========== -->
+<ToolBar name="mainToolBar" position="top" iconText="iconOnly" newline="true" noMerge="1">
+<text>Main Toolbar</text>
+ <Action name="history_back" />
+ <Action name="history_forward" />
+ <Action name="stop_reload" />
+ <Action name="go_home" />
+ <Action name="new_tab" />
+ <Action name="url_bar" />
+ <Action name="search_bar" />
+</ToolBar>
+
+<!-- ============ Bookmarks ToolBar =========== -->
+<ToolBar name="bookmarksToolBar" fullWidth="true" iconText="icontextright" iconSize="16" newline="true" hidden="true" noEdit="true">
+ <text>Bookmark Toolbar</text>
+ <Action noEdit="true" name="bookmarks_bar" />
+</ToolBar>
+
+</gui>
diff --git a/src/searchbar.cpp b/src/searchbar.cpp
new file mode 100644
index 00000000..fad35748
--- /dev/null
+++ b/src/searchbar.cpp
@@ -0,0 +1,129 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2008-2009 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "searchbar.h"
+#include "searchbar.moc"
+
+// Local Includes
+#include "application.h"
+#include "mainwindow.h"
+
+// KDE Includes
+#include <KUrl>
+
+// Qt Includes
+#include <QtCore>
+#include <QtGui>
+#include <QtNetwork>
+
+
+SearchBar::SearchBar(QWidget *parent) :
+ KLineEdit(parent)
+ , m_networkAccessManager(new QNetworkAccessManager(this))
+ , m_timer(new QTimer(this))
+{
+ setMinimumWidth(180);
+
+ setFocusPolicy(Qt::WheelFocus);
+ setMouseTracking(true);
+ setAcceptDrops(true);
+
+ QSizePolicy policy = sizePolicy();
+ setSizePolicy(QSizePolicy::Preferred, policy.verticalPolicy());
+
+ setClearButtonShown(true);
+
+ // better solution than using QPalette(s)..
+ setClickMessage(i18n("Search.."));
+
+ // setting QNetworkAccessManager..
+ connect(m_networkAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(handleNetworkData(QNetworkReply*)));
+
+ // setting QTimer..
+ m_timer->setSingleShot(true);
+ m_timer->setInterval(200);
+ connect(m_timer, SIGNAL(timeout()), SLOT(autoSuggest()));
+ connect(this, SIGNAL(textEdited(QString)), m_timer, SLOT(start()));
+
+ // connect searchNow slot..
+ connect(this, SIGNAL(returnPressed()) , this , SLOT(searchNow()));
+}
+
+
+SearchBar::~SearchBar()
+{
+}
+
+
+void SearchBar::searchNow()
+{
+ m_timer->stop();
+ QString searchText = text();
+
+ KUrl url(QLatin1String("http://www.google.com/search"));
+ url.addQueryItem(QLatin1String("q"), searchText);
+ url.addQueryItem(QLatin1String("ie"), QLatin1String("UTF-8"));
+ url.addQueryItem(QLatin1String("oe"), QLatin1String("UTF-8"));
+ url.addQueryItem(QLatin1String("client"), QLatin1String("rekonq"));
+ emit search(url);
+}
+
+
+void SearchBar::focusInEvent(QFocusEvent *event)
+{
+ KLineEdit::focusInEvent(event);
+ clear();
+}
+
+
+void SearchBar::autoSuggest()
+{
+ QString str = text();
+ QString url = QString("http://google.com/complete/search?output=toolbar&q=%1").arg(str);
+ m_networkAccessManager->get(QNetworkRequest(QString(url)));
+}
+
+
+void SearchBar::handleNetworkData(QNetworkReply *networkReply)
+{
+ QUrl url = networkReply->url();
+ if (!networkReply->error())
+ {
+ QStringList choices;
+
+ QString response(networkReply->readAll());
+ QXmlStreamReader xml(response);
+ while (!xml.atEnd())
+ {
+ xml.readNext();
+ if (xml.tokenType() == QXmlStreamReader::StartElement)
+ if (xml.name() == "suggestion")
+ {
+ QStringRef str = xml.attributes().value("data");
+ choices << str.toString();
+ }
+ }
+
+ setCompletedItems(choices, true);
+ }
+
+ networkReply->deleteLater();
+}
diff --git a/src/searchbar.h b/src/searchbar.h
new file mode 100644
index 00000000..3fdf55b4
--- /dev/null
+++ b/src/searchbar.h
@@ -0,0 +1,67 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2008-2009 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+
+#ifndef SEARCHBAR_H
+#define SEARCHBAR_H
+
+// KDE Includes
+#include <KLineEdit>
+
+// Forward Declarations
+class KUrl;
+class QFocusEvent;
+class QTimer;
+class QNetworkAccessManager;
+class QNetworkReply;
+
+/**
+ * This class defines an internet search bar.
+ */
+class SearchBar : public KLineEdit
+{
+ Q_OBJECT
+
+public:
+ SearchBar(QWidget *parent = 0);
+ ~SearchBar();
+
+public slots:
+ void autoSuggest();
+ void handleNetworkData(QNetworkReply *networkReply);
+
+ /**
+ * Use this slot to perform one search in one search engine
+ *
+ */
+ void searchNow();
+
+protected:
+ void focusInEvent(QFocusEvent *);
+
+signals:
+ void search(const KUrl &);
+
+private:
+ QNetworkAccessManager *m_networkAccessManager;
+ QTimer *m_timer;
+};
+
+#endif
diff --git a/src/settings.cpp b/src/settings.cpp
new file mode 100644
index 00000000..1e42413f
--- /dev/null
+++ b/src/settings.cpp
@@ -0,0 +1,212 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007-2008 Trolltech ASA. All rights reserved
+* Copyright (C) 2008-2009 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+
+// Self Includes
+#include "settings.h"
+#include "settings.moc"
+
+// Auto Includes
+#include "rekonq.h"
+
+// Local Includes
+#include "application.h"
+#include "mainwindow.h"
+#include "cookiejar.h"
+#include "history.h"
+#include "networkaccessmanager.h"
+#include "webview.h"
+
+//Ui Includes
+#include "ui_settings_general.h"
+#include "ui_settings_fonts.h"
+#include "ui_settings_privacy.h"
+#include "ui_settings_proxy.h"
+#include "ui_settings_webkit.h"
+
+// KDE Includes
+#include <KConfig>
+#include <KStandardDirs>
+#include <KConfigSkeleton>
+#include <KPageWidgetItem>
+#include <KFontDialog>
+#include <KUrl>
+
+// Qt Includes
+#include <QtGui>
+#include <QtWebKit>
+
+
+class Private
+{
+private:
+ Ui::general generalUi;
+ Ui::fonts fontsUi;
+ Ui::privacy privacyUi;
+ Ui::proxy proxyUi;
+ Ui::webkit webkitUi;
+
+ Private(SettingsDialog *parent);
+
+ friend class SettingsDialog;
+};
+
+
+Private::Private(SettingsDialog *parent)
+{
+ QWidget *widget;
+ KPageWidgetItem *pageItem;
+
+ widget = new QWidget;
+ generalUi.setupUi(widget);
+ widget->layout()->setMargin(0);
+ pageItem = parent->addPage(widget , i18n("General"));
+ pageItem->setIcon(KIcon("rekonq"));
+
+ widget = new QWidget;
+ fontsUi.setupUi(widget);
+ widget->layout()->setMargin(0);
+ pageItem = parent->addPage(widget , i18n("Fonts"));
+ pageItem->setIcon(KIcon("preferences-desktop-font"));
+
+ widget = new QWidget;
+ privacyUi.setupUi(widget);
+ widget->layout()->setMargin(0);
+ pageItem = parent->addPage(widget , i18n("Privacy"));
+ pageItem->setIcon(KIcon("preferences-desktop-personal"));
+
+ widget = new QWidget;
+ proxyUi.setupUi(widget);
+ widget->layout()->setMargin(0);
+ pageItem = parent->addPage(widget , i18n("Proxy"));
+ pageItem->setIcon(KIcon("preferences-system-network"));
+
+ widget = new QWidget;
+ webkitUi.setupUi(widget);
+ widget->layout()->setMargin(0);
+ pageItem = parent->addPage(widget , i18n("Webkit"));
+ QString webkitIconPath = KStandardDirs::locate("appdata", "pics/webkit-icon.png");
+ kWarning() << webkitIconPath;
+ KIcon webkitIcon = KIcon(QIcon(webkitIconPath));
+ pageItem->setIcon(webkitIcon);
+}
+
+// -----------------------------------------------------------------------------------------------------
+
+SettingsDialog::SettingsDialog(QWidget *parent)
+ : KConfigDialog(parent, "rekonfig", ReKonfig::self())
+ , d(new Private(this))
+{
+ setFaceType(KPageDialog::List);
+ showButtonSeparator(true);
+
+ setWindowTitle(i18n("rekonfig.."));
+ setModal(true);
+
+ readConfig();
+
+ connect(d->generalUi.setHomeToCurrentPageButton, SIGNAL(clicked()), this, SLOT(setHomeToCurrentPage()));
+ connect(d->privacyUi.exceptionsButton, SIGNAL(clicked()), this, SLOT(showExceptions()));
+ connect(d->privacyUi.cookiesButton, SIGNAL(clicked()), this, SLOT(showCookies()));
+
+ setWebSettingsToolTips();
+}
+
+
+
+SettingsDialog::~SettingsDialog()
+{
+ delete d;
+}
+
+
+void SettingsDialog::setWebSettingsToolTips()
+{
+ d->webkitUi.kcfg_autoLoadImages->setToolTip(i18n("Specifies whether images are automatically loaded in web pages"));
+ d->webkitUi.kcfg_javascriptEnabled->setToolTip(i18n("Enables the running of JavaScript programs."));
+ d->webkitUi.kcfg_javaEnabled->setToolTip(i18n("Enables Java applets."));
+ d->webkitUi.kcfg_pluginsEnabled->setToolTip(i18n("Enables plugins in web pages."));
+ d->webkitUi.kcfg_javascriptCanOpenWindows->setToolTip(i18n("Allows JavaScript programs to opening new windows."));
+ d->webkitUi.kcfg_javascriptCanAccessClipboard->setToolTip(i18n("Allows JavaScript programs to reading/writing to the clipboard."));
+ d->webkitUi.kcfg_linksIncludedInFocusChain->setToolTip(i18n("Includes hyperlinks in the keyboard focus chain."));
+ d->webkitUi.kcfg_zoomTextOnly->setToolTip(i18n("Applies the zoom factor on a frame to only the text or all content."));
+ d->webkitUi.kcfg_printElementBackgrounds->setToolTip(i18n("Draws also background color and images when the page is printed."));
+ d->webkitUi.kcfg_offlineStorageDatabaseEnabled->setToolTip(i18n("Support for the HTML 5 offline storage feature."));
+ d->webkitUi.kcfg_offlineWebApplicationCacheEnabled->setToolTip(i18n("Support for the HTML 5 web application cache feature."));
+ d->webkitUi.kcfg_localStorageDatabaseEnabled->setToolTip(i18n("Support for the HTML 5 local storage feature."));
+}
+
+
+// we need this function to UPDATE the config widget data..
+void SettingsDialog::readConfig()
+{
+ // ======= General
+ d->generalUi.downloadDirUrlRequester->setMode(KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly);
+ d->generalUi.downloadDirUrlRequester->setUrl(ReKonfig::downloadDir());
+ connect(d->generalUi.downloadDirUrlRequester, SIGNAL(textChanged(QString)), this, SLOT(saveSettings()));
+
+ // ======= Fonts
+ d->fontsUi.kcfg_fixedFont->setOnlyFixed(true);
+
+ // ======= Proxy
+ bool proxyEnabled = ReKonfig::isProxyEnabled();
+ d->proxyUi.groupBox->setEnabled(proxyEnabled);
+ connect(d->proxyUi.kcfg_isProxyEnabled, SIGNAL(clicked(bool)), d->proxyUi.groupBox, SLOT(setEnabled(bool)));
+}
+
+
+// we need this function to SAVE settings in rc file..
+void SettingsDialog::saveSettings()
+{
+ // General
+ ReKonfig::setDownloadDir(d->generalUi.downloadDirUrlRequester->url().prettyUrl());
+
+ // Save
+ ReKonfig::self()->writeConfig();
+}
+
+
+// ----------------------------------------------------------------------------------------------
+
+
+void SettingsDialog::showCookies()
+{
+ CookiesDialog *dialog = new CookiesDialog(Application::cookieJar(), this);
+ dialog->exec();
+}
+
+
+void SettingsDialog::showExceptions()
+{
+ CookiesExceptionsDialog *dialog = new CookiesExceptionsDialog(Application::cookieJar(), this);
+ dialog->exec();
+}
+
+
+void SettingsDialog::setHomeToCurrentPage()
+{
+ MainWindow *mw = static_cast<MainWindow*>(parent());
+ WebView *webView = mw->currentTab();
+ if (webView)
+ {
+ d->generalUi.kcfg_homePage->setText(webView->url().prettyUrl());
+ }
+}
diff --git a/src/settings.h b/src/settings.h
new file mode 100644
index 00000000..26fd2d16
--- /dev/null
+++ b/src/settings.h
@@ -0,0 +1,55 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007-2008 Trolltech ASA. All rights reserved
+* Copyright (C) 2008-2009 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+#ifndef SETTINGS_H
+#define SETTINGS_H
+
+// KDE Includes
+#include <KConfigDialog>
+
+// Forward Declarations
+class QWidget;
+class Private;
+
+
+class SettingsDialog : public KConfigDialog
+{
+ Q_OBJECT
+
+public:
+ SettingsDialog(QWidget *parent = 0);
+ ~SettingsDialog();
+
+private:
+ Private* const d;
+
+ void setWebSettingsToolTips();
+
+private slots:
+ void readConfig();
+ void saveSettings();
+
+ void setHomeToCurrentPage();
+ void showCookies();
+ void showExceptions();
+};
+
+#endif // SETTINGS_H
diff --git a/src/settings_fonts.ui b/src/settings_fonts.ui
new file mode 100644
index 00000000..de258cad
--- /dev/null
+++ b/src/settings_fonts.ui
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>fonts</class>
+ <widget class="QWidget" name="fonts">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>414</width>
+ <height>298</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Appearance</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Fonts</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Standard Font</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Fixed Font</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="KFontComboBox" name="kcfg_fixedFont"/>
+ </item>
+ <item row="0" column="1">
+ <widget class="KFontComboBox" name="kcfg_standardFont"/>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string>Dimension</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Font Size</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="kcfg_fontSize"/>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>KFontComboBox</class>
+ <extends>KComboBox</extends>
+ <header>kfontcombobox.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/settings_general.ui b/src/settings_general.ui
new file mode 100644
index 00000000..44561b02
--- /dev/null
+++ b/src/settings_general.ui
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>general</class>
+ <widget class="QWidget" name="general">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>515</width>
+ <height>415</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>General</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Places</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Home Page:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="KLineEdit" name="kcfg_homePage">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QPushButton" name="setHomeToCurrentPageButton">
+ <property name="text">
+ <string>Set to current page</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="1">
+ <widget class="KUrlRequester" name="downloadDirUrlRequester"/>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_7">
+ <property name="text">
+ <string>Save downloads to:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QCheckBox" name="kcfg_downloadToDefaultDir">
+ <property name="text">
+ <string>ask where saving downloads</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_3">
+ <property name="title">
+ <string>Tabbed Browsing</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QCheckBox" name="kcfg_alwaysShowTabBar">
+ <property name="text">
+ <string>Always show tab bar</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="kcfg_openTabsBack">
+ <property name="text">
+ <string>Open tabs in the background</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>KLineEdit</class>
+ <extends>QLineEdit</extends>
+ <header>klineedit.h</header>
+ </customwidget>
+ <customwidget>
+ <class>KUrlRequester</class>
+ <extends>QFrame</extends>
+ <header>kurlrequester.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/settings_privacy.ui b/src/settings_privacy.ui
new file mode 100644
index 00000000..78202688
--- /dev/null
+++ b/src/settings_privacy.ui
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>privacy</class>
+ <widget class="QWidget" name="privacy">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>461</width>
+ <height>313</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Privacy</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string>History</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Remove history items:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="kcfg_expireHistory">
+ <item>
+ <property name="text">
+ <string>After one day</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>After one week</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>After two weeks</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>After one month</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>After one year</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Manually</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="cookiesGroupBox">
+ <property name="title">
+ <string>Cookies</string>
+ </property>
+ <layout class="QGridLayout" name="_2">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Accept Cookies:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="kcfg_acceptCookies">
+ <item>
+ <property name="text">
+ <string>Always</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Never</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Only from sites you visit</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QPushButton" name="exceptionsButton">
+ <property name="text">
+ <string>Exceptions...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Keep until:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="kcfg_keepCookiesUntil">
+ <item>
+ <property name="text">
+ <string>They expire</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>I exit the application</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>At most 90 days</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QPushButton" name="cookiesButton">
+ <property name="text">
+ <string>Cookies...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>136</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/settings_proxy.ui b/src/settings_proxy.ui
new file mode 100644
index 00000000..90e308a2
--- /dev/null
+++ b/src/settings_proxy.ui
@@ -0,0 +1,152 @@
+<ui version="4.0" >
+ <class>proxy</class>
+ <widget class="QWidget" name="proxy" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>440</width>
+ <height>223</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Proxy</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout" >
+ <item>
+ <widget class="QCheckBox" name="kcfg_isProxyEnabled" >
+ <property name="text" >
+ <string>Enable proxy</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox" >
+ <property name="title" >
+ <string>Proxy Settings</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_6" >
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label_9" >
+ <property name="text" >
+ <string>Type:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" colspan="2" >
+ <widget class="QComboBox" name="kcfg_proxyType" >
+ <item>
+ <property name="text" >
+ <string>SOCKS 5</string>
+ </property>
+ </item>
+ <item>
+ <property name="text" >
+ <string>HTTP</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <widget class="QLabel" name="label_10" >
+ <property name="text" >
+ <string>Host:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" colspan="2" >
+ <widget class="KLineEdit" name="kcfg_proxyHostName" />
+ </item>
+ <item row="3" column="0" >
+ <widget class="QLabel" name="label_11" >
+ <property name="text" >
+ <string>Port:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" >
+ <widget class="QSpinBox" name="kcfg_proxyPort" >
+ <property name="maximum" >
+ <number>10000</number>
+ </property>
+ <property name="value" >
+ <number>1080</number>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="2" >
+ <spacer name="horizontalSpacer_2" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>293</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="4" column="0" >
+ <widget class="QLabel" name="label_12" >
+ <property name="text" >
+ <string>Username:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1" colspan="2" >
+ <widget class="KLineEdit" name="kcfg_proxyUserName" />
+ </item>
+ <item row="5" column="0" >
+ <widget class="QLabel" name="label_13" >
+ <property name="text" >
+ <string>Password:</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1" colspan="2" >
+ <widget class="KLineEdit" name="kcfg_proxyPassword" />
+ </item>
+ <item row="6" column="0" >
+ <spacer name="verticalSpacer_2" >
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>20</width>
+ <height>8</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>KLineEdit</class>
+ <extends>QLineEdit</extends>
+ <header>klineedit.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/settings_webkit.ui b/src/settings_webkit.ui
new file mode 100644
index 00000000..362e392a
--- /dev/null
+++ b/src/settings_webkit.ui
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>webkit</class>
+ <widget class="QWidget" name="webkit">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>564</width>
+ <height>360</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>WebKit Settings</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QCheckBox" name="kcfg_autoLoadImages">
+ <property name="text">
+ <string>Auto Load Images</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" rowspan="6">
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QCheckBox" name="kcfg_linksIncludedInFocusChain">
+ <property name="text">
+ <string>Links included in focus chain</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QCheckBox" name="kcfg_javascriptEnabled">
+ <property name="text">
+ <string>Javascript support</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QCheckBox" name="kcfg_zoomTextOnly">
+ <property name="text">
+ <string>Zoom Text Only</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QCheckBox" name="kcfg_javaEnabled">
+ <property name="text">
+ <string>Java support</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QCheckBox" name="kcfg_printElementBackgrounds">
+ <property name="text">
+ <string>Print element Backgrounds</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QCheckBox" name="kcfg_pluginsEnabled">
+ <property name="text">
+ <string>Plugins</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="2">
+ <widget class="QCheckBox" name="kcfg_offlineStorageDatabaseEnabled">
+ <property name="text">
+ <string>Offline storage Database</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QCheckBox" name="kcfg_javascriptCanOpenWindows">
+ <property name="text">
+ <string>Javascript can open windows</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="2">
+ <widget class="QCheckBox" name="kcfg_offlineWebApplicationCacheEnabled">
+ <property name="text">
+ <string>Offline Web Application Cache </string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QCheckBox" name="kcfg_javascriptCanAccessClipboard">
+ <property name="text">
+ <string>Javascript can access clipboard</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="2">
+ <widget class="QCheckBox" name="kcfg_localStorageDatabaseEnabled">
+ <property name="text">
+ <string>Local storage database</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>146</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/sidepanel.cpp b/src/sidepanel.cpp
new file mode 100644
index 00000000..0fab81c0
--- /dev/null
+++ b/src/sidepanel.cpp
@@ -0,0 +1,53 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009 by Paweł Prażak <pawelprazak 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+// Self Includes
+#include "sidepanel.h"
+#include "sidepanel.moc"
+
+// Auto Includes
+#include "rekonq.h"
+
+// Local Includes
+#include "panelhistory.h"
+
+
+SidePanel::SidePanel(const QString &title, QWidget *parent, Qt::WindowFlags flags)
+ : QDockWidget(title, parent, flags)
+ , m_panelHistory(new PanelHistory(this))
+{
+ setObjectName("sidePanel");
+ setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
+
+ setShown(ReKonfig::showSideBar());
+
+ connect(m_panelHistory, SIGNAL(openUrl(const KUrl&)), this, SIGNAL(openUrl(const KUrl&)));
+
+ setWidget(m_panelHistory);
+}
+
+
+SidePanel::~SidePanel()
+{
+ // Save side panel's state
+ ReKonfig::setShowSideBar(!isHidden());
+
+ delete m_panelHistory;
+}
+
diff --git a/src/sidepanel.h b/src/sidepanel.h
new file mode 100644
index 00000000..c0af7827
--- /dev/null
+++ b/src/sidepanel.h
@@ -0,0 +1,50 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009 by Paweł Prażak <pawelprazak 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+#ifndef SIDEPANEL_H
+#define SIDEPANEL_H
+
+// Qt Includes
+#include <QDockWidget>
+
+// Local Includes
+#include "application.h"
+
+class KUrl;
+class PanelHistory;
+
+
+class SidePanel : public QDockWidget
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(SidePanel)
+
+public:
+ explicit SidePanel(const QString &title, QWidget *parent = 0, Qt::WindowFlags flags = 0);
+ ~SidePanel();
+
+signals:
+ void openUrl(const KUrl &);
+
+private:
+ PanelHistory *m_panelHistory;
+
+};
+
+#endif // SIDEPANEL_H
diff --git a/src/stackedurlbar.cpp b/src/stackedurlbar.cpp
new file mode 100644
index 00000000..113c8769
--- /dev/null
+++ b/src/stackedurlbar.cpp
@@ -0,0 +1,152 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009 by Paweł Prażak <pawelprazak 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "stackedurlbar.h"
+#include "stackedurlbar.moc"
+
+// KDE Includes
+#include "kdebug.h"
+
+// Local Includes
+#include "application.h"
+#include "history.h"
+#include "urlbar.h"
+
+
+StackedUrlBar::StackedUrlBar(QWidget *parent)
+ : QStackedWidget(parent)
+ , m_completion(0)
+ , m_completionModel(0)
+{
+}
+
+
+StackedUrlBar::~StackedUrlBar()
+{
+ delete m_completion;
+ delete m_completionModel;
+}
+
+
+UrlBar *StackedUrlBar::currentUrlBar()
+{
+ return urlBar(currentIndex());
+}
+
+
+UrlBar *StackedUrlBar::urlBar(int index)
+{
+ UrlBar *urlBar = qobject_cast<UrlBar*>(QStackedWidget::widget(index));
+ if (!urlBar)
+ {
+ kWarning() << "URL bar with index" << index << "not found. Returning NULL. line:" << __LINE__;
+ }
+
+ return urlBar;
+}
+
+
+void StackedUrlBar::addUrlBar(UrlBar* urlBar)
+{
+ QStackedWidget::addWidget(urlBar);
+
+ // setup completion objects
+ urlBar->setCompletionObject(completion());
+}
+
+
+void StackedUrlBar::setCurrentUrlBar(UrlBar* urlBar)
+{
+ QStackedWidget::setCurrentWidget(urlBar);
+}
+
+
+void StackedUrlBar::removeUrlBar(UrlBar* urlBar)
+{
+ QStackedWidget::removeWidget(urlBar);
+}
+
+
+void StackedUrlBar::clear()
+{
+ currentUrlBar()->clearHistory();
+
+ for (int i = 0; i < count(); ++i)
+ {
+ urlBar(i)->clear();
+ }
+}
+
+
+QList<const UrlBar* > StackedUrlBar::urlBars()
+{
+ QList<const UrlBar *> list;
+ for (int i = 0; i < count(); ++i)
+ {
+ const UrlBar* u = urlBar(i);
+ list.append(u);
+ }
+ return list;
+}
+
+
+KCompletion *StackedUrlBar::completion()
+{
+ // make sure completion was created
+ if (!m_completion)
+ {
+ m_completion = new KCompletion();
+ m_completion->setCompletionMode(KGlobalSettings::CompletionPopupAuto);
+ m_completion->setOrder(KCompletion::Weighted);
+ m_completion->setIgnoreCase(true);
+
+ kDebug() << "Initialize completion list...";
+
+ HistoryCompletionModel *model = completionModel();
+ int count = model->rowCount();
+
+ kDebug() << "...initialize history items" << count;
+
+ // change order to insertion to avoid confusion of the addItem method
+ // in weighted it expects format string:number and it thinks http it the whole string
+ m_completion->setOrder(KCompletion::Insertion);
+ for (int i = 0; i < count; ++i)
+ {
+ QString item = model->data(model->index(i, 0)).toString();
+ item.remove(QRegExp("^http://|/$"));
+ m_completion->addItem(item);
+ }
+ m_completion->setOrder(KCompletion::Weighted);
+ }
+
+ return m_completion;
+}
+
+
+HistoryCompletionModel *StackedUrlBar::completionModel()
+{
+ if (!m_completionModel)
+ {
+ m_completionModel = new HistoryCompletionModel(this);
+ m_completionModel->setSourceModel(Application::historyManager()->historyFilterModel());
+ }
+ return m_completionModel;
+}
diff --git a/src/stackedurlbar.h b/src/stackedurlbar.h
new file mode 100644
index 00000000..d3aea16f
--- /dev/null
+++ b/src/stackedurlbar.h
@@ -0,0 +1,64 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2008 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009 by Paweł Prażak <pawelprazak 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+
+#ifndef STACKEDURLBAR_H
+#define STACKEDURLBAR_H
+
+// Qt Includes
+#include <QStackedWidget>
+
+class KCompletion;
+class HistoryCompletionModel;
+class UrlBar;
+
+class StackedUrlBar : public QStackedWidget
+{
+ Q_OBJECT
+
+public:
+ StackedUrlBar(QWidget *parent = 0);
+ ~StackedUrlBar();
+
+public:
+ UrlBar *currentUrlBar();
+ UrlBar *urlBar(int index);
+ void addUrlBar(UrlBar *urlBar);
+ void setCurrentUrlBar(UrlBar *urlBar);
+ void removeUrlBar(UrlBar *urlBar);
+
+ QList<const UrlBar *> urlBars();
+
+ KCompletion *completion();
+ HistoryCompletionModel *completionModel();
+
+public slots:
+ void clear();
+
+private:
+ Q_DISABLE_COPY(StackedUrlBar)
+
+ KCompletion *m_completion;
+ HistoryCompletionModel *m_completionModel;
+};
+
+#endif // STACKEDURLBAR_H
+
diff --git a/src/tabbar.cpp b/src/tabbar.cpp
new file mode 100644
index 00000000..be1b05fd
--- /dev/null
+++ b/src/tabbar.cpp
@@ -0,0 +1,145 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007-2008 Trolltech ASA. All rights reserved
+* Copyright (C) 2008-2009 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009 by Paweł Prażak <pawelprazak 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+//Self Includes
+#include "tabbar.h"
+#include "tabbar.moc"
+
+// Local Includes
+#include "application.h"
+#include "mainwindow.h"
+#include "history.h"
+#include "urlbar.h"
+#include "webview.h"
+
+// KDE Includes
+#include <KShortcut>
+#include <KStandardShortcut>
+#include <KMessageBox>
+#include <KAction>
+#include <KDebug>
+#include <KGlobalSettings>
+
+// Qt Includes
+#include <QtGui>
+
+
+TabBar::TabBar(QWidget *parent)
+ : KTabBar(parent)
+ , m_parent(parent)
+{
+ setElideMode(Qt::ElideRight);
+ setContextMenuPolicy(Qt::CustomContextMenu);
+ setMovable(true);
+ connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this,
+ SLOT(contextMenuRequested(const QPoint &)));
+
+ // tabbar font
+ QFont standardFont = KGlobalSettings::generalFont();
+ QString fontFamily = standardFont.family();
+ int dim = standardFont.pointSize();
+ setFont(QFont(fontFamily, dim - 1));
+}
+
+
+TabBar::~TabBar()
+{
+}
+
+
+QSize TabBar::tabSizeHint(int index) const
+{
+ QSize s = m_parent->sizeHint();
+ int w;
+
+ int n = count();
+
+ if (n > 6)
+ {
+ w = s.width() / 5;
+ }
+ else
+ {
+ if (n > 3)
+ {
+ w = s.width() / 4;
+ }
+ else
+ {
+ w = s.width() / 3;
+ }
+ }
+ int h = KTabBar::tabSizeHint(index).height();
+
+ QSize ts = QSize(w, h);
+ return ts;
+}
+
+
+void TabBar::contextMenuRequested(const QPoint &position)
+{
+ KMenu menu;
+ MainWindow *mainWindow = Application::instance()->mainWindow();
+
+ menu.addAction(mainWindow->actionByName(QLatin1String("new_tab")));
+ int index = tabAt(position);
+ if (-1 != index)
+ {
+ m_actualIndex = index;
+
+ menu.addAction(KIcon("tab-duplicate"), i18n("Clone Tab"), this, SLOT(cloneTab()));
+ menu.addSeparator();
+ menu.addAction(KIcon("tab-close"), i18n("&Close Tab"), this, SLOT(closeTab()));
+ menu.addAction(KIcon("tab-close-other"), i18n("Close &Other Tabs"), this, SLOT(closeOtherTabs()));
+ menu.addSeparator();
+ menu.addAction(KIcon("view-refresh"), i18n("Reload Tab"), this, SLOT(reloadTab()));
+ }
+ else
+ {
+ menu.addSeparator();
+ }
+ menu.addAction(i18n("Reload All Tabs"), this, SIGNAL(reloadAllTabs()));
+ menu.exec(QCursor::pos());
+}
+
+
+void TabBar::cloneTab()
+{
+ emit cloneTab(m_actualIndex);
+}
+
+
+void TabBar::closeTab()
+{
+ emit closeTab(m_actualIndex);
+}
+
+
+void TabBar::closeOtherTabs()
+{
+ emit closeOtherTabs(m_actualIndex);
+}
+
+
+void TabBar::reloadTab()
+{
+ emit reloadTab(m_actualIndex);
+}
diff --git a/src/tabbar.h b/src/tabbar.h
new file mode 100644
index 00000000..8563793f
--- /dev/null
+++ b/src/tabbar.h
@@ -0,0 +1,78 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007-2008 Trolltech ASA. All rights reserved
+* Copyright (C) 2008-2009 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009 by Paweł Prażak <pawelprazak 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+#ifndef TABBAR_H
+#define TABBAR_H
+
+// KDE Includes
+#include <KTabBar>
+
+// Qt Includes
+#include <QShortcut>
+
+/**
+ * Tab bar with a few more features such as
+ * a context menu and shortcuts
+ *
+ */
+
+class TabBar : public KTabBar
+{
+ Q_OBJECT
+
+
+public:
+ TabBar(QWidget *parent = 0);
+ ~TabBar();
+
+signals:
+ void cloneTab(int index);
+ void closeTab(int index);
+ void closeOtherTabs(int index);
+ void reloadTab(int index);
+ void reloadAllTabs();
+
+protected:
+ /**
+ * Added to fix tab dimension
+ */
+ virtual QSize tabSizeHint(int index) const;
+
+private slots:
+ void cloneTab();
+ void closeTab();
+ void closeOtherTabs();
+ void reloadTab();
+ void contextMenuRequested(const QPoint &position);
+
+private:
+ friend class MainView;
+
+ QWidget *m_parent;
+
+ /**
+ * the index in which we are seeing a Context menu
+ */
+ int m_actualIndex;
+};
+
+#endif
diff --git a/src/urlbar.cpp b/src/urlbar.cpp
new file mode 100644
index 00000000..29eaed70
--- /dev/null
+++ b/src/urlbar.cpp
@@ -0,0 +1,240 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2008-2009 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009 by Domrachev Alexandr <alexandr.domrachev@gmail.com>
+* Copyright (C) 2009 by Paweł Prażak <pawelprazak 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "urlbar.h"
+#include "urlbar.moc"
+
+// Qt Includes
+#include <QtCore>
+#include <QtGui>
+
+// KDE Includes
+#include <KDebug>
+#include <KCompletionBox>
+#include <KUrl>
+
+// Local Includes
+#include "application.h"
+#include "history.h"
+#include "lineedit.h"
+#include "mainwindow.h"
+#include "webview.h"
+
+
+QColor UrlBar::s_defaultBaseColor;
+
+UrlBar::UrlBar(QWidget *parent)
+ : KHistoryComboBox(true, parent)
+ , m_lineEdit(new LineEdit)
+ , m_progress(0)
+{
+ setUrlDropsEnabled(true);
+ setAutoDeleteCompletionObject(true);
+ setMinimumWidth(180);
+
+ setTrapReturnKey(true);
+
+ setupLineEdit();
+
+ // add every item to history
+ connect(this, SIGNAL(returnPressed(const QString&)), SLOT(slotActivated(const QString&)));
+ connect(completionBox(), SIGNAL(activated(const QString&)), SLOT(slotActivated(const QString&)));
+
+ connect(this, SIGNAL(cleared()), SLOT(slotCleared()));
+
+ // setup completion box
+ completionBox()->setTabHandling(true); // Konqueror bug #167135
+
+ // set dropdown list background
+ QPalette p = view()->palette();
+ p.setColor(QPalette::Base, palette().color(QPalette::Base));
+ view()->setPalette(p);
+
+ // set empty item with default icon
+ slotUpdateUrl();
+}
+
+
+UrlBar::~UrlBar()
+{
+}
+
+
+void UrlBar::setupLineEdit()
+{
+ // Make m_lineEdit background transparent
+ QPalette p = m_lineEdit->palette();
+ p.setColor(QPalette::Base, Qt::transparent);
+ m_lineEdit->setPalette(p);
+
+ if (!s_defaultBaseColor.isValid())
+ {
+ s_defaultBaseColor = palette().color(QPalette::Base);
+ }
+
+ setLineEdit(m_lineEdit);
+
+ // Make the lineedit consume the Qt::Key_Enter event...
+ lineEdit()->setTrapReturnKey(true);
+
+ lineEdit()->setHandleSignals(true);
+
+ // clear the URL bar
+ lineEdit()->clear();
+}
+
+
+void UrlBar::setUrl(const QUrl& url)
+{
+ if (url.isEmpty())
+ return;
+
+ m_currentUrl = url;
+ slotUpdateUrl();
+}
+
+
+void UrlBar::slotUpdateUrl()
+{
+ if (count())
+ {
+ changeUrl(0, Application::instance()->icon(m_currentUrl), m_currentUrl);
+ }
+ else
+ {
+ insertUrl(0, Application::instance()->icon(m_currentUrl), m_currentUrl);
+ }
+
+ setCurrentIndex(0);
+
+ // important security consideration: always display the beginning
+ // of the url rather than its end to prevent spoofing attempts.
+ // Must be AFTER setCurrentIndex
+ if (!hasFocus())
+ {
+ lineEdit()->setCursorPosition(0);
+ }
+}
+
+
+inline void UrlBar::slotActivated(const QString& url)
+{
+ if (url.isEmpty())
+ return;
+
+ setUrl(url);
+
+ Application::historyManager()->addHistoryEntry(url);
+
+ emit activated(m_currentUrl);
+}
+
+
+inline void UrlBar::slotCleared()
+{
+ // clear the history on user's request from context menu
+ clear();
+ Application::historyManager()->clear();
+}
+
+
+inline void UrlBar::slotLoadFinished(bool)
+{
+ // reset progress bar after small delay
+ m_progress = 0;
+ QTimer::singleShot(200, this, SLOT(repaint()));
+}
+
+
+inline void UrlBar::slotUpdateProgress(int progress)
+{
+ m_progress = progress;
+ repaint();
+}
+
+
+void UrlBar::paintEvent(QPaintEvent *event)
+{
+ // set background color of UrlBar
+ QPalette p = palette();
+ p.setColor(QPalette::Base, s_defaultBaseColor);
+ setPalette(p);
+
+ KHistoryComboBox::paintEvent(event);
+
+ if (!hasFocus())
+ {
+ QPainter painter(this);
+
+ QColor loadingColor;
+ if (m_currentUrl.scheme() == QLatin1String("https"))
+ {
+ loadingColor = QColor(248, 248, 100);
+ }
+ else
+ {
+ loadingColor = QColor(116, 192, 250);
+ }
+ painter.setBrush(generateGradient(loadingColor, height()));
+ painter.setPen(Qt::transparent);
+
+ QRect backgroundRect = lineEdit()->frameGeometry();
+ int mid = backgroundRect.width() / 100 * m_progress;
+ QRect progressRect(backgroundRect.x(), backgroundRect.y(), mid, backgroundRect.height());
+ painter.drawRect(progressRect);
+ painter.end();
+ }
+}
+
+
+void UrlBar::focusOutEvent(QFocusEvent *event)
+{
+ // set back last loaded url in case user cleared it
+ setUrl(m_currentUrl);
+
+ KHistoryComboBox::focusOutEvent(event);
+}
+
+
+QSize UrlBar::sizeHint() const
+{
+ QSize size(lineEdit()->sizeHint());
+ // make it (more or less) the same height with search bar (at least on oxygen)
+// size.setHeight(size.height() + 2);
+ return size;
+}
+
+QLinearGradient UrlBar::generateGradient(const QColor &color, int height)
+{
+ QColor base = s_defaultBaseColor;
+ base.setAlpha(0);
+ QColor barColor = color;
+ barColor.setAlpha(200);
+ QLinearGradient gradient(0, 0, 0, height);
+ gradient.setColorAt(0, base);
+ gradient.setColorAt(0.25, barColor.lighter(120));
+ gradient.setColorAt(0.5, barColor);
+ gradient.setColorAt(0.75, barColor.lighter(120));
+ gradient.setColorAt(1, base);
+ return gradient;
+}
diff --git a/src/urlbar.h b/src/urlbar.h
new file mode 100644
index 00000000..236792bd
--- /dev/null
+++ b/src/urlbar.h
@@ -0,0 +1,99 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2008-2009 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009 by Domrachev Alexandr <alexandr.domrachev@gmail.com>
+* Copyright (C) 2009 by Paweł Prażak <pawelprazak 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+#ifndef URLBAR_H
+#define URLBAR_H
+
+// Qt Includes
+#include <QIcon>
+#include <QPointer>
+#include <QUrl>
+
+// KDE Includes
+#include <KUrl>
+#include <KHistoryComboBox>
+
+// Local Includes
+#include "lineedit.h"
+
+
+// Forward Declarations
+class QLinearGradient;
+class QWidget;
+
+
+class UrlBar : public KHistoryComboBox
+{
+ Q_OBJECT
+
+public:
+ UrlBar(QWidget *parent = 0);
+ ~UrlBar();
+
+ void selectAll() const
+ {
+ lineEdit()->selectAll();
+ }
+ KUrl url() const
+ {
+ return m_currentUrl;
+ }
+
+ QSize sizeHint() const;
+
+signals:
+ void activated(const KUrl&);
+
+public slots:
+ void setUrl(const QUrl &url);
+ void slotUpdateProgress(int progress);
+
+private slots:
+ void slotActivated(const QString&);
+ void slotLoadFinished(bool);
+ void slotCleared();
+ void slotUpdateUrl();
+
+protected:
+ virtual void paintEvent(QPaintEvent *event);
+ virtual void focusOutEvent(QFocusEvent *event);
+
+private:
+ void setupLineEdit();
+
+ KLineEdit *lineEdit() const
+ {
+ return m_lineEdit;
+ }
+
+ static QLinearGradient generateGradient(const QColor &color, int height);
+
+ static QColor s_defaultBaseColor;
+
+ LineEdit *m_lineEdit;
+
+ QIcon m_currentIcon;
+ KUrl m_currentUrl;
+ int m_progress;
+};
+
+#endif
diff --git a/src/webview.cpp b/src/webview.cpp
new file mode 100644
index 00000000..5f42112b
--- /dev/null
+++ b/src/webview.cpp
@@ -0,0 +1,504 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007-2008 Trolltech ASA. All rights reserved
+* Copyright (C) 2008 Benjamin C. Meyer <ben@meyerhome.net>
+* Copyright (C) 2008-2009 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009 by Paweł Prażak <pawelprazak 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "webview.h"
+#include "webview.moc"
+
+// Auto Includes
+#include "rekonq.h"
+
+// Local Includes
+#include "application.h"
+#include "mainwindow.h"
+#include "mainview.h"
+#include "cookiejar.h"
+#include "networkaccessmanager.h"
+#include "download.h"
+#include "history.h"
+
+
+// KDE Includes
+#include <KStandardDirs>
+#include <KUrl>
+#include <KActionCollection>
+#include <KDebug>
+#include <KToolInvocation>
+
+// Qt Includes
+#include <QtCore>
+#include <QtGui>
+#include <QtWebKit>
+#include <QUiLoader>
+
+
+WebPage::WebPage(QObject *parent)
+ : QWebPage(parent)
+ , m_keyboardModifiers(Qt::NoModifier)
+ , m_pressedButtons(Qt::NoButton)
+ , m_openInNewTab(false)
+{
+ setNetworkAccessManager(Application::networkAccessManager());
+
+ setForwardUnsupportedContent(true);
+ connect(this, SIGNAL(unsupportedContent(QNetworkReply *)), this, SLOT(handleUnsupportedContent(QNetworkReply *)));
+}
+
+
+WebPage::~WebPage()
+{
+}
+
+
+bool WebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, NavigationType type)
+{
+ QString scheme = request.url().scheme();
+ if (scheme == QLatin1String("mailto"))
+ {
+ KToolInvocation::invokeMailer(request.url());
+ return false;
+ }
+
+ WebView *webView;
+
+ switch (type)
+ {
+
+ // user clicked on a link or pressed return on a focused link.
+ case QWebPage::NavigationTypeLinkClicked:
+
+ if (m_keyboardModifiers & Qt::ControlModifier || m_pressedButtons == Qt::MidButton)
+ {
+ webView = Application::instance()->newWebView();
+ webView->setFocus();
+ webView->load(request);
+ m_keyboardModifiers = Qt::NoModifier;
+ m_pressedButtons = Qt::NoButton;
+ return false;
+ }
+
+ if (frame == mainFrame())
+ {
+ m_loadingUrl = request.url();
+ emit loadingUrl(m_loadingUrl);
+ }
+ else
+ {
+ // if frame doesn't exists (perhaps) we are pointing to a blank target..
+ if (!frame)
+ {
+ webView = Application::instance()->newWebView();
+ webView->setFocus();
+ webView->load(request);
+ return false;
+ }
+ }
+ break;
+
+ // user activated a submit button for an HTML form.
+ case QWebPage::NavigationTypeFormSubmitted:
+ break;
+
+ // Navigation to a previously shown document in the back or forward history is requested.
+ case QWebPage::NavigationTypeBackOrForward:
+ break;
+
+ // user activated the reload action.
+ case QWebPage::NavigationTypeReload:
+
+#if QT_VERSION <= 040500
+ // HACK Ported from Arora
+ // A short term hack until QtWebKit can get a reload without cache QAction
+ // *FYI* currently type is never NavigationTypeReload
+ // See: https://bugs.webkit.org/show_bug.cgi?id=24283
+ if (qApp->keyboardModifiers() & Qt::ShiftModifier)
+ {
+ QNetworkRequest newRequest(request);
+ newRequest.setAttribute(QNetworkRequest::CacheLoadControlAttribute,
+ QNetworkRequest::AlwaysNetwork);
+ mainFrame()->load(request);
+ return false;
+ }
+#endif
+
+ break;
+
+ // An HTML form was submitted a second time.
+ case QWebPage::NavigationTypeFormResubmitted:
+ break;
+
+ // A navigation to another document using a method not listed above.
+ case QWebPage::NavigationTypeOther:
+ break;
+
+ // should be nothing..
+ default:
+ break;
+ }
+
+ return QWebPage::acceptNavigationRequest(frame, request, type);
+}
+
+
+QWebPage *WebPage::createWindow(QWebPage::WebWindowType type)
+{
+ // added to manage web modal dialogs
+ if (type == QWebPage::WebModalDialog)
+ {
+ // FIXME : need a "real" implementation..
+ kWarning() << "Modal Dialog ---------------------------------------";
+ QWebView *w = new QWebView();
+ w->show();
+ return w->page();
+ }
+
+ if (m_keyboardModifiers & Qt::ControlModifier || m_pressedButtons == Qt::MidButton)
+ {
+ m_openInNewTab = true;
+ }
+
+ if (m_openInNewTab)
+ {
+ m_openInNewTab = false;
+ return Application::instance()->newWebView()->page();
+ }
+
+ MainWindow *mainWindow = Application::instance()->mainWindow();
+ return mainWindow->currentTab()->page();
+}
+
+
+QObject *WebPage::createPlugin(const QString &classId, const QUrl &url, const QStringList &paramNames, const QStringList &paramValues)
+{
+ kWarning() << "creating PLUGIN for rekonq ";
+ kWarning() << "classId = " << classId;
+ kWarning() << "url = " << url;
+ kWarning() << "Param Names = " << paramNames;
+ kWarning() << "Param Values = " << paramValues;
+
+ QUiLoader loader;
+ return loader.createWidget(classId, view());
+}
+
+
+void WebPage::handleUnsupportedContent(QNetworkReply *reply)
+{
+ // create convenience fake api:// protocol for KDE apidox search and Qt docs
+ if (reply->url().scheme() == "api")
+ {
+ QString path;
+ QString className = reply->url().host().toLower();
+ if (className[0] == 'k')
+ {
+ path = QString("http://api.kde.org/new.classmapper.php?class=%1").arg(className);
+ }
+ else if (className[0] == 'q')
+ {
+ path = QString("http://doc.trolltech.com/4.5/%1.html").arg(className);
+ }
+ QUrl url(path);
+
+ Application::instance()->mainWindow()->loadUrl(url);
+ return;
+ }
+
+ if (reply->error() == QNetworkReply::NoError)
+ {
+ // st iframe unwanted download fix
+ if (reply->header(QNetworkRequest::ContentTypeHeader).isValid())
+ {
+ KUrl srcUrl = reply->url();
+ Application::downloadManager()->newDownload(srcUrl);
+ }
+ return;
+ }
+
+ // display "not found" page
+ QString notfoundFilePath = KStandardDirs::locate("data", "rekonq/htmls/notfound.html");
+ QFile file(notfoundFilePath);
+ bool isOpened = file.open(QIODevice::ReadOnly);
+ if (!isOpened)
+ {
+ kWarning() << "Couldn't open the notfound.html file";
+ return;
+ }
+ QString title = i18n("Error loading page: ") + reply->url().toString();
+
+ QString imagePath = KIconLoader::global()->iconPath("rekonq", KIconLoader::NoGroup, false);
+
+ QString html = QString(QLatin1String(file.readAll()))
+ .arg(title)
+ .arg("file://" + imagePath)
+ .arg(reply->errorString())
+ .arg(reply->url().toString());
+
+ QList<QWebFrame*> frames;
+ frames.append(mainFrame());
+ while (!frames.isEmpty())
+ {
+ QWebFrame *firstFrame = frames.takeFirst();
+ if (firstFrame->url() == reply->url())
+ {
+ firstFrame->setHtml(html, reply->url());
+ return;
+ }
+ QList<QWebFrame *> children = firstFrame->childFrames();
+ foreach(QWebFrame *frame, children)
+ {
+ frames.append(frame);
+ }
+ }
+ if (m_loadingUrl == reply->url())
+ {
+ mainFrame()->setHtml(html, reply->url());
+ // Don't put error pages to the history.
+ Application::historyManager()->removeHistoryEntry(reply->url(), mainFrame()->title());
+ }
+}
+
+
+// -----------------------------------------------------------------------------------------------------------------
+
+
+KActionCollection* WebView::s_webActionCollection;
+
+
+WebView::WebView(QWidget* parent)
+ : QWebView(parent)
+ , m_page(new WebPage(this))
+ , m_progress(0)
+{
+ setPage(m_page);
+ connect(page(), SIGNAL(statusBarMessage(const QString&)), this, SLOT(setStatusBarText(const QString&)));
+ connect(this, SIGNAL(loadProgress(int)), this, SLOT(setProgress(int)));
+ connect(this, SIGNAL(loadFinished(bool)), this, SLOT(loadFinished()));
+ connect(page(), SIGNAL(loadingUrl(const QUrl&)), this, SIGNAL(urlChanged(const QUrl &)));
+ connect(page(), SIGNAL(downloadRequested(const QNetworkRequest &)), this, SLOT(downloadRequested(const QNetworkRequest &)));
+ page()->setForwardUnsupportedContent(true);
+}
+
+
+KActionCollection* WebView::webActions()
+{
+ if (!s_webActionCollection)
+ {
+ s_webActionCollection = new KActionCollection(this);
+
+ QAction *a;
+
+ a = new KAction(KIcon("tab-new"), i18n("Open Link in New &Tab"), this);
+ connect(a, SIGNAL(triggered()), this, SLOT(openLinkInNewTab()));
+ s_webActionCollection->addAction(QLatin1String("open_link_in_new_tab"), a);
+
+ a = pageAction(QWebPage::Cut);
+ a->setIcon(KIcon("edit-cut"));
+ a->setText(i18n("Cu&t"));
+ s_webActionCollection->addAction(QLatin1String("edit_cut"), a);
+
+ a = pageAction(QWebPage::Copy);
+ a->setIcon(KIcon("edit-copy"));
+ a->setText(i18n("&Copy"));
+ s_webActionCollection->addAction(QLatin1String("edit_copy"), a);
+
+ a = pageAction(QWebPage::Paste);
+ a->setIcon(KIcon("edit-paste"));
+ a->setText(i18n("&Paste"));
+ s_webActionCollection->addAction(QLatin1String("edit_paste"), a);
+
+ a = pageAction(QWebPage::DownloadImageToDisk);
+ a->setIcon(KIcon("folder-image"));
+ a->setText(i18n("&Save Image As..."));
+ s_webActionCollection->addAction(QLatin1String("save_image_as"), a);
+
+ a = pageAction(QWebPage::CopyImageToClipboard);
+ a->setIcon(KIcon("insert-image"));
+ a->setText(i18n("&Copy This Image"));
+ s_webActionCollection->addAction(QLatin1String("copy_this_image"), a);
+
+ a = pageAction(QWebPage::DownloadLinkToDisk);
+ a->setIcon(KIcon("folder-downloads"));
+ a->setText(i18n("&Save Link As..."));
+ s_webActionCollection->addAction(QLatin1String("save_link_as"), a);
+
+ a = pageAction(QWebPage::CopyLinkToClipboard);
+ a->setIcon(KIcon("insert-link"));
+ a->setText(i18n("&Copy Link Location"));
+ s_webActionCollection->addAction(QLatin1String("copy_link_location"), a);
+
+ a = pageAction(QWebPage::InspectElement);
+ a->setIcon(KIcon("tools-report-bug"));
+ a->setText(i18n("&Inspect Element"));
+ s_webActionCollection->addAction(QLatin1String("inspect_element"), a);
+ }
+
+ return s_webActionCollection;
+}
+
+
+void WebView::contextMenuEvent(QContextMenuEvent *event)
+{
+ QWebHitTestResult result = page()->mainFrame()->hitTestContent(event->pos());
+ MainWindow *mainwindow = Application::instance()->mainWindow();
+
+ QAction *addBookmarkAction = Application::bookmarkProvider()->actionByName("add_bookmark_payload");
+ addBookmarkAction->setText(i18n("Bookmark This Page"));
+ addBookmarkAction->setData(QVariant());
+ KMenu menu(this);
+
+ bool linkIsEmpty = result.linkUrl().isEmpty();
+ if (!linkIsEmpty)
+ {
+ menu.addAction(webActions()->action("open_link_in_new_tab"));
+ }
+ else
+ {
+ menu.addAction(mainwindow->actionByName("new_tab"));
+ }
+ menu.addAction(mainwindow->actionByName("view_redisplay"));
+ menu.addSeparator();
+
+ if (page()->settings()->testAttribute(QWebSettings::DeveloperExtrasEnabled))
+ {
+ menu.addAction(webActions()->action("inspect_element"));
+ menu.addSeparator();
+ }
+
+ menu.addAction(mainwindow->actionByName("history_back"));
+ menu.addAction(mainwindow->actionByName("history_forward"));
+ menu.addSeparator();
+
+ if (result.isContentSelected() && result.isContentEditable())
+ {
+ menu.addAction(webActions()->action("edit_cut"));
+ }
+
+ if (result.isContentSelected())
+ {
+ menu.addAction(webActions()->action("edit_copy"));
+ }
+
+ if (result.isContentEditable())
+ {
+ menu.addAction(webActions()->action("edit_paste"));
+ }
+
+ if (!linkIsEmpty)
+ {
+ menu.addSeparator();
+ if (!result.pixmap().isNull())
+ {
+ // TODO Add "View Image"
+ menu.addAction(webActions()->action("save_image_as"));
+ menu.addAction(webActions()->action("copy_this_image"));
+ }
+ menu.addAction(webActions()->action("save_link_as"));
+ menu.addAction(webActions()->action("copy_link_location"));
+ addBookmarkAction->setData(result.linkUrl());
+ addBookmarkAction->setText(i18n("&Bookmark This Link"));
+ }
+ menu.addSeparator();
+
+ menu.addAction(addBookmarkAction);
+ menu.exec(mapToGlobal(event->pos()));
+}
+
+
+void WebView::wheelEvent(QWheelEvent *event)
+{
+ if (QApplication::keyboardModifiers() & Qt::ControlModifier)
+ {
+ int numDegrees = event->delta() / 8;
+ int numSteps = numDegrees / 15;
+ setTextSizeMultiplier(textSizeMultiplier() + numSteps * 0.1);
+ event->accept();
+ return;
+ }
+ QWebView::wheelEvent(event);
+}
+
+
+void WebView::openLinkInNewTab()
+{
+ m_page->m_openInNewTab = true;
+ pageAction(QWebPage::OpenLinkInNewWindow)->trigger();
+}
+
+
+void WebView::loadFinished()
+{
+ if (m_progress != 100)
+ {
+ kWarning() << "Recieved finished signal while progress is still:" << progress()
+ << "Url:" << url();
+ }
+ m_progress = 0;
+}
+
+
+void WebView::mousePressEvent(QMouseEvent *event)
+{
+ m_page->m_pressedButtons = event->buttons();
+ m_page->m_keyboardModifiers = event->modifiers();
+ QWebView::mousePressEvent(event);
+}
+
+
+void WebView::mouseReleaseEvent(QMouseEvent *event)
+{
+ QWebView::mouseReleaseEvent(event);
+ if (!event->isAccepted() && (m_page->m_pressedButtons & Qt::MidButton))
+ {
+ KUrl url(QApplication::clipboard()->text(QClipboard::Selection));
+ if (!url.isEmpty() && url.isValid() && !url.scheme().isEmpty())
+ {
+ setUrl(url);
+ }
+ }
+}
+
+
+void WebView::downloadRequested(const QNetworkRequest &request)
+{
+ KUrl srcUrl = request.url();
+ QString path = ReKonfig::downloadDir() + QString("/") + srcUrl.fileName();
+ KUrl destUrl = KUrl(path);
+ Application::downloadManager()->newDownload(srcUrl);
+}
+
+
+void WebView::keyPressEvent(QKeyEvent *event)
+{
+ if ((event->modifiers() == Qt::ControlModifier) && (event->key() == Qt::Key_Tab))
+ {
+ emit ctrlTabPressed();
+ return;
+ }
+
+ if ((event->modifiers() == Qt::ControlModifier + Qt::ShiftModifier) && (event->key() == Qt::Key_Backtab))
+ {
+ emit shiftCtrlTabPressed();
+ return;
+ }
+
+ QWebView::keyPressEvent(event);
+}
diff --git a/src/webview.h b/src/webview.h
new file mode 100644
index 00000000..11f04571
--- /dev/null
+++ b/src/webview.h
@@ -0,0 +1,155 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2007-2008 Trolltech ASA. All rights reserved
+* Copyright (C) 2008 Benjamin C. Meyer <ben@meyerhome.net>
+* Copyright (C) 2008-2009 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009 by Paweł Prażak <pawelprazak 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, or (at your option) any later version.
+*
+* 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.
+*
+* ============================================================ */
+
+
+#ifndef WEBVIEW_H
+#define WEBVIEW_H
+
+// KDE Includes
+#include <KUrl>
+
+// Qt Includes
+#include <QWebPage>
+
+// Forward Declarations
+class MainWindow;
+class Application;
+
+class KActionCollection;
+
+class QWebFrame;
+class QAuthenticator;
+class QMouseEvent;
+class QNetworkProxy;
+class QNetworkReply;
+class QSslError;
+
+
+class WebPage : public QWebPage
+{
+ Q_OBJECT
+
+signals:
+ void loadingUrl(const QUrl &url); // WARNING has to be QUrl!!
+
+public:
+ WebPage(QObject *parent = 0);
+ ~WebPage();
+
+protected:
+ bool acceptNavigationRequest(QWebFrame *frame,
+ const QNetworkRequest &request,
+ NavigationType type);
+
+ QWebPage *createWindow(QWebPage::WebWindowType type);
+ QObject *createPlugin(const QString &classId,
+ const QUrl &url,
+ const QStringList &paramNames,
+ const QStringList &paramValues);
+
+private slots:
+ void handleUnsupportedContent(QNetworkReply *reply);
+
+private:
+ friend class WebView;
+
+ // set the webview mousepressedevent
+ Qt::KeyboardModifiers m_keyboardModifiers;
+ Qt::MouseButtons m_pressedButtons;
+ bool m_openInNewTab;
+ KUrl m_loadingUrl;
+};
+
+
+// ----------------------------------------------------------------------------------------------------
+
+// Qt Includes
+#include <QWebView>
+
+
+class WebView : public QWebView
+{
+ Q_OBJECT
+
+public:
+ WebView(QWidget *parent = 0);
+
+ KActionCollection* webActions();
+
+ // inline
+ WebPage *webPage() const
+ {
+ return m_page;
+ }
+ KUrl url() const
+ {
+ return KUrl(QWebView::url());
+ }
+ QString lastStatusBarText() const
+ {
+ return m_statusBarText;
+ }
+ int progress() const
+ {
+ return m_progress;
+ }
+
+signals:
+ // switching tabs
+ void ctrlTabPressed();
+ void shiftCtrlTabPressed();
+
+protected:
+ void mousePressEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *event);
+ void contextMenuEvent(QContextMenuEvent *event);
+ void wheelEvent(QWheelEvent *event);
+
+ /**
+ * Filters (SHIFT + ) CTRL + TAB events and emit (shift)ctrlTabPressed()
+ * to make switch tab
+ */
+ void keyPressEvent(QKeyEvent *event);
+
+private slots:
+ void setProgress(int progress)
+ {
+ m_progress = progress;
+ }
+ void loadFinished();
+ void setStatusBarText(const QString &string)
+ {
+ m_statusBarText = string;
+ }
+ void downloadRequested(const QNetworkRequest &request);
+ void openLinkInNewTab();
+
+private:
+ static KActionCollection* s_webActionCollection;
+
+ WebPage *m_page;
+
+ int m_progress;
+ QString m_statusBarText;
+};
+
+#endif