Use ReportsWidgetBase for browser statistics

This commit is contained in:
Agoston Szepessy 2025-12-29 02:44:56 -08:00
parent d7cb5b1374
commit bcac630a9f
7 changed files with 42 additions and 188 deletions

View file

@ -18,8 +18,8 @@
#ifndef KEEPASSXC_PROXYMODELS_H
#define KEEPASSXC_PROXYMODELS_H
#include <QSortFilterProxyModel>
#include <QModelIndex>
#include <QSortFilterProxyModel>
enum class SortProxyModelKind
{
@ -32,7 +32,9 @@ class HibpReportSortPoxyModel : public QSortFilterProxyModel
{
public:
HibpReportSortPoxyModel(QObject* parent)
: QSortFilterProxyModel(parent){}
: QSortFilterProxyModel(parent)
{
}
~HibpReportSortPoxyModel() override = default;
protected:
@ -40,8 +42,7 @@ protected:
{
// Sort count column by user data
if (left.column() == 2) {
return sourceModel()->data(left, Qt::UserRole).toInt()
< sourceModel()->data(right, Qt::UserRole).toInt();
return sourceModel()->data(left, Qt::UserRole).toInt() < sourceModel()->data(right, Qt::UserRole).toInt();
}
// Otherwise use default sorting
return QSortFilterProxyModel::lessThan(left, right);
@ -52,7 +53,9 @@ class HealthcheckReportSortProxyModel : public QSortFilterProxyModel
{
public:
HealthcheckReportSortProxyModel(QObject* parent)
: QSortFilterProxyModel(parent){}
: QSortFilterProxyModel(parent)
{
}
~HealthcheckReportSortProxyModel() override = default;
protected:

View file

@ -184,6 +184,19 @@ QMenu *ReportsWidgetBase::customMenuRequestedBase()
return menu;
}
QList<Entry*> ReportsWidgetBase::getSelectedEntries() const
{
QList<Entry*> selectedEntries;
for (auto index : getTableView()->selectionModel()->selectedRows()) {
auto row = m_modelProxy->mapToSource(index).row();
auto entry = m_rowToEntry[row].second;
if (entry) {
selectedEntries << entry;
}
}
return selectedEntries;
}
QList<Entry*> ReportsWidgetBase::getSelectedEntries()
{
QList<Entry*> selectedEntries;

View file

@ -44,9 +44,11 @@ public:
virtual ~ReportsWidgetBase();
protected:
virtual QTableView *getTableView() = 0;
virtual QTableView *getTableView() const = 0;
virtual void updateWidget() = 0;
QMenu *customMenuRequestedBase();
QList<Entry*> getSelectedEntries() const;
public slots:
QList<Entry*> getSelectedEntries();

View file

@ -93,10 +93,8 @@ BrowserStatistics::BrowserStatistics(QSharedPointer<Database> db)
}
ReportsWidgetBrowserStatistics::ReportsWidgetBrowserStatistics(QWidget* parent)
: QWidget(parent)
: ReportsWidgetBase(parent, SortProxyModelKind::Default)
, m_ui(new Ui::ReportsWidgetBrowserStatistics())
, m_referencesModel(new QStandardItemModel(this))
, m_modelProxy(new QSortFilterProxyModel(this))
{
m_ui->setupUi(this);
@ -265,35 +263,13 @@ void ReportsWidgetBrowserStatistics::emitEntryActivated(const QModelIndex& index
void ReportsWidgetBrowserStatistics::customMenuRequested(QPoint pos)
{
auto selected = m_ui->browserStatisticsTableView->selectionModel()->selectedRows();
if (selected.isEmpty()) {
auto menu = customMenuRequestedBase();
if(!menu) {
return;
}
// Create the context menu
const auto menu = new QMenu(this);
// Create the "edit entry" menu item (only if 1 row is selected)
if (selected.size() == 1) {
const auto edit = new QAction(icons()->icon("entry-edit"), tr("Edit Entry…"), this);
menu->addAction(edit);
connect(edit, &QAction::triggered, edit, [this, selected] {
auto row = m_modelProxy->mapToSource(selected[0]).row();
auto entry = m_rowToEntry[row].second;
emit entryActivated(entry);
});
}
// 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);
menu->addAction(deleteEntry);
connect(deleteEntry, &QAction::triggered, this, &ReportsWidgetBrowserStatistics::deleteSelectedEntries);
auto selected = getTableView()->selectionModel()->selectedRows();
// Create the "delete plugin data" menu item
const auto deletePluginData =
@ -304,99 +280,6 @@ void ReportsWidgetBrowserStatistics::customMenuRequested(QPoint pos)
this,
&ReportsWidgetBrowserStatistics::deletePluginDataFromSelectedEntries);
// Create the "exclude from reports" menu item
const auto excludeAction = new QAction(icons()->icon("reports-exclude"), tr("Exclude Entry(s) from reports"), this);
const auto excludeGroupsAction =
new QAction(icons()->icon("reports-exclude"), tr("Exclude Group(s) from reports"), this);
bool isExcluded = false;
bool isGroupExcluded = false;
for (auto index : selected) {
auto row = m_modelProxy->mapToSource(index).row();
auto entry = m_rowToEntry[row].second;
if (entry) {
// If at least one entry is excluded switch to inclusion
if (entry->excludeFromReports() || entry->group()->excludeFromReports()) {
isExcluded = true;
}
if (entry->group()->excludeFromReports()) {
isGroupExcluded = true;
}
break;
}
}
excludeAction->setCheckable(true);
excludeAction->setChecked(isExcluded);
excludeGroupsAction->setCheckable(true);
excludeGroupsAction->setChecked(isGroupExcluded);
menu->addAction(excludeAction);
connect(excludeAction, &QAction::toggled, excludeAction, [this, selected](bool checked) {
QSet<Group*> groups;
// If we are including entries (checked is false) but a group is excluded, ask the user if they
// would like to include the rest of the group as well (or keep it excluded).
// If they exclude it, we need to include the whole group, and then exclude
// the entries that aren't selected here.
if (!checked) {
for (const auto index : selected) {
auto row = m_modelProxy->mapToSource(index).row();
auto entry = m_rowToEntry[row].second;
if (entry) {
auto* group = entry->group();
if (group->excludeFromReports() && !groups.contains(group)) {
QString msg = tr("The Group for \"%1\" is excluded. Would you like to include all Entries from "
"there as well?")
.arg(entry->title());
auto response = MessageBox::question(this,
tr("Include Group?"),
msg,
MessageBox::Yes | MessageBox::No | MessageBox::Cancel,
MessageBox::No);
if (response == MessageBox::Cancel) {
return;
} else if (response == MessageBox::Yes) {
group->setExcludeFromReports(false);
} else if (response == MessageBox::No) {
// We'll exclude all entries from the group here and then
// include the selected ones below
group->setExcludeFromReports(false);
group->markAllEntriesExcludedFromReports();
}
groups.insert(group);
}
}
}
}
for (auto index : selected) {
auto row = m_modelProxy->mapToSource(index).row();
auto entry = m_rowToEntry[row].second;
if (entry) {
entry->setExcludeFromReports(checked);
}
}
calculateBrowserStatistics();
});
menu->addAction(excludeGroupsAction);
connect(excludeGroupsAction, &QAction::toggled, excludeGroupsAction, [this, selected](bool checked) {
for (const auto index : selected) {
auto row = m_modelProxy->mapToSource(index).row();
auto entry = m_rowToEntry[row].second;
if (entry) {
entry->group()->setExcludeFromReports(checked);
}
}
calculateBrowserStatistics();
});
// Show the context menu
menu->popup(m_ui->browserStatisticsTableView->viewport()->mapToGlobal(pos));
}
@ -406,40 +289,6 @@ void ReportsWidgetBrowserStatistics::saveSettings()
// Nothing to do - the tab is passive
}
QList<Entry*> ReportsWidgetBrowserStatistics::getSelectedEntries()
{
QList<Entry*> 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()
{
for (auto entry : getSelectedEntries()) {
entry->expireNow();
}
calculateBrowserStatistics();
}
void ReportsWidgetBrowserStatistics::deleteSelectedEntries()
{
const auto& selectedEntries = getSelectedEntries();
bool permanent = !m_db->metadata()->recycleBinEnabled();
if (GuiTools::confirmDeleteEntries(this, selectedEntries, permanent)) {
GuiTools::deleteEntriesResolveReferences(this, selectedEntries, permanent);
}
calculateBrowserStatistics();
}
void ReportsWidgetBrowserStatistics::deletePluginDataFromSelectedEntries()
{
const auto& selectedEntries = getSelectedEntries();
@ -488,16 +337,12 @@ QMap<QString, QStringList> ReportsWidgetBrowserStatistics::getBrowserConfigFromE
return configList;
}
QList<Entry*> ReportsWidgetBrowserStatistics::getSelectedEntries() const
QTableView *ReportsWidgetBrowserStatistics::getTableView() const
{
QList<Entry*> 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;
return m_ui->browserStatisticsTableView;
}
void ReportsWidgetBrowserStatistics::updateWidget()
{
calculateBrowserStatistics();
}

View file

@ -19,6 +19,7 @@
#define KEEPASSXC_REPORTSWIDGETBROWSERSTATISTICS_H
#include "gui/entry/EntryModel.h"
#include "gui/reports/ReportsWidgetBase.h"
#include <QWidget>
class Database;
@ -33,7 +34,7 @@ namespace Ui
class ReportsWidgetBrowserStatistics;
}
class ReportsWidgetBrowserStatistics : public QWidget
class ReportsWidgetBrowserStatistics : public ReportsWidgetBase
{
Q_OBJECT
public:
@ -45,6 +46,8 @@ public:
protected:
void showEvent(QShowEvent* event) override;
void updateWidget() override;
QTableView *getTableView() const override;
signals:
void entryActivated(Entry*);
@ -53,23 +56,15 @@ public slots:
void calculateBrowserStatistics();
void emitEntryActivated(const QModelIndex& index);
void customMenuRequested(QPoint);
QList<Entry*> getSelectedEntries();
void expireSelectedEntries();
void deleteSelectedEntries();
void deletePluginDataFromSelectedEntries();
private:
void addStatisticsRow(bool hasUrls, bool hasSettings, Group*, Entry*, bool);
QList<Entry*> getSelectedEntries() const;
QMap<QString, QStringList> getBrowserConfigFromEntry(Entry* entry) const;
QScopedPointer<Ui::ReportsWidgetBrowserStatistics> m_ui;
bool m_statisticsCalculated = false;
QScopedPointer<QStandardItemModel> m_referencesModel;
QScopedPointer<QSortFilterProxyModel> m_modelProxy;
QSharedPointer<Database> m_db;
QList<QPair<Group*, Entry*>> m_rowToEntry;
};
#endif // KEEPASSXC_REPORTSWIDGETBROWSERSTATISTICS_H

View file

@ -343,7 +343,7 @@ void ReportsWidgetHealthcheck::updateWidget()
calculateHealth();
}
QTableView *ReportsWidgetHealthcheck::getTableView()
QTableView *ReportsWidgetHealthcheck::getTableView() const
{
return m_ui->healthcheckTableView;
}

View file

@ -48,7 +48,7 @@ public:
protected:
void showEvent(QShowEvent* event) override;
void updateWidget() override;
QTableView *getTableView() override;
QTableView *getTableView() const override;
signals:
void entryActivated(Entry*);
@ -65,10 +65,6 @@ private:
QScopedPointer<Ui::ReportsWidgetHealthcheck> m_ui;
bool m_healthCalculated = false;
// QScopedPointer<QStandardItemModel> m_referencesModel;
// QScopedPointer<QSortFilterProxyModel> m_modelProxy;
// QSharedPointer<Database> m_db;
// QList<QPair<Group*, Entry*>> m_rowToEntry;
};
#endif // KEEPASSXC_REPORTSWIDGETHEALTHCHECK_H