Fix: address #12631

This commit is contained in:
Jess Sullivan 2026-01-19 08:58:32 -05:00
parent 5bd42c4725
commit c74fcc8fc2
No known key found for this signature in database
GPG key ID: D34D0D8F65EE5C88
3 changed files with 74 additions and 0 deletions

View file

@ -596,6 +596,11 @@ void DatabaseWidget::expireSelectedEntries()
void DatabaseWidget::deleteSelectedEntries()
{
// Prevent deletion when a modal dialog (e.g., file save dialog) is active
if (QApplication::activeModalWidget()) {
return;
}
const QModelIndexList selected = m_entryView->selectionModel()->selectedRows();
if (selected.isEmpty()) {
return;
@ -1115,6 +1120,11 @@ void DatabaseWidget::cloneGroup()
void DatabaseWidget::deleteGroup()
{
// Prevent deletion when a modal dialog is active
if (QApplication::activeModalWidget()) {
return;
}
Group* currentGroup = m_groupView->currentGroup();
Q_ASSERT(currentGroup && canDeleteCurrentGroup());
if (!currentGroup || !canDeleteCurrentGroup()) {

View file

@ -21,6 +21,7 @@
#include <QCheckBox>
#include <QClipboard>
#include <QDialog>
#include <QListWidget>
#include <QMenu>
#include <QMenuBar>
@ -2464,6 +2465,68 @@ void TestGui::testMenuActionStates()
QVERIFY(isActionEnabled("actionPasswordGenerator"));
}
void TestGui::testDeleteEntryDuringModalDialog()
{
// Delete key in native file dialogs on macOS
// should not delete password entries
// Add canned entries for consistent testing
addCannedEntries();
auto* entryView = m_dbWidget->findChild<EntryView*>("entryView");
auto* entryDeleteAction = m_mainWindow->findChild<QAction*>("actionEntryDelete");
// Count initial entries
int initialEntryCount = entryView->model()->rowCount();
QVERIFY(initialEntryCount > 0);
// Select the first entry
clickIndex(entryView->model()->index(0, 1), entryView, Qt::LeftButton);
entryView->setFocus();
QApplication::processEvents();
// Create and show a modal dialog to simulate the file save dialog
QDialog modalDialog(m_mainWindow.data());
modalDialog.setModal(true);
// Use a timer to trigger the delete action while modal dialog is shown
bool deleteTriggered = false;
QTimer::singleShot(50, [&]() {
// Verify modal dialog is active
QVERIFY(QApplication::activeModalWidget() == &modalDialog);
// Trigger delete action while modal is open
entryDeleteAction->trigger();
deleteTriggered = true;
// Close the modal dialog
modalDialog.accept();
});
// Show modal dialog (blocks until closed)
modalDialog.exec();
QVERIFY(deleteTriggered);
QApplication::processEvents();
// Verify entry count unchanged - delete should have been blocked
QCOMPARE(entryView->model()->rowCount(), initialEntryCount);
// Now verify normal deletion still works after modal closes
clickIndex(entryView->model()->index(0, 1), entryView, Qt::LeftButton);
entryView->setFocus();
QApplication::processEvents();
if (!config()->get(Config::Security_NoConfirmMoveEntryToRecycleBin).toBool()) {
MessageBox::setNextAnswer(MessageBox::Move);
}
entryDeleteAction->trigger();
QApplication::processEvents();
// Verify entry was deleted normally
QCOMPARE(entryView->model()->rowCount(), initialEntryCount - 1);
}
void TestGui::addCannedEntries()
{
// Find buttons

View file

@ -71,6 +71,7 @@ private slots:
void testTrayRestoreHide();
void testShortcutConfig();
void testMenuActionStates();
void testDeleteEntryDuringModalDialog();
private:
void addCannedEntries();