diff --git a/src/fdosecrets/objects/Service.cpp b/src/fdosecrets/objects/Service.cpp index e3fcefeb5f..b524b1d5fb 100644 --- a/src/fdosecrets/objects/Service.cpp +++ b/src/fdosecrets/objects/Service.cpp @@ -610,6 +610,15 @@ namespace FdoSecrets m_unlockingAnyDatabase = false; m_unlockingDb.remove(dbWidget); } else { + // The database may have been unlocked externally while the unlock dialog + // was open, in which case no future databaseUnlocked signal will arrive. + if (dbWidget && !dbWidget->isLocked()) { + emit doneUnlockDatabaseInDialog(true, dbWidget); + m_unlockingAnyDatabase = false; + m_unlockingDb.remove(dbWidget); + return; + } + // delay the done signal to when the database is actually done with unlocking // this is a oneshot connection to prevent superfluous signals auto conn = connect(dbWidget, &DatabaseWidget::databaseUnlocked, this, [dbWidget, this]() { diff --git a/src/gui/DatabaseOpenDialog.cpp b/src/gui/DatabaseOpenDialog.cpp index db83d35027..906c7d1369 100644 --- a/src/gui/DatabaseOpenDialog.cpp +++ b/src/gui/DatabaseOpenDialog.cpp @@ -196,6 +196,26 @@ QSharedPointer DatabaseOpenDialog::database() const return m_db; } +void DatabaseOpenDialog::completeExternalUnlock(DatabaseWidget* dbWidget) +{ + if (!dbWidget) { + return; + } + + hide(); + + // The database is already unlocked, so do not route this completion back through + // DatabaseWidget::unlockDatabase() and replace the database a second time. + if (m_currentDbWidget) { + disconnect(this, &DatabaseOpenDialog::dialogFinished, m_currentDbWidget, nullptr); + } + + emit dialogFinished(true, dbWidget); + clearForms(); + + QDialog::done(QDialog::Accepted); +} + void DatabaseOpenDialog::done(int result) { hide(); diff --git a/src/gui/DatabaseOpenDialog.h b/src/gui/DatabaseOpenDialog.h index ba6fcb4e81..5f26782889 100644 --- a/src/gui/DatabaseOpenDialog.h +++ b/src/gui/DatabaseOpenDialog.h @@ -52,6 +52,7 @@ class DatabaseOpenDialog : public QDialog Intent intent() const; QSharedPointer database() const; void clearForms(); + void completeExternalUnlock(DatabaseWidget* dbWidget); void showMessage(const QString& text, MessageWidget::MessageType type, int autoHideTimeout); signals: diff --git a/src/gui/DatabaseTabWidget.cpp b/src/gui/DatabaseTabWidget.cpp index 82a1468218..2b70018cfd 100644 --- a/src/gui/DatabaseTabWidget.cpp +++ b/src/gui/DatabaseTabWidget.cpp @@ -760,6 +760,12 @@ void DatabaseTabWidget::unlockDatabaseInDialog(DatabaseWidget* dbWidget, const QString& filePath) { m_databaseOpenDialog->clearForms(); + + // Keep the requested targets outside the dialog because the dialog can be + // cleared while an external unlock is still in progress. + m_databaseOpenDialogTargets.clear(); + m_databaseOpenDialogTargets.append(dbWidget); + m_databaseOpenDialog->setIntent(intent); m_databaseOpenDialog->setTarget(dbWidget, filePath); displayUnlockDialog(); @@ -774,13 +780,15 @@ void DatabaseTabWidget::unlockDatabaseInDialog(DatabaseWidget* dbWidget, void DatabaseTabWidget::unlockAnyDatabaseInDialog(DatabaseOpenDialog::Intent intent) { m_databaseOpenDialog->clearForms(); + m_databaseOpenDialogTargets.clear(); m_databaseOpenDialog->setIntent(intent); - // add a tab to the dialog for each open unlocked database + // add a tab to the dialog for each open locked database for (int i = 0, c = count(); i < c; ++i) { auto* dbWidget = databaseWidgetFromIndex(i); if (dbWidget && dbWidget->isLocked()) { m_databaseOpenDialog->addDatabaseTab(dbWidget); + m_databaseOpenDialogTargets.append(dbWidget); } } // default to the current tab @@ -836,6 +844,7 @@ void DatabaseTabWidget::handleDatabaseUnlockDialogFinished(bool accepted, Databa // signal other objects that the dialog finished emit databaseUnlockDialogFinished(accepted, dbWidget); + m_databaseOpenDialogTargets.clear(); } /** @@ -904,9 +913,18 @@ void DatabaseTabWidget::emitDatabaseLockChanged() } else { emit databaseUnlocked(dbWidget); m_databaseOpenInProgress = false; + + if (m_databaseOpenDialog->isVisible() && isDatabaseOpenDialogTarget(dbWidget)) { + m_databaseOpenDialog->completeExternalUnlock(dbWidget); + } } } +bool DatabaseTabWidget::isDatabaseOpenDialogTarget(DatabaseWidget* dbWidget) const +{ + return dbWidget && m_databaseOpenDialogTargets.contains(dbWidget); +} + void DatabaseTabWidget::performGlobalAutoType(const QString& search) { auto currentDbWidget = currentDatabaseWidget(); diff --git a/src/gui/DatabaseTabWidget.h b/src/gui/DatabaseTabWidget.h index 5f71fb4d77..5d63d9fb9d 100644 --- a/src/gui/DatabaseTabWidget.h +++ b/src/gui/DatabaseTabWidget.h @@ -120,10 +120,12 @@ private slots: void updateLastDatabases(const QSharedPointer& database); bool warnOnExport(); void displayUnlockDialog(); + bool isDatabaseOpenDialogTarget(DatabaseWidget* dbWidget) const; QPointer m_dbWidgetStateSync; QPointer m_dbWidgetPendingLock; QPointer m_databaseOpenDialog; + QList> m_databaseOpenDialogTargets; QPointer m_importWizard; QTimer m_lockDelayTimer; bool m_databaseOpenInProgress;