diff --git a/src/gui/ApplicationSettingsWidgetSecurity.ui b/src/gui/ApplicationSettingsWidgetSecurity.ui
index 4052e5d630..344c2b81c9 100644
--- a/src/gui/ApplicationSettingsWidgetSecurity.ui
+++ b/src/gui/ApplicationSettingsWidgetSecurity.ui
@@ -175,7 +175,7 @@
-
- Show passwords in cleartext by default
+ Don't hide passwords when editing them
diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp
index 10f8c54b37..8e022a16d6 100644
--- a/src/gui/DatabaseWidget.cpp
+++ b/src/gui/DatabaseWidget.cpp
@@ -1326,7 +1326,7 @@ bool DatabaseWidget::isGroupSelected() const
bool DatabaseWidget::currentEntryHasFocus()
{
- return m_entryView->currentEntry() && m_entryView->hasFocus();
+ return m_entryView->numberOfSelectedEntries() > 0 && m_entryView->hasFocus();
}
bool DatabaseWidget::currentEntryHasTitle()
diff --git a/src/gui/EntryPreviewWidget.cpp b/src/gui/EntryPreviewWidget.cpp
index af6ffac33e..b9fa263837 100644
--- a/src/gui/EntryPreviewWidget.cpp
+++ b/src/gui/EntryPreviewWidget.cpp
@@ -47,12 +47,14 @@ EntryPreviewWidget::EntryPreviewWidget(QWidget* parent)
// Entry
m_ui->entryTotpButton->setIcon(filePath()->icon("actions", "chronometer"));
m_ui->entryCloseButton->setIcon(filePath()->icon("actions", "dialog-close"));
+ m_ui->togglePasswordButton->setIcon(filePath()->onOffIcon("actions", "password-show"));
m_ui->entryAttachmentsWidget->setReadOnly(true);
m_ui->entryAttachmentsWidget->setButtonsVisible(false);
connect(m_ui->entryTotpButton, SIGNAL(toggled(bool)), m_ui->entryTotpWidget, SLOT(setVisible(bool)));
connect(m_ui->entryCloseButton, SIGNAL(clicked()), SLOT(hide()));
+ connect(m_ui->togglePasswordButton, SIGNAL(clicked(bool)), SLOT(setPasswordVisible(bool)));
connect(m_ui->entryTabWidget, SIGNAL(tabBarClicked(int)), SLOT(updateTabIndexes()), Qt::QueuedConnection);
connect(&m_totpTimer, SIGNAL(timeout()), this, SLOT(updateTotpLabel()));
@@ -152,18 +154,40 @@ void EntryPreviewWidget::updateEntryTotp()
}
}
+void EntryPreviewWidget::setPasswordVisible(bool state)
+{
+ const QString password = m_currentEntry->resolveMultiplePlaceholders(m_currentEntry->password());
+ auto flags = m_ui->entryPasswordLabel->textInteractionFlags();
+ if (state) {
+ m_ui->entryPasswordLabel->setRawText(password);
+ m_ui->entryPasswordLabel->setToolTip(password);
+ m_ui->entryPasswordLabel->setTextInteractionFlags(flags | Qt::TextSelectableByMouse);
+ } else {
+ m_ui->entryPasswordLabel->setTextInteractionFlags(flags & ~Qt::TextSelectableByMouse);
+ m_ui->entryPasswordLabel->setToolTip({});
+ if (password.isEmpty() && config()->get("security/passwordemptynodots").toBool()) {
+ m_ui->entryPasswordLabel->setRawText("");
+ } else {
+ m_ui->entryPasswordLabel->setRawText(QString("\u25cf").repeated(6));
+ }
+ }
+}
+
void EntryPreviewWidget::updateEntryGeneralTab()
{
Q_ASSERT(m_currentEntry);
m_ui->entryUsernameLabel->setText(m_currentEntry->resolveMultiplePlaceholders(m_currentEntry->username()));
- if (!config()->get("security/HidePasswordPreviewPanel").toBool()) {
- const QString password = m_currentEntry->resolveMultiplePlaceholders(m_currentEntry->password());
- m_ui->entryPasswordLabel->setRawText(password);
- m_ui->entryPasswordLabel->setToolTip(password);
+ if (config()->get("security/HidePasswordPreviewPanel").toBool()) {
+ // Hide password
+ setPasswordVisible(false);
+ // Show the password toggle button if there are dots in the label
+ m_ui->togglePasswordButton->setVisible(!m_ui->entryPasswordLabel->rawText().isEmpty());
+ m_ui->togglePasswordButton->setChecked(false);
} else {
- m_ui->entryPasswordLabel->setRawText(QString("\u25cf").repeated(6));
- m_ui->entryPasswordLabel->setToolTip({});
+ // Show password
+ setPasswordVisible(true);
+ m_ui->togglePasswordButton->setVisible(false);
}
m_ui->entryUrlLabel->setRawText(m_currentEntry->displayUrl());
diff --git a/src/gui/EntryPreviewWidget.h b/src/gui/EntryPreviewWidget.h
index 88c729626b..9e687c6d8c 100644
--- a/src/gui/EntryPreviewWidget.h
+++ b/src/gui/EntryPreviewWidget.h
@@ -51,6 +51,7 @@ private slots:
void updateEntryAttributesTab();
void updateEntryAttachmentsTab();
void updateEntryAutotypeTab();
+ void setPasswordVisible(bool state);
void updateGroupHeaderLine();
void updateGroupGeneralTab();
diff --git a/src/gui/EntryPreviewWidget.ui b/src/gui/EntryPreviewWidget.ui
index 1fde8aa3ce..7e84d4120b 100644
--- a/src/gui/EntryPreviewWidget.ui
+++ b/src/gui/EntryPreviewWidget.ui
@@ -6,8 +6,8 @@
0
0
- 280
- 267
+ 573
+ 330
@@ -168,7 +168,7 @@
-
-
+
0
@@ -181,48 +181,48 @@
0
-
-
-
-
-
- 0
- 0
-
+
-
+
+
+ Qt::Horizontal
-
+
+ QSizePolicy::Fixed
+
+
- 100
- 0
+ 20
+ 20
-
+
- -
-
+
-
+
-
+
0
0
-
-
- 100
- 0
-
+
+
+ 75
+ true
+
-
- PointingHandCursor
+
+ Qt::LeftToRight
-
+ Username
-
- Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
- -
+
-
@@ -236,13 +236,16 @@
0
+
+ username
+
Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse
- -
-
+
-
+
0
@@ -255,11 +258,8 @@
true
-
- Qt::LeftToRight
-
- Username
+ Password
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
@@ -288,7 +288,45 @@
- -
+
-
+
+
+ Qt::Vertical
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 100
+ 0
+
+
+
+ PointingHandCursor
+
+
+ https://example.com
+
+
+ Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse
+
+
+
+ -
@@ -296,6 +334,9 @@
0
+
+ expired
+
-
@@ -320,8 +361,47 @@
- -
-
+
-
+
+
+ 6
+
+
+ 4
+
+
-
+
+
+
+
+
+ true
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 100
+ 0
+
+
+
+ password
+
+
+
+
+
+ -
+
Qt::Horizontal
@@ -336,37 +416,34 @@
- -
-
-
-
- 0
- 0
-
-
-
-
- 75
- true
-
+
-
+
+
+ Qt::Horizontal
-
- Password
+
+ QSizePolicy::Fixed
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ 20
+ 20
+
-
+
- -
-
+
-
+
- Qt::Vertical
+ Qt::Horizontal
+
+
+ QSizePolicy::Fixed
- 0
- 0
+ 20
+ 20
@@ -688,6 +765,12 @@
Qt::Vertical
+
+
+ 0
+ 0
+
+
diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp
index ee4351a2f7..f35949afb4 100644
--- a/src/gui/MainWindow.cpp
+++ b/src/gui/MainWindow.cpp
@@ -200,12 +200,17 @@ MainWindow::MainWindow()
m_ui->actionEntryOpenUrl->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_U);
m_ui->actionEntryCopyURL->setShortcut(Qt::CTRL + Qt::Key_U);
+ // Control window state
new QShortcut(Qt::CTRL + Qt::Key_M, this, SLOT(showMinimized()));
new QShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_M, this, SLOT(hideWindow()));
+ // Control database tabs
new QShortcut(Qt::CTRL + Qt::Key_Tab, this, SLOT(selectNextDatabaseTab()));
new QShortcut(Qt::CTRL + Qt::Key_PageUp, this, SLOT(selectNextDatabaseTab()));
new QShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_Tab, this, SLOT(selectPreviousDatabaseTab()));
new QShortcut(Qt::CTRL + Qt::Key_PageDown, this, SLOT(selectPreviousDatabaseTab()));
+ // Toggle password and username visibility in entry view
+ new QShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_C, this, SLOT(togglePasswordsHidden()));
+ new QShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_B, this, SLOT(toggleUsernamesHidden()));
m_ui->actionDatabaseNew->setIcon(filePath()->icon("actions", "document-new"));
m_ui->actionDatabaseOpen->setIcon(filePath()->icon("actions", "document-open"));
@@ -717,6 +722,22 @@ void MainWindow::databaseTabChanged(int tabIndex)
m_actionMultiplexer.setCurrentObject(m_ui->tabWidget->currentDatabaseWidget());
}
+void MainWindow::togglePasswordsHidden()
+{
+ auto dbWidget = m_ui->tabWidget->currentDatabaseWidget();
+ if (dbWidget) {
+ dbWidget->setPasswordsHidden(!dbWidget->isPasswordsHidden());
+ }
+}
+
+void MainWindow::toggleUsernamesHidden()
+{
+ auto dbWidget = m_ui->tabWidget->currentDatabaseWidget();
+ if (dbWidget) {
+ dbWidget->setUsernamesHidden(!dbWidget->isUsernamesHidden());
+ }
+}
+
void MainWindow::closeEvent(QCloseEvent* event)
{
// ignore double close events (happens on macOS when closing from the dock)
diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h
index d83b4a1ff6..b7ef04d427 100644
--- a/src/gui/MainWindow.h
+++ b/src/gui/MainWindow.h
@@ -112,6 +112,8 @@ private slots:
void showErrorMessage(const QString& message);
void selectNextDatabaseTab();
void selectPreviousDatabaseTab();
+ void togglePasswordsHidden();
+ void toggleUsernamesHidden();
private:
static void setShortcut(QAction* action, QKeySequence::StandardKey standard, int fallback = 0);
diff --git a/src/gui/entry/EntryModel.cpp b/src/gui/entry/EntryModel.cpp
index 0616374ac1..ebf6a20bec 100644
--- a/src/gui/entry/EntryModel.cpp
+++ b/src/gui/entry/EntryModel.cpp
@@ -468,9 +468,10 @@ bool EntryModel::isUsernamesHidden() const
/**
* Set state of 'Hide Usernames' setting and signal change
*/
-void EntryModel::setUsernamesHidden(const bool hide)
+void EntryModel::setUsernamesHidden(bool hide)
{
m_hideUsernames = hide;
+ emit dataChanged(index(0, 0), index(rowCount()-1, columnCount() - 1));
emit usernamesHiddenChanged();
}
@@ -485,28 +486,13 @@ bool EntryModel::isPasswordsHidden() const
/**
* Set state of 'Hide Passwords' setting and signal change
*/
-void EntryModel::setPasswordsHidden(const bool hide)
+void EntryModel::setPasswordsHidden(bool hide)
{
m_hidePasswords = hide;
+ emit dataChanged(index(0, 0), index(rowCount()-1, columnCount() - 1));
emit passwordsHiddenChanged();
}
-/**
- * Toggle state of 'Hide Usernames' setting
- */
-void EntryModel::toggleUsernamesHidden(const bool hide)
-{
- setUsernamesHidden(hide);
-}
-
-/**
- * Toggle state of 'Hide Passwords' setting
- */
-void EntryModel::togglePasswordsHidden(const bool hide)
-{
- setPasswordsHidden(hide);
-}
-
void EntryModel::setPaperClipPixmap(const QPixmap& paperclip)
{
m_paperClipPixmap = paperclip;
diff --git a/src/gui/entry/EntryModel.h b/src/gui/entry/EntryModel.h
index e8c90f7e4f..3e9f2824ab 100644
--- a/src/gui/entry/EntryModel.h
+++ b/src/gui/entry/EntryModel.h
@@ -61,13 +61,9 @@ class EntryModel : public QAbstractTableModel
QMimeData* mimeData(const QModelIndexList& indexes) const override;
void setEntryList(const QList& entries);
-
+ void setPaperClipPixmap(const QPixmap& paperclip);
bool isUsernamesHidden() const;
- void setUsernamesHidden(const bool hide);
bool isPasswordsHidden() const;
- void setPasswordsHidden(const bool hide);
-
- void setPaperClipPixmap(const QPixmap& paperclip);
signals:
void switchedToListMode();
@@ -77,8 +73,8 @@ class EntryModel : public QAbstractTableModel
public slots:
void setGroup(Group* group);
- void toggleUsernamesHidden(const bool hide);
- void togglePasswordsHidden(const bool hide);
+ void setUsernamesHidden(bool hide);
+ void setPasswordsHidden(bool hide);
private slots:
void entryAboutToAdd(Entry* entry);
diff --git a/src/gui/entry/EntryView.cpp b/src/gui/entry/EntryView.cpp
index 86ef027325..472aeffc8a 100644
--- a/src/gui/entry/EntryView.cpp
+++ b/src/gui/entry/EntryView.cpp
@@ -62,9 +62,9 @@ EntryView::EntryView(QWidget* parent)
m_headerMenu->setTitle(tr("Customize View"));
m_headerMenu->addSection(tr("Customize View"));
- m_hideUsernamesAction = m_headerMenu->addAction(tr("Hide Usernames"), m_model, SLOT(toggleUsernamesHidden(bool)));
+ m_hideUsernamesAction = m_headerMenu->addAction(tr("Hide Usernames"), m_model, SLOT(setUsernamesHidden(bool)));
m_hideUsernamesAction->setCheckable(true);
- m_hidePasswordsAction = m_headerMenu->addAction(tr("Hide Passwords"), m_model, SLOT(togglePasswordsHidden(bool)));
+ m_hidePasswordsAction = m_headerMenu->addAction(tr("Hide Passwords"), m_model, SLOT(setPasswordsHidden(bool)));
m_hidePasswordsAction->setCheckable(true);
m_headerMenu->addSeparator();
@@ -274,6 +274,11 @@ bool EntryView::isUsernamesHidden() const
*/
void EntryView::setUsernamesHidden(const bool hide)
{
+ bool block = m_hideUsernamesAction->signalsBlocked();
+ m_hideUsernamesAction->blockSignals(true);
+ m_hideUsernamesAction->setChecked(hide);
+ m_hideUsernamesAction->blockSignals(block);
+
m_model->setUsernamesHidden(hide);
}
@@ -291,6 +296,11 @@ bool EntryView::isPasswordsHidden() const
*/
void EntryView::setPasswordsHidden(const bool hide)
{
+ bool block = m_hidePasswordsAction->signalsBlocked();
+ m_hidePasswordsAction->blockSignals(true);
+ m_hidePasswordsAction->setChecked(hide);
+ m_hidePasswordsAction->blockSignals(block);
+
m_model->setPasswordsHidden(hide);
}
diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp
index 986d01ab29..719e4afc85 100644
--- a/tests/gui/TestGui.cpp
+++ b/tests/gui/TestGui.cpp
@@ -755,6 +755,7 @@ void TestGui::testTotp()
auto* setupTotpButtonBox = setupTotpDialog->findChild("buttonBox");
QTest::mouseClick(setupTotpButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton);
+ clickIndex(item, entryView, Qt::LeftButton);
auto* entryEditAction = m_mainWindow->findChild("actionEntryEdit");
QWidget* entryEditWidget = toolBar->widgetForAction(entryEditAction);
QTest::mouseClick(entryEditWidget, Qt::LeftButton);