|  | Home · All Classes · Main Classes · Grouped Classes · Modules · Functions |

# browsermainwindow.cpp Example File
demos/browser/browsermainwindow.cpp

     /****************************************************************************
     **
     ** Copyright (C) 2007-2008 Trolltech ASA. All rights reserved.
     **
     ** This file is part of the documentation of the Qt Toolkit.
     **
     ** This file may be used under the terms of the GNU General Public
    ** License versions 2.0 or 3.0 as published by the Free Software
    ** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
    ** included in the packaging of this file.  Alternatively you may (at
    ** your option) use any later version of the GNU General Public
    ** License if such license has been publicly approved by Trolltech ASA
    ** (or its successors, if any) and the KDE Free Qt Foundation. In
    ** addition, as a special exception, Trolltech gives you certain
    ** additional rights. These rights are described in the Trolltech GPL
    ** Exception version 1.2, which can be found at
    ** http://www.trolltech.com/products/qt/gplexception/ and in the file
    ** GPL_EXCEPTION.txt in this package.
    **
    ** Please review the following information to ensure GNU General
    ** Public Licensing requirements will be met:
    ** http://trolltech.com/products/qt/licenses/licensing/opensource/. If
    ** you are unsure which license is appropriate for your use, please
    ** review the following information:
    ** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
    ** or contact the sales department at sales@trolltech.com.
    **
    ** In addition, as a special exception, Trolltech, as the sole
    ** copyright holder for Qt Designer, grants users of the Qt/Eclipse
    ** Integration plug-in the right for the Qt/Eclipse Integration to
    ** link to functionality provided by Qt Designer and its related
    ** libraries.
    **
    ** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
    ** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
    ** A PARTICULAR PURPOSE. Trolltech reserves all rights not expressly
    ** granted herein.
     **
     ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
     ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     **
     ****************************************************************************/

     #include "browsermainwindow.h"

     #include "webview.h"
     #include "browsertabproxy.h"
     #include "chasewidget.h"
     #include "sourcecodeview.h"
     #include "cookiejar.h"
     #include "history.h"
     #include "settings.h"
     #include "autosave.h"
     #include "toolbarsearch.h"
     #include "ui_passworddialog.h"
     #include "downloadmanager.h"

     #include <QtCore/QSettings>
     #include <qdebug.h>
     #include <QtGui/QApplication>
     #include <QtGui/QDesktopWidget>
     #include <QtGui/QFileDialog>
     #include <QtGui/QLabel>
     #include <QtGui/QLineEdit>
     #include <QtGui/QMenu>
     #include <QtGui/QMenuBar>
     #include <QtGui/QMessageBox>
     #include <QtGui/QMovie>
     #include <QtGui/QStatusBar>
     #include <QtGui/QStyle>
     #include <QtGui/QShortcut>
     #include <QtGui/QTabWidget>
     #include <QtGui/QTextDocument>
     #include <QtGui/QToolBar>
     #include <QtGui/QToolButton>
     #include <QtGui/QCompleter>

     #include <QtNetwork/QAuthenticator>
     #include <QtNetwork/QNetworkReply>

     #include <QtWebKit/QWebFrame>
     #include <QtWebKit/QWebPage>

     #define PERFORM_WEBPAGE_ACTION(ACTION) \
         if (currentTab())                  \
             currentTab()->page()->triggerAction(QWebPage::ACTION);

     BrowserMainWindow::BrowserMainWindow()
         : m_mainTabWidget(new QTabWidget(this))
         , m_cookieJar(0)
         , m_history(0)
         , m_autoSave(new AutoSave(this))
         , m_downloadManager()
         , m_historyBack(0)
         , m_historyForward(0)
         , m_stop(0)
         , m_reload(0)
         , m_cut(0)
         , m_copy(0)
         , m_paste(0)
         , m_undo(0)
         , m_redo(0)
         , m_newTab(0)
         , m_closeTab(0)
         , m_proxy(new BrowserTabProxy(this))
     {
         if (!QWebHistoryInterface::defaultInterface()) {
             m_history = new History(0);
             QWebHistoryInterface::setDefaultInterface(m_history);
         } else {
             m_history = qobject_cast<History*>(QWebHistoryInterface::defaultInterface());
         }

         setAttribute(Qt::WA_DeleteOnClose);
         statusBar()->setSizeGripEnabled(true);

         setupMenu();
         setupToolBar();
         setCentralWidget(m_mainTabWidget);

         slotNewTab();

         connect(m_mainTabWidget, SIGNAL(currentChanged(int)),
                 SLOT(slotCurrentTabChanged(int)));
         connect(m_proxy, SIGNAL(linkHovered(const QString&)),
                 statusBar(), SLOT(showMessage(const QString&)));
         m_mainTabWidget->setElideMode(Qt::ElideRight);

         QToolButton *addTabButton = new QToolButton;
         m_newTab->setIcon(QIcon(":addtab.png"));
         m_newTab->setIconVisibleInMenu(false);
         addTabButton->setDefaultAction(m_newTab);
         addTabButton->setAutoRaise(true);
         addTabButton->setToolButtonStyle(Qt::ToolButtonIconOnly);
         m_mainTabWidget->setCornerWidget(addTabButton, Qt::TopLeftCorner);

         QToolButton *closeTabButton = new QToolButton;
         m_closeTab->setIcon(QIcon(":closetab.png"));
         m_closeTab->setIconVisibleInMenu(false);
         closeTabButton->setDefaultAction(m_closeTab);
         closeTabButton->setAutoRaise(true);
         closeTabButton->setToolButtonStyle(Qt::ToolButtonIconOnly);
         m_mainTabWidget->setCornerWidget(closeTabButton, Qt::TopRightCorner);

         QShortcut *locationBarShortcut = new QShortcut(QKeySequence(Qt::ControlModifier + Qt::Key_L), this);
         connect(locationBarShortcut, SIGNAL(activated()), m_urlEdit, SLOT(selectAll()));
         connect(locationBarShortcut, SIGNAL(activated()), m_urlEdit, SLOT(setFocus()));

         currentTab()->setFocus();
         slotUpdateWindowTitle(QString());
         setWindowIcon(QIcon(":browser.svg"));
         restore();
     }

     BrowserMainWindow::~BrowserMainWindow()
     {
         m_autoSave->changed();
         m_autoSave->saveNow();
     }

     void BrowserMainWindow::restore()
     {
         QSettings settings;
         settings.beginGroup("MainWindow");

         QRect desktopRect = QApplication::desktop()->screenGeometry();
         QSize size = settings.value("Size", desktopRect.size() * 0.8).toSize();
         resize(size);

         bool showStatusbar = (settings.value("viewStatusbar", false).toBool());
         statusBar()->setVisible(showStatusbar);
         updateStatusbarActionText(showStatusbar);

         bool showToolbar = settings.value("viewNavigationbar", true).toBool();
         navigationBar->setVisible(showToolbar);
         updateToolbarActionText(showToolbar);

         QStringList openTabs = settings.value("openTabs").toStringList();
         m_restoreLastSession->setEnabled(openTabs.count() > 0);

         QStringList args = QCoreApplication::arguments();
         if (args.count() > 1)
             loadPage(args.last());
         else
             QTimer::singleShot(0, this, SLOT(slotHome()));
         settings.endGroup();
     }

     void BrowserMainWindow::restoreLastSession()
     {
         QSettings settings;
         settings.beginGroup("MainWindow");
         QStringList openTabs = settings.value("openTabs").toStringList();
         for (int i = 0; i < openTabs.count(); ++i) {
             slotNewTab();
             loadPage(openTabs.at(i));
         }
     }

     void BrowserMainWindow::save()
     {
         QSettings settings;
         settings.beginGroup("MainWindow");
         settings.setValue("Size", size());
         settings.setValue("viewNavigationbar", !navigationBar->isHidden());
         settings.setValue("viewStatusbar", !statusBar()->isHidden());

         QStringList openTabs;
         for (int i = 0; i < m_mainTabWidget->count(); ++i) {
             QWidget *widget = m_mainTabWidget->widget(i);
             if (WebView *tab = qobject_cast<WebView*>(widget)) {
                 openTabs.append(tab->url().toString());
             }
         }
         settings.setValue("openTabs", openTabs);
         settings.endGroup();
     }

     void BrowserMainWindow::setupMenu()
     {
         QMenu *fileMenu = menuBar()->addMenu(tr("&File"));

         fileMenu->addAction(tr("&New Window"), this, SLOT(slotNewWindow()), QKeySequence::New);
         m_newTab = fileMenu->addAction(tr("New &Tab"), this, SLOT(slotNewTab()), QKeySequence::AddTab);
         fileMenu->addAction(tr("&Open File"), this, SLOT(slotOpenFile()), QKeySequence::Open);
         m_closeTab = fileMenu->addAction(tr("&Close Tab"), this, SLOT(slotCloseTab()), QKeySequence::Close);
         fileMenu->addSeparator();

         fileMenu->addAction(tr("&Quit"), qApp, SLOT(quit()));

         QMenu *editMenu = menuBar()->addMenu(tr("&Edit"));
         m_undo = editMenu->addAction(tr("&Undo"), this, SLOT(slotUndo()), QKeySequence::Undo);
         m_redo = editMenu->addAction(tr("&Redo"), this, SLOT(slotRedo()), QKeySequence::Redo);
         editMenu->addSeparator();
         m_cut = editMenu->addAction(tr("Cu&t"), this, SLOT(slotCut()), QKeySequence::Cut);
         m_copy = editMenu->addAction(tr("&Copy"), this, SLOT(slotCopy()), QKeySequence::Copy);
         m_paste = editMenu->addAction(tr("&Paste"), this, SLOT(slotPaste()), QKeySequence::Paste);
         editMenu->addSeparator();
         editMenu->addAction(tr("&Preferences"), this, SLOT(slotPreferences()), tr("Ctrl+,"));

         QMenu *viewMenu = menuBar()->addMenu(tr("&View"));

         m_viewStatusbar = new QAction(this);
         updateStatusbarActionText(true);
         m_viewStatusbar->setShortcut(tr("Ctrl+/"));
         connect(m_viewStatusbar, SIGNAL(triggered()), this, SLOT(slotToggleStatusbar()));
         viewMenu->addAction(m_viewStatusbar);

         m_viewToolbar = new QAction(this);
         updateToolbarActionText(true);
         m_viewToolbar->setShortcut(tr("Ctrl+|"));
         connect(m_viewToolbar, SIGNAL(triggered()), this, SLOT(slotToggleToolbar()));
         viewMenu->addAction(m_viewToolbar);
         viewMenu->addSeparator();

         m_stop = viewMenu->addAction(tr("&Stop"), this, SLOT(slotStop()), QKeySequence(Qt::CTRL | Qt::Key_Period));
         m_reload = viewMenu->addAction(tr("Reload Page"), this, SLOT(slotReload()), QKeySequence::Refresh);
         m_stopIcon = style()->standardIcon(QStyle::SP_BrowserStop);
         m_reloadIcon = style()->standardIcon(QStyle::SP_BrowserReload);

         m_textBigger = viewMenu->addAction(tr("&Make Text Bigger"), this, SLOT(slotTextBigger()), QKeySequence(Qt::CTRL | Qt::Key_Plus));
         m_textNormal = viewMenu->addAction(tr("&Make Text Normal"), this, SLOT(slotTextNormal()), QKeySequence(Qt::CTRL | Qt::Key_0));
         m_textSmaller = viewMenu->addAction(tr("&Make Text Smaller"), this, SLOT(slotTextSmaller()), QKeySequence(Qt::CTRL | Qt::Key_Minus));

     #if 0
         viewMenu->addSeparator();
         viewMenu->addAction(tr("&Zoom In"), this, SLOT(slotZoomIn()));
         viewMenu->addAction(tr("Zoom &Out"), this, SLOT(slotZoomOut()));
     #endif
         viewMenu->addSeparator();
         viewMenu->addAction(tr("Page S&ource"), this, SLOT(slotPageSource()), tr("Ctrl+Alt+U"));
         QAction *a = viewMenu->addAction(tr("&Full Screen"), this, SLOT(slotToggleFullScreen(bool)));
         a->setCheckable(true);

         HistoryMenu *historyMenu = new HistoryMenu(m_history, this);
         connect(historyMenu, SIGNAL(openUrl(const QUrl&)), this, SLOT(slotLoadUrl(const QUrl&)));
         historyMenu->setTitle(tr("Hi&story"));
         menuBar()->addMenu(historyMenu);
         QList<QAction*> historyActions;

         m_historyBack = new QAction(tr("Back"), this);
         connect(m_historyBack, SIGNAL(triggered()), this, SLOT(slotBack()));
         m_historyBack->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_BracketLeft));
         m_historyBack->setIconVisibleInMenu(false);

         m_historyForward = new QAction(tr("Forward"), this);
         connect(m_historyForward, SIGNAL(triggered()), this, SLOT(slotForward()));
         m_historyForward->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_BracketRight));
         m_historyForward->setIconVisibleInMenu(false);

         QAction *m_historyHome = new QAction(tr("Home"), this);
         connect(m_historyHome, SIGNAL(triggered()), this, SLOT(slotHome()));
         m_historyHome->setShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_H));

         m_recentlyClosedTabsMenu = new QMenu(this);
         connect(m_recentlyClosedTabsMenu, SIGNAL(aboutToShow()),
                 this, SLOT(slotAboutToShowRecentTabs()));
         connect(m_recentlyClosedTabsMenu, SIGNAL(triggered(QAction *)),
                 this, SLOT(slotAboutToShowRecentTriggered(QAction *)));
         m_recentlyClosedTabsAction = new QAction("Recently Closed Tabs", this);
         m_recentlyClosedTabsAction->setMenu(m_recentlyClosedTabsMenu);
         m_recentlyClosedTabsAction->setEnabled(false);

         m_restoreLastSession = new QAction(tr("Restore Last Session"), this);
         connect(m_restoreLastSession, SIGNAL(triggered()), this, SLOT(restoreLastSession()));

         historyActions.append(m_historyBack);
         historyActions.append(m_historyForward);
         historyActions.append(m_historyHome);
         historyActions.append(m_recentlyClosedTabsAction);
         historyActions.append(m_restoreLastSession);
         historyMenu->setInitialActions(historyActions);

         QMenu *windowMenu = menuBar()->addMenu(tr("&Window"));
         m_nextTab = windowMenu->addAction(tr("Show Next Tab"), this, SLOT(slotNextTab()), QKeySequence(tr("Ctrl+}")));
         m_previousTab = windowMenu->addAction(tr("Show Previous Tab"), this, SLOT(slotPreviousTab()), QKeySequence(tr("Ctrl+{")));
         (void)new QShortcut(Qt::ControlModifier + Qt::Key_PageDown, this, SLOT(slotNextTab()));
         (void)new QShortcut(Qt::ControlModifier + Qt::Key_PageUp, this, SLOT(slotPreviousTab()));
         windowMenu->addSeparator();
         m_downloads = windowMenu->addAction(tr("Downloads"), this, SLOT(slotDownloadManager()), QKeySequence(tr("Alt+Ctrl+L", "Download Manager")));

         QMenu *toolsMenu = menuBar()->addMenu(tr("&Tools"));
         toolsMenu->addAction(tr("Web &Search"), this, SLOT(slotWebSearch()), QKeySequence(tr("Ctrl+K", "Web Search")));
     #ifndef Q_CC_MINGW
         a = toolsMenu->addAction(tr("Enable Web &Inspector"), this, SLOT(slotToggleInspector(bool)));
         a->setCheckable(true);
     #endif

         QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
         helpMenu->addAction(tr("About &Qt"), qApp, SLOT(aboutQt()));
         helpMenu->addAction(tr("About &WebKit"), this, SLOT(slotAboutApplication()));
     }

     void BrowserMainWindow::setupToolBar()
     {
         setUnifiedTitleAndToolBarOnMac(true);
         navigationBar = addToolBar(tr("Navigation"));

         m_historyBack->setIcon(style()->standardIcon(QStyle::SP_ArrowBack, 0, this));
         navigationBar->addAction(m_historyBack);

         m_historyForward->setIcon(style()->standardIcon(QStyle::SP_ArrowForward, 0, this));
         navigationBar->addAction(m_historyForward);

         m_stopReload = new QAction(this);
         navigationBar->addAction(m_stopReload);

         m_urlEdit = new QLineEdit(navigationBar);
         navigationBar->addWidget(m_urlEdit);
         HistoryCompletionModel *completionModel = new HistoryCompletionModel();
         completionModel->setSourceModel(m_history->historyFilterModel());
         QCompleter *completer = new QCompleter(completionModel, m_urlEdit);
         m_urlEdit->setCompleter(completer);
         connect(m_urlEdit, SIGNAL(returnPressed()), SLOT(slotUrlEntered()));

         m_toolbarSearch = new ToolbarSearch(navigationBar);
         navigationBar->addWidget(m_toolbarSearch);
         connect(m_toolbarSearch, SIGNAL(search(const QUrl&)), SLOT(slotSearch(const QUrl&)));

         m_chaseWidget = new ChaseWidget(this);
         navigationBar->addWidget(m_chaseWidget);
     }

     void BrowserMainWindow::slotToggleToolbar()
     {
         if (navigationBar->isVisible()) {
             updateToolbarActionText(false);
             navigationBar->close();
         } else {
             updateToolbarActionText(true);
             navigationBar->show();
         }
         m_autoSave->changed();
     }

     void BrowserMainWindow::updateStatusbarActionText(bool visible)
     {
         m_viewStatusbar->setText(!visible ? tr("Show Status Bar") : tr("Hide Status Bar"));
     }

     void BrowserMainWindow::updateToolbarActionText(bool visible)
     {
         m_viewToolbar->setText(!visible ? tr("Show Toolbar") : tr("Hide Toolbar"));
     }

     void BrowserMainWindow::slotToggleStatusbar()
     {
         if (statusBar()->isVisible()) {
             updateStatusbarActionText(false);
             statusBar()->close();
         } else {
             updateStatusbarActionText(true);
             statusBar()->show();
         }
         m_autoSave->changed();
     }

     QUrl BrowserMainWindow::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 url(urlStr, QUrl::TolerantMode);
             if (url.isValid())
                 return url;
         }

         // Might be a file.
         if (QFile::exists(urlStr))
             return QUrl::fromLocalFile(urlStr);

         // 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 url(schema + QLatin1String("://") + urlStr, QUrl::TolerantMode);
                 if (url.isValid())
                     return url;
             }
         }

         // Fall back to QUrl's own tolerant parser.
         return QUrl(string, QUrl::TolerantMode);
     }

     void BrowserMainWindow::slotSearch(const QUrl &url)
     {
         replaceCurrentUrl(url);

         if (currentTab()) {
             currentTab()->loadUrl(url);
             currentTab()->setFocus();
         }
     }

     void BrowserMainWindow::slotDownloadManager()
     {
         m_downloadManager->show();
     }

     WebView *BrowserMainWindow::createTab()
     {
         WebView *tab = new WebView(this, m_mainTabWidget);
         if (CookieJar *jar = qobject_cast<CookieJar*>(tab->page()->networkAccessManager()->cookieJar())) {
             m_cookieJar = jar;
         } else {
             m_cookieJar = new CookieJar(this);
             tab->page()->networkAccessManager()->setCookieJar(m_cookieJar);
         }

         connect(tab, SIGNAL(titleChanged(const QString&)), SLOT(slotWebViewTitleChanged(const QString&)));
         connect(tab, SIGNAL(iconChanged()), SLOT(slotWebViewIconChanged()));
         connect(tab, SIGNAL(authenticationRequired(WebView*,QNetworkReply*,QAuthenticator*)),
                 SLOT(slotAuthenticationRequired(WebView*,QNetworkReply*,QAuthenticator*)));
         connect(tab, SIGNAL(proxyAuthenticationRequired(WebView*,const QNetworkProxy&, QAuthenticator*)),
                 SLOT(slotProxyAuthenticationRequired(WebView*,const QNetworkProxy&, QAuthenticator*)));
         connect(tab, SIGNAL(sslErrors(WebView*,QNetworkReply*, const QList<QSslError>&)),
                 SLOT(slotSslErrors(WebView*, QNetworkReply*, const QList<QSslError>&)));

         if (!m_downloadManager)
             m_downloadManager = new DownloadManager(tab->page()->networkAccessManager(), this);
         tab->page()->setForwardUnsupportedContent(true);
         connect(tab->page(), SIGNAL(unsupportedContent(QNetworkReply *)),
                 this, SLOT(slotHandleUnsupportedContent(QNetworkReply *)));
         connect(tab->page(), SIGNAL(downloadRequested(const QNetworkRequest &)),
                 m_downloadManager, SLOT(download(const QNetworkRequest &)));

         m_mainTabWidget->addTab(tab, tr("(Untitled)"));

         replaceCurrentUrl(QString());
         m_urlEdit->setFocus();
         m_autoSave->changed();

         return tab;
     }

     void BrowserMainWindow::slotHandleUnsupportedContent(QNetworkReply *reply)
     {
         if (reply->error() == QNetworkReply::NoError) {
             m_downloadManager->handleUnsupportedContent(reply);
             return;
         }
         // Simple, basic solution for now.
         QMessageBox::information(this, tr("Network Error"),
             QString("Error: %1\nUrl: %2").arg(reply->errorString()).arg(reply->url().toString()));
     }

     void BrowserMainWindow::slotNewTab()
     {
         WebView *tab = createTab();
         m_urlEdit->setFocus();
         m_mainTabWidget->setCurrentWidget(tab);
         setCurrentTab(tab);
         m_autoSave->changed();
     }

     void BrowserMainWindow::slotPreferences()
     {
         if (!m_cookieJar)
             return;
         SettingsDialog *s = new SettingsDialog(m_cookieJar, this);
         s->show();
     }

     void BrowserMainWindow::slotCloseTab(int index)
     {
         QWidget *widget = m_mainTabWidget->widget(index);

         if (qobject_cast<WebView*>(widget)) {
             WebView *tab = static_cast<WebView*>(widget);
             if (tab->isModified()) {
                 QMessageBox closeConfirmation(tab);
                 closeConfirmation.setWindowFlags(Qt::Sheet);
                 closeConfirmation.setWindowTitle(tr("Do you really want to close this page?"));
                 closeConfirmation.setInformativeText(tr("You have modified this page and when closing it you will lose the modification.\n"
                                                          "Do you really want to close this page?\n"));
                 closeConfirmation.setIcon(QMessageBox::Question);
                 closeConfirmation.addButton(QMessageBox::Yes);
                 closeConfirmation.addButton(QMessageBox::No);
                 closeConfirmation.setEscapeButton(QMessageBox::No);
                 if (closeConfirmation.exec() == QMessageBox::No)
                     return;
             }

             m_recentlyClosedTabsAction->setEnabled(true);
             m_recentlyClosedUrls.prepend(tab->url());
             if (m_recentlyClosedUrls.size() >= BrowserMainWindow::LastClosedUrlsSize)
                 m_recentlyClosedUrls.removeLast();
         }

         m_mainTabWidget->removeTab(index);
         setCurrentTab(currentTab());

         if (m_mainTabWidget->count() == 0) {
             close();
             slotNewTab();
             slotHome();
         }
         m_autoSave->changed();
     }

     void BrowserMainWindow::slotUpdateStatusbar(const QString& txt)
     {
         statusBar()->showMessage(txt);
     }

     void BrowserMainWindow::slotUpdateWindowTitle(const QString& title)
     {
         if (title.isEmpty())
             setWindowTitle(tr("Qt Example Browser"));
         else
             setWindowTitle(tr("%1 - Qt Example Browser", "Page title and Browser name").arg(title));
     }

     void BrowserMainWindow::slotWebViewTitleChanged(const QString& newTitle)
     {
         WebView *tab = qobject_cast<WebView*>(sender());
         Q_ASSERT(sender() && tab);
         m_history->updateHistoryItem(tab->url(), newTitle);
         m_mainTabWidget->setTabText(m_mainTabWidget->indexOf(tab), newTitle);
     }

     void BrowserMainWindow::slotWebViewIconChanged()
     {
         WebView *browser = qobject_cast<WebView*>(sender());

         m_mainTabWidget->setTabIcon(m_mainTabWidget->indexOf(browser), browser->icon());
     }

     void BrowserMainWindow::slotNextTab()
     {
         int next = m_mainTabWidget->currentIndex() + 1;
         if (next == m_mainTabWidget->count())
             next = 0;
         m_mainTabWidget->setCurrentIndex(next);
     }

     void BrowserMainWindow::slotPreviousTab()
     {
         int next = m_mainTabWidget->currentIndex() - 1;
         if (next < 0)
             next = m_mainTabWidget->count() - 1;
         m_mainTabWidget->setCurrentIndex(next);
     }

     void BrowserMainWindow::slotAboutApplication()
     {
         QMessageBox::about(this, tr("About"), tr(
             "Version %1"
             "<p>This example demonstrates Qt's "
             "webkit facilities in action, providing an example "
             "browser for you to experiment with.<p>"
             "<p>QtWebKit is based on the Open Source WebKit Project developed at <a href=\"http://webkit.org/\">http://webkit.org/</a>."
             ).arg(QCoreApplication::applicationVersion()));
     }

     void BrowserMainWindow::slotNewWindow()
     {
         QWidget *w = new BrowserMainWindow;
         w->show();
     }

     void BrowserMainWindow::slotOpenFile()
     {
         QString file = QFileDialog::getOpenFileName(this, tr("Open Web Resource"), QString(),
                 tr("Web Resources (*.html *.htm *.svg *.svgz)"));

         if (file.isEmpty())
             return;

         loadPage(file);
     }

     void BrowserMainWindow::slotCloseTab()
     {
         if (!m_mainTabWidget->currentWidget())
             return;

         slotCloseTab(m_mainTabWidget->currentIndex());
     }

     void BrowserMainWindow::slotUndo()
     {
         PERFORM_WEBPAGE_ACTION(Undo)
     }

     void BrowserMainWindow::slotRedo()
     {
         PERFORM_WEBPAGE_ACTION(Redo)
     }

     void BrowserMainWindow::slotCut()
     {
         PERFORM_WEBPAGE_ACTION(Cut)
     }

     void BrowserMainWindow::slotCopy()
     {
         PERFORM_WEBPAGE_ACTION(Copy)
     }

     void BrowserMainWindow::slotPaste()
     {
         PERFORM_WEBPAGE_ACTION(Paste)
     }

     void BrowserMainWindow::slotStop()
     {
         PERFORM_WEBPAGE_ACTION(Stop)
     }

     void BrowserMainWindow::slotReload()
     {
         PERFORM_WEBPAGE_ACTION(Reload)
     }

     void BrowserMainWindow::slotTextBigger()
     {
         if (!currentTab())
             return;
         currentTab()->setTextSizeMultiplier(currentTab()->textSizeMultiplier() + 0.5);
     }

     void BrowserMainWindow::slotTextNormal()
     {
         if (!currentTab())
             return;
         currentTab()->setTextSizeMultiplier(1.0);
     }

     void BrowserMainWindow::slotTextSmaller()
     {
         if (!currentTab())
             return;
         currentTab()->setTextSizeMultiplier(currentTab()->textSizeMultiplier() - 0.5);
     }

     void BrowserMainWindow::slotToggleFullScreen(bool makeFullScreen)
     {
         makeFullScreen ? showFullScreen() : showNormal();
     }

     void BrowserMainWindow::slotPageSource()
     {
         if (!currentTab())
             return;

         QString markup = currentTab()->page()->mainFrame()->toHtml();
         SourceCodeView *view = new SourceCodeView(markup);
         view->setWindowTitle(tr("Page Source of %1").arg(currentTab()->title()));
         view->setMinimumWidth(640);
         view->setAttribute(Qt::WA_DeleteOnClose);
         view->show();
     }

     void BrowserMainWindow::slotBack()
     {
         PERFORM_WEBPAGE_ACTION(Back)
     }

     void BrowserMainWindow::slotForward()
     {
         PERFORM_WEBPAGE_ACTION(Forward)
     }

     void BrowserMainWindow::slotHome()
     {
         QSettings settings;
         settings.beginGroup("MainWindow");
         QString home = settings.value("home", "http://www.trolltech.com/").toString();
         loadPage(home);
     }

     void BrowserMainWindow::slotWebSearch()
     {
         m_toolbarSearch->selectAll();
         m_toolbarSearch->setFocus();
     }

     void BrowserMainWindow::slotToggleInspector(bool enable)
     {
         QWebSettings::globalSettings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, enable);
         if (enable) {
             int result = QMessageBox::question(this, tr("Web Inspector"),
                                                tr("The web inspector will only work correctly for pages that were loaded after enabling.\n"
                                                "Do you want to reload all pages?"),
                                                QMessageBox::Yes | QMessageBox::No);
             if (result == QMessageBox::Yes) {
                 for (int i = 0; i < m_mainTabWidget->count(); ++i)
                     static_cast<WebView *>(m_mainTabWidget->widget(i))->triggerPageAction(QWebPage::Reload);
             }
         }
     }

     void BrowserMainWindow::slotUrlEntered()
     {
         loadPage(m_urlEdit->text());

         if (currentTab())
             currentTab()->setFocus();
     }

     void BrowserMainWindow::slotAboutToShowRecentTabs()
     {
         m_recentlyClosedTabsMenu->clear();
         for (int i = 0; i < m_recentlyClosedUrls.count(); ++i) {
             QAction *action = new QAction(this);
             action->setData(i);
             action->setIcon(style()->standardIcon(QStyle::SP_FileIcon));
             action->setText(m_recentlyClosedUrls.at(i).toString());
             m_recentlyClosedTabsMenu->addAction(action);
         }
     }

     void BrowserMainWindow::slotAboutToShowRecentTriggered(QAction *action)
     {
         int row = action->data().toInt();
         slotLoadUrl(m_recentlyClosedUrls.value(row));
     }

     void BrowserMainWindow::loadPage(const QString& page)
     {
         if (!currentTab())
             return;

         QUrl url = guessUrlFromString(page);
         m_urlEdit->setText(url.toString());
         slotLoadUrl(url);
     }

     void BrowserMainWindow::slotLoadUrl(const QUrl &url)
     {
         currentTab()->loadUrl(url);
     }

     WebView *BrowserMainWindow::currentTab() const
     {
         // We might not have a tab, or it might be some kind of special widget
         return qobject_cast<WebView*>(m_mainTabWidget->currentWidget());
     }

     /*
      * The goal is to not change URL when the user is currently entering something.
      *
      * We assume that if the URL Edit has focus the user is trying to enter something
      */
     void BrowserMainWindow::replaceCurrentUrl(const QUrl& url)
     {
         if (!m_urlEdit->hasFocus())
             m_urlEdit->setText(url.toString());
     }

     void BrowserMainWindow::slotCurrentTabChanged(int index)
     {
         // Can be 0, e.g. if we don't have a BrowserTab in our tabwidget
         setCurrentTab(qobject_cast<WebView*>(m_mainTabWidget->widget(index)));
     }

     void BrowserMainWindow::setCurrentTab(WebView *tab)
     {
         // All the magic will happen there
         m_proxy->setTab(tab);
     }

     void BrowserMainWindow::slotLoadStarted()
     {
         m_chaseWidget->setAnimated(true);
         m_stopReload->setIcon(m_stopIcon);
         m_stopReload->setToolTip(tr("Stop loading the current page"));
     }

     void BrowserMainWindow::slotLoadFinished()
     {
         m_chaseWidget->setAnimated(false);
         disconnect(m_stopReload, SIGNAL(triggered()), this, SLOT(slotStop()));
         m_stopReload->setIcon(m_reloadIcon);
         connect(m_stopReload, SIGNAL(triggered()), this, SLOT(slotReload()));
         m_stopReload->setToolTip(tr("Reload the current page"));
     }

     void BrowserMainWindow::slotUrlChanged(const QUrl &url)
     {
         m_autoSave->changed();
         disconnect(m_stopReload, SIGNAL(triggered()), this, SLOT(slotReload()));
         replaceCurrentUrl(url);
         connect(m_stopReload, SIGNAL(triggered()), this, SLOT(slotStop()));
     }

     QString BrowserMainWindow::currentPage() const
     {
         return m_urlEdit->text();
     }

     void BrowserMainWindow::slotAuthenticationRequired(WebView *tab, QNetworkReply *reply, QAuthenticator *auth)
     {
         QDialog dialog(this);
         dialog.setWindowFlags(Qt::Sheet);

         Ui::PasswordDialog passwordDialog;
         passwordDialog.setupUi(&dialog);

         passwordDialog.lblInfo->setText(QString());
         passwordDialog.lblInfo->setPixmap(style()->standardIcon(QStyle::SP_MessageBoxQuestion, 0, this).pixmap(32, 32));

         QString introMessage = QCoreApplication::translate("PasswordDialog", "<qt>Please enter a Username and Password for \"%1\" from %2</qt>");
         introMessage = introMessage.arg(Qt::escape(tab->title())).arg(Qt::escape(reply->url().toString()));
         passwordDialog.lblIntro->setText(introMessage);
         passwordDialog.lblIntro->setWordWrap(true);

         if (dialog.exec() == QDialog::Accepted) {
             auth->setUser(passwordDialog.lneUsername->text());
             auth->setPassword(passwordDialog.lnePassword->text());
         }
     }

     void BrowserMainWindow::slotProxyAuthenticationRequired(WebView*, const QNetworkProxy&, QAuthenticator*)
     {
     }

     void BrowserMainWindow::slotSslErrors(WebView*, QNetworkReply *reply, const QList<QSslError>&)
     {
         reply->ignoreSslErrors();
     }