mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-02-02 17:44:46 -05:00
Add support for Browser statistics (#7197)
Co-authored-by: Jonathan White <support@dmapps.us>
This commit is contained in:
parent
15d1b2f0ab
commit
cd642e7fee
@ -7731,6 +7731,10 @@ Please consider generating a new key file.</source>
|
|||||||
<numerusform></numerusform>
|
<numerusform></numerusform>
|
||||||
</translation>
|
</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Browser Statistics</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>QtIOCompressor</name>
|
<name>QtIOCompressor</name>
|
||||||
@ -7766,6 +7770,88 @@ Please consider generating a new key file.</source>
|
|||||||
<translation>Internal zlib error: </translation>
|
<translation>Internal zlib error: </translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>ReportsWidgetBrowserStatistics</name>
|
||||||
|
<message>
|
||||||
|
<source>Exclude expired entries from the report</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Show only entries which have URL set</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Show only entries which have browser settings in custom data</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Double-click entries to edit.</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>List of entry URLs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Entry has no URLs set</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Allowed URLs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Entry has no Browser Integration settings</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Denied URLs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source> (Excluded)</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>This entry is being excluded from reports</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Please wait, browser statistics is being calculated…</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>No entries with a URL, or none has browser extension settings saved.</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>URLs</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Title</source>
|
||||||
|
<translation type="unfinished">Title</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Path</source>
|
||||||
|
<translation type="unfinished">Path</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Edit Entry…</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message numerus="yes">
|
||||||
|
<source>Delete Entry(s)…</source>
|
||||||
|
<translation type="unfinished">
|
||||||
|
<numerusform></numerusform>
|
||||||
|
<numerusform></numerusform>
|
||||||
|
</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Exclude from reports</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>ReportsWidgetHealthcheck</name>
|
<name>ReportsWidgetHealthcheck</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -242,6 +242,8 @@ if(WITH_XC_BROWSER)
|
|||||||
set(keepassxcbrowser_LIB keepassxcbrowser)
|
set(keepassxcbrowser_LIB keepassxcbrowser)
|
||||||
set(keepassx_SOURCES ${keepassx_SOURCES} gui/dbsettings/DatabaseSettingsWidgetBrowser.cpp)
|
set(keepassx_SOURCES ${keepassx_SOURCES} gui/dbsettings/DatabaseSettingsWidgetBrowser.cpp)
|
||||||
set(keepassx_SOURCES ${keepassx_SOURCES} gui/entry/EntryURLModel.cpp)
|
set(keepassx_SOURCES ${keepassx_SOURCES} gui/entry/EntryURLModel.cpp)
|
||||||
|
set(keepassx_SOURCES ${keepassx_SOURCES} gui/reports/ReportsWidgetBrowserStatistics.cpp)
|
||||||
|
set(keepassx_SOURCES ${keepassx_SOURCES} gui/reports/ReportsPageBrowserStatistics.cpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(autotype)
|
add_subdirectory(autotype)
|
||||||
|
@ -355,6 +355,26 @@ QString Entry::url() const
|
|||||||
return m_attributes->value(EntryAttributes::URLKey);
|
return m_attributes->value(EntryAttributes::URLKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList Entry::getAllUrls() const
|
||||||
|
{
|
||||||
|
QStringList urlList;
|
||||||
|
|
||||||
|
if (!url().isEmpty()) {
|
||||||
|
urlList << url();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& key : m_attributes->keys()) {
|
||||||
|
if (key.startsWith("KP2A_URL")) {
|
||||||
|
auto additionalUrl = m_attributes->value(key);
|
||||||
|
if (!additionalUrl.isEmpty()) {
|
||||||
|
urlList << additionalUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return urlList;
|
||||||
|
}
|
||||||
|
|
||||||
QString Entry::webUrl() const
|
QString Entry::webUrl() const
|
||||||
{
|
{
|
||||||
QString url = resolveMultiplePlaceholders(m_attributes->value(EntryAttributes::URLKey));
|
QString url = resolveMultiplePlaceholders(m_attributes->value(EntryAttributes::URLKey));
|
||||||
|
@ -98,6 +98,7 @@ public:
|
|||||||
const AutoTypeAssociations* autoTypeAssociations() const;
|
const AutoTypeAssociations* autoTypeAssociations() const;
|
||||||
QString title() const;
|
QString title() const;
|
||||||
QString url() const;
|
QString url() const;
|
||||||
|
QStringList getAllUrls() const;
|
||||||
QString webUrl() const;
|
QString webUrl() const;
|
||||||
QString displayUrl() const;
|
QString displayUrl() const;
|
||||||
QString username() const;
|
QString username() const;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
|
* Copyright (C) 2021 KeePassXC Team <team@keepassxc.org>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -21,6 +21,10 @@
|
|||||||
#include "ReportsPageHealthcheck.h"
|
#include "ReportsPageHealthcheck.h"
|
||||||
#include "ReportsPageHibp.h"
|
#include "ReportsPageHibp.h"
|
||||||
#include "ReportsPageStatistics.h"
|
#include "ReportsPageStatistics.h"
|
||||||
|
#ifdef WITH_XC_BROWSER
|
||||||
|
#include "ReportsPageBrowserStatistics.h"
|
||||||
|
#include "ReportsWidgetBrowserStatistics.h"
|
||||||
|
#endif
|
||||||
#include "ReportsWidgetHealthcheck.h"
|
#include "ReportsWidgetHealthcheck.h"
|
||||||
#include "ReportsWidgetHibp.h"
|
#include "ReportsWidgetHibp.h"
|
||||||
|
|
||||||
@ -58,14 +62,20 @@ ReportsDialog::ReportsDialog(QWidget* parent)
|
|||||||
, m_healthPage(new ReportsPageHealthcheck())
|
, m_healthPage(new ReportsPageHealthcheck())
|
||||||
, m_hibpPage(new ReportsPageHibp())
|
, m_hibpPage(new ReportsPageHibp())
|
||||||
, m_statPage(new ReportsPageStatistics())
|
, m_statPage(new ReportsPageStatistics())
|
||||||
|
#ifdef WITH_XC_BROWSER
|
||||||
|
, m_browserStatPage(new ReportsPageBrowserStatistics())
|
||||||
|
#endif
|
||||||
, m_editEntryWidget(new EditEntryWidget(this))
|
, m_editEntryWidget(new EditEntryWidget(this))
|
||||||
{
|
{
|
||||||
m_ui->setupUi(this);
|
m_ui->setupUi(this);
|
||||||
|
|
||||||
connect(m_ui->buttonBox, SIGNAL(rejected()), SLOT(reject()));
|
connect(m_ui->buttonBox, SIGNAL(rejected()), SLOT(reject()));
|
||||||
|
addPage(m_statPage);
|
||||||
|
#ifdef WITH_XC_BROWSER
|
||||||
|
addPage(m_browserStatPage);
|
||||||
|
#endif
|
||||||
addPage(m_healthPage);
|
addPage(m_healthPage);
|
||||||
addPage(m_hibpPage);
|
addPage(m_hibpPage);
|
||||||
addPage(m_statPage);
|
|
||||||
|
|
||||||
m_ui->stackedWidget->setCurrentIndex(0);
|
m_ui->stackedWidget->setCurrentIndex(0);
|
||||||
|
|
||||||
@ -77,6 +87,11 @@ ReportsDialog::ReportsDialog(QWidget* parent)
|
|||||||
connect(m_ui->categoryList, SIGNAL(categoryChanged(int)), m_ui->stackedWidget, SLOT(setCurrentIndex(int)));
|
connect(m_ui->categoryList, SIGNAL(categoryChanged(int)), m_ui->stackedWidget, SLOT(setCurrentIndex(int)));
|
||||||
connect(m_healthPage->m_healthWidget, SIGNAL(entryActivated(Entry*)), SLOT(entryActivationSignalReceived(Entry*)));
|
connect(m_healthPage->m_healthWidget, SIGNAL(entryActivated(Entry*)), SLOT(entryActivationSignalReceived(Entry*)));
|
||||||
connect(m_hibpPage->m_hibpWidget, SIGNAL(entryActivated(Entry*)), SLOT(entryActivationSignalReceived(Entry*)));
|
connect(m_hibpPage->m_hibpWidget, SIGNAL(entryActivated(Entry*)), SLOT(entryActivationSignalReceived(Entry*)));
|
||||||
|
#ifdef WITH_XC_BROWSER
|
||||||
|
connect(m_browserStatPage->m_browserWidget,
|
||||||
|
SIGNAL(entryActivated(Entry*)),
|
||||||
|
SLOT(entryActivationSignalReceived(Entry*)));
|
||||||
|
#endif
|
||||||
connect(m_editEntryWidget, SIGNAL(editFinished(bool)), SLOT(switchToMainView(bool)));
|
connect(m_editEntryWidget, SIGNAL(editFinished(bool)), SLOT(switchToMainView(bool)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,6 +157,11 @@ void ReportsDialog::switchToMainView(bool previousDialogAccepted)
|
|||||||
} else if (m_sender == m_hibpPage->m_hibpWidget) {
|
} else if (m_sender == m_hibpPage->m_hibpWidget) {
|
||||||
m_hibpPage->m_hibpWidget->refreshAfterEdit();
|
m_hibpPage->m_hibpWidget->refreshAfterEdit();
|
||||||
}
|
}
|
||||||
|
#ifdef WITH_XC_BROWSER
|
||||||
|
if (m_sender == m_browserStatPage->m_browserWidget) {
|
||||||
|
m_browserStatPage->m_browserWidget->calculateBrowserStatistics();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't process the same sender twice
|
// Don't process the same sender twice
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
|
* Copyright (C) 2021 KeePassXC Team <team@keepassxc.org>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -29,6 +29,9 @@ class QTabWidget;
|
|||||||
class ReportsPageHealthcheck;
|
class ReportsPageHealthcheck;
|
||||||
class ReportsPageHibp;
|
class ReportsPageHibp;
|
||||||
class ReportsPageStatistics;
|
class ReportsPageStatistics;
|
||||||
|
#ifdef WITH_XC_BROWSER
|
||||||
|
class ReportsPageBrowserStatistics;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
{
|
{
|
||||||
@ -74,6 +77,9 @@ private:
|
|||||||
const QSharedPointer<ReportsPageHealthcheck> m_healthPage;
|
const QSharedPointer<ReportsPageHealthcheck> m_healthPage;
|
||||||
const QSharedPointer<ReportsPageHibp> m_hibpPage;
|
const QSharedPointer<ReportsPageHibp> m_hibpPage;
|
||||||
const QSharedPointer<ReportsPageStatistics> m_statPage;
|
const QSharedPointer<ReportsPageStatistics> m_statPage;
|
||||||
|
#ifdef WITH_XC_BROWSER
|
||||||
|
const QSharedPointer<ReportsPageBrowserStatistics> m_browserStatPage;
|
||||||
|
#endif
|
||||||
QPointer<EditEntryWidget> m_editEntryWidget;
|
QPointer<EditEntryWidget> m_editEntryWidget;
|
||||||
QWidget* m_sender = nullptr;
|
QWidget* m_sender = nullptr;
|
||||||
|
|
||||||
|
53
src/gui/reports/ReportsPageBrowserStatistics.cpp
Normal file
53
src/gui/reports/ReportsPageBrowserStatistics.cpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 KeePassXC Team <team@keepassxc.org>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 or (at your option)
|
||||||
|
* version 3 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ReportsPageBrowserStatistics.h"
|
||||||
|
|
||||||
|
#include "ReportsWidgetBrowserStatistics.h"
|
||||||
|
#include "gui/Icons.h"
|
||||||
|
|
||||||
|
ReportsPageBrowserStatistics::ReportsPageBrowserStatistics()
|
||||||
|
: m_browserWidget(new ReportsWidgetBrowserStatistics())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ReportsPageBrowserStatistics::name()
|
||||||
|
{
|
||||||
|
return QObject::tr("Browser Statistics");
|
||||||
|
}
|
||||||
|
|
||||||
|
QIcon ReportsPageBrowserStatistics::icon()
|
||||||
|
{
|
||||||
|
return icons()->icon("internet-web-browser");
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget* ReportsPageBrowserStatistics::createWidget()
|
||||||
|
{
|
||||||
|
return m_browserWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportsPageBrowserStatistics::loadSettings(QWidget* widget, QSharedPointer<Database> db)
|
||||||
|
{
|
||||||
|
const auto settingsWidget = reinterpret_cast<ReportsWidgetBrowserStatistics*>(widget);
|
||||||
|
settingsWidget->loadSettings(db);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportsPageBrowserStatistics::saveSettings(QWidget* widget)
|
||||||
|
{
|
||||||
|
const auto settingsWidget = reinterpret_cast<ReportsWidgetBrowserStatistics*>(widget);
|
||||||
|
settingsWidget->saveSettings();
|
||||||
|
}
|
39
src/gui/reports/ReportsPageBrowserStatistics.h
Normal file
39
src/gui/reports/ReportsPageBrowserStatistics.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 KeePassXC Team <team@keepassxc.org>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 or (at your option)
|
||||||
|
* version 3 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KEEPASSXC_REPORTSPAGEBROWSERSTATISTICS_H
|
||||||
|
#define KEEPASSXC_REPORTSPAGEBROWSERSTATISTICS_H
|
||||||
|
|
||||||
|
#include "ReportsDialog.h"
|
||||||
|
|
||||||
|
class ReportsWidgetBrowserStatistics;
|
||||||
|
|
||||||
|
class ReportsPageBrowserStatistics : public IReportsPage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ReportsWidgetBrowserStatistics* m_browserWidget;
|
||||||
|
|
||||||
|
ReportsPageBrowserStatistics();
|
||||||
|
|
||||||
|
QString name() override;
|
||||||
|
QIcon icon() override;
|
||||||
|
QWidget* createWidget() override;
|
||||||
|
void loadSettings(QWidget* widget, QSharedPointer<Database> db) override;
|
||||||
|
void saveSettings(QWidget* widget) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KEEPASSXC_REPORTSPAGEBROWSERSTATISTICS_H
|
372
src/gui/reports/ReportsWidgetBrowserStatistics.cpp
Normal file
372
src/gui/reports/ReportsWidgetBrowserStatistics.cpp
Normal file
@ -0,0 +1,372 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 KeePassXC Team <team@keepassxc.org>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 or (at your option)
|
||||||
|
* version 3 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ReportsWidgetBrowserStatistics.h"
|
||||||
|
#include "ui_ReportsWidgetBrowserStatistics.h"
|
||||||
|
|
||||||
|
#include "browser/BrowserService.h"
|
||||||
|
#include "core/AsyncTask.h"
|
||||||
|
#include "core/Group.h"
|
||||||
|
#include "core/Metadata.h"
|
||||||
|
#include "gui/GuiTools.h"
|
||||||
|
#include "gui/Icons.h"
|
||||||
|
#include "gui/styles/StateColorPalette.h"
|
||||||
|
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QShortcut>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
#include <QStandardItemModel>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class BrowserStatistics
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct Item
|
||||||
|
{
|
||||||
|
QPointer<Group> group;
|
||||||
|
QPointer<Entry> entry;
|
||||||
|
bool hasUrls;
|
||||||
|
bool hasSettings;
|
||||||
|
bool exclude = false;
|
||||||
|
|
||||||
|
Item(Group* g, Entry* e, bool hU, bool hS)
|
||||||
|
: group(g)
|
||||||
|
, entry(e)
|
||||||
|
, hasUrls(hU)
|
||||||
|
, hasSettings(hS)
|
||||||
|
, exclude(e->excludeFromReports())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit BrowserStatistics(QSharedPointer<Database>);
|
||||||
|
|
||||||
|
const QList<QSharedPointer<Item>>& items() const
|
||||||
|
{
|
||||||
|
return m_items;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSharedPointer<Database> m_db;
|
||||||
|
QList<QSharedPointer<Item>> m_items;
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
BrowserStatistics::BrowserStatistics(QSharedPointer<Database> db)
|
||||||
|
: m_db(db)
|
||||||
|
{
|
||||||
|
for (auto group : db->rootGroup()->groupsRecursive(true)) {
|
||||||
|
// Skip recycle bin
|
||||||
|
if (group->isRecycled()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto entry : group->entries()) {
|
||||||
|
if (entry->isRecycled()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto hasUrls = !entry->getAllUrls().isEmpty();
|
||||||
|
auto hasSettings = entry->customData()->contains(BrowserService::KEEPASSXCBROWSER_NAME);
|
||||||
|
|
||||||
|
const auto item = QSharedPointer<Item>(new Item(group, entry, hasUrls, hasSettings));
|
||||||
|
m_items.append(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReportsWidgetBrowserStatistics::ReportsWidgetBrowserStatistics(QWidget* parent)
|
||||||
|
: QWidget(parent)
|
||||||
|
, m_ui(new Ui::ReportsWidgetBrowserStatistics())
|
||||||
|
, m_referencesModel(new QStandardItemModel(this))
|
||||||
|
, m_modelProxy(new QSortFilterProxyModel(this))
|
||||||
|
{
|
||||||
|
m_ui->setupUi(this);
|
||||||
|
|
||||||
|
m_modelProxy->setSourceModel(m_referencesModel.data());
|
||||||
|
m_modelProxy->setSortLocaleAware(true);
|
||||||
|
m_ui->browserStatisticsTableView->setModel(m_modelProxy.data());
|
||||||
|
m_ui->browserStatisticsTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
|
||||||
|
m_ui->browserStatisticsTableView->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||||
|
|
||||||
|
connect(m_ui->browserStatisticsTableView,
|
||||||
|
SIGNAL(customContextMenuRequested(QPoint)),
|
||||||
|
SLOT(customMenuRequested(QPoint)));
|
||||||
|
connect(
|
||||||
|
m_ui->browserStatisticsTableView, SIGNAL(doubleClicked(QModelIndex)), SLOT(emitEntryActivated(QModelIndex)));
|
||||||
|
connect(m_ui->showEntriesWithUrlOnlyCheckBox, SIGNAL(stateChanged(int)), this, SLOT(calculateBrowserStatistics()));
|
||||||
|
connect(m_ui->showConnectedOnlyCheckBox, SIGNAL(stateChanged(int)), this, SLOT(calculateBrowserStatistics()));
|
||||||
|
connect(m_ui->excludeExpired, SIGNAL(stateChanged(int)), this, SLOT(calculateBrowserStatistics()));
|
||||||
|
|
||||||
|
new QShortcut(Qt::Key_Delete, this, SLOT(deleteSelectedEntries()));
|
||||||
|
}
|
||||||
|
|
||||||
|
ReportsWidgetBrowserStatistics::~ReportsWidgetBrowserStatistics()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportsWidgetBrowserStatistics::addStatisticsRow(bool hasUrls,
|
||||||
|
bool hasSettings,
|
||||||
|
Group* group,
|
||||||
|
Entry* entry,
|
||||||
|
bool excluded)
|
||||||
|
{
|
||||||
|
StateColorPalette statePalette;
|
||||||
|
|
||||||
|
auto urlList = entry->getAllUrls();
|
||||||
|
auto urlToolTip = hasUrls ? tr("List of entry URLs") : tr("Entry has no URLs set");
|
||||||
|
|
||||||
|
auto browserConfig = getBrowserConfigFromEntry(entry);
|
||||||
|
auto allowedUrlsList = browserConfig["Allow"];
|
||||||
|
auto deniedUrlsList = browserConfig["Deny"];
|
||||||
|
|
||||||
|
auto allowedUrlsToolTip = hasSettings ? tr("Allowed URLs") : tr("Entry has no Browser Integration settings");
|
||||||
|
auto deniedUrlsToolTip = hasSettings ? tr("Denied URLs") : tr("Entry has no Browser Integration settings");
|
||||||
|
|
||||||
|
auto title = entry->title();
|
||||||
|
if (excluded) {
|
||||||
|
title.append(tr(" (Excluded)"));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto row = QList<QStandardItem*>();
|
||||||
|
row << new QStandardItem(Icons::entryIconPixmap(entry), title);
|
||||||
|
row << new QStandardItem(Icons::groupIconPixmap(group), group->hierarchy().join("/"));
|
||||||
|
row << new QStandardItem(urlList.join('\n'));
|
||||||
|
row << new QStandardItem(allowedUrlsList.join('\n'));
|
||||||
|
row << new QStandardItem(deniedUrlsList.join('\n'));
|
||||||
|
|
||||||
|
// Set tooltips
|
||||||
|
row[2]->setToolTip(urlToolTip);
|
||||||
|
row[3]->setToolTip(allowedUrlsToolTip);
|
||||||
|
row[4]->setToolTip(deniedUrlsToolTip);
|
||||||
|
if (excluded) {
|
||||||
|
row[0]->setToolTip(tr("This entry is being excluded from reports"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store entry pointer per table row (used in double click handler)
|
||||||
|
m_referencesModel->appendRow(row);
|
||||||
|
m_rowToEntry.append({group, entry});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportsWidgetBrowserStatistics::loadSettings(QSharedPointer<Database> db)
|
||||||
|
{
|
||||||
|
m_db = std::move(db);
|
||||||
|
m_statisticsCalculated = false;
|
||||||
|
m_referencesModel->clear();
|
||||||
|
m_rowToEntry.clear();
|
||||||
|
|
||||||
|
auto row = QList<QStandardItem*>();
|
||||||
|
row << new QStandardItem(tr("Please wait, browser statistics is being calculated…"));
|
||||||
|
m_referencesModel->appendRow(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportsWidgetBrowserStatistics::showEvent(QShowEvent* event)
|
||||||
|
{
|
||||||
|
QWidget::showEvent(event);
|
||||||
|
|
||||||
|
if (!m_statisticsCalculated) {
|
||||||
|
// Perform stats calculation on next event loop to allow widget to appear
|
||||||
|
m_statisticsCalculated = true;
|
||||||
|
QTimer::singleShot(0, this, SLOT(calculateBrowserStatistics()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportsWidgetBrowserStatistics::calculateBrowserStatistics()
|
||||||
|
{
|
||||||
|
m_referencesModel->clear();
|
||||||
|
|
||||||
|
// Perform the statistics check
|
||||||
|
const QScopedPointer<BrowserStatistics> browserStatistics(
|
||||||
|
AsyncTask::runAndWaitForFuture([this] { return new BrowserStatistics(m_db); }));
|
||||||
|
|
||||||
|
const auto showExcluded = m_ui->showConnectedOnlyCheckBox->isChecked();
|
||||||
|
const auto showEntriesWithUrlOnly = m_ui->showEntriesWithUrlOnlyCheckBox->isChecked();
|
||||||
|
const auto showOnlyEntriesWithSettings = m_ui->showConnectedOnlyCheckBox->isChecked();
|
||||||
|
|
||||||
|
// Display the entries
|
||||||
|
m_rowToEntry.clear();
|
||||||
|
for (const auto& item : browserStatistics->items()) {
|
||||||
|
auto excluded = item->exclude || (item->entry->isExpired() && m_ui->excludeExpired->isChecked());
|
||||||
|
if (excluded && !showExcluded) {
|
||||||
|
// Exclude this entry from the report
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exclude this entry if URL are not set
|
||||||
|
if (showEntriesWithUrlOnly && !item->hasUrls) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exclude this entry if it doesn't have any Browser Integration settings
|
||||||
|
if (showOnlyEntriesWithSettings
|
||||||
|
&& !item->entry->customData()->contains(BrowserService::KEEPASSXCBROWSER_NAME)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show the entry in the report
|
||||||
|
addStatisticsRow(item->hasUrls, item->hasSettings, item->group, item->entry, item->exclude);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the table header
|
||||||
|
if (m_referencesModel->rowCount() == 0) {
|
||||||
|
m_referencesModel->setHorizontalHeaderLabels(
|
||||||
|
QStringList() << tr("No entries with a URL, or none has browser extension settings saved."));
|
||||||
|
} else {
|
||||||
|
m_referencesModel->setHorizontalHeaderLabels(QStringList() << tr("Title") << tr("Path") << tr("URLs")
|
||||||
|
<< tr("Allowed URLs") << tr("Denied URLs"));
|
||||||
|
m_ui->browserStatisticsTableView->sortByColumn(0, Qt::AscendingOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ui->browserStatisticsTableView->resizeColumnsToContents();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportsWidgetBrowserStatistics::emitEntryActivated(const QModelIndex& index)
|
||||||
|
{
|
||||||
|
if (!index.isValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto mappedIndex = m_modelProxy->mapToSource(index);
|
||||||
|
const auto row = m_rowToEntry[mappedIndex.row()];
|
||||||
|
const auto group = row.first;
|
||||||
|
const auto entry = row.second;
|
||||||
|
|
||||||
|
if (group && entry) {
|
||||||
|
emit entryActivated(const_cast<Entry*>(entry));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportsWidgetBrowserStatistics::customMenuRequested(QPoint pos)
|
||||||
|
{
|
||||||
|
auto selected = m_ui->browserStatisticsTableView->selectionModel()->selectedRows();
|
||||||
|
if (selected.isEmpty()) {
|
||||||
|
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 "delete entry" menu item
|
||||||
|
const auto delEntry = new QAction(icons()->icon("entry-delete"), tr("Delete Entry(s)…", "", selected.size()), this);
|
||||||
|
menu->addAction(delEntry);
|
||||||
|
connect(delEntry, &QAction::triggered, this, &ReportsWidgetBrowserStatistics::deleteSelectedEntries);
|
||||||
|
|
||||||
|
// Create the "exclude from reports" menu item
|
||||||
|
const auto exclude = new QAction(icons()->icon("reports-exclude"), tr("Exclude from reports"), this);
|
||||||
|
|
||||||
|
bool isExcluded = false;
|
||||||
|
for (auto index : selected) {
|
||||||
|
auto row = m_modelProxy->mapToSource(index).row();
|
||||||
|
auto entry = m_rowToEntry[row].second;
|
||||||
|
if (entry && entry->excludeFromReports()) {
|
||||||
|
// If at least one entry is excluded switch to inclusion
|
||||||
|
isExcluded = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exclude->setCheckable(true);
|
||||||
|
exclude->setChecked(isExcluded);
|
||||||
|
|
||||||
|
menu->addAction(exclude);
|
||||||
|
connect(exclude, &QAction::toggled, exclude, [this, selected](bool state) {
|
||||||
|
for (auto index : selected) {
|
||||||
|
auto row = m_modelProxy->mapToSource(index).row();
|
||||||
|
auto entry = m_rowToEntry[row].second;
|
||||||
|
if (entry) {
|
||||||
|
entry->setExcludeFromReports(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
calculateBrowserStatistics();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Show the context menu
|
||||||
|
menu->popup(m_ui->browserStatisticsTableView->viewport()->mapToGlobal(pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportsWidgetBrowserStatistics::saveSettings()
|
||||||
|
{
|
||||||
|
// Nothing to do - the tab is passive
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportsWidgetBrowserStatistics::deleteSelectedEntries()
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool permanent = !m_db->metadata()->recycleBinEnabled();
|
||||||
|
if (GuiTools::confirmDeleteEntries(this, selectedEntries, permanent)) {
|
||||||
|
GuiTools::deleteEntriesResolveReferences(this, selectedEntries, permanent);
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateBrowserStatistics();
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap<QString, QStringList> ReportsWidgetBrowserStatistics::getBrowserConfigFromEntry(Entry* entry) const
|
||||||
|
{
|
||||||
|
QMap<QString, QStringList> configList;
|
||||||
|
|
||||||
|
auto config = entry->customData()->value(BrowserService::KEEPASSXCBROWSER_NAME);
|
||||||
|
if (!config.isEmpty()) {
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(config.toUtf8());
|
||||||
|
if (!doc.isNull()) {
|
||||||
|
auto jsonObject = doc.object();
|
||||||
|
auto allowedSites = jsonObject["Allow"].toArray();
|
||||||
|
auto deniedSites = jsonObject["Deny"].toArray();
|
||||||
|
|
||||||
|
QStringList allowed;
|
||||||
|
foreach (const auto& value, allowedSites) {
|
||||||
|
auto url = value.toString();
|
||||||
|
if (!url.isEmpty()) {
|
||||||
|
allowed << url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList denied;
|
||||||
|
foreach (const auto& value, deniedSites) {
|
||||||
|
auto url = value.toString();
|
||||||
|
if (!url.isEmpty()) {
|
||||||
|
denied << url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configList.insert("Allow", allowed);
|
||||||
|
configList.insert("Deny", denied);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return configList;
|
||||||
|
}
|
71
src/gui/reports/ReportsWidgetBrowserStatistics.h
Normal file
71
src/gui/reports/ReportsWidgetBrowserStatistics.h
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 KeePassXC Team <team@keepassxc.org>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 or (at your option)
|
||||||
|
* version 3 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KEEPASSXC_REPORTSWIDGETBROWSERSTATISTICS_H
|
||||||
|
#define KEEPASSXC_REPORTSWIDGETBROWSERSTATISTICS_H
|
||||||
|
|
||||||
|
#include "gui/entry/EntryModel.h"
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
class Database;
|
||||||
|
class Entry;
|
||||||
|
class Group;
|
||||||
|
class PasswordHealth;
|
||||||
|
class QSortFilterProxyModel;
|
||||||
|
class QStandardItemModel;
|
||||||
|
|
||||||
|
namespace Ui
|
||||||
|
{
|
||||||
|
class ReportsWidgetBrowserStatistics;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ReportsWidgetBrowserStatistics : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit ReportsWidgetBrowserStatistics(QWidget* parent = nullptr);
|
||||||
|
~ReportsWidgetBrowserStatistics() override;
|
||||||
|
|
||||||
|
void loadSettings(QSharedPointer<Database> db);
|
||||||
|
void saveSettings();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void showEvent(QShowEvent* event) override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void entryActivated(Entry*);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void calculateBrowserStatistics();
|
||||||
|
void emitEntryActivated(const QModelIndex& index);
|
||||||
|
void customMenuRequested(QPoint);
|
||||||
|
void deleteSelectedEntries();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void addStatisticsRow(bool hasUrls, bool hasSettings, Group*, Entry*, bool);
|
||||||
|
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
|
100
src/gui/reports/ReportsWidgetBrowserStatistics.ui
Normal file
100
src/gui/reports/ReportsWidgetBrowserStatistics.ui
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>ReportsWidgetBrowserStatistics</class>
|
||||||
|
<widget class="QWidget" name="ReportsWidgetBrowserStatistics">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>505</width>
|
||||||
|
<height>379</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,0,0">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QTableView" name="browserStatisticsTableView">
|
||||||
|
<property name="contextMenuPolicy">
|
||||||
|
<enum>Qt::CustomContextMenu</enum>
|
||||||
|
</property>
|
||||||
|
<property name="editTriggers">
|
||||||
|
<set>QAbstractItemView::NoEditTriggers</set>
|
||||||
|
</property>
|
||||||
|
<property name="showDropIndicator" stdset="0">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="alternatingRowColors">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="selectionBehavior">
|
||||||
|
<enum>QAbstractItemView::SelectRows</enum>
|
||||||
|
</property>
|
||||||
|
<property name="textElideMode">
|
||||||
|
<enum>Qt::ElideMiddle</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sortingEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<attribute name="horizontalHeaderStretchLastSection">
|
||||||
|
<bool>true</bool>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="verticalHeaderVisible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="excludeExpired">
|
||||||
|
<property name="text">
|
||||||
|
<string>Exclude expired entries from the report</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="showEntriesWithUrlOnlyCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Show only entries which have URL set</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="showConnectedOnlyCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Show only entries which have browser settings in custom data</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="tipLabel">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<italic>true</italic>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Double-click entries to edit.</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<tabstops>
|
||||||
|
<tabstop>browserStatisticsTableView</tabstop>
|
||||||
|
<tabstop>excludeExpired</tabstop>
|
||||||
|
<tabstop>showEntriesWithUrlOnlyCheckBox</tabstop>
|
||||||
|
<tabstop>showConnectedOnlyCheckBox</tabstop>
|
||||||
|
</tabstops>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2020 KeePassXC Team <team@keepassxc.org>
|
* Copyright (C) 2021 KeePassXC Team <team@keepassxc.org>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -40,6 +40,9 @@ void StateColorPalette::initDefaultPaletteLight()
|
|||||||
setColor(ColorRole::HealthWeak, QStringLiteral("#FFD30F"));
|
setColor(ColorRole::HealthWeak, QStringLiteral("#FFD30F"));
|
||||||
setColor(ColorRole::HealthOk, QStringLiteral("#5EA10E"));
|
setColor(ColorRole::HealthOk, QStringLiteral("#5EA10E"));
|
||||||
setColor(ColorRole::HealthExcellent, QStringLiteral("#118f17"));
|
setColor(ColorRole::HealthExcellent, QStringLiteral("#118f17"));
|
||||||
|
|
||||||
|
setColor(ColorRole::True, QStringLiteral("#5EA10E"));
|
||||||
|
setColor(ColorRole::False, QStringLiteral("#C43F31"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void StateColorPalette::initDefaultPaletteDark()
|
void StateColorPalette::initDefaultPaletteDark()
|
||||||
@ -54,4 +57,7 @@ void StateColorPalette::initDefaultPaletteDark()
|
|||||||
setColor(ColorRole::HealthWeak, QStringLiteral("#F0C400"));
|
setColor(ColorRole::HealthWeak, QStringLiteral("#F0C400"));
|
||||||
setColor(ColorRole::HealthOk, QStringLiteral("#608A22"));
|
setColor(ColorRole::HealthOk, QStringLiteral("#608A22"));
|
||||||
setColor(ColorRole::HealthExcellent, QStringLiteral("#1F8023"));
|
setColor(ColorRole::HealthExcellent, QStringLiteral("#1F8023"));
|
||||||
|
|
||||||
|
setColor(ColorRole::True, QStringLiteral("#608A22"));
|
||||||
|
setColor(ColorRole::False, QStringLiteral("#C43F31"));
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2020 KeePassXC Team <team@keepassxc.org>
|
* Copyright (C) 2021 KeePassXC Team <team@keepassxc.org>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -43,7 +43,9 @@ public:
|
|||||||
HealthPoor,
|
HealthPoor,
|
||||||
HealthWeak,
|
HealthWeak,
|
||||||
HealthOk,
|
HealthOk,
|
||||||
HealthExcellent
|
HealthExcellent,
|
||||||
|
True,
|
||||||
|
False
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void setColor(ColorRole role, const QColor& color)
|
inline void setColor(ColorRole role, const QColor& color)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user