diff --git a/share/translations/keepassxc_en.ts b/share/translations/keepassxc_en.ts
index e812df0a54..7f601d793b 100644
--- a/share/translations/keepassxc_en.ts
+++ b/share/translations/keepassxc_en.ts
@@ -1749,10 +1749,6 @@ Are you sure you want to continue with this file?.
-
-
-
-
DatabaseSettingsWidgetBrowser
@@ -2237,6 +2233,50 @@ removed from the database.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
DatabaseSettingsWidgetKeeShare
diff --git a/src/core/Database.cpp b/src/core/Database.cpp
index d66552172d..0d1e2eb490 100644
--- a/src/core/Database.cpp
+++ b/src/core/Database.cpp
@@ -1036,3 +1036,51 @@ void Database::stopModifiedTimer()
{
QMetaObject::invokeMethod(&m_modifiedTimer, "stop");
}
+
+QString Database::publicName()
+{
+ return publicCustomData().value("KPXC_PUBLIC_NAME").toString();
+}
+
+void Database::setPublicName(const QString& name)
+{
+ if (name.isEmpty()) {
+ publicCustomData().remove("KPXC_PUBLIC_NAME");
+ } else {
+ publicCustomData().insert("KPXC_PUBLIC_NAME", name);
+ }
+ markAsModified();
+}
+
+QString Database::publicColor()
+{
+ return publicCustomData().value("KPXC_PUBLIC_COLOR").toString();
+}
+
+void Database::setPublicColor(const QString& color)
+{
+ if (color.isEmpty()) {
+ publicCustomData().remove("KPXC_PUBLIC_COLOR");
+ } else {
+ publicCustomData().insert("KPXC_PUBLIC_COLOR", color);
+ }
+ markAsModified();
+}
+
+int Database::publicIcon()
+{
+ if (publicCustomData().contains("KPXC_PUBLIC_ICON")) {
+ return publicCustomData().value("KPXC_PUBLIC_ICON").toInt();
+ }
+ return -1;
+}
+
+void Database::setPublicIcon(int iconIndex)
+{
+ if (iconIndex < 0) {
+ publicCustomData().remove("KPXC_PUBLIC_ICON");
+ } else {
+ publicCustomData().insert("KPXC_PUBLIC_ICON", iconIndex);
+ }
+ markAsModified();
+}
diff --git a/src/core/Database.h b/src/core/Database.h
index 35546f7432..27e187b7a5 100644
--- a/src/core/Database.h
+++ b/src/core/Database.h
@@ -107,6 +107,13 @@ class Database : public ModifiableObject
QString canonicalFilePath() const;
void setFilePath(const QString& filePath);
+ QString publicName();
+ void setPublicName(const QString& name);
+ QString publicColor();
+ void setPublicColor(const QString& color);
+ int publicIcon();
+ void setPublicIcon(int iconIndex);
+
Metadata* metadata();
const Metadata* metadata() const;
Group* rootGroup();
diff --git a/src/gui/DatabaseOpenWidget.cpp b/src/gui/DatabaseOpenWidget.cpp
index f4234b5721..0e09b81087 100644
--- a/src/gui/DatabaseOpenWidget.cpp
+++ b/src/gui/DatabaseOpenWidget.cpp
@@ -82,7 +82,6 @@ DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent)
font.setPointSize(font.pointSize() + 4);
font.setBold(true);
m_ui->labelHeadline->setFont(font);
- m_ui->labelHeadline->setText(tr("Unlock KeePassXC Database"));
m_ui->quickUnlockButton->setFont(font);
m_ui->quickUnlockButton->setIcon(
@@ -235,6 +234,31 @@ void DatabaseOpenWidget::load(const QString& filename)
m_filename = filename;
m_ui->fileNameLabel->setRawText(m_filename);
+ // Set the public name if defined
+ auto label = tr("Unlock KeePassXC Database");
+ if (!m_db->publicName().isEmpty()) {
+ label.append(QString(": %1").arg(m_db->publicName()));
+ }
+ m_ui->labelHeadline->setText(label);
+
+ // Apply the public color to the central unlock stack if defined
+ auto color = m_db->publicColor();
+ if (!color.isEmpty()) {
+ m_ui->centralStack->setStyleSheet(QString("QStackedWidget {border: 4px solid %1}").arg(color));
+ } else {
+ m_ui->centralStack->setStyleSheet("");
+ }
+
+ // Show the database icon if defined
+ auto iconIndex = m_db->publicIcon();
+ if (iconIndex >= 0 && iconIndex < databaseIcons()->count()) {
+ m_ui->dbIconLabel->setPixmap(databaseIcons()->icon(iconIndex, IconSize::Large));
+ m_ui->dbIconLabel->setVisible(true);
+ } else {
+ m_ui->dbIconLabel->setPixmap({});
+ m_ui->dbIconLabel->setVisible(false);
+ }
+
if (config()->get(Config::RememberLastKeyFiles).toBool()) {
auto lastKeyFiles = config()->get(Config::LastKeyFiles).toHash();
if (lastKeyFiles.contains(m_filename)) {
diff --git a/src/gui/DatabaseOpenWidget.ui b/src/gui/DatabaseOpenWidget.ui
index a045ba82ce..1ef04a5287 100644
--- a/src/gui/DatabaseOpenWidget.ui
+++ b/src/gui/DatabaseOpenWidget.ui
@@ -55,18 +55,54 @@
-
-
-
-
- 12
- 75
- true
-
+
+
+ 9
-
- Unlock KeePassXC Database
-
-
+
-
+
+
+
+ 32
+ 32
+
+
+
+
+
+
+ true
+
+
+
+ -
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Unlock KeePassXC Database
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
-
diff --git a/src/gui/dbsettings/DatabaseSettingsWidgetGeneral.cpp b/src/gui/dbsettings/DatabaseSettingsWidgetGeneral.cpp
index d43e6d8c53..32325f45c8 100644
--- a/src/gui/dbsettings/DatabaseSettingsWidgetGeneral.cpp
+++ b/src/gui/dbsettings/DatabaseSettingsWidgetGeneral.cpp
@@ -18,9 +18,16 @@
#include "DatabaseSettingsWidgetGeneral.h"
#include "ui_DatabaseSettingsWidgetGeneral.h"
+#include
+#include
+#include
+#include
+
#include "core/Clock.h"
#include "core/Group.h"
#include "core/Metadata.h"
+#include "gui/DatabaseIcons.h"
+#include "gui/IconModels.h"
#include "gui/MessageBox.h"
DatabaseSettingsWidgetGeneral::DatabaseSettingsWidgetGeneral(QWidget* parent)
@@ -29,6 +36,11 @@ DatabaseSettingsWidgetGeneral::DatabaseSettingsWidgetGeneral(QWidget* parent)
{
m_ui->setupUi(this);
+ connect(m_ui->dbPublicColorButton, &QPushButton::clicked, this, &DatabaseSettingsWidgetGeneral::pickPublicColor);
+ connect(m_ui->dbPublicColorClearButton, &QPushButton::clicked, this, [this] { setupPublicColorButton({}); });
+ connect(m_ui->dbPublicIconButton, &QPushButton::clicked, this, &DatabaseSettingsWidgetGeneral::pickPublicIcon);
+ connect(m_ui->dbPublicIconClearButton, &QPushButton::clicked, this, [this] { setupPublicIconButton(-1); });
+
connect(m_ui->historyMaxItemsCheckBox, SIGNAL(toggled(bool)), m_ui->historyMaxItemsSpinBox, SLOT(setEnabled(bool)));
connect(m_ui->historyMaxSizeCheckBox, SIGNAL(toggled(bool)), m_ui->historyMaxSizeSpinBox, SLOT(setEnabled(bool)));
connect(m_ui->autosaveDelayCheckBox, SIGNAL(toggled(bool)), m_ui->autosaveDelaySpinBox, SLOT(setEnabled(bool)));
@@ -48,6 +60,10 @@ void DatabaseSettingsWidgetGeneral::initialize()
m_ui->defaultUsernameEdit->setText(meta->defaultUserName());
m_ui->compressionCheckbox->setChecked(m_db->compressionAlgorithm() != Database::CompressionNone);
+ m_ui->dbPublicName->setText(m_db->publicName());
+ setupPublicColorButton(m_db->publicColor());
+ setupPublicIconButton(m_db->publicIcon());
+
if (meta->historyMaxItems() > -1) {
m_ui->historyMaxItemsSpinBox->setValue(meta->historyMaxItems());
m_ui->historyMaxItemsCheckBox->setChecked(true);
@@ -118,6 +134,10 @@ bool DatabaseSettingsWidgetGeneral::save()
meta->setRecycleBinEnabled(m_ui->recycleBinEnabledCheckBox->isChecked());
meta->setSettingsChanged(Clock::currentDateTimeUtc());
+ m_db->setPublicName(m_ui->dbPublicName->text());
+ m_db->setPublicColor(m_ui->dbPublicColorButton->property("color").toString());
+ m_db->setPublicIcon(m_ui->dbPublicIconButton->property("iconIndex").toInt());
+
bool truncate = false;
int historyMaxItems;
@@ -157,3 +177,79 @@ bool DatabaseSettingsWidgetGeneral::save()
return true;
}
+
+void DatabaseSettingsWidgetGeneral::pickPublicColor()
+{
+ auto oldColor = QColor(m_ui->dbPublicColorButton->property("color").toString());
+ auto newColor = QColorDialog::getColor(oldColor);
+ if (newColor.isValid()) {
+ setupPublicColorButton(newColor);
+ }
+}
+
+void DatabaseSettingsWidgetGeneral::setupPublicColorButton(const QColor& color)
+{
+ m_ui->dbPublicColorClearButton->setVisible(color.isValid());
+ if (color.isValid()) {
+ m_ui->dbPublicColorButton->setStyleSheet(QString("background-color:%1").arg(color.name()));
+ m_ui->dbPublicColorButton->setProperty("color", color.name());
+ } else {
+ m_ui->dbPublicColorButton->setStyleSheet("");
+ m_ui->dbPublicColorButton->setProperty("color", {});
+ }
+}
+
+void DatabaseSettingsWidgetGeneral::pickPublicIcon()
+{
+ QDialog dialog(this);
+ dialog.setSizeGripEnabled(false);
+ dialog.setWindowTitle(tr("Select Database Icon"));
+
+ auto iconList = new QListView;
+ iconList->setFlow(QListView::LeftToRight);
+ iconList->setMovement(QListView::Static);
+ iconList->setResizeMode(QListView::Adjust);
+ iconList->setWrapping(true);
+ iconList->setSpacing(4);
+
+ auto iconModel = new DefaultIconModel;
+ iconList->setModel(iconModel);
+ if (m_ui->dbPublicIconButton->property("iconIndex").toInt() >= 0) {
+ iconList->setCurrentIndex(iconModel->index(m_ui->dbPublicIconButton->property("iconIndex").toInt(), 0));
+ } else {
+ iconList->setCurrentIndex(iconModel->index(0, 0));
+ }
+
+ auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+ auto layout = new QVBoxLayout(&dialog);
+ layout->addWidget(iconList);
+ layout->addWidget(buttonBox);
+
+ // Resize the dialog to fit the default icon list
+ auto cellSize = iconList->sizeHintForIndex(iconModel->index(0, 0));
+ auto spacing = iconList->spacing() * 2;
+ dialog.resize((cellSize.width() + spacing) * 15, (cellSize.height() + spacing) * 6 + 16);
+
+ connect(iconList, &QListView::doubleClicked, &dialog, &QDialog::accept);
+ connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
+ connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
+ connect(
+ &dialog, &QDialog::accepted, this, [this, iconList] { setupPublicIconButton(iconList->currentIndex().row()); });
+
+ dialog.exec();
+}
+
+void DatabaseSettingsWidgetGeneral::setupPublicIconButton(int iconIndex)
+{
+ auto valid = iconIndex >= 0 && iconIndex < databaseIcons()->count();
+ m_ui->dbPublicIconClearButton->setVisible(valid);
+ if (valid) {
+ m_ui->dbPublicIconButton->setIcon(databaseIcons()->icon(iconIndex));
+ m_ui->dbPublicIconButton->setProperty("iconIndex", iconIndex);
+ m_ui->dbPublicIconClearButton->setVisible(true);
+ } else {
+ m_ui->dbPublicIconButton->setIcon(QIcon());
+ m_ui->dbPublicIconButton->setProperty("iconIndex", -1);
+ m_ui->dbPublicIconClearButton->setVisible(false);
+ }
+}
diff --git a/src/gui/dbsettings/DatabaseSettingsWidgetGeneral.h b/src/gui/dbsettings/DatabaseSettingsWidgetGeneral.h
index a26e1ef7a4..d54afedc98 100644
--- a/src/gui/dbsettings/DatabaseSettingsWidgetGeneral.h
+++ b/src/gui/dbsettings/DatabaseSettingsWidgetGeneral.h
@@ -20,6 +20,8 @@
#include "DatabaseSettingsWidget.h"
+#include
+
class Database;
namespace Ui
{
@@ -43,6 +45,13 @@ public slots:
protected:
void showEvent(QShowEvent* event) override;
+private slots:
+ void pickPublicColor();
+ void setupPublicColorButton(const QColor& color);
+ void pickPublicIcon();
+ void setupPublicIconButton(int iconIndex);
+
+private:
const QScopedPointer m_ui;
};
diff --git a/src/gui/dbsettings/DatabaseSettingsWidgetGeneral.ui b/src/gui/dbsettings/DatabaseSettingsWidgetGeneral.ui
index 939b699631..324ae6d3db 100644
--- a/src/gui/dbsettings/DatabaseSettingsWidgetGeneral.ui
+++ b/src/gui/dbsettings/DatabaseSettingsWidgetGeneral.ui
@@ -7,7 +7,7 @@
0
0
453
- 394
+ 647
@@ -92,6 +92,151 @@
+ -
+
+
+ Public Database Metadata
+
+
+
-
+
+
+
+ true
+
+
+
+ Warning: the following settings are not encrypted.
+
+
+
+ -
+
+
+ 0
+
+
-
+
+
+ Display name:
+
+
+
+ -
+
+
+ Publically visible display name used on the unlock dialog
+
+
+ Database public display name
+
+
+
+ -
+
+
+ Display color:
+
+
+
+ -
+
+
-
+
+
+
+ 30
+ 30
+
+
+
+ Publically visible color used on the unlock dialog
+
+
+ Database public display color chooser
+
+
+
+
+
+
+ -
+
+
+ Clear
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+ -
+
+
+ Display icon:
+
+
+
+ -
+
+
-
+
+
+
+ 30
+ 30
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+
+ -
+
+
+ Clear
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+
+
+
-
@@ -113,6 +258,19 @@ of entries remain at most.
+ -
+
+
+ Move entries to a recycle bin group
+instead of deleting them from the database.
+Entries deleted from the recycle bin are
+removed from the database.
+
+
+ Use recycle bin
+
+
+
-
@@ -158,19 +316,6 @@ add up to the specified amount at most.
- -
-
-
- Move entries to a recycle bin group
-instead of deleting them from the database.
-Entries deleted from the recycle bin are
-removed from the database.
-
-
- Use recycle bin
-
-
-
-
diff --git a/src/gui/styles/base/basestyle.qss b/src/gui/styles/base/basestyle.qss
index ee0fa4e021..8d40281a38 100644
--- a/src/gui/styles/base/basestyle.qss
+++ b/src/gui/styles/base/basestyle.qss
@@ -38,7 +38,7 @@ EntryPreviewWidget TagsEdit
padding-left: 0px;
}
-DatabaseOpenWidget #centralStack {
+DatabaseOpenWidget #centralStack, DatabaseOpenWidget #publicSummaryLabel {
border: 1px solid palette(mid);
background: palette(light);
}
diff --git a/src/gui/styles/base/classicstyle.qss b/src/gui/styles/base/classicstyle.qss
index d0ab2b88fc..72308f39e2 100644
--- a/src/gui/styles/base/classicstyle.qss
+++ b/src/gui/styles/base/classicstyle.qss
@@ -1,4 +1,4 @@
-DatabaseOpenWidget #centralStack {
+DatabaseOpenWidget #centralStack, DatabaseOpenWidget #publicSummaryLabel {
border: 2px groove palette(mid);
background: palette(light);
}