]> gitweb.stoutner.com Git - PrivacyBrowserPC.git/commitdiff
Add DevTools. https://redmine.stoutner.com/issues/1126
authorSoren Stoutner <soren@stoutner.com>
Sat, 9 Dec 2023 18:48:36 +0000 (11:48 -0700)
committerSoren Stoutner <soren@stoutner.com>
Sat, 9 Dec 2023 18:48:36 +0000 (11:48 -0700)
src/ui.rcs/browserwindowui.rc
src/widgets/CMakeLists.txt
src/widgets/DevToolsWebEngineView.cpp [new file with mode: 0644]
src/widgets/DevToolsWebEngineView.h [new file with mode: 0644]
src/widgets/PrivacyWebEngineView.cpp
src/widgets/PrivacyWebEngineView.h
src/widgets/TabWidget.cpp
src/widgets/TabWidget.h
src/windows/BrowserWindow.cpp
src/windows/BrowserWindow.h

index ab3d50336cb6b41bfaa8fcb5ef0d9c9400c13bec..f16913b6f2927149e10a42ee2f729f9eeb0bb0ca 100644 (file)
@@ -48,6 +48,7 @@
 
             <Action name="view_source" />
             <Action name="view_source_in_new_tab" />
+            <Action name="developer_tools" />
         </Menu>
 
         <!-- On-the-fly Settings. -->
index d237afbe12f8ed3025f4902e58d85207cea5a6fc..f161dec2afc0bd216808bf5b466f5be4b621cf6b 100644 (file)
@@ -18,6 +18,7 @@
 
 # List the sources to include in the executable.
 target_sources(privacybrowser PRIVATE
+    DevToolsWebEngineView.cpp
     DraggableTreeView.cpp
     PrivacyWebEngineView.cpp
     TabWidget.cpp
diff --git a/src/widgets/DevToolsWebEngineView.cpp b/src/widgets/DevToolsWebEngineView.cpp
new file mode 100644 (file)
index 0000000..a409584
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2022-2023 Soren Stoutner <soren@stoutner.com>.
+ *
+ * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
+ *
+ * Privacy Browser PC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Privacy Browser PC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Privacy Browser PC.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Application headers.
+#include "DevToolsWebEngineView.h"
+
+// Qt toolkit headers.
+#include <QWebEngineProfile>
+
+// Construct the class.
+DevToolsWebEngineView::DevToolsWebEngineView(QWidget *parentWidgetPointer) : QWebEngineView(parentWidgetPointer)
+{
+    // Create an off-the-record profile (the default when no profile name is specified).
+    QWebEngineProfile *webEngineProfilePointer = new QWebEngineProfile(QLatin1String(""));
+
+    // Create a WebEngine page.
+    QWebEnginePage *webEnginePagePointer = new QWebEnginePage(webEngineProfilePointer);
+
+    // Set the WebEngine page.
+    setPage(webEnginePagePointer);
+}
diff --git a/src/widgets/DevToolsWebEngineView.h b/src/widgets/DevToolsWebEngineView.h
new file mode 100644 (file)
index 0000000..a694bd3
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2022-2023 Soren Stoutner <soren@stoutner.com>.
+ *
+ * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
+ *
+ * Privacy Browser PC is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Privacy Browser PC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Privacy Browser PC.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DEVTOOLSWEBENGINEVIEW_H
+#define DEVTOOLSWEBENGINEVIEW_H
+
+// Qt toolkit headers.
+#include <QWebEngineView>
+
+class DevToolsWebEngineView : public QWebEngineView
+{
+    // Include the Q_OBJECT macro.
+    Q_OBJECT
+
+public:
+    // The default constructor.
+    explicit DevToolsWebEngineView(QWidget *parentWidgetPointer = nullptr);
+};
+#endif
index 38b03c31fa37c7fa3d8476dc6741897baafc3a4d..8f61f9156acd62994e26da68eab4dbb845a8cc8d 100644 (file)
@@ -30,7 +30,7 @@
 #include <QMenu>
 
 // Construct the class.
-PrivacyWebEngineView::PrivacyWebEngineView() : QWebEngineView(nullptr)
+PrivacyWebEngineView::PrivacyWebEngineView(QWidget *parentWidgetPointer) : QWebEngineView(parentWidgetPointer)
 {
     // Create an off-the-record profile (the default when no profile name is specified).
     webEngineProfilePointer = new QWebEngineProfile(QLatin1String(""));
@@ -45,7 +45,7 @@ PrivacyWebEngineView::PrivacyWebEngineView() : QWebEngineView(nullptr)
     webEngineSettingsPointer = webEnginePagePointer->settings();
 
     // Instantiate the URL request interceptor.
-    UrlRequestInterceptor *urlRequestInterceptorPointer = new UrlRequestInterceptor();
+    UrlRequestInterceptor *urlRequestInterceptorPointer = new UrlRequestInterceptor(this);
 
     // Set the URL request interceptor.
     webEngineProfilePointer->setUrlRequestInterceptor(urlRequestInterceptorPointer);
index 3077681ca86030a7717883e52cc74c1d909ee18f..171ca5e6397e4ae4daabeb77c9009a802bc63503 100644 (file)
@@ -33,7 +33,7 @@ class PrivacyWebEngineView : public QWebEngineView
 
 public:
     // The default constructor.
-    explicit PrivacyWebEngineView();
+    explicit PrivacyWebEngineView(QWidget *parentWidgetPointer = nullptr);
 
     // The public variables.
     std::list<QNetworkCookie> *cookieListPointer = new std::list<QNetworkCookie>;
index 4a6b11c64d2bb7800497c4da9c70a970b4c0c489..eb923336797868fd23e95206c1f20d7e2b6ccae2 100644 (file)
  */
 
 // Application headers.
+#include "DevToolsWebEngineView.h"
 #include "TabWidget.h"
 #include "Settings.h"
 #include "ui_AddTabWidget.h"
+#include "ui_Tab.h"
 #include "ui_TabWidget.h"
 #include "databases/CookiesDatabase.h"
 #include "dialogs/SaveDialog.h"
@@ -127,11 +129,16 @@ TabWidget::~TabWidget()
     // Manually delete each WebEngine page.
     for (int i = 0; i < numberOfTabs; ++i)
     {
-        // Get the privacy WebEngine view.
-        PrivacyWebEngineView *privacyWebEngineViewPointer = qobject_cast<PrivacyWebEngineView *>(qTabWidgetPointer->widget(i));
+        // Get the tab splitter widget.
+        QWidget *tabSplitterWidgetPointer = qTabWidgetPointer->widget(i);
 
-        // Deletion the WebEngine page to prevent the following error:  `Release of profile requested but WebEnginePage still not deleted. Expect troubles !`
+        // Get the WebEngine views.
+        PrivacyWebEngineView *privacyWebEngineViewPointer = tabSplitterWidgetPointer->findChild<PrivacyWebEngineView *>();
+        DevToolsWebEngineView *devToolsWebEngineViewPointer = tabSplitterWidgetPointer->findChild<DevToolsWebEngineView *>();
+
+        // Deletion the WebEngine pages to prevent the following error:  `Release of profile requested but WebEnginePage still not deleted. Expect troubles !`
         delete privacyWebEngineViewPointer->page();
+        delete devToolsWebEngineViewPointer->page();
     }
 }
 
@@ -173,23 +180,47 @@ void TabWidget::addFirstTab()
 
 PrivacyWebEngineView* TabWidget::addTab(const bool removeUrlLineEditFocus, const bool backgroundTab, const QString urlString)
 {
-    // Create a privacy WebEngine view.
+    // Create a splitter widget.
+    QSplitter *splitterPointer = new QSplitter();
+
+    // Set the splitter to be vertical.
+    splitterPointer->setOrientation(Qt::Vertical);
+
+    // Set the splitter handle size.
+    splitterPointer->setHandleWidth(5);
+
+    // Create the WebEngines.
     PrivacyWebEngineView *privacyWebEngineViewPointer = new PrivacyWebEngineView();
+    DevToolsWebEngineView *devToolsWebEngineViewPointer = new DevToolsWebEngineView();
+
+    // Add the WebEngines to the splitter.
+    splitterPointer->addWidget(privacyWebEngineViewPointer);
+    splitterPointer->addWidget(devToolsWebEngineViewPointer);
 
     // Add a new tab.
-    int newTabIndex = qTabWidgetPointer->addTab(privacyWebEngineViewPointer, i18nc("New tab label.", "New Tab"));
+    int newTabIndex = qTabWidgetPointer->addTab(splitterPointer, i18nc("New tab label.", "New Tab"));
 
     // Set the default tab icon.
     qTabWidgetPointer->setTabIcon(newTabIndex, defaultFavoriteIcon);
 
-    // Get handles for the WebEngine page and profile.
+    // Get handles for the WebEngine components.
     QWebEnginePage *webEnginePagePointer = privacyWebEngineViewPointer->page();
     QWebEngineProfile *webEngineProfilePointer = webEnginePagePointer->profile();
-
-    // Get handles for the web engine elements.
     QWebEngineCookieStore *webEngineCookieStorePointer = webEngineProfilePointer->cookieStore();
     QWebEngineSettings *webEngineSettingsPointer = webEnginePagePointer->settings();
 
+    // Set the development tools WebEngine.  This must be done here to preserve the bottom half of the window as the initial development tools size.
+    webEnginePagePointer->setDevToolsPage(devToolsWebEngineViewPointer->page());
+
+    // Initially hide the development tools WebEngine.
+    devToolsWebEngineViewPointer->setVisible(false);
+
+    // Initially disable the development tools WebEngine.
+    webEnginePagePointer->setDevToolsPage(nullptr);
+
+    // Disable JavaScript on the development tools WebEngine to prevent error messages from being written to the console.
+    devToolsWebEngineViewPointer->settings()->setAttribute(QWebEngineSettings::JavascriptEnabled, false);
+
     // Update the URL line edit when the URL changes.
     connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::urlChanged, [this, privacyWebEngineViewPointer] (const QUrl &newUrl)
     {
@@ -206,10 +237,10 @@ PrivacyWebEngineView* TabWidget::addTab(const bool removeUrlLineEditFocus, const
     });
 
     // Update the title when it changes.
-    connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::titleChanged, [this, privacyWebEngineViewPointer] (const QString &title)
+    connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::titleChanged, [this, splitterPointer] (const QString &title)
     {
         // Get the index for this tab.
-        int tabIndex = qTabWidgetPointer->indexOf(privacyWebEngineViewPointer);
+        int tabIndex = qTabWidgetPointer->indexOf(splitterPointer);
 
         // Update the title for this tab.
         qTabWidgetPointer->setTabText(tabIndex, title);
@@ -220,10 +251,10 @@ PrivacyWebEngineView* TabWidget::addTab(const bool removeUrlLineEditFocus, const
     });
 
     // Connect the loading favorite icon movie to the tab icon.
-    connect(loadingFavoriteIconMoviePointer, &QMovie::frameChanged, [this, privacyWebEngineViewPointer]
+    connect(loadingFavoriteIconMoviePointer, &QMovie::frameChanged, [this, splitterPointer, privacyWebEngineViewPointer]
     {
         // Get the index for this tab.
-        int tabIndex = qTabWidgetPointer->indexOf(privacyWebEngineViewPointer);
+        int tabIndex = qTabWidgetPointer->indexOf(splitterPointer);
 
         // Display the loading favorite icon if this tab is loading.
         if (privacyWebEngineViewPointer->isLoading)
@@ -231,7 +262,7 @@ PrivacyWebEngineView* TabWidget::addTab(const bool removeUrlLineEditFocus, const
     });
 
     // Update the icon when it changes.
-    connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::iconChanged, [this, privacyWebEngineViewPointer] (const QIcon &newFavoriteIcon)
+    connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::iconChanged, [this, splitterPointer, privacyWebEngineViewPointer] (const QIcon &newFavoriteIcon)
     {
         // Store the favorite icon in the privacy web engine view.
         if (newFavoriteIcon.isNull())
@@ -240,7 +271,7 @@ PrivacyWebEngineView* TabWidget::addTab(const bool removeUrlLineEditFocus, const
             privacyWebEngineViewPointer->favoriteIcon = newFavoriteIcon;
 
         // Get the index for this tab.
-        int tabIndex = qTabWidgetPointer->indexOf(privacyWebEngineViewPointer);
+        int tabIndex = qTabWidgetPointer->indexOf(splitterPointer);
 
         // Update the icon for this tab.
         if (newFavoriteIcon.isNull())
@@ -278,7 +309,7 @@ PrivacyWebEngineView* TabWidget::addTab(const bool removeUrlLineEditFocus, const
     });
 
     // Update the progress bar when a load finishes.
-    connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::loadFinished, [this, privacyWebEngineViewPointer] ()
+    connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::loadFinished, [this, splitterPointer, privacyWebEngineViewPointer] ()
     {
         // Set the privacy web engine view to be not loading.
         privacyWebEngineViewPointer->isLoading = false;
@@ -291,7 +322,7 @@ PrivacyWebEngineView* TabWidget::addTab(const bool removeUrlLineEditFocus, const
             emit hideProgressBar();
 
         // Get the index for this tab.
-        int tabIndex = qTabWidgetPointer->indexOf(privacyWebEngineViewPointer);
+        int tabIndex = qTabWidgetPointer->indexOf(splitterPointer);
 
         // Display the current favorite icon
         qTabWidgetPointer->setTabIcon(tabIndex, privacyWebEngineViewPointer->favoriteIcon);
@@ -306,7 +337,7 @@ PrivacyWebEngineView* TabWidget::addTab(const bool removeUrlLineEditFocus, const
         for (int i = 0; i < numberOfTabs; i++)
         {
             // Get the privacy WebEngine view for the tab.
-            PrivacyWebEngineView *privacyWebEngineViewPointer = qobject_cast<PrivacyWebEngineView*>(qTabWidgetPointer->widget(i));
+            PrivacyWebEngineView *privacyWebEngineViewPointer = qTabWidgetPointer->widget(i)->findChild<PrivacyWebEngineView *>();
 
             // Check to see if it is currently loading.  If at least one tab is loading, this flag will end up being marked `false` when the for loop has finished.
             if (privacyWebEngineViewPointer->isLoading)
@@ -475,7 +506,7 @@ void TabWidget::applyApplicationSettings()
     // Apply the spatial navigation settings to each WebEngine.
     for (int i = 0; i < numberOfTabs; ++i) {
         // Get the WebEngine view pointer.
-        PrivacyWebEngineView *privacyWebEngineViewPointer = qobject_cast<PrivacyWebEngineView *>(qTabWidgetPointer->widget(i));
+        PrivacyWebEngineView *privacyWebEngineViewPointer = qTabWidgetPointer->widget(i)->findChild<PrivacyWebEngineView *>();
 
         // Apply the spatial navigation settings to each page.
         privacyWebEngineViewPointer->page()->settings()->setAttribute(QWebEngineSettings::SpatialNavigationEnabled, Settings::spatialNavigation());
@@ -496,7 +527,7 @@ void TabWidget::applyDomainSettingsAndReload()
     // Apply the domain settings to each WebEngine.
     for (int i = 0; i < numberOfTabs; ++i) {
         // Get the WebEngine view pointer.
-        PrivacyWebEngineView *privacyWebEngineViewPointer = qobject_cast<PrivacyWebEngineView *>(qTabWidgetPointer->widget(i));
+        PrivacyWebEngineView *privacyWebEngineViewPointer = qTabWidgetPointer->widget(i)->findChild<PrivacyWebEngineView *>();
 
         // Apply the spatial navigation settings to each page.
         privacyWebEngineViewPointer->applyDomainSettings(privacyWebEngineViewPointer->url().host(), true);
@@ -551,7 +582,7 @@ void TabWidget::applySpellCheckLanguages() const
     for (int i = 0; i < numberOfTabs; ++i)
     {
         // Get the WebEngine view pointer.
-        PrivacyWebEngineView *privacyWebEngineViewPointer = qobject_cast<PrivacyWebEngineView *>(qTabWidgetPointer->widget(i));
+        PrivacyWebEngineView *privacyWebEngineViewPointer = qTabWidgetPointer->widget(i)->findChild<PrivacyWebEngineView *>();
 
         // Get the WebEngine page pointer.
         QWebEnginePage *webEnginePagePointer = privacyWebEngineViewPointer->page();
@@ -584,20 +615,29 @@ void TabWidget::deleteCookieFromStore(const QNetworkCookie &cookie) const
 
 void TabWidget::deleteTab(const int tabIndex)
 {
-    // Get the privacy WebEngine view.
-    PrivacyWebEngineView *privacyWebEngineViewPointer = qobject_cast<PrivacyWebEngineView *>(qTabWidgetPointer->widget(tabIndex));
+    // Get the tab splitter widget.
+    QWidget *tabSplitterWidgetPointer = qTabWidgetPointer->widget(tabIndex);
+
+    // Get the WebEngine views.
+    PrivacyWebEngineView *privacyWebEngineViewPointer = tabSplitterWidgetPointer->findChild<PrivacyWebEngineView *>();
+    DevToolsWebEngineView *devToolsWebEngineViewPointer = tabSplitterWidgetPointer->findChild<DevToolsWebEngineView *>();
 
     // Process the tab delete according to the number of tabs.
     if (qTabWidgetPointer->count() > 1)  // There is more than one tab.
     {
-        // Delete the tab.
+        // Remove the tab.
         qTabWidgetPointer->removeTab(tabIndex);
 
-        // Delete the WebEngine page to prevent the following error:  `Release of profile requested but WebEnginePage still not deleted. Expect troubles !`
+        // Delete the WebEngine pages to prevent the following error:  `Release of profile requested but WebEnginePage still not deleted. Expect troubles !`
         delete privacyWebEngineViewPointer->page();
+        delete devToolsWebEngineViewPointer->page();
 
-        // Delete the privacy WebEngine view.
+        // Delete the WebEngine views.
         delete privacyWebEngineViewPointer;
+        delete devToolsWebEngineViewPointer;
+
+        // Delete the tab splitter widget.
+        delete tabSplitterWidgetPointer;
     }
     else  // There is only one tab.
     {
@@ -1064,6 +1104,38 @@ void TabWidget::showSaveDialog(QWebEngineDownloadItem *webEngineDownloadItemPoin
     savingArchive = false;
 }
 
+void TabWidget::toggleDeveloperTools(const bool enabled) const
+{
+    // Get a handle for the current developer tools WebEngine.
+    DevToolsWebEngineView *devToolsWebEngineViewPointer = qTabWidgetPointer->currentWidget()->findChild<DevToolsWebEngineView *>();
+
+    if (enabled)
+    {
+        // Set the zoom factor on the development tools WebEngine.
+        devToolsWebEngineViewPointer->setZoomFactor(currentWebEnginePagePointer->zoomFactor());
+
+        // Enable the development tools.
+        currentWebEnginePagePointer->setDevToolsPage(devToolsWebEngineViewPointer->page());
+
+        // Enable JavaScript on the development tools WebEngine.
+        devToolsWebEngineViewPointer->settings()->setAttribute(QWebEngineSettings::JavascriptEnabled, true);
+
+        // Display the developer tools.
+        devToolsWebEngineViewPointer->setVisible(true);
+    }
+    else
+    {
+        // Disable JavaScript on the development tools WebEngine to prevent error messages from being written to the console.
+        devToolsWebEngineViewPointer->settings()->setAttribute(QWebEngineSettings::JavascriptEnabled, false);
+
+        // Disable the development tools.
+        currentWebEnginePagePointer->setDevToolsPage(nullptr);
+
+        // Hide the developer tools.
+        devToolsWebEngineViewPointer->setVisible(false);
+    }
+}
+
 void TabWidget::toggleDomStorage() const
 {
     // Toggle DOM storage.
@@ -1134,7 +1206,7 @@ void TabWidget::updateUiFromWebEngineView(const PrivacyWebEngineView *privacyWeb
 void TabWidget::updateUiWithTabSettings()
 {
     // Update the current WebEngine pointers.
-    currentPrivacyWebEngineViewPointer = qobject_cast<PrivacyWebEngineView *>(qTabWidgetPointer->currentWidget());
+    currentPrivacyWebEngineViewPointer = qTabWidgetPointer->currentWidget()->findChild<PrivacyWebEngineView *>();
     currentWebEngineSettingsPointer = currentPrivacyWebEngineViewPointer->settings();
     currentWebEnginePagePointer = currentPrivacyWebEngineViewPointer->page();
     currentWebEngineProfilePointer = currentWebEnginePagePointer->profile();
@@ -1144,10 +1216,14 @@ void TabWidget::updateUiWithTabSettings()
     // Clear the URL line edit focus.
     emit clearUrlLineEditFocus();
 
+    // Get a handle for the development tools WebEngine view.
+    DevToolsWebEngineView *devToolsWebEngineViewPointer = qTabWidgetPointer->currentWidget()->findChild<DevToolsWebEngineView *>();
+
     // Update the actions.
     emit updateDefaultZoomFactor(currentPrivacyWebEngineViewPointer->defaultZoomFactor);
     emit updateBackAction(currentWebEngineHistoryPointer->canGoBack());
     emit updateCookiesAction(currentPrivacyWebEngineViewPointer->cookieListPointer->size());
+    emit updateDeveloperToolsAction(devToolsWebEngineViewPointer->isVisible());
     emit updateDomStorageAction(currentWebEngineSettingsPointer->testAttribute(QWebEngineSettings::LocalStorageEnabled));
     emit updateForwardAction(currentWebEngineHistoryPointer->canGoForward());
     emit updateJavaScriptAction(currentWebEngineSettingsPointer->testAttribute(QWebEngineSettings::JavascriptEnabled));
index ab6167188c8d09d4949c4574213c03c381c0e435..5b9f2f9fe9de7d4a8f311ac5a282ce2cd7014a27 100644 (file)
@@ -62,6 +62,7 @@ public:
     QString getCurrentTabUrl() const;
     QString& getDomainSettingsName() const;
     void setTabBarVisible(const bool visible) const;
+    void toggleDeveloperTools(const bool enabled) const;
     void toggleDomStorage() const;
     void toggleFindCaseSensitive(const QString &text);
     void toggleJavaScript() const;
@@ -82,6 +83,7 @@ signals:
     void updateBackAction(const bool &isEnabled) const;
     void updateCookiesAction(const int numberOfCookies) const;
     void updateDefaultZoomFactor(const double newDefaultZoomFactor) const;
+    void updateDeveloperToolsAction(const bool &isEnabled) const;
     void updateDomStorageAction(const bool &isEnabled) const;
     void updateDomainSettingsIndicator(const bool status) const;
     void updateFindText(const QString &text, const bool findCaseSensitive) const;
index 214b0af6888b16801986eef1189bd1363b93ffa3..2eb4ab14fab687edc954e65d421be2beed5de5f2 100644 (file)
@@ -96,6 +96,7 @@ BrowserWindow::BrowserWindow(bool firstWindow, QString *initialUrlStringPointer)
     QAction *reloadAndBypassCacheActionPointer = actionCollectionPointer->addAction(QLatin1String("reload_and_bypass_cache"));
     viewSourceActionPointer = actionCollectionPointer->addAction(QLatin1String("view_source"));
     viewSourceInNewTabActionPointer = actionCollectionPointer->addAction(QLatin1String("view_source_in_new_tab"));
+    developerToolsActionPointer = actionCollectionPointer->addAction(QLatin1String("developer_tools"));
     javaScriptActionPointer = actionCollectionPointer->addAction(QLatin1String("javascript"));
     localStorageActionPointer = actionCollectionPointer->addAction(QLatin1String("local_storage"));
     domStorageActionPointer = actionCollectionPointer->addAction(QLatin1String("dom_storage"));
@@ -150,6 +151,7 @@ BrowserWindow::BrowserWindow(bool firstWindow, QString *initialUrlStringPointer)
     domStorageActionPointer->setCheckable(true);
     findCaseSensitiveActionPointer->setCheckable(true);
     viewSourceActionPointer->setCheckable(true);
+    developerToolsActionPointer->setCheckable(true);
     userAgentPrivacyBrowserActionPointer->setCheckable(true);
     userAgentWebEngineDefaultActionPointer->setCheckable(true);
     userAgentFirefoxLinuxActionPointer->setCheckable(true);
@@ -179,6 +181,7 @@ BrowserWindow::BrowserWindow(bool firstWindow, QString *initialUrlStringPointer)
     reloadAndBypassCacheActionPointer->setText(i18nc("Reload and bypass cache action", "Reload and Bypass Cache"));
     viewSourceActionPointer->setText(i18nc("View source action", "View Source"));
     viewSourceInNewTabActionPointer->setText(i18nc("View source in new tab action", "View Source in New Tab"));
+    developerToolsActionPointer->setText(i18nc("Developer tools action", "Developer Tools"));
     javaScriptActionPointer->setText(i18nc("JavaScript action", "JavaScript"));
     localStorageActionPointer->setText(i18nc("The Local Storage action", "Local Storage"));
     domStorageActionPointer->setText(i18nc("DOM Storage action", "DOM Storage"));
@@ -211,6 +214,7 @@ BrowserWindow::BrowserWindow(bool firstWindow, QString *initialUrlStringPointer)
     reloadAndBypassCacheActionPointer->setIcon(QIcon::fromTheme(QLatin1String("view-refresh")));
     viewSourceActionPointer->setIcon(QIcon::fromTheme(QLatin1String("view-choose"), QIcon::fromTheme(QLatin1String("accessories-text-editor"))));
     viewSourceInNewTabActionPointer->setIcon(QIcon::fromTheme(QLatin1String("view-choose"), QIcon::fromTheme(QLatin1String("accessories-text-editor"))));
+    developerToolsActionPointer->setIcon(QIcon::fromTheme(QLatin1String("add-subtitle"), QIcon::fromTheme("system-run")));
     domStorageActionPointer->setIcon(QIcon::fromTheme(QLatin1String("code-class"), QIcon(QLatin1String("/usr/share/icons/gnome/32x32/actions/gtk-unindent-ltr.png"))));
     userAgentPrivacyBrowserActionPointer->setIcon(QIcon(":/icons/privacy-mode.svg"));
     userAgentWebEngineDefaultActionPointer->setIcon(QIcon::fromTheme(QLatin1String("qtlogo"), QIcon::fromTheme(QLatin1String("user-group-properties"), QIcon::fromTheme(QLatin1String("contact-new")))));
@@ -246,6 +250,7 @@ BrowserWindow::BrowserWindow(bool firstWindow, QString *initialUrlStringPointer)
     QKeySequence ctrlF5KeySequence = QKeySequence(i18nc("The reload and bypass cache key sequence.", "Ctrl+F5"));
     QKeySequence ctrlUKeySequence = QKeySequence(i18nc("The view source key sequence.", "Ctrl+U"));
     QKeySequence ctrlShiftUKeySequence = QKeySequence(i18nc("The view source in new tab key sequence.", "Ctrl+Shift+U"));
+    QKeySequence f12KeySequence = QKeySequence(i18nc("The developer tools key sequence.", "F12"));
     QKeySequence ctrlShiftPKeySequence = QKeySequence(i18nc("The print preview key sequence.", "Ctrl+Shift+P"));
     QKeySequence ctrlJKeySequence = QKeySequence(i18nc("The JavaScript key sequence.", "Ctrl+J"));
     QKeySequence ctrlLKeySequence = QKeySequence(i18nc("The local storage key sequence.", "Ctrl+L"));
@@ -281,6 +286,7 @@ BrowserWindow::BrowserWindow(bool firstWindow, QString *initialUrlStringPointer)
     actionCollectionPointer->setDefaultShortcut(reloadAndBypassCacheActionPointer, ctrlF5KeySequence);
     actionCollectionPointer->setDefaultShortcut(viewSourceActionPointer, ctrlUKeySequence);
     actionCollectionPointer->setDefaultShortcut(viewSourceInNewTabActionPointer, ctrlShiftUKeySequence);
+    actionCollectionPointer->setDefaultShortcut(developerToolsActionPointer, f12KeySequence);
     actionCollectionPointer->setDefaultShortcut(printPreviewActionPointer, ctrlShiftPKeySequence);
     actionCollectionPointer->setDefaultShortcut(javaScriptActionPointer, ctrlJKeySequence);
     actionCollectionPointer->setDefaultShortcut(localStorageActionPointer, ctrlLKeySequence);
@@ -316,6 +322,7 @@ BrowserWindow::BrowserWindow(bool firstWindow, QString *initialUrlStringPointer)
     connect(reloadAndBypassCacheActionPointer, SIGNAL(triggered()), this, SLOT(reloadAndBypassCache()));
     connect(viewSourceActionPointer, SIGNAL(triggered()), this, SLOT(toggleViewSource()));
     connect(viewSourceInNewTabActionPointer, SIGNAL(triggered()), this, SLOT(toggleViewSourceInNewTab()));
+    connect(developerToolsActionPointer, SIGNAL(triggered()), this, SLOT(toggleDeveloperTools()));
     connect(zoomFactorActionPointer, SIGNAL(triggered()), this, SLOT(getZoomFactorFromUser()));
     connect(viewBookmarksToolBarActionPointer, SIGNAL(triggered()), this, SLOT(toggleViewBookmarksToolBar()));
     connect(cookiesActionPointer, SIGNAL(triggered()), this, SLOT(showCookiesDialog()));
@@ -341,7 +348,8 @@ BrowserWindow::BrowserWindow(bool firstWindow, QString *initialUrlStringPointer)
     connect(localStorageActionPointer, SIGNAL(triggered()), this, SLOT(toggleLocalStorage()));
     connect(domStorageActionPointer, SIGNAL(triggered()), this, SLOT(toggleDomStorage()));
 
-    // Update the URL toolbar actions.
+    // Update the actions from the tab widget.
+    connect(tabWidgetPointer, SIGNAL(updateDeveloperToolsAction(bool)), developerToolsActionPointer, SLOT(setChecked(bool)));
     connect(tabWidgetPointer, SIGNAL(updateBackAction(bool)), backActionPointer, SLOT(setEnabled(bool)));
     connect(tabWidgetPointer, SIGNAL(updateForwardAction(bool)), forwardActionPointer, SLOT(setEnabled(bool)));
     connect(tabWidgetPointer, SIGNAL(updateJavaScriptAction(bool)), this, SLOT(updateJavaScriptAction(bool)));
@@ -1026,8 +1034,6 @@ void BrowserWindow::populateBookmarksInAllWindows() const
 
 void BrowserWindow::populateBookmarksInThisWindow()
 {
-    qDebug() << "Populating bookmarks.";
-
     // Remove all the final bookmark folder menu actions.
     for (QPair<QMenu *, QAction *> *finalBookmarkFolderMenuActionPair : finalBookmarkFolderMenuActionList)
     {
@@ -1693,6 +1699,12 @@ void BrowserWindow::toggleBookmark()
     populateBookmarksInAllWindows();
 }
 
+void BrowserWindow::toggleDeveloperTools() const
+{
+    // Toggle the developer tools.
+    tabWidgetPointer->toggleDeveloperTools(developerToolsActionPointer->isChecked());
+}
+
 void BrowserWindow::toggleDomStorage() const
 {
     // Remove the focus from the URL line edit.
index 6910f8ae474c968fbbab68a173508fea62690909..e62b7b29c9b338a8f96981865f24b04bb1e95cf8 100644 (file)
@@ -82,6 +82,7 @@ private Q_SLOTS:
     void showProgressBar(const int &progress) const;
     void showSettingsDialog();
     void toggleBookmark();
+    void toggleDeveloperTools() const;
     void toggleDomStorage() const;
     void toggleFindCaseSensitive() const;
     void toggleJavaScript() const;
@@ -129,6 +130,7 @@ private:
     bool customSearchEngineEnabled;
     bool customUserAgentEnabled;
     double defaultZoomFactor;
+    QAction *developerToolsActionPointer;
     QAction *domStorageActionPointer;
     QComboBox *downloadLocationComboBoxPointer;
     QList<QPair<QMenu *, QAction *> *> finalBookmarkFolderMenuActionList;