diff --git a/share/translations/keepassxc_en.ts b/share/translations/keepassxc_en.ts
index 945527b29..99b1eef2b 100644
--- a/share/translations/keepassxc_en.ts
+++ b/share/translations/keepassxc_en.ts
@@ -460,6 +460,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ApplicationSettingsWidgetSecurity
@@ -2385,6 +2401,14 @@ Disable safe saves and try again?
+
+
+
+
+
+
+
+
EditEntryWidget
diff --git a/src/core/Config.cpp b/src/core/Config.cpp
index 0b6be5e4e..0b7d67e67 100644
--- a/src/core/Config.cpp
+++ b/src/core/Config.cpp
@@ -111,6 +111,8 @@ static const QHash configStrings = {
{Config::GUI_CheckForUpdates, {QS("GUI/CheckForUpdates"), Roaming, true}},
{Config::GUI_CheckForUpdatesNextCheck, {QS("GUI/CheckForUpdatesNextCheck"), Local, 0}},
{Config::GUI_CheckForUpdatesIncludeBetas, {QS("GUI/CheckForUpdatesIncludeBetas"), Roaming, false}},
+ {Config::GUI_ShowExpiredEntriesOnDatabaseUnlock, {QS("GUI/ShowExpiredEntriesOnDatabaseUnlock"), Roaming, true}},
+ {Config::GUI_ShowExpiredEntriesOnDatabaseUnlockOffsetDays, {QS("GUI/ShowExpiredEntriesOnDatabaseUnlockOffsetDays"), Roaming, 3}},
{Config::GUI_MainWindowGeometry, {QS("GUI/MainWindowGeometry"), Local, {}}},
{Config::GUI_MainWindowState, {QS("GUI/MainWindowState"), Local, {}}},
diff --git a/src/core/Config.h b/src/core/Config.h
index 19f684293..24da06bad 100644
--- a/src/core/Config.h
+++ b/src/core/Config.h
@@ -91,6 +91,8 @@ public:
GUI_CompactMode,
GUI_CheckForUpdates,
GUI_CheckForUpdatesIncludeBetas,
+ GUI_ShowExpiredEntriesOnDatabaseUnlock,
+ GUI_ShowExpiredEntriesOnDatabaseUnlockOffsetDays,
GUI_MainWindowGeometry,
GUI_MainWindowState,
diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp
index c90760765..6feb2624c 100644
--- a/src/core/Entry.cpp
+++ b/src/core/Entry.cpp
@@ -441,7 +441,12 @@ int Entry::size() const
bool Entry::isExpired() const
{
- return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < Clock::currentDateTimeUtc();
+ return willExpireInDays(0);
+}
+
+bool Entry::willExpireInDays(int days) const
+{
+ return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < Clock::currentDateTime().addDays(days);
}
bool Entry::isRecycled() const
diff --git a/src/core/Entry.h b/src/core/Entry.h
index edfedc705..6984a9845 100644
--- a/src/core/Entry.h
+++ b/src/core/Entry.h
@@ -121,6 +121,7 @@ public:
bool hasTotp() const;
bool isExpired() const;
+ bool willExpireInDays(int days) const;
bool isRecycled() const;
bool isAttributeReference(const QString& key) const;
bool isAttributeReferenceOf(const QString& key, const QUuid& uuid) const;
diff --git a/src/gui/ApplicationSettingsWidget.cpp b/src/gui/ApplicationSettingsWidget.cpp
index ac96d23b4..61a3cc0f5 100644
--- a/src/gui/ApplicationSettingsWidget.cpp
+++ b/src/gui/ApplicationSettingsWidget.cpp
@@ -120,6 +120,8 @@ ApplicationSettingsWidget::ApplicationSettingsWidget(QWidget* parent)
connect(m_generalUi->backupBeforeSaveCheckBox, SIGNAL(toggled(bool)),
m_generalUi->backupFilePathPicker, SLOT(setEnabled(bool)));
connect(m_generalUi->backupFilePathPicker, SIGNAL(pressed()), SLOT(selectBackupDirectory()));
+ connect(m_generalUi->showExpiredEntriesOnDatabaseUnlockCheckBox, SIGNAL(toggled(bool)),
+ SLOT(showExpiredEntriesOnDatabaseUnlockToggled(bool)));
connect(m_secUi->clearClipboardCheckBox, SIGNAL(toggled(bool)),
m_secUi->clearClipboardSpinBox, SLOT(setEnabled(bool)));
@@ -251,6 +253,12 @@ void ApplicationSettingsWidget::loadSettings()
m_generalUi->checkForUpdatesIncludeBetasCheckBox->setChecked(
config()->get(Config::GUI_CheckForUpdatesIncludeBetas).toBool());
+ m_generalUi->showExpiredEntriesOnDatabaseUnlockCheckBox->setChecked(
+ config()->get(Config::GUI_ShowExpiredEntriesOnDatabaseUnlock).toBool());
+ m_generalUi->showExpiredEntriesOnDatabaseUnlockOffsetSpinBox->setValue(
+ config()->get(Config::GUI_ShowExpiredEntriesOnDatabaseUnlockOffsetDays).toInt());
+ showExpiredEntriesOnDatabaseUnlockToggled(m_generalUi->showExpiredEntriesOnDatabaseUnlockCheckBox->isChecked());
+
m_generalUi->autoTypeAskCheckBox->setChecked(config()->get(Config::Security_AutoTypeAsk).toBool());
if (autoType()->isAvailable()) {
@@ -378,6 +386,11 @@ void ApplicationSettingsWidget::saveSettings()
config()->set(Config::GUI_CheckForUpdatesIncludeBetas,
m_generalUi->checkForUpdatesIncludeBetasCheckBox->isChecked());
+ config()->set(Config::GUI_ShowExpiredEntriesOnDatabaseUnlock,
+ m_generalUi->showExpiredEntriesOnDatabaseUnlockCheckBox->isChecked());
+ config()->set(Config::GUI_ShowExpiredEntriesOnDatabaseUnlockOffsetDays,
+ m_generalUi->showExpiredEntriesOnDatabaseUnlockOffsetSpinBox->value());
+
config()->set(Config::Security_AutoTypeAsk, m_generalUi->autoTypeAskCheckBox->isChecked());
if (autoType()->isAvailable()) {
@@ -520,6 +533,11 @@ void ApplicationSettingsWidget::checkUpdatesToggled(bool checked)
m_generalUi->checkForUpdatesIncludeBetasCheckBox->setEnabled(checked);
}
+void ApplicationSettingsWidget::showExpiredEntriesOnDatabaseUnlockToggled(bool checked)
+{
+ m_generalUi->showExpiredEntriesOnDatabaseUnlockOffsetSpinBox->setEnabled(checked);
+}
+
void ApplicationSettingsWidget::selectBackupDirectory()
{
auto backupDirectory =
diff --git a/src/gui/ApplicationSettingsWidget.h b/src/gui/ApplicationSettingsWidget.h
index c5f2ed7e3..15fc5a344 100644
--- a/src/gui/ApplicationSettingsWidget.h
+++ b/src/gui/ApplicationSettingsWidget.h
@@ -62,6 +62,7 @@ private slots:
void systrayToggled(bool checked);
void rememberDatabasesToggled(bool checked);
void checkUpdatesToggled(bool checked);
+ void showExpiredEntriesOnDatabaseUnlockToggled(bool checked);
void selectBackupDirectory();
private:
diff --git a/src/gui/ApplicationSettingsWidgetGeneral.ui b/src/gui/ApplicationSettingsWidgetGeneral.ui
index e4abc647b..f0404b215 100644
--- a/src/gui/ApplicationSettingsWidgetGeneral.ui
+++ b/src/gui/ApplicationSettingsWidgetGeneral.ui
@@ -234,6 +234,73 @@
+ -
+
+
+ QLayout::SetMaximumSize
+
+
+ 6
+
+
-
+
+
+ On database unlock, show entries that
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+ Qt::StrongFocus
+
+
+ On database unlock, show entries that
+
+
+ will expire within
+
+
+ days
+
+
+ 0
+
+
+ 30
+
+
+ 0
+
+
+ are expired
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
@@ -1138,6 +1205,8 @@
rememberLastKeyFilesCheckBox
checkForUpdatesOnStartupCheckBox
checkForUpdatesIncludeBetasCheckBox
+ showExpiredEntriesOnDatabaseUnlockCheckBox
+ showExpiredEntriesOnDatabaseUnlockOffsetSpinBox
autoSaveAfterEveryChangeCheckBox
autoSaveOnExitCheckBox
autoSaveNonDataChangesCheckBox
diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp
index b97aaf973..c974c1c9b 100644
--- a/src/gui/DatabaseWidget.cpp
+++ b/src/gui/DatabaseWidget.cpp
@@ -1119,7 +1119,29 @@ void DatabaseWidget::loadDatabase(bool accepted)
replaceDatabase(openWidget->database());
switchToMainView();
processAutoOpen();
+
restoreGroupEntryFocus(m_groupBeforeLock, m_entryBeforeLock);
+
+ // Only show expired entries if first unlock and option is enabled
+ if (m_groupBeforeLock.isNull() && config()->get(Config::GUI_ShowExpiredEntriesOnDatabaseUnlock).toBool()) {
+ int expirationOffset = config()->get(Config::GUI_ShowExpiredEntriesOnDatabaseUnlockOffsetDays).toInt();
+ QList expiredEntries;
+ for (auto entry : m_db->rootGroup()->entriesRecursive()) {
+ if (entry->willExpireInDays(expirationOffset) && !entry->excludeFromReports() && !entry->isRecycled()) {
+ expiredEntries << entry;
+ }
+ }
+
+ if (!expiredEntries.isEmpty()) {
+ m_entryView->displaySearch(expiredEntries);
+ m_entryView->setFirstEntryActive();
+ m_searchingLabel->setText(expirationOffset == 0
+ ? tr("Expired entries")
+ : tr("Entries expiring within %1 days").arg(expirationOffset));
+ m_searchingLabel->setVisible(true);
+ }
+ }
+
m_groupBeforeLock = QUuid();
m_entryBeforeLock = QUuid();
m_saveAttempts = 0;