diff --git a/share/translations/keepassxc_en.ts b/share/translations/keepassxc_en.ts
index 3b5ae5f4a8..79e756fccd 100644
--- a/share/translations/keepassxc_en.ts
+++ b/share/translations/keepassxc_en.ts
@@ -3919,6 +3919,10 @@ Error: %1
+
+
+
+
EntryView
diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp
index af28bab680..6e3a606b24 100644
--- a/src/gui/entry/EditEntryWidget.cpp
+++ b/src/gui/entry/EditEntryWidget.cpp
@@ -326,17 +326,18 @@ void EditEntryWidget::insertURL()
{
Q_ASSERT(!m_history);
- QString name("KP2A_URL");
+ QString name(BrowserService::ADDITIONAL_URL);
int i = 1;
while (m_entryAttributes->keys().contains(name)) {
- name = QString("KP2A_URL_%1").arg(i);
+ name = QString("%1_%2").arg(BrowserService::ADDITIONAL_URL, QString::number(i));
i++;
}
m_entryAttributes->set(name, tr(""));
QModelIndex index = m_additionalURLsDataModel->indexByKey(name);
+ m_additionalURLsDataModel->setEntryUrl(m_entry->url());
m_browserUi->additionalURLsView->setCurrentIndex(index);
m_browserUi->additionalURLsView->edit(index);
diff --git a/src/gui/entry/EntryURLModel.cpp b/src/gui/entry/EntryURLModel.cpp
index 3222c7d308..d5b79eaad5 100644
--- a/src/gui/entry/EntryURLModel.cpp
+++ b/src/gui/entry/EntryURLModel.cpp
@@ -1,6 +1,6 @@
/*
+ * Copyright (C) 2023 KeePassXC Team
* Copyright (C) 2012 Felix Geyer
- * Copyright (C) 2019 KeePassXC Team
*
* 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
@@ -18,6 +18,7 @@
#include "EntryURLModel.h"
+#include "browser/BrowserService.h"
#include "core/EntryAttributes.h"
#include "core/Tools.h"
#include "gui/Icons.h"
@@ -68,13 +69,21 @@ QVariant EntryURLModel::data(const QModelIndex& index, int role) const
const auto value = m_entryAttributes->value(key);
const auto urlValid = Tools::checkUrlValid(value);
- if (role == Qt::BackgroundRole && !urlValid) {
+ // Check for duplicate URLs in the attribute list
+ auto customKeys = m_entryAttributes->customKeys();
+ customKeys.removeOne(key);
+ const auto values = m_entryAttributes->values(customKeys);
+ const auto duplicateUrl = values.contains(value) || value == m_entryUrl;
+
+ if (role == Qt::BackgroundRole && (!urlValid || duplicateUrl)) {
StateColorPalette statePalette;
return statePalette.color(StateColorPalette::ColorRole::Error);
- } else if (role == Qt::DecorationRole && !urlValid) {
+ } else if (role == Qt::DecorationRole && (!urlValid || duplicateUrl)) {
return m_errorIcon;
} else if (role == Qt::DisplayRole || role == Qt::EditRole) {
return value;
+ } else if (role == Qt::ToolTipRole && duplicateUrl) {
+ return tr("Duplicate URL");
} else if (role == Qt::ToolTipRole && !urlValid) {
return tr("Invalid URL");
}
@@ -82,17 +91,21 @@ QVariant EntryURLModel::data(const QModelIndex& index, int role) const
return {};
}
+void EntryURLModel::setEntryUrl(const QString& entryUrl)
+{
+ m_entryUrl = entryUrl;
+}
+
bool EntryURLModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
if (!index.isValid() || role != Qt::EditRole || value.type() != QVariant::String || value.toString().isEmpty()) {
return false;
}
- const int row = index.row();
- const QString key = m_urls.at(row).first;
- const QString oldValue = m_urls.at(row).second;
+ const auto row = index.row();
+ const auto key = m_urls.at(row).first;
- if (EntryAttributes::isDefaultAttribute(key) || m_entryAttributes->containsValue(value.toString())) {
+ if (EntryAttributes::isDefaultAttribute(key)) {
return false;
}
@@ -113,7 +126,7 @@ QModelIndex EntryURLModel::indexByKey(const QString& key) const
}
if (row == -1) {
- return QModelIndex();
+ return {};
} else {
return index(row, 0);
}
@@ -122,7 +135,7 @@ QModelIndex EntryURLModel::indexByKey(const QString& key) const
QString EntryURLModel::keyByIndex(const QModelIndex& index) const
{
if (!index.isValid()) {
- return QString();
+ return {};
} else {
return m_urls.at(index.row()).first;
}
@@ -133,9 +146,9 @@ void EntryURLModel::updateAttributes()
clear();
m_urls.clear();
- const QList attributesKeyList = m_entryAttributes->keys();
- for (const QString& key : attributesKeyList) {
- if (!EntryAttributes::isDefaultAttribute(key) && key.contains("KP2A_URL")) {
+ const auto attributesKeyList = m_entryAttributes->keys();
+ for (const auto& key : attributesKeyList) {
+ if (!EntryAttributes::isDefaultAttribute(key) && key.contains(BrowserService::ADDITIONAL_URL)) {
const auto value = m_entryAttributes->value(key);
m_urls.append(qMakePair(key, value));
diff --git a/src/gui/entry/EntryURLModel.h b/src/gui/entry/EntryURLModel.h
index f9ffa48288..2801f9ffe6 100644
--- a/src/gui/entry/EntryURLModel.h
+++ b/src/gui/entry/EntryURLModel.h
@@ -1,6 +1,6 @@
/*
+ * Copyright (C) 2023 KeePassXC Team
* Copyright (C) 2012 Felix Geyer
- * Copyright (C) 2019 KeePassXC Team
*
* 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
@@ -19,6 +19,7 @@
#ifndef KEEPASSXC_ENTRYURLMODEL_H
#define KEEPASSXC_ENTRYURLMODEL_H
+#include "core/Entry.h"
#include
#include
@@ -43,8 +44,10 @@ class EntryURLModel : public QStandardItemModel
public:
explicit EntryURLModel(QObject* parent = nullptr);
+
void setEntryAttributes(EntryAttributes* entryAttributes);
void insertRow(const QString& key, const QString& value);
+ void setEntryUrl(const QString& entryUrl);
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
QVariant data(const QModelIndex& index, int role) const override;
QModelIndex indexByKey(const QString& key) const;
@@ -57,6 +60,7 @@ private slots:
QList> m_urls;
EntryAttributes* m_entryAttributes;
QIcon m_errorIcon;
+ QString m_entryUrl;
};
#endif // KEEPASSXC_ENTRYURLMODEL_H