]> gitweb.stoutner.com Git - PrivacyBrowserPC.git/commitdiff
Create an animated loading favorite icon. https://redmine.stoutner.com/issues/980
authorSoren Stoutner <soren@stoutner.com>
Mon, 27 Mar 2023 23:54:38 +0000 (16:54 -0700)
committerSoren Stoutner <soren@stoutner.com>
Mon, 27 Mar 2023 23:54:38 +0000 (16:54 -0700)
doc/CMakeLists.txt
doc/index.docbook
src/resources.qrc
src/widgets/PrivacyWebEngineView.h
src/widgets/TabWidget.cpp
src/widgets/TabWidget.h

index 22771ec87c58a4f627280ae4b84a49c8dc23d7ff..3f656fcc5866d8d56be0918987d81b9a592aea2d 100644 (file)
@@ -17,3 +17,7 @@
 
 # Create the documentation.
 kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${KDE_INSTALL_DOCBUNDLEDIR}/en SUBDIR privacybrowser)
+
+# Install loading.gif.
+install(FILES loading.gif DESTINATION ${KDE_INSTALL_DOCBUNDLEDIR}/en/privacybrowser)
+install(FILES privacy-browser.png DESTINATION ${KDE_INSTALL_DOCBUNDLEDIR}/en/privacybrowser)
index 0d0e6f8ff3f967cb1563a5a35677a0ba98a6e415..4628bdce043a20cbec56b678c7b191b3eefe4508 100644 (file)
     <title>Credits and License</title>
 
     <para>
-      Program copyright 2016-2017,2021-2023 Soren Stoutner <ulink url="mailto:soren@stoutner.com">soren@stoutner.com</ulink>.
+      Privacy Browser PC copyright 2016-2017,2021-2023 Soren Stoutner <ulink url="mailto:soren@stoutner.com">soren@stoutner.com</ulink>.
     </para>
 
-    <para>
-      Translators:
-      <itemizedlist>
-        <listitem><para>Translations will be added in a future release.</para></listitem>
-      </itemizedlist>
-    </para>
+    <!-- Program. -->
+    <sect1 id="program">
+      <title>Program</title>
 
-    <!-- The program license. -->
-    &underGPL;
+      <para>
+        The source code is available at <ulink url="https://gitweb.stoutner.com/?p=PrivacyBrowserPC.git;a=summary">gitweb.stoutner.com</ulink>
+        or by running <filename>git clone https://git.stoutner.com/PrivacyBrowserPC.git</filename>.
+      </para>
 
-    <para>
-      Documentation copyright 2023 Soren Stoutner <ulink url="mailto:soren@stoutner.com">soren@stoutner.com</ulink>.
-    </para>
+      <para>
+        Translators:
+        <itemizedlist>
+          <listitem><para>Translations will be added in a future release.</para></listitem>
+        </itemizedlist>
+      </para>
+
+      <!-- The program license. -->
+      &underGPL;
+    </sect1>
+
+    <!-- Documentation. -->
+    <sect1 id="documentation">
+      <title>Documentation</title>
 
-    <!-- The documentation license. -->
-    &underFDL;
+      <para>
+        <filename>doc/index.docbook</filename> and <filename>src/com.stoutner.privacybrowser.appdata.xml</filename> are released under the
+        <ulink url="https://www.gnu.org/licenses/fdl-1.3.html">GFDL-1.3 license</ulink> with no Front-Cover or Back-Cover Texts or Invariant Sections.
+        All other documentation is released under the <ulink url="https://www.gnu.org/licenses/gpl-3.0.html">GPLv3+ license</ulink>.
+      </para>
+
+      <!-- The documentation license. -->
+      &underFDL;
+    </sect1>
+
+    <!-- Icons. -->
+    <sect1 id="icons">
+      <title>Icons</title>
+
+      <para>
+        <inlinemediaobject>
+          <imageobject>
+            <imagedata fileref="privacy-browser.png" format="PNG"/>
+          </imageobject>
+          <textobject>
+            <phrase>JavaScript</phrase>
+          </textobject>
+        </inlinemediaobject>
+
+        <inlinemediaobject>
+          <imageobject>
+            <imagedata fileref="javascript.png" format="PNG"/>
+          </imageobject>
+          <textobject>
+            <phrase>JavaScript</phrase>
+          </textobject>
+        </inlinemediaobject>
+
+        are derived from <filename>security</filename> and <filename>language</filename>, which are part of the <ulink url="https://fonts.google.com/icons">Android Material icon set</ulink>
+        and are released under the <ulink url="https://www.apache.org/licenses/LICENSE-2.0">Apache License 2.0</ulink>. Modifications copyright 2016-2017,2021-2023 Soren Stoutner.
+        The resulting images are released under the <ulink url="https://www.gnu.org/licenses/gpl-3.0.html">GPLv3+ license</ulink>.
+      </para>
+
+      <para>
+        <inlinemediaobject>
+          <imageobject>
+            <imagedata fileref="loading.gif" format="GIF"/>
+          </imageobject>
+          <textobject>
+            <phrase>Loading</phrase>
+          </textobject>
+        </inlinemediaobject>
+
+        comes from <ulink url="https://github.com/Codelessly/FlutterLoadingGIFs/blob/master/packages/cupertino_activity_indicator_selective.gif">FlutterLoadingGIFs</ulink>
+        where it is named <filename>cupertino_activity_indicator_selective.gif</filename>.
+        It is released under the <ulink url="https://opensource.org/license/0bsd/">Zero-Clause BSD License</ulink>.
+      </para>
+    </sect1>
   </chapter>
 </book>
index c86aa0c8043e5bb0cb8f02bf4165969d06aea149..c55f51857bdb172152aa1a18700bb23f141e490c 100644 (file)
@@ -20,6 +20,7 @@
 <RCC version="1.0">
     <qresource>
         <file>icons/javascript-warning.svg</file>
+        <file>icons/loading.gif</file>
         <file>icons/privacy-mode.svg</file>
         <file>icons/sc-apps-privacybrowser.svg</file>
         <file>licenses/GPLv3+.txt</file>
index 5548ec422dc56a567443c881f591621dedf255ea..061f65725d0825e5286e3ecdfeb183d6ca1f91b0 100644 (file)
@@ -21,6 +21,7 @@
 #define PRIVACYWEBENGINEVIEW_H
 
 // Qt toolkit headers.
+#include <QIcon>
 #include <QNetworkCookie>
 #include <QWebEngineFindTextResult>
 #include <QWebEngineView>
@@ -37,9 +38,11 @@ public:
     // The public variables.
     std::list<QNetworkCookie> *cookieListPointer = new std::list<QNetworkCookie>;
     QString domainSettingsName = QStringLiteral("");
+    QIcon favoriteIcon = QIcon::fromTheme(QStringLiteral("globe"));
     bool findCaseSensitive = false;
     QString findString = QStringLiteral("");
     QWebEngineFindTextResult findTextResult = QWebEngineFindTextResult();
+    bool isLoading = false;
     int loadProgressInt = -1;
     bool localStorageEnabled = false;
 
index ec555faa50c3bcf88884ece0143083cbe85ea431..76ff617c3e180f3e253884d277dfd2a536f94dce 100644 (file)
@@ -72,6 +72,12 @@ TabWidget::TabWidget(QWidget *parent) : QWidget(parent)
     // Display the add tab widget.
     qTabWidgetPointer->setCornerWidget(addTabWidgetPointer);
 
+    // Create the loading favorite icon movie.
+    loadingFavoriteIconMoviePointer = new QMovie();
+
+    // Set the loading favorite icon movie file name.
+    loadingFavoriteIconMoviePointer->setFileName(QStringLiteral(":/icons/loading.gif"));
+
     // Add the first tab.
     addFirstTab();
 
@@ -152,7 +158,7 @@ PrivacyWebEngineView* TabWidget::addTab(const bool removeUrlLineEditFocus, const
     int newTabIndex = qTabWidgetPointer->addTab(privacyWebEngineViewPointer, i18nc("New tab label.", "New Tab"));
 
     // Set the default tab icon.
-    qTabWidgetPointer->setTabIcon(newTabIndex, defaultTabIcon);
+    qTabWidgetPointer->setTabIcon(newTabIndex, defaultFavoriteIcon);
 
     // Get handles for the WebEngine page and profile.
     QWebEnginePage *webEnginePagePointer = privacyWebEngineViewPointer->page();
@@ -177,15 +183,65 @@ PrivacyWebEngineView* TabWidget::addTab(const bool removeUrlLineEditFocus, const
         }
     });
 
-    // Update the progress bar when a load is started.
+    // Update the title when it changes.
+    connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::titleChanged, [this, privacyWebEngineViewPointer] (const QString &title)
+    {
+        // Get the index for this tab.
+        int tabIndex = qTabWidgetPointer->indexOf(privacyWebEngineViewPointer);
+
+        // Update the title for this tab.
+        qTabWidgetPointer->setTabText(tabIndex, title);
+
+        // Update the window title if this is the current tab.
+        if (tabIndex == qTabWidgetPointer->currentIndex())
+            emit updateWindowTitle(title);
+    });
+
+    // Connect the loading favorite icon movie to the tab icon.
+    connect(loadingFavoriteIconMoviePointer, &QMovie::frameChanged, [privacyWebEngineViewPointer, this]
+    {
+        // Get the index for this tab.
+        int tabIndex = qTabWidgetPointer->indexOf(privacyWebEngineViewPointer);
+
+        // Display the loading favorite icon if this tab is loading.
+        if (privacyWebEngineViewPointer->isLoading)
+            qTabWidgetPointer->setTabIcon(tabIndex, loadingFavoriteIconMoviePointer->currentPixmap());
+    });
+
+    // Update the icon when it changes.
+    connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::iconChanged, [privacyWebEngineViewPointer, this] (const QIcon &newFavoriteIcon)
+    {
+        // Store the favorite icon in the privacy web engine view.
+        if (newFavoriteIcon.isNull())
+            privacyWebEngineViewPointer->favoriteIcon = defaultFavoriteIcon;
+        else
+            privacyWebEngineViewPointer->favoriteIcon = newFavoriteIcon;
+
+        // Get the index for this tab.
+        int tabIndex = qTabWidgetPointer->indexOf(privacyWebEngineViewPointer);
+
+        // Update the icon for this tab.
+        if (newFavoriteIcon.isNull())
+            qTabWidgetPointer->setTabIcon(tabIndex, defaultFavoriteIcon);
+        else
+            qTabWidgetPointer->setTabIcon(tabIndex, newFavoriteIcon);
+    });
+
+    // Update the progress bar and the favorite icon when a load is started.
     connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::loadStarted, [privacyWebEngineViewPointer, this] ()
     {
+        // Set the privacy web engine view to be loading.
+        privacyWebEngineViewPointer->isLoading = true;
+
         // Store the load progress.
         privacyWebEngineViewPointer->loadProgressInt = 0;
 
         // Show the progress bar if this is the current tab.
         if (privacyWebEngineViewPointer == currentPrivacyWebEngineViewPointer)
             emit showProgressBar(0);
+
+        // Start the loading favorite icon movie.
+        loadingFavoriteIconMoviePointer->start();
     });
 
     // Update the progress bar when a load progresses.
@@ -202,12 +258,39 @@ PrivacyWebEngineView* TabWidget::addTab(const bool removeUrlLineEditFocus, const
     // Update the progress bar when a load finishes.
     connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::loadFinished, [privacyWebEngineViewPointer, this] ()
     {
+        // Set the privacy web engine view to be not loading.
+        privacyWebEngineViewPointer->isLoading = false;
+
         // Store the load progress.
         privacyWebEngineViewPointer->loadProgressInt = -1;
 
         // Hide the progress bar if this is the current tab.
         if (privacyWebEngineViewPointer == currentPrivacyWebEngineViewPointer)
             emit hideProgressBar();
+
+        // Get the index for this tab.
+        int tabIndex = qTabWidgetPointer->indexOf(privacyWebEngineViewPointer);
+
+        // Display the current favorite icon
+        qTabWidgetPointer->setTabIcon(tabIndex, privacyWebEngineViewPointer->favoriteIcon);
+
+        // Create a no tabs loading variable.
+        bool noTabsLoading = true;
+
+        // Check to see if any other tabs are loading.
+        for (int i = 0; i < qTabWidgetPointer->count(); i++)
+        {
+            // Get the privacy WebEngine view for the tab.
+            PrivacyWebEngineView *webEngineViewPointer = qobject_cast<PrivacyWebEngineView*>(qTabWidgetPointer->widget(i));
+
+            // Check to see if it is currently loading.
+            if (webEngineViewPointer->isLoading)
+                noTabsLoading = false;
+        }
+
+        // Stop the loading favorite icon movie if there are no loading tabs.
+        if (noTabsLoading)
+            loadingFavoriteIconMoviePointer->stop();
     });
 
     // Display HTTP Ping blocked dialogs.
@@ -326,33 +409,6 @@ PrivacyWebEngineView* TabWidget::addTab(const bool removeUrlLineEditFocus, const
     for (QNetworkCookie *cookiePointer : *durableCookiesListPointer)
         addCookieToStore(*cookiePointer, webEngineCookieStorePointer);
 
-    // Update the title when it changes.
-    connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::titleChanged, [this, privacyWebEngineViewPointer] (const QString &title)
-    {
-        // Get the index for this tab.
-        int tabIndex = qTabWidgetPointer->indexOf(privacyWebEngineViewPointer);
-
-        // Update the title for this tab.
-        qTabWidgetPointer->setTabText(tabIndex, title);
-
-        // Update the window title if this is the current tab.
-        if (tabIndex == qTabWidgetPointer->currentIndex())
-            emit updateWindowTitle(title);
-    });
-
-    // Update the icon when it changes.
-    connect(privacyWebEngineViewPointer, &PrivacyWebEngineView::iconChanged, [privacyWebEngineViewPointer, this] (const QIcon &icon)
-    {
-        // Get the index for this tab.
-        int tabIndex = qTabWidgetPointer->indexOf(privacyWebEngineViewPointer);
-
-        // Update the icon for this tab.
-        if (icon.isNull())
-            qTabWidgetPointer->setTabIcon(tabIndex, defaultTabIcon);
-        else
-            qTabWidgetPointer->setTabIcon(tabIndex, icon);
-    });
-
     // Enable spell checking.
     webEngineProfilePointer->setSpellCheckEnabled(true);
 
index ccaefb9c5aa465237ab6f9a6e3a3446ecbd41c28..578206ccc6ba31885c6b42a9da70f96fd5f44863 100644 (file)
@@ -28,6 +28,7 @@
 #include <KLineEdit>
 
 // Qt toolkit headers.
+#include <QMovie>
 #include <QPushButton>
 #include <QTabWidget>
 #include <QWebEngineCookieStore>
@@ -132,7 +133,8 @@ private:
     QWebEnginePage *currentWebEnginePagePointer;
     QWebEngineProfile *currentWebEngineProfilePointer;
     QWebEngineSettings *currentWebEngineSettingsPointer;
-    QIcon defaultTabIcon = QIcon::fromTheme(QStringLiteral("globe"));
+    QIcon defaultFavoriteIcon = QIcon::fromTheme(QStringLiteral("globe"));
+    QMovie *loadingFavoriteIconMoviePointer;
     QString searchEngineUrl;
     QTabWidget *qTabWidgetPointer;
     UserAgentHelper *userAgentHelperPointer;