diff --git a/share/translations/keepassxc_en.ts b/share/translations/keepassxc_en.ts
index 5d52cc5e69..b999f2679f 100644
--- a/share/translations/keepassxc_en.ts
+++ b/share/translations/keepassxc_en.ts
@@ -3980,6 +3980,10 @@ Error: %1
Would you like to overwrite the existing attachment?
+
+
+
+
EntryAttributesModel
@@ -6349,6 +6353,33 @@ Expect some bugs and minor issues, this version is meant for testing purposes.
+
+ NewEntryAttachmentsDialog
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
NixUtils
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5c7326b5c5..59c4587f3f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -157,6 +157,7 @@ set(gui_SOURCES
gui/entry/EntryAttachmentsModel.cpp
gui/entry/EntryAttachmentsWidget.cpp
gui/entry/EntryAttributesModel.cpp
+ gui/entry/NewEntryAttachmentsDialog.cpp
gui/entry/EntryHistoryModel.cpp
gui/entry/EntryModel.cpp
gui/entry/EntryView.cpp
diff --git a/src/gui/entry/EntryAttachmentsWidget.cpp b/src/gui/entry/EntryAttachmentsWidget.cpp
index d514804f8e..ab6d3e50b9 100644
--- a/src/gui/entry/EntryAttachmentsWidget.cpp
+++ b/src/gui/entry/EntryAttachmentsWidget.cpp
@@ -16,8 +16,10 @@
*/
#include "EntryAttachmentsWidget.h"
+#include "NewEntryAttachmentsDialog.h"
#include "ui_EntryAttachmentsWidget.h"
+#include
#include
#include
#include
@@ -68,6 +70,7 @@ EntryAttachmentsWidget::EntryAttachmentsWidget(QWidget* parent)
connect(m_ui->saveAttachmentButton, SIGNAL(clicked()), SLOT(saveSelectedAttachments()));
connect(m_ui->openAttachmentButton, SIGNAL(clicked()), SLOT(openSelectedAttachments()));
connect(m_ui->addAttachmentButton, SIGNAL(clicked()), SLOT(insertAttachments()));
+ connect(m_ui->newAttachmentButton, SIGNAL(clicked()), SLOT(newAttachments()));
connect(m_ui->removeAttachmentButton, SIGNAL(clicked()), SLOT(removeSelectedAttachments()));
connect(m_ui->renameAttachmentButton, SIGNAL(clicked()), SLOT(renameSelectedAttachments()));
@@ -163,6 +166,20 @@ void EntryAttachmentsWidget::insertAttachments()
emit widgetUpdated();
}
+void EntryAttachmentsWidget::newAttachments()
+{
+ Q_ASSERT(m_entryAttachments);
+ Q_ASSERT(!isReadOnly());
+ if (isReadOnly()) {
+ return;
+ }
+
+ auto newWidnow = new NewEntryAttachmentsDialog(m_entryAttachments, this);
+ if (newWidnow->exec() == QDialog::Accepted) {
+ emit widgetUpdated();
+ }
+}
+
void EntryAttachmentsWidget::removeSelectedAttachments()
{
Q_ASSERT(m_entryAttachments);
@@ -300,6 +317,7 @@ void EntryAttachmentsWidget::updateButtonsEnabled()
const bool hasSelection = m_ui->attachmentsView->selectionModel()->hasSelection();
m_ui->addAttachmentButton->setEnabled(!m_readOnly);
+ m_ui->newAttachmentButton->setEnabled(!m_readOnly);
m_ui->removeAttachmentButton->setEnabled(hasSelection && !m_readOnly);
m_ui->renameAttachmentButton->setEnabled(hasSelection && !m_readOnly);
diff --git a/src/gui/entry/EntryAttachmentsWidget.h b/src/gui/entry/EntryAttachmentsWidget.h
index 0f104a82a6..5424dfa64d 100644
--- a/src/gui/entry/EntryAttachmentsWidget.h
+++ b/src/gui/entry/EntryAttachmentsWidget.h
@@ -57,6 +57,7 @@ public slots:
private slots:
void insertAttachments();
+ void newAttachments();
void removeSelectedAttachments();
void renameSelectedAttachments();
void saveSelectedAttachments();
diff --git a/src/gui/entry/EntryAttachmentsWidget.ui b/src/gui/entry/EntryAttachmentsWidget.ui
index e685813b3d..a0c9f37830 100644
--- a/src/gui/entry/EntryAttachmentsWidget.ui
+++ b/src/gui/entry/EntryAttachmentsWidget.ui
@@ -51,6 +51,16 @@
0
+ -
+
+
+ false
+
+
+ New
+
+
+
-
diff --git a/src/gui/entry/NewEntryAttachmentsDialog.cpp b/src/gui/entry/NewEntryAttachmentsDialog.cpp
new file mode 100644
index 0000000000..0704eef8a5
--- /dev/null
+++ b/src/gui/entry/NewEntryAttachmentsDialog.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2021 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
+ * 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 .
+ */
+
+#include "NewEntryAttachmentsDialog.h"
+#include "core/EntryAttachments.h"
+#include "ui_NewEntryAttachmentsDialog.h"
+
+#include
+#include
+
+#include
+
+NewEntryAttachmentsDialog::NewEntryAttachmentsDialog(QPointer attachments, QWidget* parent)
+ : QDialog(parent)
+ , m_attachments(std::move(attachments))
+ , m_ui(new Ui::NewEntryAttachmentsDialog)
+{
+ m_ui->setupUi(this);
+
+ connect(m_ui->dialogButtons, SIGNAL(accepted()), this, SLOT(saveAttachment()));
+ connect(m_ui->dialogButtons, SIGNAL(rejected()), this, SLOT(reject()));
+ connect(m_ui->titleEdit, SIGNAL(textChanged(const QString&)), this, SLOT(fileNameTextChanged(const QString&)));
+
+ fileNameTextChanged(m_ui->titleEdit->text());
+}
+
+NewEntryAttachmentsDialog::~NewEntryAttachmentsDialog() = default;
+
+std::optional NewEntryAttachmentsDialog::ValidateFileName(const QString& fileName) const
+{
+ if (fileName.isEmpty()) {
+ return tr("Attachment name cannot be empty");
+ }
+
+ if (m_attachments->hasKey(fileName)) {
+ return tr("Attachment with the same name already exists");
+ }
+
+ return std::nullopt;
+}
+
+void NewEntryAttachmentsDialog::saveAttachment()
+{
+ auto fileName = m_ui->titleEdit->text();
+ auto text = m_ui->attachmentTextEdit->toPlainText().toUtf8();
+
+ if (auto error = ValidateFileName(fileName); error) {
+ QMessageBox::warning(this, tr("Save attachment"), error.value());
+ return;
+ }
+
+ m_attachments->set(fileName, text);
+
+ accept();
+}
+
+void NewEntryAttachmentsDialog::fileNameTextChanged(const QString& fileName)
+{
+ const auto error = ValidateFileName(fileName);
+
+ m_ui->errorLabel->setText(error.value_or(QString{}));
+ m_ui->errorLabel->setVisible(error.has_value());
+
+ if (auto okButton = m_ui->dialogButtons->button(QDialogButtonBox::Ok); okButton) {
+ okButton->setDisabled(error.has_value());
+ }
+}
diff --git a/src/gui/entry/NewEntryAttachmentsDialog.h b/src/gui/entry/NewEntryAttachmentsDialog.h
new file mode 100644
index 0000000000..515d110a1d
--- /dev/null
+++ b/src/gui/entry/NewEntryAttachmentsDialog.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2021 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
+ * 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 .
+ */
+
+#ifndef NEWENTRYATTACHMENTSWIDGET_H
+#define NEWENTRYATTACHMENTSWIDGET_H
+
+#include
+#include
+
+#include
+#include
+
+namespace Ui
+{
+ class NewEntryAttachmentsDialog;
+}
+
+class QByteArray;
+class EntryAttachments;
+
+class NewEntryAttachmentsDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ explicit NewEntryAttachmentsDialog(QPointer attachments, QWidget* parent = nullptr);
+ ~NewEntryAttachmentsDialog() override;
+
+private slots:
+ void saveAttachment();
+ void fileNameTextChanged(const QString& fileName);
+
+private:
+ std::optional ValidateFileName(const QString& fileName) const;
+
+private:
+ QPointer m_attachments;
+
+ QScopedPointer m_ui;
+};
+
+#endif // NEWENTRYATTACHMENTSWIDGET_H
diff --git a/src/gui/entry/NewEntryAttachmentsDialog.ui b/src/gui/entry/NewEntryAttachmentsDialog.ui
new file mode 100644
index 0000000000..7c7397bb8f
--- /dev/null
+++ b/src/gui/entry/NewEntryAttachmentsDialog.ui
@@ -0,0 +1,55 @@
+
+
+ NewEntryAttachmentsDialog
+
+
+
+ 0
+ 0
+ 402
+ 300
+
+
+
+ New entry attachments
+
+
+
-
+
+
+ File name
+
+
+
+ -
+
+
+ true
+
+
+ color: #FF9696
+
+
+
+
+
+
+ -
+
+
+ File contents...
+
+
+
+ -
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+
+
+