comparison demos/browser/browsermainwindow.d @ 45:71b382c10ef6

add coarse and incomplete QT browser port
author mandel
date Sun, 17 May 2009 18:49:59 +0000
parents
children 7bfd46c330dc
comparison
equal deleted inserted replaced
44:3cb15c92ac28 45:71b382c10ef6
1 /****************************************************************************
2 **
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: Qt Software Information (qt-info@nokia.com)
5 **
6 ** This file is part of the demonstration applications of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial Usage
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Nokia.
14 **
15 ** GNU Lesser General Public License Usage
16 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** General Public License version 2.1 as published by the Free Software
18 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** packaging of this file. Please review the following information to
20 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22 **
23 ** In addition, as a special exception, Nokia gives you certain
24 ** additional rights. These rights are described in the Nokia Qt LGPL
25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26 ** package.
27 **
28 ** GNU General Public License Usage
29 ** Alternatively, this file may be used under the terms of the GNU
30 ** General Public License version 3.0 as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL included in the
32 ** packaging of this file. Please review the following information to
33 ** ensure the GNU General Public License version 3.0 requirements will be
34 ** met: http://www.gnu.org/copyleft/gpl.html.
35 **
36 ** If you are unsure which license is appropriate for your use, please
37 ** contact the sales department at qt-sales@nokia.com.
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 import QtGui.QMainWindow;
43 import QtGui.QIcon;
44 import QtCore.QUrl;
45
46 import browsermainwindow;
47
48 import autosaver;
49 import bookmarks;
50 import browserapplication;
51 import chasewidget;
52 import downloadmanager;
53 import history;
54 import settings;
55 import tabwidget;
56 import toolbarsearch;
57 import ui_passworddialog;
58 import webview;
59
60 import QtCore.QSettings;
61
62 import QtGui.QDesktopWidget;
63 import QtGui.QFileDialog;
64 import QtGui.QPlainTextEdit;
65 import QtGui.QPrintDialog;
66 import QtGui.QPrintPreviewDialog;
67 import QtGui.QPrinter;
68 import QtGui.QMenuBar;
69 import QtGui.QMessageBox;
70 import QtGui.QStatusBar;
71 import QtGui.QToolBar;
72 import QtGui.QInputDialog;
73
74 import QtWebKit.QWebFrame;
75 import QtWebKit.QWebHistory;
76
77 import QtCore.QDebug;
78
79
80 class AutoSaver;
81 class BookmarksToolBar;
82 class ChaseWidget;
83 class QWebFrame;
84 class TabWidget;
85 class ToolbarSearch;
86 class WebView;
87
88 /*!
89 The MainWindow of the Browser Application.
90
91 Handles the tab widget and all the actions
92 */
93 class BrowserMainWindow : public QMainWindow {
94 Q_OBJECT
95
96 static const qint32 BrowserMainWindowMagic = 0xba;
97
98 public:
99 this(QWidget *parent = null, Qt.WindowFlags flags = 0);
100 {
101
102 super(parent, flags);
103 m_tabWidget = new TabWidget(this);
104 m_autoSaver = new AutoSaver(this);
105 m_historyBack = 0;
106 m_historyForward = 0;
107 m_stop = 0;
108 m_reload = 0;
109
110 setAttribute(Qt.WA_DeleteOnClose, true);
111 statusBar().setSizeGripEnabled(true);
112 setupMenu();
113 setupToolBar();
114
115 QWidget *centralWidget = new QWidget(this);
116 BookmarksModel *boomarksModel = BrowserApplication::bookmarksManager().bookmarksModel();
117 m_bookmarksToolbar = new BookmarksToolBar(boomarksModel, this);
118 connect(m_bookmarksToolbar, SIGNAL(openUrl(const QUrl&)),
119 m_tabWidget, SLOT(loadUrlInCurrentTab(const QUrl&)));
120 connect(m_bookmarksToolbar.toggleViewAction(), SIGNAL(toggled(bool)),
121 this, SLOT(updateBookmarksToolbarActionText(bool)));
122
123 QVBoxLayout *layout = new QVBoxLayout;
124 layout.setSpacing(0);
125 layout.setMargin(0);
126 version(Q_WS_MAC)
127 {
128 layout.addWidget(m_bookmarksToolbar);
129 layout.addWidget(new QWidget); // <- OS X tab widget style bug
130 } else {
131 addToolBarBreak();
132 addToolBar(m_bookmarksToolbar);
133 }
134 layout.addWidget(m_tabWidget);
135 centralWidget.setLayout(layout);
136 setCentralWidget(centralWidget);
137
138 connect(m_tabWidget, SIGNAL(loadPage(const QString &)),
139 this, SLOT(loadPage(const QString &)));
140 connect(m_tabWidget, SIGNAL(setCurrentTitle(const QString &)),
141 this, SLOT(slotUpdateWindowTitle(const QString &)));
142 connect(m_tabWidget, SIGNAL(showStatusBarMessage(const QString&)),
143 statusBar(), SLOT(showMessage(const QString&)));
144 connect(m_tabWidget, SIGNAL(linkHovered(const QString&)),
145 statusBar(), SLOT(showMessage(const QString&)));
146 connect(m_tabWidget, SIGNAL(loadProgress(int)),
147 this, SLOT(slotLoadProgress(int)));
148 connect(m_tabWidget, SIGNAL(tabsChanged()),
149 m_autoSaver, SLOT(changeOccurred()));
150 connect(m_tabWidget, SIGNAL(geometryChangeRequested(const QRect &)),
151 this, SLOT(geometryChangeRequested(const QRect &)));
152 connect(m_tabWidget, SIGNAL(printRequested(QWebFrame *)),
153 this, SLOT(printRequested(QWebFrame *)));
154 connect(m_tabWidget, SIGNAL(menuBarVisibilityChangeRequested(bool)),
155 menuBar(), SLOT(setVisible(bool)));
156 connect(m_tabWidget, SIGNAL(statusBarVisibilityChangeRequested(bool)),
157 statusBar(), SLOT(setVisible(bool)));
158 connect(m_tabWidget, SIGNAL(toolBarVisibilityChangeRequested(bool)),
159 m_navigationBar, SLOT(setVisible(bool)));
160 connect(m_tabWidget, SIGNAL(toolBarVisibilityChangeRequested(bool)),
161 m_bookmarksToolbar, SLOT(setVisible(bool)));
162 version(Q_WS_MAC) {
163 connect(m_tabWidget, SIGNAL(lastTabClosed()),
164 this, SLOT(close()));
165 } else {
166 connect(m_tabWidget, SIGNAL(lastTabClosed()),
167 m_tabWidget, SLOT(newTab()));
168 }
169
170 slotUpdateWindowTitle();
171 loadDefaultState();
172 m_tabWidget.newTab();
173
174 int size = m_tabWidget.lineEditStack().sizeHint().height();
175 m_navigationBar.setIconSize(QSize(size, size));
176
177 }
178
179
180
181 ~this()
182 {
183 m_autoSaver.changeOccurred();
184 m_autoSaver.saveIfNeccessary();
185 }
186
187
188 QSize sizeHint()
189 {
190 QRect desktopRect = QApplication::desktop().screenGeometry();
191 QSize size = desktopRect.size() * qreal(0.9);
192 return size;
193 }
194
195 public:
196 static QUrl guessUrlFromString(const QString &string)
197 {
198 QString urlStr = string.trimmed();
199 QRegExp test(QLatin1String("^[a-zA-Z]+\\:.*"));
200
201 // Check if it looks like a qualified URL. Try parsing it and see.
202 bool hasSchema = test.exactMatch(urlStr);
203 if (hasSchema) {
204 QUrl url = QUrl::fromEncoded(urlStr.toUtf8(), QUrl::TolerantMode);
205 if (url.isValid())
206 return url;
207 }
208
209 // Might be a file.
210 if (QFile::exists(urlStr)) {
211 QFileInfo info(urlStr);
212 return QUrl::fromLocalFile(info.absoluteFilePath());
213 }
214
215 // Might be a shorturl - try to detect the schema.
216 if (!hasSchema) {
217 int dotIndex = urlStr.indexOf(QLatin1Char('.'));
218 if (dotIndex != -1) {
219 QString prefix = urlStr.left(dotIndex).toLower();
220 QByteArray schema = (prefix == QLatin1String("ftp")) ? prefix.toLatin1() : "http";
221 QUrl url =
222 QUrl::fromEncoded(schema + "://" + urlStr.toUtf8(), QUrl::TolerantMode);
223 if (url.isValid())
224 return url;
225 }
226 }
227
228 // Fall back to QUrl's own tolerant parser.
229 QUrl url = QUrl::fromEncoded(string.toUtf8(), QUrl::TolerantMode);
230
231 // finally for cases where the user just types in a hostname add http
232 if (url.scheme().isEmpty())
233 url = QUrl::fromEncoded("http://" + string.toUtf8(), QUrl::TolerantMode);
234 return url;
235 }
236
237
238
239 TabWidget* tabWidget()
240 {
241 return m_tabWidget;
242 }
243
244 WebView* currentTab()
245 {
246 return m_tabWidget.currentWebView();
247 }
248
249 QByteArray saveState(bool withTabs)
250 {
251 int version = 2;
252 QByteArray data;
253 QDataStream stream(&data, QIODevice::WriteOnly);
254
255 stream << qint32(BrowserMainWindowMagic);
256 stream << qint32(version);
257
258 stream << size();
259 stream << !m_navigationBar.isHidden();
260 stream << !m_bookmarksToolbar.isHidden();
261 stream << !statusBar().isHidden();
262 if (withTabs)
263 stream << tabWidget().saveState();
264 else
265 stream << QByteArray();
266 return data;
267 }
268
269
270 bool restoreState(const QByteArray &state)
271 {
272 int version = 2;
273 QByteArray sd = state;
274 QDataStream stream(&sd, QIODevice::ReadOnly);
275 if (stream.atEnd())
276 return false;
277
278 qint32 marker;
279 qint32 v;
280 stream >> marker;
281 stream >> v;
282 if (marker != BrowserMainWindowMagic || v != version)
283 return false;
284
285 QSize size;
286 bool showToolbar;
287 bool showBookmarksBar;
288 bool showStatusbar;
289 QByteArray tabState;
290
291 stream >> size;
292 stream >> showToolbar;
293 stream >> showBookmarksBar;
294 stream >> showStatusbar;
295 stream >> tabState;
296
297 resize(size);
298
299 m_navigationBar.setVisible(showToolbar);
300 updateToolbarActionText(showToolbar);
301
302 m_bookmarksToolbar.setVisible(showBookmarksBar);
303 updateBookmarksToolbarActionText(showBookmarksBar);
304
305 statusBar().setVisible(showStatusbar);
306 updateStatusbarActionText(showStatusbar);
307
308 if (!tabWidget().restoreState(tabState))
309 return false;
310
311 return true;
312 }
313
314
315 public slots:
316 void loadPage(const QString &page)
317 {
318 QUrl url = guessUrlFromString(page);
319 loadUrl(url);
320 }
321
322
323 void slotHome()
324 {
325 QSettings settings;
326 settings.beginGroup(QLatin1String("MainWindow"));
327 QString home = settings.value(QLatin1String("home"), QLatin1String("http://qtsoftware.com/")).toString();
328 loadPage(home);
329 }
330
331 protected:
332 void closeEvent(QCloseEvent *event);
333 {
334 if (m_tabWidget.count() > 1) {
335 int ret = QMessageBox.warning(this, QString(),
336 tr("Are you sure you want to close the window?"
337 " There are %1 tab open").arg(m_tabWidget.count()),
338 QMessageBox.Yes | QMessageBox.No,
339 QMessageBox.No);
340 if (ret == QMessageBox.No) {
341 event.ignore();
342 return;
343 }
344 }
345 event.accept();
346 deleteLater();
347 }
348
349 private slots:
350 void save()
351 {
352 BrowserApplication::instance().saveSession();
353
354 QSettings settings;
355 settings.beginGroup(QLatin1String("BrowserMainWindow"));
356 QByteArray data = saveState(false);
357 settings.setValue(QLatin1String("defaultState"), data);
358 settings.endGroup();
359 }
360
361 void slotLoadProgress(int progress)
362 {
363 if (progress < 100 && progress > 0) {
364 m_chaseWidget.setAnimated(true);
365 disconnect(m_stopReload, SIGNAL(triggered()), m_reload, SLOT(trigger()));
366 if (m_stopIcon.isNull())
367 m_stopIcon = style().standardIcon(QStyle::SP_BrowserStop);
368 m_stopReload.setIcon(m_stopIcon);
369 connect(m_stopReload, SIGNAL(triggered()), m_stop, SLOT(trigger()));
370 m_stopReload.setToolTip(tr("Stop loading the current page"));
371 } else {
372 m_chaseWidget.setAnimated(false);
373 disconnect(m_stopReload, SIGNAL(triggered()), m_stop, SLOT(trigger()));
374 m_stopReload.setIcon(m_reloadIcon);
375 connect(m_stopReload, SIGNAL(triggered()), m_reload, SLOT(trigger()));
376 m_stopReload.setToolTip(tr("Reload the current page"));
377 }
378 }
379
380 void slotUpdateStatusbar(const QString &string);
381 {
382 statusBar().showMessage(string, 2000);
383 }
384
385
386 void slotUpdateWindowTitle(const QString &title = QString())
387 {
388 if (title.isEmpty()) {
389 setWindowTitle(tr("Qt Demo Browser"));
390 } else {
391 version(Q_WS_MAC)
392 {
393 setWindowTitle(title);
394 } else {
395 setWindowTitle(tr("%1 - Qt Demo Browser", "Page title and Browser name").arg(title));
396 }
397 }
398 }
399
400 void loadUrl(const QUrl &url);
401 {
402 if (!currentTab() || !url.isValid())
403 return;
404
405 m_tabWidget.currentLineEdit().setText(QString::fromUtf8(url.toEncoded()));
406 m_tabWidget.loadUrlInCurrentTab(url);
407 }
408
409 void slotPreferences()
410 {
411 SettingsDialog *s = new SettingsDialog(this);
412 s.show();
413 }
414
415 void slotFileNew()
416 {
417 BrowserApplication::instance().newMainWindow();
418 BrowserMainWindow *mw = BrowserApplication::instance().mainWindow();
419 mw.slotHome();
420 }
421
422 void slotFileOpen()
423 {
424 QString file = QFileDialog::getOpenFileName(this, tr("Open Web Resource"), QString(),
425 tr("Web Resources (*.html *.htm *.svg *.png *.gif *.svgz);;All files (*.*)"));
426
427 if (file.isEmpty())
428 return;
429
430 loadPage(file);
431 }
432
433 void slotFilePrintPreview();
434 {
435 version(QT_NO_PRINTER)
436 {
437 if (!currentTab())
438 return;
439 QPrintPreviewDialog *dialog = new QPrintPreviewDialog(this);
440 connect(dialog, SIGNAL(paintRequested(QPrinter *)),
441 currentTab(), SLOT(print(QPrinter *)));
442 dialog.exec();
443 }
444 }
445
446
447 void slotFilePrint()
448 {
449 if (!currentTab())
450 return;
451 printRequested(currentTab().page().mainFrame());
452 }
453
454 void slotPrivateBrowsing()
455 {
456 QWebSettings *settings = QWebSettings::globalSettings();
457 bool pb = settings.testAttribute(QWebSettings::PrivateBrowsingEnabled);
458 if (!pb) {
459 QString title = tr("Are you sure you want to turn on private browsing?");
460 QString text = tr("<b>%1</b><br><br>When private browsing in turned on,"
461 " webpages are not added to the history,"
462 " items are automatically removed from the Downloads window," \
463 " new cookies are not stored, current cookies can't be accessed," \
464 " site icons wont be stored, session wont be saved, " \
465 " and searches are not addded to the pop-up menu in the Google search box." \
466 " Until you close the window, you can still click the Back and Forward buttons" \
467 " to return to the webpages you have opened.").arg(title);
468
469 QMessageBox.StandardButton button = QMessageBox.question(this, QString(), text,
470 QMessageBox.Ok | QMessageBox.Cancel,
471 QMessageBox.Ok);
472 if (button == QMessageBox.Ok) {
473 settings.setAttribute(QWebSettings::PrivateBrowsingEnabled, true);
474 }
475 } else {
476 settings.setAttribute(QWebSettings::PrivateBrowsingEnabled, false);
477
478 QList<BrowserMainWindow*> windows = BrowserApplication::instance().mainWindows();
479 for (int i = 0; i < windows.count(); ++i) {
480 BrowserMainWindow *window = windows.at(i);
481 window.m_lastSearch = QString::null;
482 window.tabWidget().clear();
483 }
484 }
485 }
486
487 void slotFileSaveAs()
488 {
489 BrowserApplication::downloadManager().download(currentTab().url(), true);
490 }
491
492 void slotEditFind()
493 {
494 if (!currentTab())
495 return;
496 bool ok;
497 QString search = QInputDialog::getText(this, tr("Find"),
498 tr("Text:"), QLineEdit::Normal,
499 m_lastSearch, &ok);
500 if (ok && !search.isEmpty()) {
501 m_lastSearch = search;
502 if (!currentTab().findText(m_lastSearch))
503 slotUpdateStatusbar(tr("\"%1\" not found.").arg(m_lastSearch));
504 }
505 }
506
507 void slotEditFindNext()
508 {
509 if (!currentTab() && !m_lastSearch.isEmpty())
510 return;
511 currentTab().findText(m_lastSearch);
512 }
513
514 void slotEditFindPrevious()
515 {
516 if (!currentTab() && !m_lastSearch.isEmpty())
517 return;
518 currentTab().findText(m_lastSearch, QWebPage::FindBackward);
519 }
520
521
522 void slotShowBookmarksDialog();
523 {
524 BookmarksDialog *dialog = new BookmarksDialog(this);
525 connect(dialog, SIGNAL(openUrl(const QUrl&)),
526 m_tabWidget, SLOT(loadUrlInCurrentTab(const QUrl&)));
527 dialog.show();
528 }
529
530 void slotAddBookmark()
531 {
532 WebView *webView = currentTab();
533 QString url = webView.url().toString();
534 QString title = webView.title();
535 AddBookmarkDialog dialog(url, title);
536 dialog.exec();
537 }
538
539 void slotViewZoomIn()
540 {
541 if (!currentTab())
542 return;
543 currentTab().setZoomFactor(currentTab().zoomFactor() + 0.1);
544 }
545
546 void BslotViewZoomOut()
547 {
548 if (!currentTab())
549 return;
550 currentTab().setZoomFactor(currentTab().zoomFactor() - 0.1);
551 }
552
553 void slotViewResetZoom()
554 {
555 if (!currentTab())
556 return;
557 currentTab().setZoomFactor(1.0);
558 }
559
560 void slotViewZoomTextOnly(bool enable)
561 {
562 if (!currentTab())
563 return;
564 currentTab().page().settings().setAttribute(QWebSettings::ZoomTextOnly, enable);
565 }
566
567
568 void slotViewToolbar()
569 {
570 if (m_navigationBar.isVisible()) {
571 updateToolbarActionText(false);
572 m_navigationBar.close();
573 } else {
574 updateToolbarActionText(true);
575 m_navigationBar.show();
576 }
577 m_autoSaver.changeOccurred();
578 }
579
580
581 void slotViewBookmarksBar()
582 {
583 if (m_bookmarksToolbar.isVisible()) {
584 updateBookmarksToolbarActionText(false);
585 m_bookmarksToolbar.close();
586 } else {
587 updateBookmarksToolbarActionText(true);
588 m_bookmarksToolbar.show();
589 }
590 m_autoSaver.changeOccurred();
591 }
592
593 void slotViewStatusbar()
594 {
595 if (statusBar().isVisible()) {
596 updateStatusbarActionText(false);
597 statusBar().close();
598 } else {
599 updateStatusbarActionText(true);
600 statusBar().show();
601 }
602 m_autoSaver.changeOccurred();
603 }
604
605 void slotViewPageSource()
606 {
607 if (!currentTab())
608 return;
609
610 QString markup = currentTab().page().mainFrame().toHtml();
611 QPlainTextEdit *view = new QPlainTextEdit(markup);
612 view.setWindowTitle(tr("Page Source of %1").arg(currentTab().title()));
613 view.setMinimumWidth(640);
614 view.setAttribute(Qt.WA_DeleteOnClose);
615 view.show();
616 }
617
618
619 void slotViewFullScreen(bool makeFullScreen)
620 {
621 if (makeFullScreen) {
622 showFullScreen();
623 } else {
624 if (isMinimized())
625 showMinimized();
626 else if (isMaximized())
627 showMaximized();
628 else showNormal();
629 }
630 }
631
632 void slotWebSearch()
633 {
634 m_toolbarSearch.lineEdit().selectAll();
635 m_toolbarSearch.lineEdit().setFocus();
636 }
637
638
639 void slotToggleInspector(bool enable);
640 {
641 QWebSettings::globalSettings().setAttribute(QWebSettings::DeveloperExtrasEnabled, enable);
642 if (enable) {
643 int result = QMessageBox.question(this, tr("Web Inspector"),
644 tr("The web inspector will only work correctly for pages that were loaded after enabling.\n"
645 "Do you want to reload all pages?"),
646 QMessageBox.Yes | QMessageBox.No);
647 if (result == QMessageBox.Yes) {
648 m_tabWidget.reloadAllTabs();
649 }
650 }
651 }
652
653
654 void slotAboutApplication()
655 {
656 QMessageBox.about(this, tr("About"), tr(
657 "Version %1"
658 "<p>This demo demonstrates Qt's "
659 "webkit facilities in action, providing an example "
660 "browser for you to experiment with.<p>"
661 "<p>QtWebKit is based on the Open Source WebKit Project developed at <a href=\"http://webkit.org/\">http://webkit.org/</a>."
662 ).arg(QCoreApplication::applicationVersion()));
663 }
664
665 void slotDownloadManager()
666 {
667 BrowserApplication::downloadManager().show();
668 }
669
670 void slotSelectLineEdit();
671 {
672 m_tabWidget.currentLineEdit().selectAll();
673 m_tabWidget.currentLineEdit().setFocus();
674 }
675
676 void slotAboutToShowBackMenu();
677 {
678 m_historyBackMenu.clear();
679 if (!currentTab())
680 return;
681 QWebHistory *history = currentTab().history();
682 int historyCount = history.count();
683 for (int i = history.backItems(historyCount).count() - 1; i >= 0; --i) {
684 QWebHistoryItem item = history.backItems(history.count()).at(i);
685 QAction *action = new QAction(this);
686 action.setData(-1*(historyCount-i-1));
687 QIcon icon = BrowserApplication::instance().icon(item.url());
688 action.setIcon(icon);
689 action.setText(item.title());
690 m_historyBackMenu.addAction(action);
691 }
692 }
693
694
695 void slotAboutToShowForwardMenu();
696 {
697 m_historyForwardMenu.clear();
698 if (!currentTab())
699 return;
700 QWebHistory *history = currentTab().history();
701 int historyCount = history.count();
702 for (int i = 0; i < history.forwardItems(history.count()).count(); ++i) {
703 QWebHistoryItem item = history.forwardItems(historyCount).at(i);
704 QAction *action = new QAction(this);
705 action.setData(historyCount-i);
706 QIcon icon = BrowserApplication::instance().icon(item.url());
707 action.setIcon(icon);
708 action.setText(item.title());
709 m_historyForwardMenu.addAction(action);
710 }
711 }
712
713 void slotAboutToShowWindowMenu()
714 {
715 m_windowMenu.clear();
716 m_windowMenu.addAction(m_tabWidget.nextTabAction());
717 m_windowMenu.addAction(m_tabWidget.previousTabAction());
718 m_windowMenu.addSeparator();
719 m_windowMenu.addAction(tr("Downloads"), this, SLOT(slotDownloadManager()), QKeySequence(tr("Alt+Ctrl+L", "Download Manager")));
720
721 m_windowMenu.addSeparator();
722 QList<BrowserMainWindow*> windows = BrowserApplication::instance().mainWindows();
723 for (int i = 0; i < windows.count(); ++i) {
724 BrowserMainWindow *window = windows.at(i);
725 QAction *action = m_windowMenu.addAction(window.windowTitle(), this, SLOT(slotShowWindow()));
726 action.setData(i);
727 action.setCheckable(true);
728 if (window == this)
729 action.setChecked(true);
730 }
731 }
732
733 void slotOpenActionUrl(QAction *action)
734 {
735 int offset = action.data().toInt();
736 QWebHistory *history = currentTab().history();
737 if (offset < 0)
738 history.goToItem(history.backItems(-1*offset).first()); // back
739 else if (offset > 0)
740 history.goToItem(history.forwardItems(history.count() - offset + 1).back()); // forward
741 }
742 void slotShowWindow()
743 {
744 if (QAction *action = qobject_cast<QAction*>(sender())) {
745 QVariant v = action.data();
746 if (v.canConvert<int>()) {
747 int offset = qvariant_cast<int>(v);
748 QList<BrowserMainWindow*> windows = BrowserApplication::instance().mainWindows();
749 windows.at(offset).activateWindow();
750 windows.at(offset).currentTab().setFocus();
751 }
752 }
753 }
754
755 void slotSwapFocus()
756 {
757 if (currentTab().hasFocus())
758 m_tabWidget.currentLineEdit().setFocus();
759 else
760 currentTab().setFocus();
761 }
762
763 void printRequested(QWebFrame *frame)
764 {
765 version(QT_NO_PRINTER)
766 {
767 QPrinter printer;
768 QPrintDialog *dialog = new QPrintDialog(&printer, this);
769 dialog.setWindowTitle(tr("Print Document"));
770 if (dialog.exec() != QDialog::Accepted)
771 return;
772 frame.print(&printer);
773 }
774 }
775
776 void geometryChangeRequested(const QRect &geometry)
777 {
778 setGeometry(geometry);
779 }
780
781
782 void updateToolbarActionText(bool visible)
783 {
784 m_viewToolbar.setText(!visible ? tr("Show Toolbar") : tr("Hide Toolbar"));
785 }
786
787 void updateBookmarksToolbarActionText(bool visible)
788 {
789 m_viewBookmarkBar.setText(!visible ? tr("Show Bookmarks bar") : tr("Hide Bookmarks bar"));
790 }
791
792
793 private:
794 void loadDefaultState()
795 {
796 QSettings settings;
797 settings.beginGroup(QLatin1String("BrowserMainWindow"));
798 QByteArray data = settings.value(QLatin1String("defaultState")).toByteArray();
799 restoreState(data);
800 settings.endGroup();
801 }
802
803
804 void setupMenu();
805 {
806 new QShortcut(QKeySequence(Qt.Key_F6), this, SLOT(slotSwapFocus()));
807
808 // File
809 QMenu *fileMenu = menuBar().addMenu(tr("&File"));
810
811 fileMenu.addAction(tr("&New Window"), this, SLOT(slotFileNew()), QKeySequence::New);
812 fileMenu.addAction(m_tabWidget.newTabAction());
813 fileMenu.addAction(tr("&Open File..."), this, SLOT(slotFileOpen()), QKeySequence::Open);
814 fileMenu.addAction(tr("Open &Location..."), this,
815 SLOT(slotSelectLineEdit()), QKeySequence(Qt.ControlModifier + Qt.Key_L));
816 fileMenu.addSeparator();
817 fileMenu.addAction(m_tabWidget.closeTabAction());
818 fileMenu.addSeparator();
819 fileMenu.addAction(tr("&Save As..."), this,
820 SLOT(slotFileSaveAs()), QKeySequence(QKeySequence::Save));
821 fileMenu.addSeparator();
822 BookmarksManager *bookmarksManager = BrowserApplication::bookmarksManager();
823 fileMenu.addAction(tr("&Import Bookmarks..."), bookmarksManager, SLOT(importBookmarks()));
824 fileMenu.addAction(tr("&Export Bookmarks..."), bookmarksManager, SLOT(exportBookmarks()));
825 fileMenu.addSeparator();
826 fileMenu.addAction(tr("P&rint Preview..."), this, SLOT(slotFilePrintPreview()));
827 fileMenu.addAction(tr("&Print..."), this, SLOT(slotFilePrint()), QKeySequence::Print);
828 fileMenu.addSeparator();
829 QAction *action = fileMenu.addAction(tr("Private &Browsing..."), this, SLOT(slotPrivateBrowsing()));
830 action.setCheckable(true);
831 fileMenu.addSeparator();
832
833 version(Q_WS_MAC) {
834 fileMenu.addAction(tr("&Quit"), BrowserApplication::instance(), SLOT(quitBrowser()), QKeySequence(Qt.CTRL | Qt.Key_Q));
835 } else {
836 fileMenu.addAction(tr("&Quit"), this, SLOT(close()), QKeySequence(Qt.CTRL | Qt.Key_Q));
837 }
838
839 // Edit
840 QMenu *editMenu = menuBar().addMenu(tr("&Edit"));
841 QAction *m_undo = editMenu.addAction(tr("&Undo"));
842 m_undo.setShortcuts(QKeySequence::Undo);
843 m_tabWidget.addWebAction(m_undo, QWebPage::Undo);
844 QAction *m_redo = editMenu.addAction(tr("&Redo"));
845 m_redo.setShortcuts(QKeySequence::Redo);
846 m_tabWidget.addWebAction(m_redo, QWebPage::Redo);
847 editMenu.addSeparator();
848 QAction *m_cut = editMenu.addAction(tr("Cu&t"));
849 m_cut.setShortcuts(QKeySequence::Cut);
850 m_tabWidget.addWebAction(m_cut, QWebPage::Cut);
851 QAction *m_copy = editMenu.addAction(tr("&Copy"));
852 m_copy.setShortcuts(QKeySequence::Copy);
853 m_tabWidget.addWebAction(m_copy, QWebPage::Copy);
854 QAction *m_paste = editMenu.addAction(tr("&Paste"));
855 m_paste.setShortcuts(QKeySequence::Paste);
856 m_tabWidget.addWebAction(m_paste, QWebPage::Paste);
857 editMenu.addSeparator();
858
859 QAction *m_find = editMenu.addAction(tr("&Find"));
860 m_find.setShortcuts(QKeySequence::Find);
861 connect(m_find, SIGNAL(triggered()), this, SLOT(slotEditFind()));
862 new QShortcut(QKeySequence(Qt.Key_Slash), this, SLOT(slotEditFind()));
863
864 QAction *m_findNext = editMenu.addAction(tr("&Find Next"));
865 m_findNext.setShortcuts(QKeySequence::FindNext);
866 connect(m_findNext, SIGNAL(triggered()), this, SLOT(slotEditFindNext()));
867
868 QAction *m_findPrevious = editMenu.addAction(tr("&Find Previous"));
869 m_findPrevious.setShortcuts(QKeySequence::FindPrevious);
870 connect(m_findPrevious, SIGNAL(triggered()), this, SLOT(slotEditFindPrevious()));
871
872 editMenu.addSeparator();
873 editMenu.addAction(tr("&Preferences"), this, SLOT(slotPreferences()), tr("Ctrl+,"));
874
875 // View
876 QMenu *viewMenu = menuBar().addMenu(tr("&View"));
877
878 m_viewBookmarkBar = new QAction(this);
879 updateBookmarksToolbarActionText(true);
880 m_viewBookmarkBar.setShortcut(tr("Shift+Ctrl+B"));
881 connect(m_viewBookmarkBar, SIGNAL(triggered()), this, SLOT(slotViewBookmarksBar()));
882 viewMenu.addAction(m_viewBookmarkBar);
883
884 m_viewToolbar = new QAction(this);
885 updateToolbarActionText(true);
886 m_viewToolbar.setShortcut(tr("Ctrl+|"));
887 connect(m_viewToolbar, SIGNAL(triggered()), this, SLOT(slotViewToolbar()));
888 viewMenu.addAction(m_viewToolbar);
889
890 m_viewStatusbar = new QAction(this);
891 updateStatusbarActionText(true);
892 m_viewStatusbar.setShortcut(tr("Ctrl+/"));
893 connect(m_viewStatusbar, SIGNAL(triggered()), this, SLOT(slotViewStatusbar()));
894 viewMenu.addAction(m_viewStatusbar);
895
896 viewMenu.addSeparator();
897
898 m_stop = viewMenu.addAction(tr("&Stop"));
899 QList<QKeySequence> shortcuts;
900 shortcuts.append(QKeySequence(Qt.CTRL | Qt.Key_Period));
901 shortcuts.append(Qt.Key_Escape);
902 m_stop.setShortcuts(shortcuts);
903 m_tabWidget.addWebAction(m_stop, QWebPage::Stop);
904
905 m_reload = viewMenu.addAction(tr("Reload Page"));
906 m_reload.setShortcuts(QKeySequence::Refresh);
907 m_tabWidget.addWebAction(m_reload, QWebPage::Reload);
908
909 viewMenu.addAction(tr("Zoom &In"), this, SLOT(slotViewZoomIn()), QKeySequence(Qt.CTRL | Qt.Key_Plus));
910 viewMenu.addAction(tr("Zoom &Out"), this, SLOT(slotViewZoomOut()), QKeySequence(Qt.CTRL | Qt.Key_Minus));
911 viewMenu.addAction(tr("Reset &Zoom"), this, SLOT(slotViewResetZoom()), QKeySequence(Qt.CTRL | Qt.Key_0));
912 QAction *zoomTextOnlyAction = viewMenu.addAction(tr("Zoom &Text Only"));
913 connect(zoomTextOnlyAction, SIGNAL(toggled(bool)), this, SLOT(slotViewZoomTextOnly(bool)));
914 zoomTextOnlyAction.setCheckable(true);
915 zoomTextOnlyAction.setChecked(false);
916
917 viewMenu.addSeparator();
918 viewMenu.addAction(tr("Page S&ource"), this, SLOT(slotViewPageSource()), tr("Ctrl+Alt+U"));
919 QAction *a = viewMenu.addAction(tr("&Full Screen"), this, SLOT(slotViewFullScreen(bool)), Qt.Key_F11);
920 a.setCheckable(true);
921
922 // History
923 HistoryMenu *historyMenu = new HistoryMenu(this);
924 connect(historyMenu, SIGNAL(openUrl(const QUrl&)),
925 m_tabWidget, SLOT(loadUrlInCurrentTab(const QUrl&)));
926 connect(historyMenu, SIGNAL(hovered(const QString&)), this,
927 SLOT(slotUpdateStatusbar(const QString&)));
928 historyMenu.setTitle(tr("Hi&story"));
929 menuBar().addMenu(historyMenu);
930 QList<QAction*> historyActions;
931
932 m_historyBack = new QAction(tr("Back"), this);
933 m_tabWidget.addWebAction(m_historyBack, QWebPage::Back);
934 m_historyBack.setShortcuts(QKeySequence::Back);
935 m_historyBack.setIconVisibleInMenu(false);
936
937 m_historyForward = new QAction(tr("Forward"), this);
938 m_tabWidget.addWebAction(m_historyForward, QWebPage::Forward);
939 m_historyForward.setShortcuts(QKeySequence::Forward);
940 m_historyForward.setIconVisibleInMenu(false);
941
942 QAction *m_historyHome = new QAction(tr("Home"), this);
943 connect(m_historyHome, SIGNAL(triggered()), this, SLOT(slotHome()));
944 m_historyHome.setShortcut(QKeySequence(Qt.CTRL | Qt.SHIFT | Qt.Key_H));
945
946 m_restoreLastSession = new QAction(tr("Restore Last Session"), this);
947 connect(m_restoreLastSession, SIGNAL(triggered()), BrowserApplication::instance(), SLOT(restoreLastSession()));
948 m_restoreLastSession.setEnabled(BrowserApplication::instance().canRestoreSession());
949
950 historyActions.append(m_historyBack);
951 historyActions.append(m_historyForward);
952 historyActions.append(m_historyHome);
953 historyActions.append(m_tabWidget.recentlyClosedTabsAction());
954 historyActions.append(m_restoreLastSession);
955 historyMenu.setInitialActions(historyActions);
956
957 // Bookmarks
958 BookmarksMenu *bookmarksMenu = new BookmarksMenu(this);
959 connect(bookmarksMenu, SIGNAL(openUrl(const QUrl&)),
960 m_tabWidget, SLOT(loadUrlInCurrentTab(const QUrl&)));
961 connect(bookmarksMenu, SIGNAL(hovered(const QString&)),
962 this, SLOT(slotUpdateStatusbar(const QString&)));
963 bookmarksMenu.setTitle(tr("&Bookmarks"));
964 menuBar().addMenu(bookmarksMenu);
965
966 QList<QAction*> bookmarksActions;
967
968 QAction *showAllBookmarksAction = new QAction(tr("Show All Bookmarks"), this);
969 connect(showAllBookmarksAction, SIGNAL(triggered()), this, SLOT(slotShowBookmarksDialog()));
970 m_addBookmark = new QAction(QIcon(QLatin1String(":addbookmark.png")), tr("Add Bookmark..."), this);
971 m_addBookmark.setIconVisibleInMenu(false);
972
973 connect(m_addBookmark, SIGNAL(triggered()), this, SLOT(slotAddBookmark()));
974 m_addBookmark.setShortcut(QKeySequence(Qt.CTRL | Qt.Key_D));
975
976 bookmarksActions.append(showAllBookmarksAction);
977 bookmarksActions.append(m_addBookmark);
978 bookmarksMenu.setInitialActions(bookmarksActions);
979
980 // Window
981 m_windowMenu = menuBar().addMenu(tr("&Window"));
982 connect(m_windowMenu, SIGNAL(aboutToShow()),
983 this, SLOT(slotAboutToShowWindowMenu()));
984 slotAboutToShowWindowMenu();
985
986 QMenu *toolsMenu = menuBar().addMenu(tr("&Tools"));
987 toolsMenu.addAction(tr("Web &Search"), this, SLOT(slotWebSearch()), QKeySequence(tr("Ctrl+K", "Web Search")));
988 #ifndef Q_CC_MINGW
989 a = toolsMenu.addAction(tr("Enable Web &Inspector"), this, SLOT(slotToggleInspector(bool)));
990 a.setCheckable(true);
991 #endif
992
993 QMenu *helpMenu = menuBar().addMenu(tr("&Help"));
994 helpMenu.addAction(tr("About &Qt"), qApp, SLOT(aboutQt()));
995 helpMenu.addAction(tr("About &Demo Browser"), this, SLOT(slotAboutApplication()));
996 }
997
998
999 void setupToolBar()
1000 {
1001 setUnifiedTitleAndToolBarOnMac(true);
1002 m_navigationBar = addToolBar(tr("Navigation"));
1003 connect(m_navigationBar.toggleViewAction(), SIGNAL(toggled(bool)),
1004 this, SLOT(updateToolbarActionText(bool)));
1005
1006 m_historyBack.setIcon(style().standardIcon(QStyle::SP_ArrowBack, 0, this));
1007 m_historyBackMenu = new QMenu(this);
1008 m_historyBack.setMenu(m_historyBackMenu);
1009 connect(m_historyBackMenu, SIGNAL(aboutToShow()),
1010 this, SLOT(slotAboutToShowBackMenu()));
1011 connect(m_historyBackMenu, SIGNAL(triggered(QAction *)),
1012 this, SLOT(slotOpenActionUrl(QAction *)));
1013 m_navigationBar.addAction(m_historyBack);
1014
1015 m_historyForward.setIcon(style().standardIcon(QStyle::SP_ArrowForward, 0, this));
1016 m_historyForwardMenu = new QMenu(this);
1017 connect(m_historyForwardMenu, SIGNAL(aboutToShow()),
1018 this, SLOT(slotAboutToShowForwardMenu()));
1019 connect(m_historyForwardMenu, SIGNAL(triggered(QAction *)),
1020 this, SLOT(slotOpenActionUrl(QAction *)));
1021 m_historyForward.setMenu(m_historyForwardMenu);
1022 m_navigationBar.addAction(m_historyForward);
1023
1024 m_stopReload = new QAction(this);
1025 m_reloadIcon = style().standardIcon(QStyle::SP_BrowserReload);
1026 m_stopReload.setIcon(m_reloadIcon);
1027
1028 m_navigationBar.addAction(m_stopReload);
1029
1030 m_navigationBar.addWidget(m_tabWidget.lineEditStack());
1031
1032 m_toolbarSearch = new ToolbarSearch(m_navigationBar);
1033 m_navigationBar.addWidget(m_toolbarSearch);
1034 connect(m_toolbarSearch, SIGNAL(search(const QUrl&)), SLOT(loadUrl(const QUrl&)));
1035
1036 m_chaseWidget = new ChaseWidget(this);
1037 m_navigationBar.addWidget(m_chaseWidget);
1038 }
1039
1040 void updateStatusbarActionText(bool visible)
1041 {
1042 m_viewStatusbar.setText(!visible ? tr("Show Status Bar") : tr("Hide Status Bar"));
1043 }
1044
1045
1046 private:
1047 QToolBar *m_navigationBar;
1048 ToolbarSearch *m_toolbarSearch;
1049 BookmarksToolBar *m_bookmarksToolbar;
1050 ChaseWidget *m_chaseWidget;
1051 TabWidget *m_tabWidget;
1052 AutoSaver *m_autoSaver;
1053
1054 QAction *m_historyBack;
1055 QMenu *m_historyBackMenu;
1056 QAction *m_historyForward;
1057 QMenu *m_historyForwardMenu;
1058 QMenu *m_windowMenu;
1059
1060 QAction *m_stop;
1061 QAction *m_reload;
1062 QAction *m_stopReload;
1063 QAction *m_viewToolbar;
1064 QAction *m_viewBookmarkBar;
1065 QAction *m_viewStatusbar;
1066 QAction *m_restoreLastSession;
1067 QAction *m_addBookmark;
1068
1069 QIcon m_reloadIcon;
1070 QIcon m_stopIcon;
1071
1072 QString m_lastSearch;
1073 }