uui/inc/strings.hrc         |    5 
 uui/source/passworddlg.cxx  |   75 +++++++++++---
 uui/source/passworddlg.hxx  |    3 
 uui/uiconfig/ui/password.ui |  229 ++++++++++++++++++++++++++------------------
 4 files changed, 200 insertions(+), 112 deletions(-)

New commits:
commit 9bcc5970b7d12d20536669300662e046ea361e29
Author:     varshneydevansh <[email protected]>
AuthorDate: Sun Feb 25 23:58:12 2024 +0530
Commit:     Heiko Tietze <[email protected]>
CommitDate: Fri Nov 7 15:41:27 2025 +0100

    tdf#132007: Refine password prompt dialog UI and text
    
    Refines the password dialog for a cleaner user experience.
    
    The main prompt now shows just the filename instead of the full path.
    A the label clarifies whether a password to "open" or "edit" the
    file is needed.
    
    The OK button is disabled until a password is entered.
    
    Change-Id: I1288fc94b81984b32f9ade33bd0cd52aa4439b1d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163924
    Tested-by: Jenkins
    Reviewed-by: Heiko Tietze <[email protected]>

diff --git a/uui/inc/strings.hrc b/uui/inc/strings.hrc
index 28c0ccd83ad0..62b06a656abe 100644
--- a/uui/inc/strings.hrc
+++ b/uui/inc/strings.hrc
@@ -21,12 +21,13 @@
 
 #define NC_(Context, String) TranslateId(Context, u8##String)
 
-#define STR_ENTER_PASSWORD_TO_OPEN              
NC_("STR_ENTER_PASSWORD_TO_OPEN", "Enter password to open file: 
")
-#define STR_ENTER_PASSWORD_TO_MODIFY            
NC_("STR_ENTER_PASSWORD_TO_MODIFY", "Enter password to modify file: 
")
+#define STR_ENTER_PASSWORD_TO_OPEN              
NC_("STR_ENTER_PASSWORD_TO_OPEN", "The file ā€œ%sā€ is password-protected.")
 #define STR_ENTER_SIMPLE_PASSWORD               
NC_("STR_ENTER_SIMPLE_PASSWORD", "Enter password: ")
 #define STR_CONFIRM_SIMPLE_PASSWORD             
NC_("STR_CONFIRM_SIMPLE_PASSWORD", "Confirm password: ")
 #define STR_TITLE_CREATE_PASSWORD               
NC_("STR_TITLE_CREATE_PASSWORD", "Set Password")
 #define STR_TITLE_ENTER_PASSWORD                
NC_("STR_TITLE_ENTER_PASSWORD", "Enter Password")
+//: %TITLE is the base dialog title, %FILENAME is the document's filename, 
%PRODUCTNAME is the application name (e.g. "LibreOfficeDev")
+#define STR_TITLE_FULL_FORMAT                   NC_("STR_TITLE_FULL_FORMAT", 
"%TITLE - %FILENAME - %PRODUCTNAME")
 #define STR_PASSWORD_MISMATCH                   NC_("STR_PASSWORD_MISMATCH", 
"The confirmation password did not match the password. Set the password again 
by entering the same password in both boxes.")
 
 #define STR_ALREADYOPEN_TITLE                   NC_("STR_ALREADYOPEN_TITLE", 
"Document in Use")
diff --git a/uui/source/passworddlg.cxx b/uui/source/passworddlg.cxx
index f027746a6994..b78d30c3e41f 100644
--- a/uui/source/passworddlg.cxx
+++ b/uui/source/passworddlg.cxx
@@ -20,6 +20,7 @@
 #include "passworddlg.hxx"
 #include <strings.hrc>
 
+#include <comphelper/string.hxx>
 #include <unotools/resmgr.hxx>
 #include <unotools/configmgr.hxx>
 #include <tools/urlobj.hxx>
@@ -32,7 +33,7 @@ using namespace ::com::sun::star;
 
 PasswordDialog::PasswordDialog(weld::Window* pParent,
     task::PasswordRequestMode nDialogMode, const std::locale& rResLocale,
-    const OUString& aDocURL, bool bOpenToModify, bool bIsSimplePasswordRequest)
+    const OUString& aDocURL, bool bIsPasswordToModify, bool 
bIsSimplePasswordRequest)
     : GenericDialogController(pParent, u"uui/ui/password.ui"_ustr, 
u"PasswordDialog"_ustr)
     , m_xFTPassword(m_xBuilder->weld_label(u"newpassFT"_ustr))
     , m_xEDPassword(m_xBuilder->weld_entry(u"newpassEntry"_ustr))
@@ -42,6 +43,8 @@ PasswordDialog::PasswordDialog(weld::Window* pParent,
     , nMinLen(1)
     , aPasswdMismatch(Translate::get(STR_PASSWORD_MISMATCH, rResLocale))
 {
+    // Disable the OK button until something has been entered in the password 
field
+    m_xOKBtn->set_sensitive(false);
     // tdf#115964 we can be launched before the parent has resized to its 
final size
     m_xDialog->set_centered_on_parent(true);
 
@@ -60,7 +63,6 @@ PasswordDialog::PasswordDialog(weld::Window* pParent,
     }
 
     // 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();
@@ -71,47 +73,82 @@ PasswordDialog::PasswordDialog(weld::Window* pParent,
     // settings for create password
     if (nDialogMode == task::PasswordRequestMode_PASSWORD_CREATE)
     {
-        aTitle = Translate::get(STR_TITLE_CREATE_PASSWORD, rResLocale);
-
+        m_xDialog->set_title(Translate::get(STR_TITLE_CREATE_PASSWORD, 
rResLocale));
         
m_xFTConfirmPassword->set_label(Translate::get(STR_CONFIRM_SIMPLE_PASSWORD, 
rResLocale));
 
         m_xFTConfirmPassword->show();
         m_xEDConfirmPassword->show();
         m_xFTConfirmPassword->set_sensitive(true);
         m_xEDConfirmPassword->set_sensitive(true);
+        m_xPass[1]->show();
     }
 
-    m_xDialog->set_title(aTitle);
+    auto xOpenLabel = m_xBuilder->weld_label(u"openPasswordLabel"_ustr);
+    auto xEditLabel = m_xBuilder->weld_label(u"editPasswordLabel"_ustr);
+
+    xOpenLabel->set_visible(!bIsPasswordToModify);
+    xEditLabel->set_visible(bIsPasswordToModify);
+
+    OUString aMessage(Translate::get(STR_ENTER_PASSWORD_TO_OPEN, rResLocale));
 
-    TranslateId pStrId = bOpenToModify ? STR_ENTER_PASSWORD_TO_MODIFY : 
STR_ENTER_PASSWORD_TO_OPEN;
-    OUString aMessage(Translate::get(pStrId, rResLocale));
     INetURLObject url(aDocURL);
 
-    // tdf#66553 - add file name to title bar for password managers
-    OUString aFileName = url.getName(INetURLObject::LAST_SEGMENT, true,
+    // Append filename and product name to the title for password manager 
compatibility
+    OUString sFileName = url.getName(INetURLObject::LAST_SEGMENT, true,
                                      
INetURLObject::DecodeMechanism::Unambiguous);
-    if (!aFileName.isEmpty())
-        aFileName += " - " + utl::ConfigManager::getProductName();
-    m_xDialog->set_title(aTitle + " - " + aFileName);
+    if (!sFileName.isEmpty())
+    {
+        const OUString sFinalTitle = Translate::get(STR_TITLE_FULL_FORMAT, 
rResLocale)
+            .replaceAll(u"%TITLE", m_xDialog->get_title())
+            .replaceAll(u"%FILENAME", sFileName)
+            .replaceAll(u"%PRODUCTNAME", utl::ConfigManager::getProductName());
+
+        m_xDialog->set_title(sFinalTitle);
+    }
+
+    OUString sTooltipTextToShow = 
url.GetMainURL(INetURLObject::DecodeMechanism::Unambiguous);
 
-    auto aUrl = url.HasError()
-        ? aDocURL : 
url.GetMainURL(INetURLObject::DecodeMechanism::Unambiguous);
-    aMessage += m_xFTPassword->escape_ui_str(aUrl);
-    m_xFTPassword->set_label(aMessage);
+    if (!url.HasError() && !sTooltipTextToShow.isEmpty())
+    {
+        OUStringBuffer sFileNameBuffer(sFileName);
+        OUString sFileNameShort = 
comphelper::string::truncateToLength(sFileNameBuffer, 50).makeStringAndClear();
+
+        m_xFTPassword->set_label(aMessage.replaceAll("%s", sFileNameShort));
+        m_xFTPassword->set_tooltip_text(sTooltipTextToShow);
+    }
+    else
+    {
+        m_xFTPassword->set_label(aMessage.replaceAll("%s", aDocURL));
+        m_xFTPassword->set_tooltip_text(aDocURL);
+    }
+    m_xEDPassword->grab_focus();
 
     if (bIsSimplePasswordRequest)
     {
         DBG_ASSERT( aDocURL.isEmpty(), "A simple password request should not 
have a document URL! Use document password request instead." );
         m_xFTPassword->set_label(Translate::get(STR_ENTER_SIMPLE_PASSWORD, 
rResLocale));
+        m_xFTPassword->set_tooltip_text({});
     }
 
+    // This signal handler enables/disables the OK button based on whether the 
password entry is empty
+    m_xEDPassword->connect_changed(LINK(this, PasswordDialog, 
EnableOKBtn_Impl));
+
+    EnableOKBtn_Impl(*m_xEDPassword);
+
     m_xOKBtn->connect_clicked(LINK(this, PasswordDialog, OKHdl_Impl));
 }
 
+IMPL_LINK_NOARG(PasswordDialog, EnableOKBtn_Impl, weld::Entry&, void)
+{
+    bool bFirstPasswordHasText = !m_xEDPassword->get_text().isEmpty();
+    m_xOKBtn->set_sensitive(bFirstPasswordHasText);
+}
+
 IMPL_LINK_NOARG(PasswordDialog, OKHdl_Impl, weld::Button&, void)
 {
     bool bEDPasswdValid = m_xEDPassword->get_text().getLength() >= nMinLen;
-    bool bPasswdMismatch = m_xEDConfirmPassword->get_text() != 
m_xEDPassword->get_text();
+    bool bPasswdMismatch = m_xEDConfirmPassword->get_visible() && 
(m_xEDConfirmPassword->get_text() != m_xEDPassword->get_text());
+
     bool bValid = (!m_xEDConfirmPassword->get_visible() && bEDPasswdValid) ||
             (m_xEDConfirmPassword->get_visible() && bEDPasswdValid && 
!bPasswdMismatch);
 
@@ -121,6 +158,10 @@ IMPL_LINK_NOARG(PasswordDialog, OKHdl_Impl, weld::Button&, 
void)
                                                   VclMessageType::Warning, 
VclButtonsType::Ok,
                                                   aPasswdMismatch));
         xBox->run();
+
+        m_xEDPassword->set_text({});
+        m_xEDConfirmPassword->set_text({});
+        m_xEDPassword->grab_focus();
     }
     else if (bValid)
         m_xDialog->response(RET_OK);
diff --git a/uui/source/passworddlg.hxx b/uui/source/passworddlg.hxx
index f8a303cf65f4..8e2a1a5cbf5f 100644
--- a/uui/source/passworddlg.hxx
+++ b/uui/source/passworddlg.hxx
@@ -35,11 +35,12 @@ class PasswordDialog : public weld::GenericDialogController
 
 
     DECL_LINK(OKHdl_Impl, weld::Button&, void);
+    DECL_LINK(EnableOKBtn_Impl, weld::Entry&, void);
     DECL_LINK(ShowHdl, weld::Toggleable&, void);
 
 public:
     PasswordDialog(weld::Window* pParent, css::task::PasswordRequestMode 
nDlgMode, const std::locale& rLocale, const OUString& aDocURL,
-                   bool bOpenToModify, bool bIsSimplePasswordRequest);
+                   bool bIsPasswordToModify, bool bIsSimplePasswordRequest);
 
     void            SetMinLen( sal_uInt16 nMin ) { nMinLen = nMin; }
     OUString        GetPassword() const { return m_xEDPassword->get_text(); }
diff --git a/uui/uiconfig/ui/password.ui b/uui/uiconfig/ui/password.ui
index f1a38ef93545..90c683d0cadd 100644
--- a/uui/uiconfig/ui/password.ui
+++ b/uui/uiconfig/ui/password.ui
@@ -14,8 +14,8 @@
   </object>
   <object class="GtkDialog" id="PasswordDialog">
     <property name="can-focus">False</property>
-    <property name="border-width">6</property>
-    <property name="title" translatable="yes" 
context="password|PasswordDialog">Set Password</property>
+    <property name="border-width">12</property>
+    <property name="title" translatable="yes" 
context="password|PasswordDialog">Password Protection</property>
     <property name="modal">True</property>
     <property name="window-position">center</property>
     <property name="default-width">0</property>
@@ -84,80 +84,60 @@
           </packing>
         </child>
         <child>
-          <!-- n-columns=1 n-rows=4 -->
+          <!-- n-columns=2 n-rows=3 -->
           <object class="GtkGrid" id="grid1">
             <property name="visible">True</property>
             <property name="can-focus">False</property>
             <property name="hexpand">True</property>
             <property name="row-spacing">6</property>
             <property name="column-spacing">12</property>
-            <child>
-              <object class="GtkLabel" id="confirmpassFT">
-                <property name="visible">True</property>
-                <property name="can-focus">False</property>
-                <property name="use-underline">True</property>
-                <property name="xalign">0</property>
-              </object>
-              <packing>
-                <property name="left-attach">0</property>
-                <property name="top-attach">2</property>
-              </packing>
-            </child>
+            <property name="margin-start">12</property>
+            <property name="margin-end">12</property>
+            <property name="margin-top">12</property>
+            <property name="margin-bottom">12</property>
             <child>
               <object class="GtkLabel" id="newpassFT">
                 <property name="visible">True</property>
                 <property name="can-focus">False</property>
-                <property name="use-underline">True</property>
+                <property name="margin-bottom">6</property>
+                <property name="label" translatable="yes" 
context="password|label">The file "%s" is password-protected.</property>
                 <property name="xalign">0</property>
+                <property name="width-chars">50</property>
+                <property name="wrap">True</property>
+                <property name="wrap-mode">word-char</property>
               </object>
               <packing>
                 <property name="left-attach">0</property>
                 <property name="top-attach">0</property>
+                <property name="width">2</property>
               </packing>
             </child>
             <child>
-              <object class="GtkBox" id="newpassbox">
+              <object class="GtkBox" id="passwordLabelBox">
                 <property name="visible">True</property>
                 <property name="can-focus">False</property>
-                <property name="hexpand">True</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">0</property>
+                <property name="valign">center</property>
                 <child>
-                  <object class="GtkEntry" id="newpassEntry">
+                  <object class="GtkLabel" id="openPasswordLabel">
                     <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>
+                    <property name="can-focus">False</property>
+                    <property name="label" translatable="yes" 
context="password|label">_Enter password:</property>
+                    <property name="use-underline">True</property>
+                    <property name="mnemonic-widget">newpassEntry</property>
+                    <property name="xalign">0</property>
                   </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 class="GtkLabel" id="editPasswordLabel">
+                    <property name="visible">False</property>
+                    <property name="can-focus">False</property>
+                    <property name="label" translatable="yes" 
context="password|label">_Enter password to edit:</property>
+                    <property name="use-underline">True</property>
+                    <property name="mnemonic-widget">newpassEntry</property>
+                    <property name="xalign">0</property>
                   </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">1</property>
-                  </packing>
                 </child>
               </object>
               <packing>
@@ -166,53 +146,117 @@
               </packing>
             </child>
             <child>
-              <object class="GtkBox" id="confirmpassbox">
+              <object class="GtkBox" id="newpassbox">
+                 <property name="visible">True</property>
+                 <property name="can-focus">False</property>
+                 <property name="hexpand">True</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">True</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>
+                <property name="left-attach">1</property>
+                <property name="top-attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="confirmpassFT">
                 <property name="visible">True</property>
                 <property name="can-focus">False</property>
-                <property name="hexpand">True</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>
+                <property name="label" translatable="yes" 
context="password|label">Reenter password</property>
+                <property name="use-underline">True</property>
+                <property name="mnemonic-widget">confirmpassEntry</property>
+                <property name="xalign">0</property>
               </object>
               <packing>
                 <property name="left-attach">0</property>
-                <property name="top-attach">3</property>
+                <property name="top-attach">2</property>
+              </packing>
+            </child>
+            <child>
+               <object class="GtkBox" id="confirmpassbox">
+                 <property name="visible">True</property>
+                 <property name="can-focus">False</property>
+                 <property name="hexpand">True</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">True</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>
+                <property name="left-attach">1</property>
+                <property name="top-attach">2</property>
               </packing>
             </child>
           </object>
@@ -227,6 +271,7 @@
     <action-widgets>
       <action-widget response="-6">cancel</action-widget>
       <action-widget response="-11">help</action-widget>
+      <action-widget response="-5">ok</action-widget>
     </action-widgets>
   </object>
 </interface>

Reply via email to