• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
3  * Copyright (C) 2010 University of Szeged
4  *
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "BrowserWindow.h"
30 
31 #include "UrlLoader.h"
32 #include "qwkpreferences.h"
33 
newPageFunction(QWKPage * page)34 static QWKPage* newPageFunction(QWKPage* page)
35 {
36     BrowserWindow* window = new BrowserWindow(page->context());
37     return window->page();
38 }
39 
40 QVector<qreal> BrowserWindow::m_zoomLevels;
41 
BrowserWindow(QWKContext * context,WindowOptions * options)42 BrowserWindow::BrowserWindow(QWKContext* context, WindowOptions* options)
43     : m_isZoomTextOnly(false)
44     , m_currentZoom(1)
45     , m_urlLoader(0)
46     , m_context(context)
47 {
48     if (options)
49         m_windowOptions = *options;
50     else {
51         WindowOptions tmpOptions;
52         m_windowOptions = tmpOptions;
53     }
54 
55     if (m_windowOptions.useTiledBackingStore)
56         m_browser = new BrowserView(QGraphicsWKView::Tiled, context);
57     else
58         m_browser = new BrowserView(QGraphicsWKView::Simple, context);
59 
60     setAttribute(Qt::WA_DeleteOnClose);
61 
62     connect(m_browser->view(), SIGNAL(loadProgress(int)), SLOT(loadProgress(int)));
63     connect(m_browser->view(), SIGNAL(titleChanged(const QString&)), SLOT(setWindowTitle(const QString&)));
64     connect(m_browser->view(), SIGNAL(urlChanged(const QUrl&)), SLOT(urlChanged(const QUrl&)));
65 
66     if (m_windowOptions.printLoadedUrls)
67         connect(page(), SIGNAL(urlChanged(QUrl)), this, SLOT(printURL(QUrl)));
68 
69     this->setCentralWidget(m_browser);
70     m_browser->setFocus(Qt::OtherFocusReason);
71 
72     QMenu* fileMenu = menuBar()->addMenu("&File");
73     fileMenu->addAction("New Window", this, SLOT(newWindow()), QKeySequence::New);
74     fileMenu->addAction("Open File", this, SLOT(openFile()), QKeySequence::Open);
75     fileMenu->addSeparator();
76     fileMenu->addAction("Quit", this, SLOT(close()));
77 
78     QMenu* viewMenu = menuBar()->addMenu("&View");
79     viewMenu->addAction(page()->action(QWKPage::Stop));
80     viewMenu->addAction(page()->action(QWKPage::Reload));
81     viewMenu->addSeparator();
82     QAction* zoomIn = viewMenu->addAction("Zoom &In", this, SLOT(zoomIn()));
83     QAction* zoomOut = viewMenu->addAction("Zoom &Out", this, SLOT(zoomOut()));
84     QAction* resetZoom = viewMenu->addAction("Reset Zoom", this, SLOT(resetZoom()));
85     QAction* zoomText = viewMenu->addAction("Zoom Text Only", this, SLOT(toggleZoomTextOnly(bool)));
86     zoomText->setCheckable(true);
87     zoomText->setChecked(false);
88     viewMenu->addSeparator();
89     viewMenu->addAction("Take Screen Shot...", this, SLOT(screenshot()));
90 
91     zoomIn->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Plus));
92     zoomOut->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Minus));
93     resetZoom->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_0));
94 
95     QMenu* windowMenu = menuBar()->addMenu("&Window");
96     QAction* toggleFullScreen = windowMenu->addAction("Toggle FullScreen", this, SIGNAL(enteredFullScreenMode(bool)));
97     toggleFullScreen->setShortcut(Qt::Key_F11);
98     toggleFullScreen->setCheckable(true);
99     toggleFullScreen->setChecked(false);
100     // When exit fullscreen mode by clicking on the exit area (bottom right corner) we must
101     // uncheck the Toggle FullScreen action.
102     toggleFullScreen->connect(this, SIGNAL(enteredFullScreenMode(bool)), SLOT(setChecked(bool)));
103     connect(this, SIGNAL(enteredFullScreenMode(bool)), this, SLOT(toggleFullScreenMode(bool)));
104 
105     QMenu* toolsMenu = menuBar()->addMenu("&Develop");
106     QAction* toggleFrameFlattening = toolsMenu->addAction("Toggle Frame Flattening", this, SLOT(toggleFrameFlattening(bool)));
107     toggleFrameFlattening->setCheckable(true);
108     toggleFrameFlattening->setChecked(false);
109     toolsMenu->addSeparator();
110     toolsMenu->addAction("Change User Agent", this, SLOT(showUserAgentDialog()));
111     toolsMenu->addSeparator();
112     toolsMenu->addAction("Load URLs from file", this, SLOT(loadURLListFromFile()));
113 
114     QMenu* settingsMenu = menuBar()->addMenu("&Settings");
115     QAction* toggleAutoLoadImages = settingsMenu->addAction("Disable Auto Load Images", this, SLOT(toggleAutoLoadImages(bool)));
116     toggleAutoLoadImages->setCheckable(true);
117     toggleAutoLoadImages->setChecked(false);
118     QAction* toggleDisableJavaScript = settingsMenu->addAction("Disable JavaScript", this, SLOT(toggleDisableJavaScript(bool)));
119     toggleDisableJavaScript->setCheckable(true);
120     toggleDisableJavaScript->setChecked(false);
121 
122     m_addressBar = new QLineEdit();
123     connect(m_addressBar, SIGNAL(returnPressed()), SLOT(changeLocation()));
124 
125     QToolBar* bar = addToolBar("Navigation");
126     bar->addAction(page()->action(QWKPage::Back));
127     bar->addAction(page()->action(QWKPage::Forward));
128     bar->addAction(page()->action(QWKPage::Reload));
129     bar->addAction(page()->action(QWKPage::Stop));
130     bar->addWidget(m_addressBar);
131 
132     QShortcut* selectAddressBar = new QShortcut(Qt::CTRL | Qt::Key_L, this);
133     connect(selectAddressBar, SIGNAL(activated()), this, SLOT(openLocation()));
134 
135     page()->setCreateNewPageFunction(newPageFunction);
136 
137     // the zoom values are chosen to be like in Mozilla Firefox 3
138     if (!m_zoomLevels.count()) {
139         m_zoomLevels << 0.3 << 0.5 << 0.67 << 0.8 << 0.9;
140         m_zoomLevels << 1;
141         m_zoomLevels << 1.1 << 1.2 << 1.33 << 1.5 << 1.7 << 2 << 2.4 << 3;
142     }
143 
144     if (m_windowOptions.startMaximized)
145         setWindowState(windowState() | Qt::WindowMaximized);
146     else
147         resize(800, 600);
148     show();
149 }
150 
load(const QString & url)151 void BrowserWindow::load(const QString& url)
152 {
153     m_addressBar->setText(url);
154     m_browser->load(url);
155 }
156 
page()157 QWKPage* BrowserWindow::page()
158 {
159     return m_browser->view()->page();
160 }
161 
newWindow(const QString & url)162 BrowserWindow* BrowserWindow::newWindow(const QString& url)
163 {
164     BrowserWindow* window;
165     if (m_windowOptions.useSeparateWebProcessPerWindow) {
166         QWKContext* context = new QWKContext();
167         window = new BrowserWindow(context);
168         context->setParent(window);
169     } else
170         window = new BrowserWindow(m_context);
171 
172     window->load(url);
173     return window;
174 }
175 
openLocation()176 void BrowserWindow::openLocation()
177 {
178     m_addressBar->selectAll();
179     m_addressBar->setFocus();
180 }
181 
changeLocation()182 void BrowserWindow::changeLocation()
183 {
184     QString string = m_addressBar->text();
185     m_browser->load(string);
186 }
187 
loadProgress(int progress)188 void BrowserWindow::loadProgress(int progress)
189 {
190     QColor backgroundColor = QApplication::palette().color(QPalette::Base);
191     QColor progressColor = QColor(120, 180, 240);
192     QPalette pallete = m_addressBar->palette();
193 
194     if (progress <= 0 || progress >= 100)
195         pallete.setBrush(QPalette::Base, backgroundColor);
196     else {
197         QLinearGradient gradient(0, 0, width(), 0);
198         gradient.setColorAt(0, progressColor);
199         gradient.setColorAt(((double) progress) / 100, progressColor);
200         if (progress != 100)
201             gradient.setColorAt((double) progress / 100 + 0.001, backgroundColor);
202         pallete.setBrush(QPalette::Base, gradient);
203     }
204     m_addressBar->setPalette(pallete);
205 }
206 
urlChanged(const QUrl & url)207 void BrowserWindow::urlChanged(const QUrl& url)
208 {
209     m_addressBar->setText(url.toString());
210     m_browser->setFocus();
211     m_browser->view()->setFocus();
212 }
213 
openFile()214 void BrowserWindow::openFile()
215 {
216 #ifndef QT_NO_FILEDIALOG
217     static const QString filter("HTML Files (*.htm *.html *.xhtml);;Text Files (*.txt);;Image Files (*.gif *.jpg *.png);;SVG Files (*.svg);;All Files (*)");
218 
219     QFileDialog fileDialog(this, tr("Open"), QString(), filter);
220     fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
221     fileDialog.setFileMode(QFileDialog::ExistingFile);
222     fileDialog.setOptions(QFileDialog::ReadOnly);
223 
224     if (fileDialog.exec()) {
225         QString selectedFile = fileDialog.selectedFiles()[0];
226         if (!selectedFile.isEmpty())
227             load(selectedFile);
228     }
229 #endif
230 }
231 
screenshot()232 void BrowserWindow::screenshot()
233 {
234     QPixmap pixmap = QPixmap::grabWidget(m_browser);
235     QLabel* label = 0;
236 #if !defined(Q_OS_SYMBIAN)
237     label = new QLabel;
238     label->setAttribute(Qt::WA_DeleteOnClose);
239     label->setWindowTitle("Screenshot - Preview");
240     label->setPixmap(pixmap);
241     label->show();
242 #endif
243 
244 #ifndef QT_NO_FILEDIALOG
245     QString fileName = QFileDialog::getSaveFileName(label, "Screenshot", QString(), QString("PNG File (.png)"));
246     if (!fileName.isEmpty()) {
247         QRegExp rx("*.png");
248         rx.setCaseSensitivity(Qt::CaseInsensitive);
249         rx.setPatternSyntax(QRegExp::Wildcard);
250 
251         if (!rx.exactMatch(fileName))
252             fileName += ".png";
253 
254         pixmap.save(fileName, "png");
255         if (label)
256             label->setWindowTitle(QString("Screenshot - Saved at %1").arg(fileName));
257     }
258 #endif
259 }
260 
zoomIn()261 void BrowserWindow::zoomIn()
262 {
263     if (m_isZoomTextOnly)
264         m_currentZoom = page()->textZoomFactor();
265     else
266         m_currentZoom = page()->pageZoomFactor();
267 
268     int i = m_zoomLevels.indexOf(m_currentZoom);
269     Q_ASSERT(i >= 0);
270     if (i < m_zoomLevels.count() - 1)
271         m_currentZoom = m_zoomLevels[i + 1];
272 
273     applyZoom();
274 }
275 
zoomOut()276 void BrowserWindow::zoomOut()
277 {
278     if (m_isZoomTextOnly)
279         m_currentZoom = page()->textZoomFactor();
280     else
281         m_currentZoom = page()->pageZoomFactor();
282 
283     int i = m_zoomLevels.indexOf(m_currentZoom);
284     Q_ASSERT(i >= 0);
285     if (i > 0)
286         m_currentZoom = m_zoomLevels[i - 1];
287 
288     applyZoom();
289 }
290 
resetZoom()291 void BrowserWindow::resetZoom()
292 {
293     m_currentZoom = 1;
294     applyZoom();
295 }
296 
toggleZoomTextOnly(bool b)297 void BrowserWindow::toggleZoomTextOnly(bool b)
298 {
299     m_isZoomTextOnly = b;
300 }
301 
toggleFullScreenMode(bool enable)302 void BrowserWindow::toggleFullScreenMode(bool enable)
303 {
304     bool alreadyEnabled = windowState() & Qt::WindowFullScreen;
305     if (enable ^ alreadyEnabled)
306         setWindowState(windowState() ^ Qt::WindowFullScreen);
307 }
308 
toggleFrameFlattening(bool toggle)309 void BrowserWindow::toggleFrameFlattening(bool toggle)
310 {
311     page()->preferences()->setAttribute(QWKPreferences::FrameFlatteningEnabled, toggle);
312 }
313 
314 
showUserAgentDialog()315 void BrowserWindow::showUserAgentDialog()
316 {
317     updateUserAgentList();
318 
319     QDialog dialog(this);
320     dialog.setWindowTitle("Change User Agent");
321     dialog.resize(size().width() * 0.7, dialog.size().height());
322     QVBoxLayout* layout = new QVBoxLayout(&dialog);
323     dialog.setLayout(layout);
324 
325     QComboBox* combo = new QComboBox(&dialog);
326     combo->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength);
327     combo->setEditable(true);
328     combo->insertItems(0, m_userAgentList);
329     layout->addWidget(combo);
330 
331     int index = combo->findText(page()->customUserAgent());
332     combo->setCurrentIndex(index);
333 
334     QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel
335                                                       , Qt::Horizontal, &dialog);
336     connect(buttonBox, SIGNAL(accepted()), &dialog, SLOT(accept()));
337     connect(buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject()));
338     layout->addWidget(buttonBox);
339 
340     if (dialog.exec() && !combo->currentText().isEmpty())
341         page()->setCustomUserAgent(combo->currentText());
342 }
343 
loadURLListFromFile()344 void BrowserWindow::loadURLListFromFile()
345 {
346     QString selectedFile;
347 #ifndef QT_NO_FILEDIALOG
348     selectedFile = QFileDialog::getOpenFileName(this, tr("Load URL list from file")
349                                                        , QString(), tr("Text Files (*.txt);;All Files (*)"));
350 #endif
351     if (selectedFile.isEmpty())
352        return;
353 
354     m_urlLoader = new UrlLoader(this, selectedFile, 0, 0);
355     m_urlLoader->loadNext();
356 }
357 
printURL(const QUrl & url)358 void BrowserWindow::printURL(const QUrl& url)
359 {
360     QTextStream output(stdout);
361     output << "Loaded: " << url.toString() << endl;
362 }
363 
toggleDisableJavaScript(bool enable)364 void BrowserWindow::toggleDisableJavaScript(bool enable)
365 {
366     page()->preferences()->setAttribute(QWKPreferences::JavascriptEnabled, !enable);
367 }
368 
toggleAutoLoadImages(bool enable)369 void BrowserWindow::toggleAutoLoadImages(bool enable)
370 {
371     page()->preferences()->setAttribute(QWKPreferences::AutoLoadImages, !enable);
372 }
373 
updateUserAgentList()374 void BrowserWindow::updateUserAgentList()
375 {
376     QFile file(":/useragentlist.txt");
377 
378     if (file.open(QIODevice::ReadOnly)) {
379         while (!file.atEnd()) {
380             QString agent = file.readLine().trimmed();
381             if (!m_userAgentList.contains(agent))
382                 m_userAgentList << agent;
383         }
384         file.close();
385     }
386 
387     Q_ASSERT(!m_userAgentList.isEmpty());
388     QWKPage* wkPage = page();
389     if (!(wkPage->customUserAgent().isEmpty() || m_userAgentList.contains(wkPage->customUserAgent())))
390         m_userAgentList << wkPage->customUserAgent();
391 }
392 
applyZoom()393 void BrowserWindow::applyZoom()
394 {
395     if (m_isZoomTextOnly)
396         page()->setTextZoomFactor(m_currentZoom);
397     else
398         page()->setPageZoomFactor(m_currentZoom);
399 }
400 
~BrowserWindow()401 BrowserWindow::~BrowserWindow()
402 {
403     delete m_urlLoader;
404     delete m_addressBar;
405     delete m_browser;
406 }
407