| /* |
| * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) |
| * Copyright (C) 2010 University of Szeged |
| * |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "BrowserWindow.h" |
| |
| #include "UrlLoader.h" |
| #include "qwkpreferences.h" |
| |
| static QWKPage* newPageFunction(QWKPage* page) |
| { |
| BrowserWindow* window = new BrowserWindow(page->context()); |
| return window->page(); |
| } |
| |
| QVector<qreal> BrowserWindow::m_zoomLevels; |
| |
| BrowserWindow::BrowserWindow(QWKContext* context, WindowOptions* options) |
| : m_isZoomTextOnly(false) |
| , m_currentZoom(1) |
| , m_urlLoader(0) |
| , m_context(context) |
| { |
| if (options) |
| m_windowOptions = *options; |
| else { |
| WindowOptions tmpOptions; |
| m_windowOptions = tmpOptions; |
| } |
| |
| if (m_windowOptions.useTiledBackingStore) |
| m_browser = new BrowserView(QGraphicsWKView::Tiled, context); |
| else |
| m_browser = new BrowserView(QGraphicsWKView::Simple, context); |
| |
| setAttribute(Qt::WA_DeleteOnClose); |
| |
| connect(m_browser->view(), SIGNAL(loadProgress(int)), SLOT(loadProgress(int))); |
| connect(m_browser->view(), SIGNAL(titleChanged(const QString&)), SLOT(setWindowTitle(const QString&))); |
| connect(m_browser->view(), SIGNAL(urlChanged(const QUrl&)), SLOT(urlChanged(const QUrl&))); |
| |
| if (m_windowOptions.printLoadedUrls) |
| connect(page(), SIGNAL(urlChanged(QUrl)), this, SLOT(printURL(QUrl))); |
| |
| this->setCentralWidget(m_browser); |
| m_browser->setFocus(Qt::OtherFocusReason); |
| |
| QMenu* fileMenu = menuBar()->addMenu("&File"); |
| fileMenu->addAction("New Window", this, SLOT(newWindow()), QKeySequence::New); |
| fileMenu->addAction("Open File", this, SLOT(openFile()), QKeySequence::Open); |
| fileMenu->addSeparator(); |
| fileMenu->addAction("Quit", this, SLOT(close())); |
| |
| QMenu* viewMenu = menuBar()->addMenu("&View"); |
| viewMenu->addAction(page()->action(QWKPage::Stop)); |
| viewMenu->addAction(page()->action(QWKPage::Reload)); |
| viewMenu->addSeparator(); |
| QAction* zoomIn = viewMenu->addAction("Zoom &In", this, SLOT(zoomIn())); |
| QAction* zoomOut = viewMenu->addAction("Zoom &Out", this, SLOT(zoomOut())); |
| QAction* resetZoom = viewMenu->addAction("Reset Zoom", this, SLOT(resetZoom())); |
| QAction* zoomText = viewMenu->addAction("Zoom Text Only", this, SLOT(toggleZoomTextOnly(bool))); |
| zoomText->setCheckable(true); |
| zoomText->setChecked(false); |
| viewMenu->addSeparator(); |
| viewMenu->addAction("Take Screen Shot...", this, SLOT(screenshot())); |
| |
| zoomIn->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Plus)); |
| zoomOut->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Minus)); |
| resetZoom->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_0)); |
| |
| QMenu* windowMenu = menuBar()->addMenu("&Window"); |
| QAction* toggleFullScreen = windowMenu->addAction("Toggle FullScreen", this, SIGNAL(enteredFullScreenMode(bool))); |
| toggleFullScreen->setShortcut(Qt::Key_F11); |
| toggleFullScreen->setCheckable(true); |
| toggleFullScreen->setChecked(false); |
| // When exit fullscreen mode by clicking on the exit area (bottom right corner) we must |
| // uncheck the Toggle FullScreen action. |
| toggleFullScreen->connect(this, SIGNAL(enteredFullScreenMode(bool)), SLOT(setChecked(bool))); |
| connect(this, SIGNAL(enteredFullScreenMode(bool)), this, SLOT(toggleFullScreenMode(bool))); |
| |
| QMenu* toolsMenu = menuBar()->addMenu("&Develop"); |
| QAction* toggleFrameFlattening = toolsMenu->addAction("Toggle Frame Flattening", this, SLOT(toggleFrameFlattening(bool))); |
| toggleFrameFlattening->setCheckable(true); |
| toggleFrameFlattening->setChecked(false); |
| toolsMenu->addSeparator(); |
| toolsMenu->addAction("Change User Agent", this, SLOT(showUserAgentDialog())); |
| toolsMenu->addSeparator(); |
| toolsMenu->addAction("Load URLs from file", this, SLOT(loadURLListFromFile())); |
| |
| QMenu* settingsMenu = menuBar()->addMenu("&Settings"); |
| QAction* toggleAutoLoadImages = settingsMenu->addAction("Disable Auto Load Images", this, SLOT(toggleAutoLoadImages(bool))); |
| toggleAutoLoadImages->setCheckable(true); |
| toggleAutoLoadImages->setChecked(false); |
| QAction* toggleDisableJavaScript = settingsMenu->addAction("Disable JavaScript", this, SLOT(toggleDisableJavaScript(bool))); |
| toggleDisableJavaScript->setCheckable(true); |
| toggleDisableJavaScript->setChecked(false); |
| |
| m_addressBar = new QLineEdit(); |
| connect(m_addressBar, SIGNAL(returnPressed()), SLOT(changeLocation())); |
| |
| QToolBar* bar = addToolBar("Navigation"); |
| bar->addAction(page()->action(QWKPage::Back)); |
| bar->addAction(page()->action(QWKPage::Forward)); |
| bar->addAction(page()->action(QWKPage::Reload)); |
| bar->addAction(page()->action(QWKPage::Stop)); |
| bar->addWidget(m_addressBar); |
| |
| QShortcut* selectAddressBar = new QShortcut(Qt::CTRL | Qt::Key_L, this); |
| connect(selectAddressBar, SIGNAL(activated()), this, SLOT(openLocation())); |
| |
| page()->setCreateNewPageFunction(newPageFunction); |
| |
| // the zoom values are chosen to be like in Mozilla Firefox 3 |
| if (!m_zoomLevels.count()) { |
| m_zoomLevels << 0.3 << 0.5 << 0.67 << 0.8 << 0.9; |
| m_zoomLevels << 1; |
| m_zoomLevels << 1.1 << 1.2 << 1.33 << 1.5 << 1.7 << 2 << 2.4 << 3; |
| } |
| |
| if (m_windowOptions.startMaximized) |
| setWindowState(windowState() | Qt::WindowMaximized); |
| else |
| resize(800, 600); |
| show(); |
| } |
| |
| void BrowserWindow::load(const QString& url) |
| { |
| m_addressBar->setText(url); |
| m_browser->load(url); |
| } |
| |
| QWKPage* BrowserWindow::page() |
| { |
| return m_browser->view()->page(); |
| } |
| |
| BrowserWindow* BrowserWindow::newWindow(const QString& url) |
| { |
| BrowserWindow* window; |
| if (m_windowOptions.useSeparateWebProcessPerWindow) { |
| QWKContext* context = new QWKContext(); |
| window = new BrowserWindow(context); |
| context->setParent(window); |
| } else |
| window = new BrowserWindow(m_context); |
| |
| window->load(url); |
| return window; |
| } |
| |
| void BrowserWindow::openLocation() |
| { |
| m_addressBar->selectAll(); |
| m_addressBar->setFocus(); |
| } |
| |
| void BrowserWindow::changeLocation() |
| { |
| QString string = m_addressBar->text(); |
| m_browser->load(string); |
| } |
| |
| void BrowserWindow::loadProgress(int progress) |
| { |
| QColor backgroundColor = QApplication::palette().color(QPalette::Base); |
| QColor progressColor = QColor(120, 180, 240); |
| QPalette pallete = m_addressBar->palette(); |
| |
| if (progress <= 0 || progress >= 100) |
| pallete.setBrush(QPalette::Base, backgroundColor); |
| else { |
| QLinearGradient gradient(0, 0, width(), 0); |
| gradient.setColorAt(0, progressColor); |
| gradient.setColorAt(((double) progress) / 100, progressColor); |
| if (progress != 100) |
| gradient.setColorAt((double) progress / 100 + 0.001, backgroundColor); |
| pallete.setBrush(QPalette::Base, gradient); |
| } |
| m_addressBar->setPalette(pallete); |
| } |
| |
| void BrowserWindow::urlChanged(const QUrl& url) |
| { |
| m_addressBar->setText(url.toString()); |
| m_browser->setFocus(); |
| m_browser->view()->setFocus(); |
| } |
| |
| void BrowserWindow::openFile() |
| { |
| #ifndef QT_NO_FILEDIALOG |
| static const QString filter("HTML Files (*.htm *.html *.xhtml);;Text Files (*.txt);;Image Files (*.gif *.jpg *.png);;SVG Files (*.svg);;All Files (*)"); |
| |
| QFileDialog fileDialog(this, tr("Open"), QString(), filter); |
| fileDialog.setAcceptMode(QFileDialog::AcceptOpen); |
| fileDialog.setFileMode(QFileDialog::ExistingFile); |
| fileDialog.setOptions(QFileDialog::ReadOnly); |
| |
| if (fileDialog.exec()) { |
| QString selectedFile = fileDialog.selectedFiles()[0]; |
| if (!selectedFile.isEmpty()) |
| load(selectedFile); |
| } |
| #endif |
| } |
| |
| void BrowserWindow::screenshot() |
| { |
| QPixmap pixmap = QPixmap::grabWidget(m_browser); |
| QLabel* label = 0; |
| #if !defined(Q_OS_SYMBIAN) |
| label = new QLabel; |
| label->setAttribute(Qt::WA_DeleteOnClose); |
| label->setWindowTitle("Screenshot - Preview"); |
| label->setPixmap(pixmap); |
| label->show(); |
| #endif |
| |
| #ifndef QT_NO_FILEDIALOG |
| QString fileName = QFileDialog::getSaveFileName(label, "Screenshot", QString(), QString("PNG File (.png)")); |
| if (!fileName.isEmpty()) { |
| QRegExp rx("*.png"); |
| rx.setCaseSensitivity(Qt::CaseInsensitive); |
| rx.setPatternSyntax(QRegExp::Wildcard); |
| |
| if (!rx.exactMatch(fileName)) |
| fileName += ".png"; |
| |
| pixmap.save(fileName, "png"); |
| if (label) |
| label->setWindowTitle(QString("Screenshot - Saved at %1").arg(fileName)); |
| } |
| #endif |
| } |
| |
| void BrowserWindow::zoomIn() |
| { |
| if (m_isZoomTextOnly) |
| m_currentZoom = page()->textZoomFactor(); |
| else |
| m_currentZoom = page()->pageZoomFactor(); |
| |
| int i = m_zoomLevels.indexOf(m_currentZoom); |
| Q_ASSERT(i >= 0); |
| if (i < m_zoomLevels.count() - 1) |
| m_currentZoom = m_zoomLevels[i + 1]; |
| |
| applyZoom(); |
| } |
| |
| void BrowserWindow::zoomOut() |
| { |
| if (m_isZoomTextOnly) |
| m_currentZoom = page()->textZoomFactor(); |
| else |
| m_currentZoom = page()->pageZoomFactor(); |
| |
| int i = m_zoomLevels.indexOf(m_currentZoom); |
| Q_ASSERT(i >= 0); |
| if (i > 0) |
| m_currentZoom = m_zoomLevels[i - 1]; |
| |
| applyZoom(); |
| } |
| |
| void BrowserWindow::resetZoom() |
| { |
| m_currentZoom = 1; |
| applyZoom(); |
| } |
| |
| void BrowserWindow::toggleZoomTextOnly(bool b) |
| { |
| m_isZoomTextOnly = b; |
| } |
| |
| void BrowserWindow::toggleFullScreenMode(bool enable) |
| { |
| bool alreadyEnabled = windowState() & Qt::WindowFullScreen; |
| if (enable ^ alreadyEnabled) |
| setWindowState(windowState() ^ Qt::WindowFullScreen); |
| } |
| |
| void BrowserWindow::toggleFrameFlattening(bool toggle) |
| { |
| page()->preferences()->setAttribute(QWKPreferences::FrameFlatteningEnabled, toggle); |
| } |
| |
| |
| void BrowserWindow::showUserAgentDialog() |
| { |
| updateUserAgentList(); |
| |
| QDialog dialog(this); |
| dialog.setWindowTitle("Change User Agent"); |
| dialog.resize(size().width() * 0.7, dialog.size().height()); |
| QVBoxLayout* layout = new QVBoxLayout(&dialog); |
| dialog.setLayout(layout); |
| |
| QComboBox* combo = new QComboBox(&dialog); |
| combo->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength); |
| combo->setEditable(true); |
| combo->insertItems(0, m_userAgentList); |
| layout->addWidget(combo); |
| |
| int index = combo->findText(page()->customUserAgent()); |
| combo->setCurrentIndex(index); |
| |
| QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel |
| , Qt::Horizontal, &dialog); |
| connect(buttonBox, SIGNAL(accepted()), &dialog, SLOT(accept())); |
| connect(buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject())); |
| layout->addWidget(buttonBox); |
| |
| if (dialog.exec() && !combo->currentText().isEmpty()) |
| page()->setCustomUserAgent(combo->currentText()); |
| } |
| |
| void BrowserWindow::loadURLListFromFile() |
| { |
| QString selectedFile; |
| #ifndef QT_NO_FILEDIALOG |
| selectedFile = QFileDialog::getOpenFileName(this, tr("Load URL list from file") |
| , QString(), tr("Text Files (*.txt);;All Files (*)")); |
| #endif |
| if (selectedFile.isEmpty()) |
| return; |
| |
| m_urlLoader = new UrlLoader(this, selectedFile, 0, 0); |
| m_urlLoader->loadNext(); |
| } |
| |
| void BrowserWindow::printURL(const QUrl& url) |
| { |
| QTextStream output(stdout); |
| output << "Loaded: " << url.toString() << endl; |
| } |
| |
| void BrowserWindow::toggleDisableJavaScript(bool enable) |
| { |
| page()->preferences()->setAttribute(QWKPreferences::JavascriptEnabled, !enable); |
| } |
| |
| void BrowserWindow::toggleAutoLoadImages(bool enable) |
| { |
| page()->preferences()->setAttribute(QWKPreferences::AutoLoadImages, !enable); |
| } |
| |
| void BrowserWindow::updateUserAgentList() |
| { |
| QFile file(":/useragentlist.txt"); |
| |
| if (file.open(QIODevice::ReadOnly)) { |
| while (!file.atEnd()) { |
| QString agent = file.readLine().trimmed(); |
| if (!m_userAgentList.contains(agent)) |
| m_userAgentList << agent; |
| } |
| file.close(); |
| } |
| |
| Q_ASSERT(!m_userAgentList.isEmpty()); |
| QWKPage* wkPage = page(); |
| if (!(wkPage->customUserAgent().isEmpty() || m_userAgentList.contains(wkPage->customUserAgent()))) |
| m_userAgentList << wkPage->customUserAgent(); |
| } |
| |
| void BrowserWindow::applyZoom() |
| { |
| if (m_isZoomTextOnly) |
| page()->setTextZoomFactor(m_currentZoom); |
| else |
| page()->setPageZoomFactor(m_currentZoom); |
| } |
| |
| BrowserWindow::~BrowserWindow() |
| { |
| delete m_urlLoader; |
| delete m_addressBar; |
| delete m_browser; |
| } |