Skip to content

Commit

Permalink
Add preview functionality for entry attachments
Browse files Browse the repository at this point in the history
Supported types:
- text
- image

Fixes #11506
  • Loading branch information
w15dev committed Jan 8, 2025
1 parent df95ad6 commit abf2159
Show file tree
Hide file tree
Showing 10 changed files with 262 additions and 22 deletions.
50 changes: 38 additions & 12 deletions share/translations/keepassxc_en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3826,6 +3826,21 @@ This may cause the affected plugins to malfunction.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>EntryAttachmentsDialog</name>
<message>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>File name</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>File contents...</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>EntryAttachmentsModel</name>
<message>
Expand Down Expand Up @@ -3984,6 +3999,14 @@ Would you like to overwrite the existing attachment?</source>
<source>New</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Preview</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Failed to preview an attachment: Attachment not found</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>EntryAttributesModel</name>
Expand Down Expand Up @@ -6355,18 +6378,6 @@ Expect some bugs and minor issues, this version is meant for testing purposes.</
</context>
<context>
<name>NewEntryAttachmentsDialog</name>
<message>
<source>New entry attachments</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>File name</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>File contents...</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Attachment name cannot be empty</source>
<translation type="unfinished"></translation>
Expand All @@ -6379,6 +6390,10 @@ Expect some bugs and minor issues, this version is meant for testing purposes.</
<source>Save attachment</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>New entry attachment</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>NixUtils</name>
Expand Down Expand Up @@ -7145,6 +7160,17 @@ Do you want to overwrite it?</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PreviewEntryAttachmentsDialog</name>
<message>
<source>Preview entry attachment</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>No preview available</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QMessageBox</name>
<message>
Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ set(gui_SOURCES
gui/entry/EntryAttachmentsWidget.cpp
gui/entry/EntryAttributesModel.cpp
gui/entry/NewEntryAttachmentsDialog.cpp
gui/entry/PreviewEntryAttachmentsDialog.cpp
gui/entry/EntryHistoryModel.cpp
gui/entry/EntryModel.cpp
gui/entry/EntryView.cpp
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>NewEntryAttachmentsDialog</class>
<widget class="QDialog" name="NewEntryAttachmentsDialog">
<class>EntryAttachmentsDialog</class>
<widget class="QDialog" name="EntryAttachmentsDialog">
<property name="geometry">
<rect>
<x>0</x>
Expand All @@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
<string>New entry attachments</string>
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
Expand Down
25 changes: 22 additions & 3 deletions src/gui/entry/EntryAttachmentsWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "EntryAttachmentsWidget.h"
#include "NewEntryAttachmentsDialog.h"
#include "PreviewEntryAttachmentsDialog.h"
#include "ui_EntryAttachmentsWidget.h"

#include <QDir>
Expand All @@ -26,11 +27,11 @@
#include <QTemporaryFile>

#include "EntryAttachmentsModel.h"
#include "core/Config.h"
#include "core/EntryAttachments.h"
#include "core/Tools.h"
#include "gui/FileDialog.h"
#include "gui/MessageBox.h"
#include <QDebug>

EntryAttachmentsWidget::EntryAttachmentsWidget(QWidget* parent)
: QWidget(parent)
Expand Down Expand Up @@ -70,6 +71,7 @@ EntryAttachmentsWidget::EntryAttachmentsWidget(QWidget* parent)
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->previewButton, SIGNAL(clicked()), SLOT(previewAttachments()));
connect(m_ui->removeAttachmentButton, SIGNAL(clicked()), SLOT(removeSelectedAttachments()));
connect(m_ui->renameAttachmentButton, SIGNAL(clicked()), SLOT(renameSelectedAttachments()));

Expand Down Expand Up @@ -173,12 +175,28 @@ void EntryAttachmentsWidget::newAttachments()
return;
}

auto newWidnow = new NewEntryAttachmentsDialog(m_entryAttachments, this);
if (newWidnow->exec() == QDialog::Accepted) {
NewEntryAttachmentsDialog newEntryDialog{m_entryAttachments, this};
if (newEntryDialog.exec() == QDialog::Accepted) {
emit widgetUpdated();
}
}

void EntryAttachmentsWidget::previewAttachments()
{
Q_ASSERT(m_entryAttachments);

const auto index = m_ui->attachmentsView->selectionModel()->selectedIndexes().first();
if (!index.isValid()) {
qWarning() << tr("Failed to preview an attachment: Attachment not found");
return;
}

PreviewEntryAttachmentsDialog previewDialog{m_entryAttachments, this};
previewDialog.setAttachment(m_attachmentsModel->keyByIndex(index));

previewDialog.exec();
}

void EntryAttachmentsWidget::removeSelectedAttachments()
{
Q_ASSERT(m_entryAttachments);
Expand Down Expand Up @@ -318,6 +336,7 @@ void EntryAttachmentsWidget::updateButtonsEnabled()
m_ui->addAttachmentButton->setEnabled(!m_readOnly);
m_ui->newAttachmentButton->setEnabled(!m_readOnly);
m_ui->removeAttachmentButton->setEnabled(hasSelection && !m_readOnly);
m_ui->previewButton->setEnabled(hasSelection && !m_readOnly);
m_ui->renameAttachmentButton->setEnabled(hasSelection && !m_readOnly);

m_ui->saveAttachmentButton->setEnabled(hasSelection);
Expand Down
1 change: 1 addition & 0 deletions src/gui/entry/EntryAttachmentsWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public slots:
private slots:
void insertAttachments();
void newAttachments();
void previewAttachments();
void removeSelectedAttachments();
void renameSelectedAttachments();
void saveSelectedAttachments();
Expand Down
10 changes: 10 additions & 0 deletions src/gui/entry/EntryAttachmentsWidget.ui
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,16 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="previewButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Preview</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="openAttachmentButton">
<property name="enabled">
Expand Down
12 changes: 10 additions & 2 deletions src/gui/entry/NewEntryAttachmentsDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,26 @@

#include "NewEntryAttachmentsDialog.h"
#include "core/EntryAttachments.h"
#include "ui_NewEntryAttachmentsDialog.h"
#include "ui_EntryAttachmentsDialog.h"

#include <QMessageBox>
#include <QPushButton>

NewEntryAttachmentsDialog::NewEntryAttachmentsDialog(QPointer<EntryAttachments> attachments, QWidget* parent)
: QDialog(parent)
, m_attachments(std::move(attachments))
, m_ui(new Ui::NewEntryAttachmentsDialog)
, m_ui(new Ui::EntryAttachmentsDialog)
{
Q_ASSERT(m_attachments);

m_ui->setupUi(this);

setWindowTitle(tr("New entry attachment"));

m_ui->dialogButtons->clear();
m_ui->dialogButtons->addButton(QDialogButtonBox::Ok);
m_ui->dialogButtons->addButton(QDialogButtonBox::Cancel);

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&)));
Expand Down
4 changes: 2 additions & 2 deletions src/gui/entry/NewEntryAttachmentsDialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

namespace Ui
{
class NewEntryAttachmentsDialog;
class EntryAttachmentsDialog;
}

class QByteArray;
Expand All @@ -48,7 +48,7 @@ private slots:
private:
QPointer<EntryAttachments> m_attachments;

QScopedPointer<Ui::NewEntryAttachmentsDialog> m_ui;
QScopedPointer<Ui::EntryAttachmentsDialog> m_ui;
};

#endif // NEWENTRYATTACHMENTSWIDGET_H
109 changes: 109 additions & 0 deletions src/gui/entry/PreviewEntryAttachmentsDialog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Copyright (C) 2021 KeePassXC Team <[email protected]>
*
* 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 "PreviewEntryAttachmentsDialog.h"
#include "core/EntryAttachments.h"
#include "ui_EntryAttachmentsDialog.h"

#include <QDialogButtonBox>
#include <QMimeDatabase>
#include <QTextCursor>
#include <QtGlobal>

PreviewEntryAttachmentsDialog::PreviewEntryAttachmentsDialog(QPointer<EntryAttachments> attachments, QWidget* parent)
: QDialog(parent)
, m_attachments(std::move(attachments))
, m_ui(new Ui::EntryAttachmentsDialog)
{
Q_ASSERT(m_attachments);

m_ui->setupUi(this);

setWindowTitle(tr("Preview entry attachment"));

m_ui->titleEdit->setReadOnly(true);
m_ui->attachmentTextEdit->setReadOnly(true);

m_ui->dialogButtons->clear();
m_ui->dialogButtons->addButton(QDialogButtonBox::Close);

connect(m_ui->dialogButtons, SIGNAL(rejected()), this, SLOT(reject()));
}

PreviewEntryAttachmentsDialog::~PreviewEntryAttachmentsDialog() = default;

void PreviewEntryAttachmentsDialog::setAttachment(const QString& name)
{
m_name = name;
m_type = attachmentType(m_name);

m_ui->titleEdit->setText(m_name);

update();
}

void PreviewEntryAttachmentsDialog::update()
{
if (m_type == AttachmentType::Unknown) {
updateTextAttachment(tr("No preview available").toUtf8());
} else if (const auto data = m_attachments->value(m_name); m_type == AttachmentType::Image) {
updateImageAttachment(data);
} else if (m_type == AttachmentType::PlantText) {
updateTextAttachment(data);
}
}

void PreviewEntryAttachmentsDialog::updateTextAttachment(const QByteArray& data)
{
m_ui->attachmentTextEdit->setPlainText(QString::fromUtf8(data));
}

void PreviewEntryAttachmentsDialog::updateImageAttachment(const QByteArray& data)
{
QImage image{};
image.loadFromData(data);

m_ui->attachmentTextEdit->clear();
auto cursor = m_ui->attachmentTextEdit->textCursor();

cursor.insertImage(image.scaled(m_ui->attachmentTextEdit->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
}

PreviewEntryAttachmentsDialog::AttachmentType PreviewEntryAttachmentsDialog::attachmentType(const QString& name) const
{
const auto data = m_attachments->value(name);

QMimeDatabase mimeDb{};
const auto mime = mimeDb.mimeTypeForData(data);

if (auto mimeName = mime.name(); mimeName.startsWith("image/")) {
return AttachmentType::Image;
} else if (mimeName.startsWith("text/")) {
return AttachmentType::PlantText;
}

return AttachmentType::Unknown;
}

void PreviewEntryAttachmentsDialog::resizeEvent(QResizeEvent* event)
{
QDialog::resizeEvent(event);

if (m_type == AttachmentType::Image) {
update();
}
}
Loading

0 comments on commit abf2159

Please sign in to comment.