uui/inc/bitmaps.hlst        |   17 +++++++
 uui/source/passworddlg.cxx  |   52 +++++++++++++++++++++
 uui/source/passworddlg.hxx  |    2 
 uui/uiconfig/ui/password.ui |  106 ++++++++++++++++++++++++++++++++++++--------
 4 files changed, 159 insertions(+), 18 deletions(-)

New commits:
commit bbd3f8063f496cfaf7a97cd8e1e2c6e118e611d9
Author:     Karthik <m...@karthikreddy.org>
AuthorDate: Sun Mar 9 19:02:35 2025 +0530
Commit:     Balazs Varga <balazs.varga.ext...@allotropia.de>
CommitDate: Thu Mar 13 16:41:42 2025 +0100

    tdf#146947 Add show/reveal toggle to "Enter Password" dialog
    
    Implemented password visibility toggle button in "Enter Password" dialog. 
When you open an encrypted file you will see this dialog.
    
    Change-Id: Id736a1224b5254d5f3c1ae3a96353ed65023d2c6
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182694
    Tested-by: Jenkins
    Reviewed-by: Balazs Varga <balazs.varga.ext...@allotropia.de>

diff --git a/uui/inc/bitmaps.hlst b/uui/inc/bitmaps.hlst
new file mode 100644
index 000000000000..fcf2c8074241
--- /dev/null
+++ b/uui/inc/bitmaps.hlst
@@ -0,0 +1,17 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <rtl/ustring.hxx>
+
+inline constexpr OUString RID_SVXBMP_HIDEPASS = u"res/hidepass.png"_ustr;
+inline constexpr OUString RID_SVXBMP_SHOWPASS = u"res/showpass.png"_ustr;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/uui/source/passworddlg.cxx b/uui/source/passworddlg.cxx
index 0485e4ddc201..382c387bc6b3 100644
--- a/uui/source/passworddlg.cxx
+++ b/uui/source/passworddlg.cxx
@@ -26,6 +26,7 @@
 #include <tools/debug.hxx>
 #include <vcl/svapp.hxx>
 #include <vcl/weld.hxx>
+#include <bitmaps.hlst>
 
 using namespace ::com::sun::star;
 
@@ -54,12 +55,28 @@ PasswordDialog::PasswordDialog(weld::Window* pParent,
         xBox->run();
     }
 
+    m_xPass[0] = m_xBuilder->weld_toggle_button(u"togglebt1"_ustr);
+    m_xPass[1] = m_xBuilder->weld_toggle_button(u"togglebt2"_ustr);
+
+    Link<weld::Toggleable&, void> aToggleLink = LINK(this, PasswordDialog, 
ShowHdl);
+
+    for (auto& aPass : m_xPass)
+    {
+        if (aPass->get_active())
+            aPass->set_from_icon_name(RID_SVXBMP_SHOWPASS);
+        else
+            aPass->set_from_icon_name(RID_SVXBMP_HIDEPASS);
+        aPass->connect_toggled(aToggleLink);
+    }
+
     // default settings for enter password or reenter passwd...
     OUString aTitle(Translate::get(STR_TITLE_ENTER_PASSWORD, rResLocale));
     m_xFTConfirmPassword->hide();
     m_xEDConfirmPassword->hide();
+    m_xPass[1]->hide();
     m_xFTConfirmPassword->set_sensitive(false);
     m_xEDConfirmPassword->set_sensitive(false);
+    m_xPass[1]->set_sensitive(false);
 
     // settings for create password
     if (nDialogMode == task::PasswordRequestMode_PASSWORD_CREATE)
@@ -119,5 +136,40 @@ IMPL_LINK_NOARG(PasswordDialog, OKHdl_Impl, weld::Button&, 
void)
         m_xDialog->response(RET_OK);
 }
 
+IMPL_LINK(PasswordDialog, ShowHdl, weld::Toggleable& ,rToggleable, void)
+{
+    bool bChecked = rToggleable.get_active();
+    if (&rToggleable == m_xPass[0].get())
+    {
+        if (bChecked)
+        {
+            m_xPass[0]->set_from_icon_name(RID_SVXBMP_SHOWPASS);
+            m_xEDPassword->set_visibility(true);
+            m_xEDPassword->grab_focus();
+        }
+        else
+        {
+            m_xPass[0]->set_from_icon_name(RID_SVXBMP_HIDEPASS);
+            m_xEDPassword->set_visibility(false);
+            m_xEDPassword->grab_focus();
+        }
+    }
+    else if (&rToggleable == m_xPass[1].get())
+    {
+        if (bChecked)
+        {
+            m_xPass[1]->set_from_icon_name(RID_SVXBMP_SHOWPASS);
+            m_xEDConfirmPassword->set_visibility(true);
+            m_xEDConfirmPassword->grab_focus();
+        }
+        else
+        {
+            m_xPass[1]->set_from_icon_name(RID_SVXBMP_HIDEPASS);
+            m_xEDConfirmPassword->set_visibility(false);
+            m_xEDConfirmPassword->grab_focus();
+        }
+    }
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
 
diff --git a/uui/source/passworddlg.hxx b/uui/source/passworddlg.hxx
index c21c4c3ba82f..f8a303cf65f4 100644
--- a/uui/source/passworddlg.hxx
+++ b/uui/source/passworddlg.hxx
@@ -29,11 +29,13 @@ class PasswordDialog : public weld::GenericDialogController
     std::unique_ptr<weld::Label> m_xFTConfirmPassword;
     std::unique_ptr<weld::Entry> m_xEDConfirmPassword;
     std::unique_ptr<weld::Button> m_xOKBtn;
+    std::array<std::unique_ptr<weld::ToggleButton>, 2> m_xPass;
     sal_uInt16      nMinLen;
     OUString        aPasswdMismatch;
 
 
     DECL_LINK(OKHdl_Impl, weld::Button&, void);
+    DECL_LINK(ShowHdl, weld::Toggleable&, void);
 
 public:
     PasswordDialog(weld::Window* pParent, css::task::PasswordRequestMode 
nDlgMode, const std::locale& rLocale, const OUString& aDocURL,
diff --git a/uui/uiconfig/ui/password.ui b/uui/uiconfig/ui/password.ui
index f36fbf479818..568f401b34d3 100644
--- a/uui/uiconfig/ui/password.ui
+++ b/uui/uiconfig/ui/password.ui
@@ -2,6 +2,16 @@
 <!-- Generated with glade 3.40.0 -->
 <interface domain="uui">
   <requires lib="gtk+" version="3.20"/>
+  <object class="GtkImage" id="passimg1">
+    <property name="visible">True</property>
+    <property name="can-focus">False</property>
+    <property name="icon-name">res/hidepass.png</property>
+  </object>
+  <object class="GtkImage" id="passimg2">
+    <property name="visible">True</property>
+    <property name="can-focus">False</property>
+    <property name="icon-name">res/hidepass.png</property>
+  </object>
   <object class="GtkDialog" id="PasswordDialog">
     <property name="can-focus">False</property>
     <property name="border-width">6</property>
@@ -86,7 +96,6 @@
                 <property name="visible">True</property>
                 <property name="can-focus">False</property>
                 <property name="use-underline">True</property>
-                <property name="mnemonic-widget">confirmpassEntry</property>
                 <property name="xalign">0</property>
               </object>
               <packing>
@@ -99,7 +108,6 @@
                 <property name="visible">True</property>
                 <property name="can-focus">False</property>
                 <property name="use-underline">True</property>
-                <property name="mnemonic-widget">newpassEntry</property>
                 <property name="xalign">0</property>
               </object>
               <packing>
@@ -108,17 +116,48 @@
               </packing>
             </child>
             <child>
-              <object class="GtkEntry" id="newpassEntry">
+              <object class="GtkBox" id="newpassbox">
                 <property name="visible">True</property>
-                <property name="can-focus">True</property>
+                <property name="can-focus">False</property>
                 <property name="hexpand">True</property>
-                <property name="visibility">False</property>
-                <property name="activates-default">True</property>
-                <property name="truncate-multiline">True</property>
-                <child internal-child="accessible">
-                  <object class="AtkObject" id="newpassEntry-atkobject">
-                    <property name="AtkObject::accessible-description" 
translatable="yes" context="password|extended_tip|newpassEntry">Type a 
password. A password is case sensitive.</property>
+                <child>
+                  <object class="GtkEntry" id="newpassEntry">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="hexpand">True</property>
+                    <property name="visibility">False</property>
+                    <property name="activates-default">True</property>
+                    <property name="truncate-multiline">True</property>
+                    <child internal-child="accessible">
+                      <object class="AtkObject" id="newpassEntry-atkobject">
+                        <property name="AtkObject::accessible-description" 
translatable="yes" context="password|extended_tip|newpassEntry">Type a 
password. A password is case sensitive.</property>
+                      </object>
+                    </child>
                   </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkToggleButton" id="togglebt1">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">True</property>
+                    <property name="image">passimg1</property>
+                    <child internal-child="accessible">
+                      <object class="AtkObject" id="togglebt1-atkobject">
+                        <property name="AtkObject::accessible-name" 
translatable="yes" context="password|togglebt1-atkobject">Show 
Characters</property>
+                        <property name="AtkObject::accessible-description" 
translatable="yes" context="password|extended_tip|togglebt1">Show or Hide 
password characters</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
                 </child>
               </object>
               <packing>
@@ -127,17 +166,48 @@
               </packing>
             </child>
             <child>
-              <object class="GtkEntry" id="confirmpassEntry">
+              <object class="GtkBox" id="confirmpassbox">
                 <property name="visible">True</property>
-                <property name="can-focus">True</property>
+                <property name="can-focus">False</property>
                 <property name="hexpand">True</property>
-                <property name="visibility">False</property>
-                <property name="activates-default">True</property>
-                <property name="truncate-multiline">True</property>
-                <child internal-child="accessible">
-                  <object class="AtkObject" id="confirmpassEntry-atkobject">
-                    <property name="AtkObject::accessible-description" 
translatable="yes" context="password|extended_tip|confirmpassEntry">Re-enter 
the password.</property>
+                <child>
+                  <object class="GtkEntry" id="confirmpassEntry">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="hexpand">True</property>
+                    <property name="visibility">False</property>
+                    <property name="activates-default">True</property>
+                    <property name="truncate-multiline">True</property>
+                    <child internal-child="accessible">
+                      <object class="AtkObject" 
id="confirmpassEntry-atkobject">
+                        <property name="AtkObject::accessible-description" 
translatable="yes" context="password|extended_tip|confirmpassEntry">Re-enter 
the password.</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkToggleButton" id="togglebt2">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">True</property>
+                    <property name="image">passimg2</property>
+                    <child internal-child="accessible">
+                      <object class="AtkObject" id="togglebt2-atkobject">
+                        <property name="AtkObject::accessible-name" 
translatable="yes" context="password|togglebt2-atkobject">Show 
Characters</property>
+                        <property name="AtkObject::accessible-description" 
translatable="yes" context="password|extended_tip|togglebt2">Show or Hide 
password characters</property>
+                      </object>
+                    </child>
                   </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
                 </child>
               </object>
               <packing>

Reply via email to