mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-12-31 18:26:20 -05:00
Add attachments tab to details view
This commit is contained in:
parent
90a64dbde2
commit
0c200d360b
@ -111,6 +111,11 @@ void EntryAttachments::remove(const QStringList& keys)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EntryAttachments::isEmpty() const
|
||||||
|
{
|
||||||
|
return m_attachments.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
void EntryAttachments::clear()
|
void EntryAttachments::clear()
|
||||||
{
|
{
|
||||||
if (m_attachments.isEmpty()) {
|
if (m_attachments.isEmpty()) {
|
||||||
|
@ -36,6 +36,7 @@ public:
|
|||||||
void set(const QString& key, const QByteArray& value);
|
void set(const QString& key, const QByteArray& value);
|
||||||
void remove(const QString& key);
|
void remove(const QString& key);
|
||||||
void remove(const QStringList& keys);
|
void remove(const QStringList& keys);
|
||||||
|
bool isEmpty() const;
|
||||||
void clear();
|
void clear();
|
||||||
void copyDataFrom(const EntryAttachments* other);
|
void copyDataFrom(const EntryAttachments* other);
|
||||||
bool operator==(const EntryAttachments& other) const;
|
bool operator==(const EntryAttachments& other) const;
|
||||||
|
@ -111,6 +111,9 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent)
|
|||||||
"border-radius: 5px;");
|
"border-radius: 5px;");
|
||||||
|
|
||||||
m_detailsView = new DetailsWidget(this);
|
m_detailsView = new DetailsWidget(this);
|
||||||
|
connect(m_detailsView, &DetailsWidget::errorOccured, this, [this](const QString& error) {
|
||||||
|
showMessage(error, MessageWidget::MessageType::Error, false);
|
||||||
|
});
|
||||||
|
|
||||||
QVBoxLayout* vLayout = new QVBoxLayout(rightHandSideWidget);
|
QVBoxLayout* vLayout = new QVBoxLayout(rightHandSideWidget);
|
||||||
vLayout->setMargin(0);
|
vLayout->setMargin(0);
|
||||||
|
@ -21,12 +21,16 @@
|
|||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QTemporaryFile>
|
||||||
|
|
||||||
#include "core/Config.h"
|
#include "core/Config.h"
|
||||||
#include "core/FilePath.h"
|
#include "core/FilePath.h"
|
||||||
#include "core/TimeInfo.h"
|
#include "core/TimeInfo.h"
|
||||||
#include "gui/Clipboard.h"
|
#include "gui/Clipboard.h"
|
||||||
#include "gui/DatabaseWidget.h"
|
#include "gui/DatabaseWidget.h"
|
||||||
|
#include "entry/EntryAttachmentsModel.h"
|
||||||
|
|
||||||
DetailsWidget::DetailsWidget(QWidget* parent)
|
DetailsWidget::DetailsWidget(QWidget* parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
@ -36,9 +40,11 @@ DetailsWidget::DetailsWidget(QWidget* parent)
|
|||||||
, m_currentGroup(nullptr)
|
, m_currentGroup(nullptr)
|
||||||
, m_timer(nullptr)
|
, m_timer(nullptr)
|
||||||
, m_attributesWidget(nullptr)
|
, m_attributesWidget(nullptr)
|
||||||
|
, m_attachmentsWidget(nullptr)
|
||||||
, m_autotypeWidget(nullptr)
|
, m_autotypeWidget(nullptr)
|
||||||
, m_selectedTabEntry(0)
|
, m_selectedTabEntry(0)
|
||||||
, m_selectedTabGroup(0)
|
, m_selectedTabGroup(0)
|
||||||
|
, m_attachmentsModel(new EntryAttachmentsModel(this))
|
||||||
{
|
{
|
||||||
m_ui->setupUi(this);
|
m_ui->setupUi(this);
|
||||||
|
|
||||||
@ -53,6 +59,17 @@ DetailsWidget::DetailsWidget(QWidget* parent)
|
|||||||
connect(m_ui->closeButton, SIGNAL(toggled(bool)), SLOT(hideDetails()));
|
connect(m_ui->closeButton, SIGNAL(toggled(bool)), SLOT(hideDetails()));
|
||||||
connect(m_ui->tabWidget, SIGNAL(tabBarClicked(int)), SLOT(updateTabIndex(int)));
|
connect(m_ui->tabWidget, SIGNAL(tabBarClicked(int)), SLOT(updateTabIndex(int)));
|
||||||
|
|
||||||
|
m_ui->attachmentsTableView->setModel(m_attachmentsModel);
|
||||||
|
m_ui->attachmentsTableView->horizontalHeader()->setStretchLastSection(true);
|
||||||
|
m_ui->attachmentsTableView->horizontalHeader()->resizeSection(0, 600);
|
||||||
|
m_ui->attachmentsTableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
m_ui->attachmentsTableView->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||||
|
connect(m_ui->attachmentsTableView, SIGNAL(activated(QModelIndex)), SLOT(openAttachment(QModelIndex)));
|
||||||
|
|
||||||
|
m_attributesWidget = m_ui->tabWidget->widget(AttributesTab);
|
||||||
|
m_attachmentsWidget = m_ui->tabWidget->widget(AttachmentsTab);
|
||||||
|
m_autotypeWidget = m_ui->tabWidget->widget(AutotypeTab);
|
||||||
|
|
||||||
this->hide();
|
this->hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,8 +92,9 @@ void DetailsWidget::getSelectedEntry(Entry* selectedEntry)
|
|||||||
|
|
||||||
m_ui->stackedWidget->setCurrentIndex(EntryPreview);
|
m_ui->stackedWidget->setCurrentIndex(EntryPreview);
|
||||||
|
|
||||||
if (m_ui->tabWidget->count() < 4) {
|
if (m_ui->tabWidget->count() < 5) {
|
||||||
m_ui->tabWidget->insertTab(static_cast<int>(AttributesTab), m_attributesWidget, "Attributes");
|
m_ui->tabWidget->insertTab(static_cast<int>(AttributesTab), m_attributesWidget, "Attributes");
|
||||||
|
m_ui->tabWidget->insertTab(static_cast<int>(AttachmentsTab), m_attachmentsWidget, "Attachments");
|
||||||
m_ui->tabWidget->insertTab(static_cast<int>(AutotypeTab), m_autotypeWidget, "Autotype");
|
m_ui->tabWidget->insertTab(static_cast<int>(AutotypeTab), m_autotypeWidget, "Autotype");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,6 +191,10 @@ void DetailsWidget::getSelectedEntry(Entry* selectedEntry)
|
|||||||
m_ui->attributesEdit->setText(attributesText);
|
m_ui->attributesEdit->setText(attributesText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool hasAttachments = !m_currentEntry->attachments()->isEmpty();
|
||||||
|
m_ui->tabWidget->setTabEnabled(AttachmentsTab, hasAttachments);
|
||||||
|
m_attachmentsModel->setEntryAttachments(hasAttachments ? m_currentEntry->attachments() : nullptr);
|
||||||
|
|
||||||
m_ui->autotypeTree->clear();
|
m_ui->autotypeTree->clear();
|
||||||
AutoTypeAssociations* autotypeAssociations = m_currentEntry->autoTypeAssociations();
|
AutoTypeAssociations* autotypeAssociations = m_currentEntry->autoTypeAssociations();
|
||||||
QList<QTreeWidgetItem*> items;
|
QList<QTreeWidgetItem*> items;
|
||||||
@ -209,9 +231,8 @@ void DetailsWidget::getSelectedGroup(Group* selectedGroup)
|
|||||||
m_ui->stackedWidget->setCurrentIndex(GroupPreview);
|
m_ui->stackedWidget->setCurrentIndex(GroupPreview);
|
||||||
|
|
||||||
if (m_ui->tabWidget->count() > 2) {
|
if (m_ui->tabWidget->count() > 2) {
|
||||||
m_autotypeWidget = m_ui->tabWidget->widget(AutotypeTab);
|
|
||||||
m_attributesWidget = m_ui->tabWidget->widget(AttributesTab);
|
|
||||||
m_ui->tabWidget->removeTab(AutotypeTab);
|
m_ui->tabWidget->removeTab(AutotypeTab);
|
||||||
|
m_ui->tabWidget->removeTab(AttachmentsTab);
|
||||||
m_ui->tabWidget->removeTab(AttributesTab);
|
m_ui->tabWidget->removeTab(AttributesTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,3 +359,28 @@ void DetailsWidget::updateTabIndex(int index)
|
|||||||
m_selectedTabEntry = index;
|
m_selectedTabEntry = index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DetailsWidget::openAttachment(const QModelIndex& index)
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_currentEntry != nullptr);
|
||||||
|
const QString filename = m_attachmentsModel->keyByIndex(index);
|
||||||
|
const QByteArray attachmentData = m_currentEntry->attachments()->value(filename);
|
||||||
|
|
||||||
|
// tmp file will be removed once the database (or the application) has been closed
|
||||||
|
const QString tmpFileTemplate = QDir::temp().absoluteFilePath(QString("XXXXXX.").append(filename));
|
||||||
|
QTemporaryFile* tmpFile = new QTemporaryFile(tmpFileTemplate, this);
|
||||||
|
|
||||||
|
const bool saveOk = tmpFile->open()
|
||||||
|
&& tmpFile->write(attachmentData) == attachmentData.size()
|
||||||
|
&& tmpFile->flush();
|
||||||
|
|
||||||
|
if (!saveOk) {
|
||||||
|
delete tmpFile;
|
||||||
|
emit errorOccured(tr("Unable to open the attachment:\n").append(tmpFile->errorString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpFile->close();
|
||||||
|
QDesktopServices::openUrl(QUrl::fromLocalFile(tmpFile->fileName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@ namespace Ui {
|
|||||||
class DetailsWidget;
|
class DetailsWidget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class EntryAttachmentsModel;
|
||||||
|
|
||||||
class DetailsWidget : public QWidget
|
class DetailsWidget : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -44,10 +46,14 @@ public:
|
|||||||
GeneralTab = 0,
|
GeneralTab = 0,
|
||||||
AttributesTab = 1,
|
AttributesTab = 1,
|
||||||
GroupNotesTab = 1,
|
GroupNotesTab = 1,
|
||||||
NotesTab = 2,
|
AttachmentsTab = 2,
|
||||||
AutotypeTab = 3,
|
NotesTab = 3,
|
||||||
|
AutotypeTab = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void errorOccured(const QString& error);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void getSelectedEntry(Entry* selectedEntry);
|
void getSelectedEntry(Entry* selectedEntry);
|
||||||
void getSelectedGroup(Group* selectedGroup);
|
void getSelectedGroup(Group* selectedGroup);
|
||||||
@ -56,6 +62,7 @@ private slots:
|
|||||||
void hideDetails();
|
void hideDetails();
|
||||||
void setDatabaseMode(DatabaseWidget::Mode mode);
|
void setDatabaseMode(DatabaseWidget::Mode mode);
|
||||||
void updateTabIndex(int index);
|
void updateTabIndex(int index);
|
||||||
|
void openAttachment(const QModelIndex& index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const QScopedPointer<Ui::DetailsWidget> m_ui;
|
const QScopedPointer<Ui::DetailsWidget> m_ui;
|
||||||
@ -65,9 +72,11 @@ private:
|
|||||||
quint8 m_step;
|
quint8 m_step;
|
||||||
QTimer* m_timer;
|
QTimer* m_timer;
|
||||||
QWidget* m_attributesWidget;
|
QWidget* m_attributesWidget;
|
||||||
|
QWidget* m_attachmentsWidget;
|
||||||
QWidget* m_autotypeWidget;
|
QWidget* m_autotypeWidget;
|
||||||
quint8 m_selectedTabEntry;
|
quint8 m_selectedTabEntry;
|
||||||
quint8 m_selectedTabGroup;
|
quint8 m_selectedTabGroup;
|
||||||
|
EntryAttachmentsModel* const m_attachmentsModel;
|
||||||
QString shortUrl(QString url);
|
QString shortUrl(QString url);
|
||||||
QString shortPassword(QString password);
|
QString shortPassword(QString password);
|
||||||
};
|
};
|
||||||
|
@ -454,6 +454,16 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QWidget" name="attachmentsTab">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Attachments</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||||
|
<item>
|
||||||
|
<widget class="QTableView" name="attachmentsTableView"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
<widget class="QWidget" name="notesTab">
|
<widget class="QWidget" name="notesTab">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string>Notes</string>
|
<string>Notes</string>
|
||||||
|
@ -32,7 +32,6 @@
|
|||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
|
|
||||||
|
|
||||||
#include "core/Config.h"
|
#include "core/Config.h"
|
||||||
#include "core/Database.h"
|
#include "core/Database.h"
|
||||||
#include "core/Entry.h"
|
#include "core/Entry.h"
|
||||||
@ -150,7 +149,7 @@ void EditEntryWidget::setupAdvanced()
|
|||||||
m_advancedUi->attachmentsView->horizontalHeader()->setStretchLastSection(true);
|
m_advancedUi->attachmentsView->horizontalHeader()->setStretchLastSection(true);
|
||||||
m_advancedUi->attachmentsView->horizontalHeader()->resizeSection(0, 600);
|
m_advancedUi->attachmentsView->horizontalHeader()->resizeSection(0, 600);
|
||||||
m_advancedUi->attachmentsView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
m_advancedUi->attachmentsView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
m_advancedUi->attachmentsView->setSelectionMode(QAbstractItemView::MultiSelection);
|
m_advancedUi->attachmentsView->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||||
|
|
||||||
connect(m_advancedUi->attachmentsView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
|
connect(m_advancedUi->attachmentsView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
|
||||||
SLOT(updateAttachmentButtonsEnabled()));
|
SLOT(updateAttachmentButtonsEnabled()));
|
||||||
|
Loading…
Reference in New Issue
Block a user