]> gitweb.stoutner.com Git - PrivacyBrowserPC.git/commitdiff
Add a File > New Tab action.
authorSoren Stoutner <soren@stoutner.com>
Wed, 8 Mar 2023 17:20:23 +0000 (10:20 -0700)
committerSoren Stoutner <soren@stoutner.com>
Wed, 8 Mar 2023 17:20:23 +0000 (10:20 -0700)
doc/index.docbook
src/ui.rcs/browserwindowui.rc
src/uis/DomainSettingsDialog.ui
src/uis/SettingsPrivacy.ui
src/windows/BrowserWindow.cpp
src/windows/BrowserWindow.h

index 5a08451c04da60f1e94f094172911e70e1d75e99..6974073dbd3803477bf5ea404cbe13a864608018 100644 (file)
     <para>
       To distinguish between the Android and the PC version, the website, issue tracker,
       and code base refer to this version as <ulink url="https://www.stoutner.com/privacy-browser-pc/">Privacy Browser PC</ulink>.
-      There is a list of feature requests and known bugs at <ulink url="https://redmine.stoutner.com/projects/privacy-browser-pc/issues">redmine.stoutner.com</ulink>.
-      Users should anticipate that all the current features of <ulink url="https://www.stoutner.com/privacy-browser-android/">Privacy Browser Android</ulink>
-      will also be implemented in Privacy Browser PC.
-      There is no need at this point to create features requests for these as they will be added as I start working on each feature and have a better idea of how they will be implemented.
-      However, each feature that has already been implemented should be bug free.
-      If you discover a bug that is not already documented at <ulink url="https://redmine.stoutner.com/projects/privacy-browser-pc/issues">redmine.stoutner.com</ulink> please add it.
     </para>
 
     <para>
       The best place to discuss the development of Privacy Browser is <ulink url="https://redmine.stoutner.com/projects/privacy-browser-pc/boards">on the forum</ulink>.
       I also frequently post on my <ulink url="https://fosstodon.org/@privacybrowser">Mastodon account</ulink> regarding the development status.
     </para>
+
+    <!-- Qt WebEngine. -->
+    <sect1 id="qt-webengine">
+      <title>Qt WebEngine</title>
+
+      <para>
+        Privacy Browser uses <ulink url="https://doc.qt.io/qt-5/qtwebengine-index.html">Qt WebEngine</ulink> to render websites.
+        Qt WebEngine is based on the <ulink url="https://www.chromium.org/blink/">Chromium Blink</ulink> source code.
+        Because Privacy Browser is built on the <ulink url="https://api.kde.org/frameworks/index.html">KDE Framework</ulink>,
+        it currently uses the <ulink url="https://community.kde.org/Schedules/Plasma_6">Qt 5</ulink> packages.
+      </para>
+
+      <para>
+        The current Qt 5 packages are in long-term support mode.
+        Qt WebEngine 5.15.x is based on <ulink url="https://wiki.qt.io/QtWebEngine/ChromiumVersions">Chromium 87.0.4280.144</ulink> from a feature perspective.
+        Security fixes are backported with <ulink url="https://wiki.qt.io/Qt_5.15_Release#Release_Plan">each release</ulink> every couple of months.
+      </para>
+    </sect1>
+
+    <!-- Bugs and missing features. -->
+    <sect1 id="bugs-and-missing-features">
+      <title>Bugs and Missing Features</title>
+
+      <para>
+        There is a list of feature requests and known bugs at <ulink url="https://redmine.stoutner.com/projects/privacy-browser-pc/issues">redmine.stoutner.com</ulink>.
+        Users should anticipate that all the current features of <ulink url="https://www.stoutner.com/privacy-browser-android/">Privacy Browser Android</ulink>
+        will also be implemented in Privacy Browser PC.
+        There is no need at this point to create features requests for these as they will be added as I start working on each feature and have a better idea of how they will be implemented.
+        However, each feature that has already been implemented should be bug free.
+        If you discover a bug that is not already documented at <ulink url="https://redmine.stoutner.com/projects/privacy-browser-pc/issues">redmine.stoutner.com</ulink> please add it.
+      </para>
+
+      <para>
+        Below is a list of known prominent bugs or missing features in this alpha release.
+      </para>
+
+      <itemizedlist>
+        <listitem><para>The page zoom is <ulink url="https://redmine.stoutner.com/issues/799">momentarily reset</ulink> every time a new URL is loaded.</para></listitem>
+        <listitem><para>If domain settings change the user agent, loading of the new URL is interrupted and the
+          <ulink url="https://redmine.stoutner.com/issues/821">previous site is reloaded</ulink>.</para></listitem>
+        <listitem><para>Browser <ulink url="https://redmine.stoutner.com/issues/831">error messages are not displayed</ulink> unless JavaScript is enabled.</para></listitem>
+        <listitem><para>Bookmarks are <ulink url="https://redmine.stoutner.com/issues/968">not yet implemented</ulink>.</para></listitem>
+        <listitem><para>Blocklists are <ulink url="https://redmine.stoutner.com/issues/969">not yet implemented</ulink>.</para></listitem>
+      </itemizedlist>
+    </sect1>
   </chapter>
 
   <!-- Using Privacy Browser. -->
     <title>Using &privacybrowser;</title>
 
     <para>
-      <screenshot>
-        <screeninfo>Here's a screenshot of &privacybrowser;</screeninfo>
-        <mediaobject>
+      <mediaobject>
+        <imageobject>
+          <imagedata fileref="privacybrowser.png" format="PNG"/>
+        </imageobject>
+        <textobject>
+          <phrase>Screenshot</phrase>
+        </textobject>
+      </mediaobject>
+    </para>
+
+    <!-- JavaScript. -->
+    <sect1 id="javascript">
+      <title>JavaScript</title>
+
+      <para>
+        JavaScript allows web pages to run scripts (programs) on your device. It allows web pages to function more like apps, but it also allows web pages to spy on you.
+        Most of the tracking on the internet does not work when JavaScript is disabled.
+        JavaScript can be toggled by clicking on the privacy shield, which is blue if JavaScript is disabled and red when it is enabled.
+        <inlinemediaobject>
           <imageobject>
-            <imagedata fileref="screenshot.png" format="PNG"/>
+            <imagedata fileref="javascript.png" format="PNG"/>
           </imageobject>
           <textobject>
-            <phrase>Screenshot</phrase>
+            <phrase>JavaScript</phrase>
           </textobject>
-        </mediaobject>
-      </screenshot>
-    </para>
+        </inlinemediaobject>
+      </para>
+    </sect1>
 
-    <sect1 id="kapp-features">
-      <title>More &privacybrowser; features</title>
+    <!-- Local Storage. -->
+    <sect1 id="local-storage">
+      <title>Local Storage</title>
 
       <para>
-        It slices! It dices! and it comes with a free toaster!
+        <ulink url="https://doc.qt.io/qt-5/qwebenginecookiestore.html#setCookieFilter">Local storage</ulink>
+        in Privacy Browser encompasses cookies, DOM storage, IndexedDB, service workers, and the filesystem API.
+        Local storage can be toggled through an action on the toolbar.
       </para>
 
+      <!-- Cookies. -->
+      <sect2 id="cookies">
+        <title>Cookies</title>
+
+        <para>
+          <mediaobject>
+            <imageobject>
+              <imagedata fileref="cookies.png" format="PNG"/>
+            </imageobject>
+            <textobject>
+              <phrase>Cookies</phrase>
+            </textobject>
+          </mediaobject>
+        </para>
+
+        <para>
+          <ulink url="https://en.wikipedia.org/wiki/HTTP_cookie">Cookies</ulink>
+          allow websites to store small pieces of information for a specific host that are sent in the HTTP header every time the browser connects to that host.
+          Privacy Browser allows a maximum of <ulink url="http://browsercookielimits.iain.guru/">180 cookies with a maximum size of 4096 bytes per cookie</ulink> to be set per domain.
+          Cookies are often used to track users across the web, particularly third-party cookies (which are completely blocked in Privacy Browser).
+          They are also used as a security mechanism on websites where you log in to identify it is you as you browse from page to page on a site.
+        </para>
+
+        <para>
+          Durable cookies are shared with all tabs that are opened after they are made durable and are preserved even when Privacy Browser is restarted.
+          This allows users to stay logged in to sites of their choosing. No cookies are durable by default. Making a cookie durable requires specific user interaction.
+        </para>
+
+        <para>
+          All other cookies are specific to the tab where they are created and are destroyed when the tab is closed.
+        </para>
+      </sect2>
+
+      <!-- DOM storage. -->
+      <sect2 id="dom-storage">
+        <title>DOM storage</title>
+
+        <para>
+          <ulink url="https://en.wikipedia.org/wiki/Web_storage">DOM (Document Object Model) storage</ulink>, also knows as web storage, allows web pages to store information on a client device.
+          The storage capacity is larger than for cookies and the data is not automatically sent in the headers with every HTTP request.
+          In Privacy Browser, each website is allowed to store a <ulink url="https://arty.name/localstorage.html">5 MB of data</ulink> in DOM storage.
+          DOM storage requires JavaScript to function, and, in addition, requires an extra toggle to be enabled.
+          In Privacy Browser, DOM storage is limited to the tab where it is created and is destroyed when the tab is closed.
+        </para>
+      </sect2>
+
+      <!-- IndexedDB. -->
+      <sect2 id="indexeddb">
+        <title>IndexedDB</title>
+
+        <para>
+          <ulink url="https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API">IndexedDB</ulink>
+          provides web pages with a local database where they can store “significant amounts of structured data”.
+          There is disagreement on the internet about the maximum size of an IndexedDB database, probably because the various rendering engines keep changing their mind.
+          But it is usually listed at somewhere between 20% and 80% of <emphasis>your entire hard drive</emphasis> with each individual domain limited to some segment of that.
+          IndexedDB requires JavaScript to function.
+          In Privacy Browser, this database is limited to the tab where it is created and is destroyed when the tab is closed.
+        </para>
+      </sect2>
+
+      <!-- Service Workers. -->
+      <sect2 id="service-workers">
+        <title>Service Workers</title>
+
+        <para>
+          <ulink url="https://developer.chrome.com/docs/workbox/service-worker-overview/">Service workers</ulink> are offline JavaScript proxies of a website. They have their own cache that is usually hidden and hard to clear.
+          They were designed by people who want the web browser to become the operating system and run full “apps”.
+          In Privacy Browser, service workers are limited to the tab where they are created and are destroyed when the tab is closed.
+        </para>
+      </sect2>
+
+      <!-- Filesystem API. -->
+      <sect2 id="filesystem-api">
+        <title>Filesystem API</title>
+
+        <para>
+          The <ulink url="https://developer.chrome.com/articles/file-system-access/">filesystem API</ulink> grants the browser direct access to the files on your system.
+          Like service workers, the filesystem API is a summarily bad idea thought up by those who want the browser to become an operating system.
+          Even when JavaScript and local storage are enabled, the filesystem API does not work in Privacy Browser.
+        </para>
+      </sect2>
+    </sect1>
+
+    <!-- User Agent. -->
+    <sect1 id="user-agent">
+      <title>User Agent</title>
+
       <para>
-        The Squiggle Tool <guiicon><inlinemediaobject>
-          <imageobject>
-            <imagedata fileref="squiggle.png" format="PNG"/>
-          </imageobject>
-          <textobject>
-            <phrase>Squiggle</phrase>
-          </textobject>
-        </inlinemediaobject></guiicon> is used to draw squiggly lines all over the &privacybrowser; main window. It's not a bug, it's a feature!
+        The user agent is a text string that is sent as part of every HTTP header that identifies the browser to the web server.
+        Privacy Browser's default user agent is <code>PrivacyBrowser/1.0</code>.
+        Qt WebEngine 5.15.12’s default user agent is <code>Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) QtWebEngine/5.15.12 Chrome/87.0.4280.144 Safari/537.36</code>.
+      </para>
+
+      <para>
+        Over the years user agents have become quite lengthy,
+        partially because they tend to include a <ulink url="https://webaim.org/blog/user-agent-string-history/">brief history of the internet</ulink>.
+        In the modern world they serve almost no good purpose, but some web developers still think they need them so they can send different version of their website to different browsers.
+        Some servers <ulink url="https://www.stoutner.com/user-agent-problems/">refuse to function correctly</ulink> if they don't like the user agent that is sent.
+      </para>
+
+      <para>
+        At some point in the future Privacy Browser will send no user agent by default.
+        Not only is that currently impossible because the Qt WebEngine doesn't allow you to not send a user agent (I will probably have to fork it to enable that functionality),
+        but even web servers that don't care what the user agent is often refuse to send an answer if there is no user agent at all.
+        Getting rid of this relic of the internet is going to take some time and a retraining of common expectations.
+      </para>
+    </sect1>
+
+    <!-- Domain Settings. -->
+    <sect1 id="domain-settings">
+      <title>Domain Settings</title>
+
+      <para>
+        Domain setting make it easy to automatically change JavaScript, local storage, user agent, and other settings when the domain changes.
+        Domain settings for the current domain can be accessed through the domain settings button at the far right of the URL line edit.
+        Domain settings for all domains can be accessed through the settings menu. When domain settings are active, the URL line edit will have a green background.
       </para>
     </sect1>
   </chapter>
   <chapter id="commands">
     <title>Command Reference</title>
 
-    <sect1 id="kapp-mainwindow">
+    <!-- Main Window. -->
+    <sect1 id="main-window">
       <title>The main &privacybrowser; window</title>
 
+      <!-- File Menu. -->
       <sect2>
         <title>The File Menu</title>
 
         <para>
           <variablelist>
-            <varlistentry  id="file-new">
-  <!-- Tip: With id's here, then you can use them like
-  "select <xref linkend="file-new"/> to open the file dialog"
-  which will be expanded to:
-  "select File->New (Ctrl+N) to open the file dialog"
-  -->
+            <!-- File > New Tab. -->
+            <varlistentry id="file-new-tab">
+              <term>
+                <menuchoice>
+                  <shortcut>
+                    <keycombo action="simul">&Ctrl;<keycap>T</keycap></keycombo>
+                  </shortcut>
+                  <guimenu>File</guimenu>
+                  <guimenuitem>New Tab</guimenuitem>
+                </menuchoice>
+              </term>
+
+              <listitem>
+                <para>
+                  <action>Create a new tab.</action>
+                </para>
+              </listitem>
+            </varlistentry>
+
+            <!-- File > New Window. -->
+            <varlistentry id="file-new-window">
               <term>
                 <menuchoice>
                   <shortcut>
                     <keycombo action="simul">&Ctrl;<keycap>N</keycap></keycombo>
                   </shortcut>
                   <guimenu>File</guimenu>
-                  <guimenuitem>New</guimenuitem>
+                  <guimenuitem>New Window</guimenuitem>
                 </menuchoice>
               </term>
 
               <listitem>
                 <para>
-                  <action>Creates a new document</action>
+                  <action>Create a new window.</action>
                 </para>
               </listitem>
             </varlistentry>
index 2ee3cd775f455a136a9a961c70d2005904b32ae1..186b784200bcf957b5b81194b8b87bcecc140d2f 100644 (file)
 
     <!-- The menu bar. -->
     <MenuBar>
+        <!-- File. -->
+        <Menu name="file">
+            <Action name="new_tab" append="new_merge"/>
+            <Action name="new_window" append="new_merge"/>
+        </Menu>
+
         <!-- On-the-fly Settings. -->
         <Menu name="on_the_fly_settings"> <text>On-The-Fly Settings</text>
             <Menu name="user_agent" icon="user-group-properties">
index addcbdee473c97cf8911a96959f13b6b47d11e60..d498a106e786c8202ea78d26a25b80a20b92bf9f 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-  Copyright 2022 Soren Stoutner <soren@stoutner.com>.
+  Copyright 2022-2023 Soren Stoutner <soren@stoutner.com>.
 
   This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
 
                                                     </property>
 
                                                     <property name="toolTip">
-                                                        <string>Local storage includes cookies, IndexedDB, DOM storage, filesystem API, and service workers.  DOM storage also requires a separate control to be enabled.  Local storage is disabled by default.</string>
+                                                        <string>Local storage includes cookies, DOM storage, IndexedDB, service workers, and the filesystem API.  DOM storage also requires a separate control to be enabled.  Local storage is disabled by default.</string>
                                                     </property>
                                                 </widget>
                                             </item>
index 098ba09b638b798a556d8b75fd99b37cf738ec38..780a239f4b2539c97b89483085c0c6d49082042b 100644 (file)
@@ -45,7 +45,7 @@
                     </property>
 
                     <property name="toolTip">
-                        <string>Local storage includes cookies, IndexedDB, DOM storage, filesystem API, and service workers.  DOM storage also requires a separate control to be enabled.  Local storage is disabled by default.</string>
+                        <string>Local storage includes cookies, DOM storage, IndexedDB, service workers, and the filesystem API.  DOM storage also requires a separate control to be enabled.  Local storage is disabled by default.</string>
                     </property>
                 </widget>
             </item>
index a0a7a97346211e0a52f59b026b1fceb307834f6b..effb0918b0faeca5b1bace2b017300e6dae7a1d7 100644 (file)
@@ -59,7 +59,6 @@ BrowserWindow::BrowserWindow(bool firstWindow) : KXmlGuiWindow()
     KActionCollection *actionCollectionPointer = this->actionCollection();
 
     // Add the standard actions.
-    KStandardAction::openNew(this, SLOT(fileNew()), actionCollectionPointer);
     KStandardAction::print(tabWidgetPointer, SLOT(print()), actionCollectionPointer);
     KStandardAction::printPreview(tabWidgetPointer, SLOT(printPreview()), actionCollectionPointer);
     KStandardAction::quit(qApp, SLOT(closeAllWindows()), actionCollectionPointer);
@@ -74,6 +73,8 @@ BrowserWindow::BrowserWindow(bool firstWindow) : KXmlGuiWindow()
     findPreviousActionPointer = KStandardAction::findPrev(this, SLOT(findPrevious()), actionCollectionPointer);
 
     // Add the custom actions.
+    QAction *newTabActionPointer = actionCollectionPointer->addAction(QLatin1String("new_tab"));
+    QAction *newWindowActionPointer = actionCollectionPointer->addAction(QLatin1String("new_window"));
     userAgentPrivacyBrowserActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_privacy_browser"));
     userAgentWebEngineDefaultActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_webengine_default"));
     userAgentFirefoxLinuxActionPointer = actionCollectionPointer->addAction(QLatin1String("user_agent_firefox_linux"));
@@ -147,6 +148,8 @@ BrowserWindow::BrowserWindow(bool firstWindow) : KXmlGuiWindow()
     UserAgentHelper *userAgentHelperPointer = new UserAgentHelper();
 
     // Set the action text.
+    newTabActionPointer->setText(i18nc("New tab action", "New Tab"));
+    newWindowActionPointer->setText(i18nc("New window action", "New Window"));
     userAgentPrivacyBrowserActionPointer->setText(userAgentHelperPointer->PRIVACY_BROWSER_TRANSLATED);
     userAgentWebEngineDefaultActionPointer->setText(userAgentHelperPointer->WEB_ENGINE_DEFAULT_TRANSLATED);
     userAgentFirefoxLinuxActionPointer->setText(userAgentHelperPointer->FIREFOX_LINUX_TRANSLATED);
@@ -170,6 +173,8 @@ BrowserWindow::BrowserWindow(bool firstWindow) : KXmlGuiWindow()
     hideFindTextActionPointer->setText(i18nc("Hide Find Text action", "Hide Find Text"));
 
     // Set the action icons.
+    newTabActionPointer->setIcon(QIcon::fromTheme(QLatin1String("tab-new")));
+    newWindowActionPointer->setIcon(QIcon::fromTheme(QLatin1String("window-new")));
     userAgentPrivacyBrowserActionPointer->setIcon(QIcon(":/icons/privacy-mode"));
     userAgentWebEngineDefaultActionPointer->setIcon(QIcon::fromTheme(QLatin1String("user-group-properties")));
     userAgentFirefoxLinuxActionPointer->setIcon(QIcon::fromTheme(QLatin1String("firefox-esr")));
@@ -193,6 +198,21 @@ BrowserWindow::BrowserWindow(bool firstWindow) : KXmlGuiWindow()
     findCaseSensitiveActionPointer->setIcon(QIcon::fromTheme(QLatin1String("format-text-lowercase")));
     hideFindTextActionPointer->setIcon(QIcon::fromTheme(QLatin1String("window-close-symbolic")));
 
+    // Create the key sequences.
+    QKeySequence ctrlTKeySequence = QKeySequence(i18nc("The open new tab key sequence.", "Ctrl+T"));
+    QKeySequence ctrlNKeySequence = QKeySequence(i18nc("The open new window key sequence.", "Ctrl+N"));
+
+    // Set the action key sequences.
+    newTabActionPointer->setShortcut(ctrlTKeySequence);
+    newWindowActionPointer->setShortcut(ctrlNKeySequence);
+
+    // Execute the actions.
+    connect(newTabActionPointer, SIGNAL(triggered()), tabWidgetPointer, SLOT(addTab()));
+    connect(newWindowActionPointer, SIGNAL(triggered()), this, SLOT(newWindow()));
+    connect(zoomFactorActionPointer, SIGNAL(triggered()), this, SLOT(getZoomFactorFromUser()));
+    connect(cookiesActionPointer, SIGNAL(triggered()), this, SLOT(showCookiesDialog()));
+    connect(domainSettingsActionPointer, SIGNAL(triggered()), this, SLOT(showDomainSettingsDialog()));
+
     // Update the on-the-fly menus.
     connect(tabWidgetPointer, SIGNAL(updateUserAgentActions(QString, bool)), this, SLOT(updateUserAgentActions(QString, bool)));
     connect(tabWidgetPointer, SIGNAL(updateZoomFactorAction(double)), this, SLOT(updateZoomFactorAction(double)));
@@ -205,11 +225,6 @@ BrowserWindow::BrowserWindow(bool firstWindow) : KXmlGuiWindow()
     // Process cookie changes.
     connect(tabWidgetPointer, SIGNAL(updateCookiesAction(int)), this, SLOT(updateCookiesAction(int)));
 
-    // Display dialogs.
-    connect(zoomFactorActionPointer, SIGNAL(triggered()), this, SLOT(getZoomFactorFromUser()));
-    connect(cookiesActionPointer, SIGNAL(triggered()), this, SLOT(showCookiesDialog()));
-    connect(domainSettingsActionPointer, SIGNAL(triggered()), this, SLOT(showDomainSettingsDialog()));
-
     // Connect the URL toolbar actions.
     connect(javaScriptActionPointer, SIGNAL(triggered()), this, SLOT(toggleJavaScript()));
     connect(localStorageActionPointer, SIGNAL(triggered()), this, SLOT(toggleLocalStorage()));
@@ -353,12 +368,10 @@ BrowserWindow::BrowserWindow(bool firstWindow) : KXmlGuiWindow()
     connect(tabWidgetPointer, SIGNAL(fullScreenRequested(bool)), this, SLOT(fullScreenRequested(bool)));
 
     // Create keyboard shortcuts.
-    QShortcut *ctrlTShortcutPointer = new QShortcut(QKeySequence(i18nc("The open new tab shortcut.", "Ctrl+t")), this);
     QShortcut *f11ShortcutPointer = new QShortcut(QKeySequence(i18nc("The toggle full screen shortcut.", "F11")), this);
     QShortcut *escapeShortcutPointer = new QShortcut(QKeySequence::Cancel, this);
 
-    // Connect the keyboard shortcuts to the actions.
-    connect(ctrlTShortcutPointer, SIGNAL(activated()), tabWidgetPointer, SLOT(addTab()));
+    // Connect the keyboard shortcuts.
     connect(f11ShortcutPointer, SIGNAL(activated()), fullScreenActionPointer, SLOT(trigger()));
     connect(escapeShortcutPointer, SIGNAL(activated()), this, SLOT(escape()));
 
@@ -449,12 +462,6 @@ void BrowserWindow::escape() const
     }
 }
 
-void BrowserWindow::fileNew() const
-{
-    // Display a new instance of Privacy Browser.
-    (new BrowserWindow)->show();
-}
-
 void BrowserWindow::findNext() const
 {
     // Get the find string.
@@ -566,6 +573,12 @@ void BrowserWindow::loadUrlFromLineEdit(const QString &url) const
     tabWidgetPointer->loadUrlFromLineEdit(url);
 }
 
+void BrowserWindow::newWindow() const
+{
+    // Display a new instance of Privacy Browser.
+    (new BrowserWindow)->show();
+}
+
 void BrowserWindow::refresh() const
 {
     // Remove the focus from the URL line edit.
index 1c22d1df2e28edd7b0694b3ef74fe384e9e07bea..beb3f03024251c957fa554a5200c32c4b18dec82 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2022 Soren Stoutner <soren@stoutner.com>.
+ * Copyright © 2022-2023 Soren Stoutner <soren@stoutner.com>.
  *
  * This file is part of Privacy Browser PC <https://www.stoutner.com/privacy-browser-pc>.
  *
@@ -54,7 +54,6 @@ private Q_SLOTS:
     void back() const;
     void clearUrlLineEditFocus() const;
     void escape() const;
-    void fileNew() const;
     void findNext() const;
     void findPrevious() const;
     void forward() const;
@@ -63,6 +62,7 @@ private Q_SLOTS:
     void hideFindTextActions() const;
     void home() const;
     void loadUrlFromLineEdit(const QString &url) const;
+    void newWindow() const;
     void refresh() const;
     void showCookiesDialog();
     void showDownloadLocationBrowseDialog() const;