From bc57985e2c5d6ce499a22ded7ca6033de850f29d Mon Sep 17 00:00:00 2001
From: mattesony <49170923+mattesony@users.noreply.github.com>
Date: Tue, 1 Nov 2022 19:08:46 -0700
Subject: [PATCH 1/7] Expire now option
---
src/gui/entry/EditEntryWidget.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp
index 9af9aa6014..ec9b894650 100644
--- a/src/gui/entry/EditEntryWidget.cpp
+++ b/src/gui/entry/EditEntryWidget.cpp
@@ -1678,6 +1678,7 @@ void EditEntryWidget::deleteAllHistoryEntries()
QMenu* EditEntryWidget::createPresetsMenu()
{
auto* expirePresetsMenu = new QMenu(this);
+ expirePresetsMenu->addAction(tr("Now"))->setData(QVariant::fromValue(TimeDelta(0,0,0,0)));
expirePresetsMenu->addAction(tr("%n hour(s)", nullptr, 12))->setData(QVariant::fromValue(TimeDelta::fromHours(12)));
expirePresetsMenu->addAction(tr("%n hour(s)", nullptr, 24))->setData(QVariant::fromValue(TimeDelta::fromHours(24)));
expirePresetsMenu->addSeparator();
From b60c02b600f9175135c15b440b998ad93b762212 Mon Sep 17 00:00:00 2001
From: mattesony <49170923+mattesony@users.noreply.github.com>
Date: Tue, 1 Nov 2022 22:39:17 -0700
Subject: [PATCH 2/7] Added expire entry option
---
share/translations/keepassxc_en.ts | 63 ++++++++++++++-----
src/gui/DatabaseWidget.cpp | 25 ++++++++
src/gui/DatabaseWidget.h | 2 +
src/gui/GuiTools.cpp | 14 +++++
src/gui/GuiTools.h | 1 +
src/gui/MainWindow.cpp | 7 ++-
src/gui/MainWindow.ui | 10 +++
src/gui/entry/EditEntryWidget.cpp | 2 +-
.../ReportsWidgetBrowserStatistics.cpp | 29 +++++++++
.../reports/ReportsWidgetBrowserStatistics.h | 2 +
src/gui/reports/ReportsWidgetHealthcheck.cpp | 23 ++++++-
src/gui/reports/ReportsWidgetHealthcheck.h | 2 +
src/gui/reports/ReportsWidgetHibp.cpp | 20 +++++-
src/gui/reports/ReportsWidgetHibp.h | 2 +
14 files changed, 181 insertions(+), 21 deletions(-)
diff --git a/share/translations/keepassxc_en.ts b/share/translations/keepassxc_en.ts
index bc9e17f226..e8ea3f0059 100644
--- a/share/translations/keepassxc_en.ts
+++ b/share/translations/keepassxc_en.ts
@@ -2919,6 +2919,10 @@ Would you like to correct it?
+
+
+
+
@@ -5950,6 +5954,14 @@ Expect some bugs and minor issues, this version is meant for testing purposes.
+
+
+
+
+
+
+
+
@@ -6054,6 +6066,10 @@ Expect some bugs and minor issues, this version is meant for testing purposes.
+
+
+
+
@@ -6199,25 +6215,17 @@ Expect some bugs and minor issues, this version is meant for testing purposes.
-
+
-
+
-
-
-
-
-
-
-
-
@@ -9281,6 +9289,13 @@ This option is deprecated, use --set-key-file instead.
+
+
+
+
+
+
+
@@ -9307,6 +9322,14 @@ This option is deprecated, use --set-key-file instead.
ReportsWidgetHealthcheck
+
+
+
+
+
+
+
+
@@ -9370,18 +9393,17 @@ This option is deprecated, use --set-key-file instead.
-
-
-
+
+
+
+
+
+
-
-
-
-
ReportsWidgetHibp
@@ -9480,6 +9502,13 @@ This option is deprecated, use --set-key-file instead.
+
+
+
+
+
+
+
ReportsWidgetPasskeys
diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp
index b651b52850..ed9d5a8981 100644
--- a/src/gui/DatabaseWidget.cpp
+++ b/src/gui/DatabaseWidget.cpp
@@ -569,6 +569,22 @@ void DatabaseWidget::setupTotp()
setupTotpDialog->open();
}
+void DatabaseWidget::expireSelectedEntries()
+{
+ const QModelIndexList selected = m_entryView->selectionModel()->selectedRows();
+ if (selected.isEmpty()) {
+ return;
+ }
+
+ // Resolve entries from the selection model
+ QList selectedEntries;
+ for (const QModelIndex& index : selected) {
+ selectedEntries.append(m_entryView->entryFromIndex(index));
+ }
+
+ expireEntries(std::move(selectedEntries));
+}
+
void DatabaseWidget::deleteSelectedEntries()
{
const QModelIndexList selected = m_entryView->selectionModel()->selectedRows();
@@ -605,6 +621,15 @@ void DatabaseWidget::restoreSelectedEntries()
}
}
+void DatabaseWidget::expireEntries(QList selectedEntries)
+{
+ if (selectedEntries.isEmpty()) {
+ return;
+ }
+
+ GuiTools::expireEntries(this, selectedEntries);
+}
+
void DatabaseWidget::deleteEntries(QList selectedEntries, bool confirm)
{
if (selectedEntries.isEmpty()) {
diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h
index 5ef8709259..7b6a267b81 100644
--- a/src/gui/DatabaseWidget.h
+++ b/src/gui/DatabaseWidget.h
@@ -180,8 +180,10 @@ public slots:
void replaceDatabase(QSharedPointer db);
void createEntry();
void cloneEntry();
+ void expireSelectedEntries();
void deleteSelectedEntries();
void restoreSelectedEntries();
+ void expireEntries(QList entries);
void deleteEntries(QList entries, bool confirm = true);
void focusOnEntries(bool editIfFocused = false);
void focusOnGroups(bool editIfFocused = false);
diff --git a/src/gui/GuiTools.cpp b/src/gui/GuiTools.cpp
index b2dfa63f3a..1c6437b595 100644
--- a/src/gui/GuiTools.cpp
+++ b/src/gui/GuiTools.cpp
@@ -17,6 +17,7 @@
#include "GuiTools.h"
+#include "core/Clock.h"
#include "core/Config.h"
#include "core/Group.h"
#include "gui/MessageBox.h"
@@ -81,6 +82,19 @@ namespace GuiTools
return answer == MessageBox::Delete;
}
+ size_t expireEntries(QWidget* parent, const QList& entries)
+ {
+ if (!parent || entries.isEmpty()) {
+ return 0;
+ }
+
+ for (auto entry : asConst(entries)) {
+ entry->setExpiryTime(Clock::currentDateTimeUtc());
+ entry->setExpires(true);
+ }
+ return entries.size();
+ }
+
size_t deleteEntriesResolveReferences(QWidget* parent, const QList& entries, bool permanent)
{
if (!parent || entries.isEmpty()) {
diff --git a/src/gui/GuiTools.h b/src/gui/GuiTools.h
index c5e7108964..133f6a0370 100644
--- a/src/gui/GuiTools.h
+++ b/src/gui/GuiTools.h
@@ -27,6 +27,7 @@ namespace GuiTools
{
bool confirmDeleteEntries(QWidget* parent, const QList& entries, bool permanent);
bool confirmDeletePluginData(QWidget* parent, const QList& entries);
+ size_t expireEntries(QWidget* parent, const QList& entries);
size_t deleteEntriesResolveReferences(QWidget* parent, const QList& entries, bool permanent);
} // namespace GuiTools
#endif // KEEPASSXC_GUITOOLS_H
diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp
index 3191b45aa1..3a19f06683 100644
--- a/src/gui/MainWindow.cpp
+++ b/src/gui/MainWindow.cpp
@@ -144,6 +144,7 @@ MainWindow::MainWindow()
m_entryContextMenu->addSeparator();
#endif
m_entryContextMenu->addAction(m_ui->actionEntryEdit);
+ m_entryContextMenu->addAction(m_ui->actionEntryExpire);
m_entryContextMenu->addAction(m_ui->actionEntryClone);
m_entryContextMenu->addAction(m_ui->actionEntryDelete);
m_entryContextMenu->addAction(m_ui->actionEntryNew);
@@ -276,6 +277,7 @@ MainWindow::MainWindow()
// Unfortunately, Qt::AA_DontShowShortcutsInContextMenus is broken, have to manually enable them
m_ui->actionEntryNew->setShortcutVisibleInContextMenu(true);
m_ui->actionEntryEdit->setShortcutVisibleInContextMenu(true);
+ m_ui->actionEntryExpire->setShortcutVisibleInContextMenu(true);
m_ui->actionEntryDelete->setShortcutVisibleInContextMenu(true);
m_ui->actionEntryRestore->setShortcutVisibleInContextMenu(true);
m_ui->actionEntryClone->setShortcutVisibleInContextMenu(true);
@@ -372,6 +374,7 @@ MainWindow::MainWindow()
m_ui->actionEntryNew->setIcon(icons()->icon("entry-new"));
m_ui->actionEntryClone->setIcon(icons()->icon("entry-clone"));
m_ui->actionEntryEdit->setIcon(icons()->icon("entry-edit"));
+ m_ui->actionEntryExpire->setIcon(icons()->icon("entry-expire"));
m_ui->actionEntryDelete->setIcon(icons()->icon("entry-delete"));
m_ui->actionEntryRestore->setIcon(icons()->icon("entry-restore"));
m_ui->actionEntryAutoType->setIcon(icons()->icon("auto-type"));
@@ -489,8 +492,9 @@ MainWindow::MainWindow()
connect(m_ui->actionQuit, SIGNAL(triggered()), SLOT(appExit()));
m_actionMultiplexer.connect(m_ui->actionEntryNew, SIGNAL(triggered()), SLOT(createEntry()));
- m_actionMultiplexer.connect(m_ui->actionEntryClone, SIGNAL(triggered()), SLOT(cloneEntry()));
m_actionMultiplexer.connect(m_ui->actionEntryEdit, SIGNAL(triggered()), SLOT(switchToEntryEdit()));
+ m_actionMultiplexer.connect(m_ui->actionEntryExpire, SIGNAL(triggered()), SLOT(expireSelectedEntries()));
+ m_actionMultiplexer.connect(m_ui->actionEntryClone, SIGNAL(triggered()), SLOT(cloneEntry()));
m_actionMultiplexer.connect(m_ui->actionEntryDelete, SIGNAL(triggered()), SLOT(deleteSelectedEntries()));
m_actionMultiplexer.connect(m_ui->actionEntryRestore, SIGNAL(triggered()), SLOT(restoreSelectedEntries()));
@@ -912,6 +916,7 @@ void MainWindow::updateMenuActionState()
m_ui->actionEntryNew->setEnabled(inDatabase && !inRecycleBin);
m_ui->actionEntryClone->setEnabled(singleEntrySelected && !inRecycleBin);
m_ui->actionEntryEdit->setEnabled(singleEntrySelected);
+ m_ui->actionEntryExpire->setEnabled(multiEntrySelected);
m_ui->actionEntryDelete->setEnabled(multiEntrySelected);
m_ui->actionEntryRestore->setVisible(multiEntrySelected && inRecycleBin);
m_ui->actionEntryRestore->setEnabled(multiEntrySelected && inRecycleBin);
diff --git a/src/gui/MainWindow.ui b/src/gui/MainWindow.ui
index 1110b64262..292ab3aa0b 100644
--- a/src/gui/MainWindow.ui
+++ b/src/gui/MainWindow.ui
@@ -321,6 +321,7 @@
+
@@ -429,6 +430,7 @@
+
@@ -544,6 +546,14 @@
Ctrl+E
+
+
+ false
+
+
+ &Expire Entry…
+
+
&Delete Entry…
diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp
index ec9b894650..2a843759db 100644
--- a/src/gui/entry/EditEntryWidget.cpp
+++ b/src/gui/entry/EditEntryWidget.cpp
@@ -1678,7 +1678,7 @@ void EditEntryWidget::deleteAllHistoryEntries()
QMenu* EditEntryWidget::createPresetsMenu()
{
auto* expirePresetsMenu = new QMenu(this);
- expirePresetsMenu->addAction(tr("Now"))->setData(QVariant::fromValue(TimeDelta(0,0,0,0)));
+ expirePresetsMenu->addAction(tr("Now"))->setData(QVariant::fromValue(TimeDelta(0, 0, 0, 0)));
expirePresetsMenu->addAction(tr("%n hour(s)", nullptr, 12))->setData(QVariant::fromValue(TimeDelta::fromHours(12)));
expirePresetsMenu->addAction(tr("%n hour(s)", nullptr, 24))->setData(QVariant::fromValue(TimeDelta::fromHours(24)));
expirePresetsMenu->addSeparator();
diff --git a/src/gui/reports/ReportsWidgetBrowserStatistics.cpp b/src/gui/reports/ReportsWidgetBrowserStatistics.cpp
index 579840a24d..6d00ac769d 100644
--- a/src/gui/reports/ReportsWidgetBrowserStatistics.cpp
+++ b/src/gui/reports/ReportsWidgetBrowserStatistics.cpp
@@ -275,6 +275,11 @@ void ReportsWidgetBrowserStatistics::customMenuRequested(QPoint pos)
});
}
+ // Create the "expire entry" menu item
+ const auto expEntry = new QAction(icons()->icon("entry-expire"), tr("Expire Entry(s)…", "", selected.size()), this);
+ menu->addAction(expEntry);
+ connect(expEntry, &QAction::triggered, this, &ReportsWidgetBrowserStatistics::expireSelectedEntries);
+
// Create the "delete entry" menu item
const auto deleteEntry =
new QAction(icons()->icon("entry-delete"), tr("Delete Entry(s)…", "", selected.size()), this);
@@ -327,6 +332,30 @@ void ReportsWidgetBrowserStatistics::saveSettings()
// Nothing to do - the tab is passive
}
+QList ReportsWidgetBrowserStatistics::getSelectedEntries()
+{
+ QList selectedEntries;
+ for (auto index : m_ui->browserStatisticsTableView->selectionModel()->selectedRows()) {
+ auto row = m_modelProxy->mapToSource(index).row();
+ auto entry = m_rowToEntry[row].second;
+ if (entry) {
+ selectedEntries << entry;
+ }
+ }
+ return selectedEntries;
+}
+
+void ReportsWidgetBrowserStatistics::expireSelectedEntries()
+{
+ QList selectedEntries = getSelectedEntries();
+ if (selectedEntries.isEmpty()) {
+ return;
+ }
+ GuiTools::expireEntries(this, selectedEntries);
+
+ calculateBrowserStatistics();
+}
+
void ReportsWidgetBrowserStatistics::deleteSelectedEntries()
{
const auto& selectedEntries = getSelectedEntries();
diff --git a/src/gui/reports/ReportsWidgetBrowserStatistics.h b/src/gui/reports/ReportsWidgetBrowserStatistics.h
index 9de20086f9..9b1cc7d602 100644
--- a/src/gui/reports/ReportsWidgetBrowserStatistics.h
+++ b/src/gui/reports/ReportsWidgetBrowserStatistics.h
@@ -53,6 +53,8 @@ public slots:
void calculateBrowserStatistics();
void emitEntryActivated(const QModelIndex& index);
void customMenuRequested(QPoint);
+ QList getSelectedEntries();
+ void expireSelectedEntries();
void deleteSelectedEntries();
void deletePluginDataFromSelectedEntries();
diff --git a/src/gui/reports/ReportsWidgetHealthcheck.cpp b/src/gui/reports/ReportsWidgetHealthcheck.cpp
index a50fd1d7db..b7043934b8 100644
--- a/src/gui/reports/ReportsWidgetHealthcheck.cpp
+++ b/src/gui/reports/ReportsWidgetHealthcheck.cpp
@@ -323,6 +323,11 @@ void ReportsWidgetHealthcheck::customMenuRequested(QPoint pos)
});
}
+ // Create the "Expire entry" menu item
+ const auto expEntry = new QAction(tr("Expire Entry(s)…", "", selected.size()), this);
+ menu->addAction(expEntry);
+ connect(expEntry, &QAction::triggered, this, &ReportsWidgetHealthcheck::expireSelectedEntries);
+
// Create the "delete entry" menu item
const auto delEntry = new QAction(icons()->icon("entry-delete"), tr("Delete Entry(s)…", "", selected.size()), this);
menu->addAction(delEntry);
@@ -365,7 +370,7 @@ void ReportsWidgetHealthcheck::saveSettings()
// nothing to do - the tab is passive
}
-void ReportsWidgetHealthcheck::deleteSelectedEntries()
+QList ReportsWidgetHealthcheck::getSelectedEntries()
{
QList selectedEntries;
for (auto index : m_ui->healthcheckTableView->selectionModel()->selectedRows()) {
@@ -375,7 +380,23 @@ void ReportsWidgetHealthcheck::deleteSelectedEntries()
selectedEntries << entry;
}
}
+ return selectedEntries;
+}
+
+void ReportsWidgetHealthcheck::expireSelectedEntries()
+{
+ QList selectedEntries = getSelectedEntries();
+ if (selectedEntries.isEmpty()) {
+ return;
+ }
+ GuiTools::expireEntries(this, selectedEntries);
+
+ calculateHealth();
+}
+void ReportsWidgetHealthcheck::deleteSelectedEntries()
+{
+ QList selectedEntries = getSelectedEntries();
bool permanent = !m_db->metadata()->recycleBinEnabled();
if (GuiTools::confirmDeleteEntries(this, selectedEntries, permanent)) {
GuiTools::deleteEntriesResolveReferences(this, selectedEntries, permanent);
diff --git a/src/gui/reports/ReportsWidgetHealthcheck.h b/src/gui/reports/ReportsWidgetHealthcheck.h
index 21d121b00b..9a46b36b1f 100644
--- a/src/gui/reports/ReportsWidgetHealthcheck.h
+++ b/src/gui/reports/ReportsWidgetHealthcheck.h
@@ -53,6 +53,8 @@ public slots:
void calculateHealth();
void emitEntryActivated(const QModelIndex& index);
void customMenuRequested(QPoint);
+ QList getSelectedEntries();
+ void expireSelectedEntries();
void deleteSelectedEntries();
private:
diff --git a/src/gui/reports/ReportsWidgetHibp.cpp b/src/gui/reports/ReportsWidgetHibp.cpp
index 201b1010f0..0f4dd1dd24 100644
--- a/src/gui/reports/ReportsWidgetHibp.cpp
+++ b/src/gui/reports/ReportsWidgetHibp.cpp
@@ -374,6 +374,11 @@ void ReportsWidgetHibp::customMenuRequested(QPoint pos)
});
}
+ // Create the "Expire entry" menu item
+ const auto expEntry = new QAction(tr("Expire Entry(s)…", "", selected.size()), this);
+ menu->addAction(expEntry);
+ connect(expEntry, &QAction::triggered, this, &ReportsWidgetHibp::expireSelectedEntries);
+
// Create the "delete entry" menu item
const auto delEntry = new QAction(icons()->icon("entry-delete"), tr("Delete Entry(s)…", "", selected.size()), this);
menu->addAction(delEntry);
@@ -411,7 +416,7 @@ void ReportsWidgetHibp::customMenuRequested(QPoint pos)
menu->popup(m_ui->hibpTableView->viewport()->mapToGlobal(pos));
}
-void ReportsWidgetHibp::deleteSelectedEntries()
+QList ReportsWidgetHibp::getSelectedEntries()
{
QList selectedEntries;
for (auto index : m_ui->hibpTableView->selectionModel()->selectedRows()) {
@@ -421,7 +426,20 @@ void ReportsWidgetHibp::deleteSelectedEntries()
selectedEntries << entry;
}
}
+ return selectedEntries;
+}
+
+void ReportsWidgetHibp::expireSelectedEntries()
+{
+ QList selectedEntries = getSelectedEntries();
+ GuiTools::expireEntries(this, selectedEntries);
+ makeHibpTable();
+}
+
+void ReportsWidgetHibp::deleteSelectedEntries()
+{
+ QList selectedEntries = getSelectedEntries();
bool permanent = !m_db->metadata()->recycleBinEnabled();
if (GuiTools::confirmDeleteEntries(this, selectedEntries, permanent)) {
GuiTools::deleteEntriesResolveReferences(this, selectedEntries, permanent);
diff --git a/src/gui/reports/ReportsWidgetHibp.h b/src/gui/reports/ReportsWidgetHibp.h
index 29a2c4ff1f..8e0d5e47bc 100644
--- a/src/gui/reports/ReportsWidgetHibp.h
+++ b/src/gui/reports/ReportsWidgetHibp.h
@@ -58,6 +58,8 @@ public slots:
void fetchFailed(const QString& error);
void makeHibpTable();
void customMenuRequested(QPoint);
+ QList getSelectedEntries();
+ void expireSelectedEntries();
void deleteSelectedEntries();
private:
From f397cc27b414900bc860f4f8e92df36c59ce5f94 Mon Sep 17 00:00:00 2001
From: mattesony <49170923+mattesony@users.noreply.github.com>
Date: Tue, 1 Nov 2022 23:23:29 -0700
Subject: [PATCH 3/7] Added icon for expire action
---
COPYING | 3 +-
.../scalable/actions/entry-expire.svg | 51 +++++++++++++++++++
share/icons/icons.qrc | 1 +
src/gui/reports/ReportsWidgetHealthcheck.cpp | 2 +-
src/gui/reports/ReportsWidgetHibp.cpp | 2 +-
5 files changed, 56 insertions(+), 3 deletions(-)
create mode 100644 share/icons/application/scalable/actions/entry-expire.svg
diff --git a/COPYING b/COPYING
index ed03b77f82..a5bbc01858 100644
--- a/COPYING
+++ b/COPYING
@@ -131,7 +131,8 @@ Copyright: none
License: CC0
Comment: Taken from https://github.com/paomedia/small-n-flat
-Files: share/icons/badges/2_Expired.svg
+Files: share/icons/application/scalable/actions/entry-expire.svg
+ share/icons/badges/2_Expired.svg
share/icons/database/C37_KPercentage.svg
share/icons/database/C45_Cancel.svg
share/icons/database/C46_Help.svg
diff --git a/share/icons/application/scalable/actions/entry-expire.svg b/share/icons/application/scalable/actions/entry-expire.svg
new file mode 100644
index 0000000000..0a3a1f1ec6
--- /dev/null
+++ b/share/icons/application/scalable/actions/entry-expire.svg
@@ -0,0 +1,51 @@
+
+
diff --git a/share/icons/icons.qrc b/share/icons/icons.qrc
index a5f86b28d1..e92c98a351 100644
--- a/share/icons/icons.qrc
+++ b/share/icons/icons.qrc
@@ -40,6 +40,7 @@
application/scalable/actions/edit-clear-locationbar-rtl.svg
application/scalable/actions/entry-clone.svg
application/scalable/actions/entry-delete.svg
+ application/scalable/actions/entry-expire.svg
application/scalable/actions/entry-restore.svg
application/scalable/actions/entry-edit.svg
application/scalable/actions/entry-new.svg
diff --git a/src/gui/reports/ReportsWidgetHealthcheck.cpp b/src/gui/reports/ReportsWidgetHealthcheck.cpp
index b7043934b8..7baffe25e2 100644
--- a/src/gui/reports/ReportsWidgetHealthcheck.cpp
+++ b/src/gui/reports/ReportsWidgetHealthcheck.cpp
@@ -324,7 +324,7 @@ void ReportsWidgetHealthcheck::customMenuRequested(QPoint pos)
}
// Create the "Expire entry" menu item
- const auto expEntry = new QAction(tr("Expire Entry(s)…", "", selected.size()), this);
+ const auto expEntry = new QAction(icons()->icon("entry-expire"), tr("Expire Entry(s)…", "", selected.size()), this);
menu->addAction(expEntry);
connect(expEntry, &QAction::triggered, this, &ReportsWidgetHealthcheck::expireSelectedEntries);
diff --git a/src/gui/reports/ReportsWidgetHibp.cpp b/src/gui/reports/ReportsWidgetHibp.cpp
index 0f4dd1dd24..9fa7e9b6c8 100644
--- a/src/gui/reports/ReportsWidgetHibp.cpp
+++ b/src/gui/reports/ReportsWidgetHibp.cpp
@@ -375,7 +375,7 @@ void ReportsWidgetHibp::customMenuRequested(QPoint pos)
}
// Create the "Expire entry" menu item
- const auto expEntry = new QAction(tr("Expire Entry(s)…", "", selected.size()), this);
+ const auto expEntry = new QAction(icons()->icon("entry-expire"), tr("Expire Entry(s)…", "", selected.size()), this);
menu->addAction(expEntry);
connect(expEntry, &QAction::triggered, this, &ReportsWidgetHibp::expireSelectedEntries);
From e4ed9bccbb7530aadb972de0e1e52e2bd96d38cc Mon Sep 17 00:00:00 2001
From: mattesony <49170923+mattesony@users.noreply.github.com>
Date: Wed, 2 Nov 2022 14:39:58 -0700
Subject: [PATCH 4/7] Changed expire icon to timer-alert-outline
---
COPYING | 4 +-
.../scalable/actions/entry-expire.svg | 52 +------------------
2 files changed, 3 insertions(+), 53 deletions(-)
diff --git a/COPYING b/COPYING
index a5bbc01858..4e85fc078d 100644
--- a/COPYING
+++ b/COPYING
@@ -131,8 +131,7 @@ Copyright: none
License: CC0
Comment: Taken from https://github.com/paomedia/small-n-flat
-Files: share/icons/application/scalable/actions/entry-expire.svg
- share/icons/badges/2_Expired.svg
+Files: share/icons/badges/2_Expired.svg
share/icons/database/C37_KPercentage.svg
share/icons/database/C45_Cancel.svg
share/icons/database/C46_Help.svg
@@ -179,6 +178,7 @@ Files: share/icons/application/scalable/actions/application-exit.svg
share/icons/application/scalable/actions/entry-delete.svg
share/icons/application/scalable/actions/entry-restore.svg
share/icons/application/scalable/actions/entry-edit.svg
+ share/icons/application/scalable/actions/entry-expire.svg
share/icons/application/scalable/actions/entry-new.svg
share/icons/application/scalable/actions/favicon-download.svg
share/icons/application/scalable/actions/fingerprint.svg
diff --git a/share/icons/application/scalable/actions/entry-expire.svg b/share/icons/application/scalable/actions/entry-expire.svg
index 0a3a1f1ec6..a0a9ad53bf 100644
--- a/share/icons/application/scalable/actions/entry-expire.svg
+++ b/share/icons/application/scalable/actions/entry-expire.svg
@@ -1,51 +1 @@
-
-
+
\ No newline at end of file
From 7338b501e97871634263ab1837658d84cb408a52 Mon Sep 17 00:00:00 2001
From: mattesony <49170923+mattesony@users.noreply.github.com>
Date: Wed, 2 Nov 2022 15:33:41 -0700
Subject: [PATCH 5/7] Revert "Expire now option"
This reverts commit 30c0842ac939033dff68ca69ff2e14b7e98bb294.
---
src/gui/entry/EditEntryWidget.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp
index 2a843759db..9af9aa6014 100644
--- a/src/gui/entry/EditEntryWidget.cpp
+++ b/src/gui/entry/EditEntryWidget.cpp
@@ -1678,7 +1678,6 @@ void EditEntryWidget::deleteAllHistoryEntries()
QMenu* EditEntryWidget::createPresetsMenu()
{
auto* expirePresetsMenu = new QMenu(this);
- expirePresetsMenu->addAction(tr("Now"))->setData(QVariant::fromValue(TimeDelta(0, 0, 0, 0)));
expirePresetsMenu->addAction(tr("%n hour(s)", nullptr, 12))->setData(QVariant::fromValue(TimeDelta::fromHours(12)));
expirePresetsMenu->addAction(tr("%n hour(s)", nullptr, 24))->setData(QVariant::fromValue(TimeDelta::fromHours(24)));
expirePresetsMenu->addSeparator();
From 5860e3ef58a89e77d3b4e7f1754360e162faf630 Mon Sep 17 00:00:00 2001
From: mattesony <49170923+mattesony@users.noreply.github.com>
Date: Wed, 2 Nov 2022 15:43:20 -0700
Subject: [PATCH 6/7] Update translations after removing Now preset
---
share/translations/keepassxc_en.ts | 4 ----
1 file changed, 4 deletions(-)
diff --git a/share/translations/keepassxc_en.ts b/share/translations/keepassxc_en.ts
index e8ea3f0059..11612309d9 100644
--- a/share/translations/keepassxc_en.ts
+++ b/share/translations/keepassxc_en.ts
@@ -2919,10 +2919,6 @@ Would you like to correct it?
-
-
-
-
From 43915ec670e4fad9aa1253a69ab9c212fb16d5a5 Mon Sep 17 00:00:00 2001
From: Jonathan White
Date: Sat, 11 Jan 2025 23:42:14 -0500
Subject: [PATCH 7/7] Code cleanup
---
share/translations/keepassxc_en.ts | 8 +++----
src/core/Entry.cpp | 6 +++++
src/core/Entry.h | 1 +
src/gui/DatabaseWidget.cpp | 24 ++++---------------
src/gui/DatabaseWidget.h | 1 -
src/gui/GuiTools.cpp | 14 -----------
src/gui/GuiTools.h | 1 -
src/gui/MainWindow.ui | 3 +--
.../ReportsWidgetBrowserStatistics.cpp | 6 ++---
src/gui/reports/ReportsWidgetHealthcheck.cpp | 6 ++---
src/gui/reports/ReportsWidgetHibp.cpp | 5 ++--
11 files changed, 24 insertions(+), 51 deletions(-)
diff --git a/share/translations/keepassxc_en.ts b/share/translations/keepassxc_en.ts
index 11612309d9..ed4effabc9 100644
--- a/share/translations/keepassxc_en.ts
+++ b/share/translations/keepassxc_en.ts
@@ -5950,10 +5950,6 @@ Expect some bugs and minor issues, this version is meant for testing purposes.
-
-
-
-
@@ -6226,6 +6222,10 @@ Expect some bugs and minor issues, this version is meant for testing purposes.
+
+
+
+
ManageDatabase
diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp
index 9587e8d67e..1acf663818 100644
--- a/src/core/Entry.cpp
+++ b/src/core/Entry.cpp
@@ -460,6 +460,12 @@ bool Entry::willExpireInDays(int days) const
return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < Clock::currentDateTime().addDays(days);
}
+void Entry::expireNow()
+{
+ setExpiryTime(Clock::currentDateTimeUtc());
+ setExpires(true);
+}
+
bool Entry::isRecycled() const
{
const Database* db = database();
diff --git a/src/core/Entry.h b/src/core/Entry.h
index 749a9fe542..3fb3fbcbbc 100644
--- a/src/core/Entry.h
+++ b/src/core/Entry.h
@@ -126,6 +126,7 @@ class Entry : public ModifiableObject
bool hasTotp() const;
bool isExpired() const;
bool willExpireInDays(int days) const;
+ void expireNow();
bool isRecycled() const;
bool isAttributeReference(const QString& key) const;
bool isAttributeReferenceOf(const QString& key, const QUuid& uuid) const;
diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp
index ed9d5a8981..2b4266c907 100644
--- a/src/gui/DatabaseWidget.cpp
+++ b/src/gui/DatabaseWidget.cpp
@@ -572,17 +572,12 @@ void DatabaseWidget::setupTotp()
void DatabaseWidget::expireSelectedEntries()
{
const QModelIndexList selected = m_entryView->selectionModel()->selectedRows();
- if (selected.isEmpty()) {
- return;
- }
-
- // Resolve entries from the selection model
- QList selectedEntries;
- for (const QModelIndex& index : selected) {
- selectedEntries.append(m_entryView->entryFromIndex(index));
+ for (const auto& index : selected) {
+ auto entry = m_entryView->entryFromIndex(index);
+ if (entry) {
+ entry->expireNow();
+ }
}
-
- expireEntries(std::move(selectedEntries));
}
void DatabaseWidget::deleteSelectedEntries()
@@ -621,15 +616,6 @@ void DatabaseWidget::restoreSelectedEntries()
}
}
-void DatabaseWidget::expireEntries(QList selectedEntries)
-{
- if (selectedEntries.isEmpty()) {
- return;
- }
-
- GuiTools::expireEntries(this, selectedEntries);
-}
-
void DatabaseWidget::deleteEntries(QList selectedEntries, bool confirm)
{
if (selectedEntries.isEmpty()) {
diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h
index 7b6a267b81..1e85dd312c 100644
--- a/src/gui/DatabaseWidget.h
+++ b/src/gui/DatabaseWidget.h
@@ -183,7 +183,6 @@ public slots:
void expireSelectedEntries();
void deleteSelectedEntries();
void restoreSelectedEntries();
- void expireEntries(QList entries);
void deleteEntries(QList entries, bool confirm = true);
void focusOnEntries(bool editIfFocused = false);
void focusOnGroups(bool editIfFocused = false);
diff --git a/src/gui/GuiTools.cpp b/src/gui/GuiTools.cpp
index 1c6437b595..b2dfa63f3a 100644
--- a/src/gui/GuiTools.cpp
+++ b/src/gui/GuiTools.cpp
@@ -17,7 +17,6 @@
#include "GuiTools.h"
-#include "core/Clock.h"
#include "core/Config.h"
#include "core/Group.h"
#include "gui/MessageBox.h"
@@ -82,19 +81,6 @@ namespace GuiTools
return answer == MessageBox::Delete;
}
- size_t expireEntries(QWidget* parent, const QList& entries)
- {
- if (!parent || entries.isEmpty()) {
- return 0;
- }
-
- for (auto entry : asConst(entries)) {
- entry->setExpiryTime(Clock::currentDateTimeUtc());
- entry->setExpires(true);
- }
- return entries.size();
- }
-
size_t deleteEntriesResolveReferences(QWidget* parent, const QList& entries, bool permanent)
{
if (!parent || entries.isEmpty()) {
diff --git a/src/gui/GuiTools.h b/src/gui/GuiTools.h
index 133f6a0370..c5e7108964 100644
--- a/src/gui/GuiTools.h
+++ b/src/gui/GuiTools.h
@@ -27,7 +27,6 @@ namespace GuiTools
{
bool confirmDeleteEntries(QWidget* parent, const QList& entries, bool permanent);
bool confirmDeletePluginData(QWidget* parent, const QList& entries);
- size_t expireEntries(QWidget* parent, const QList& entries);
size_t deleteEntriesResolveReferences(QWidget* parent, const QList& entries, bool permanent);
} // namespace GuiTools
#endif // KEEPASSXC_GUITOOLS_H
diff --git a/src/gui/MainWindow.ui b/src/gui/MainWindow.ui
index 292ab3aa0b..c84727c3e8 100644
--- a/src/gui/MainWindow.ui
+++ b/src/gui/MainWindow.ui
@@ -430,7 +430,6 @@
-
@@ -551,7 +550,7 @@
false
- &Expire Entry…
+ E&xpire Entry…
diff --git a/src/gui/reports/ReportsWidgetBrowserStatistics.cpp b/src/gui/reports/ReportsWidgetBrowserStatistics.cpp
index 6d00ac769d..63267d77fd 100644
--- a/src/gui/reports/ReportsWidgetBrowserStatistics.cpp
+++ b/src/gui/reports/ReportsWidgetBrowserStatistics.cpp
@@ -347,11 +347,9 @@ QList ReportsWidgetBrowserStatistics::getSelectedEntries()
void ReportsWidgetBrowserStatistics::expireSelectedEntries()
{
- QList selectedEntries = getSelectedEntries();
- if (selectedEntries.isEmpty()) {
- return;
+ for (auto entry : getSelectedEntries()) {
+ entry->expireNow();
}
- GuiTools::expireEntries(this, selectedEntries);
calculateBrowserStatistics();
}
diff --git a/src/gui/reports/ReportsWidgetHealthcheck.cpp b/src/gui/reports/ReportsWidgetHealthcheck.cpp
index 7baffe25e2..f6151dda43 100644
--- a/src/gui/reports/ReportsWidgetHealthcheck.cpp
+++ b/src/gui/reports/ReportsWidgetHealthcheck.cpp
@@ -385,11 +385,9 @@ QList ReportsWidgetHealthcheck::getSelectedEntries()
void ReportsWidgetHealthcheck::expireSelectedEntries()
{
- QList selectedEntries = getSelectedEntries();
- if (selectedEntries.isEmpty()) {
- return;
+ for (auto entry : getSelectedEntries()) {
+ entry->expireNow();
}
- GuiTools::expireEntries(this, selectedEntries);
calculateHealth();
}
diff --git a/src/gui/reports/ReportsWidgetHibp.cpp b/src/gui/reports/ReportsWidgetHibp.cpp
index 9fa7e9b6c8..a559208aaa 100644
--- a/src/gui/reports/ReportsWidgetHibp.cpp
+++ b/src/gui/reports/ReportsWidgetHibp.cpp
@@ -431,8 +431,9 @@ QList ReportsWidgetHibp::getSelectedEntries()
void ReportsWidgetHibp::expireSelectedEntries()
{
- QList selectedEntries = getSelectedEntries();
- GuiTools::expireEntries(this, selectedEntries);
+ for (auto entry : getSelectedEntries()) {
+ entry->expireNow();
+ }
makeHibpTable();
}