2015-09-06 20:20:00 +02:00
|
|
|
#include "./attachmentsedit.h"
|
2015-04-22 19:33:53 +02:00
|
|
|
|
2015-09-06 20:20:00 +02:00
|
|
|
#include "./attachmentsmodel.h"
|
2015-04-22 19:33:53 +02:00
|
|
|
|
2015-12-05 22:55:05 +01:00
|
|
|
#include "ui_attachmentsedit.h"
|
2015-09-06 15:41:17 +02:00
|
|
|
|
2015-04-22 19:33:53 +02:00
|
|
|
#include <tagparser/abstractattachment.h>
|
2018-03-06 02:04:35 +01:00
|
|
|
#include <tagparser/diagnostics.h>
|
2018-03-07 01:18:01 +01:00
|
|
|
#include <tagparser/mediafileinfo.h>
|
2021-02-04 23:22:43 +01:00
|
|
|
#include <tagparser/progressfeedback.h>
|
2015-04-22 19:33:53 +02:00
|
|
|
|
2016-12-19 23:53:12 +01:00
|
|
|
#include <qtutilities/misc/conversion.h>
|
|
|
|
|
2018-03-07 01:18:01 +01:00
|
|
|
#include <c++utilities/io/copy.h>
|
2016-12-19 23:53:12 +01:00
|
|
|
#include <c++utilities/io/nativefilestream.h>
|
2015-04-22 19:33:53 +02:00
|
|
|
|
|
|
|
#include <QFileDialog>
|
|
|
|
#include <QMessageBox>
|
|
|
|
|
|
|
|
#include <fstream>
|
|
|
|
|
|
|
|
using namespace std;
|
2019-06-10 22:49:46 +02:00
|
|
|
using namespace CppUtilities;
|
|
|
|
using namespace QtUtilities;
|
2018-03-06 23:10:13 +01:00
|
|
|
using namespace TagParser;
|
2015-04-22 19:33:53 +02:00
|
|
|
|
|
|
|
namespace QtGui {
|
|
|
|
|
2018-03-07 01:18:01 +01:00
|
|
|
AttachmentsEdit::AttachmentsEdit(MediaFileInfo *fileInfo, QWidget *parent)
|
|
|
|
: QWidget(parent)
|
|
|
|
, m_ui(new Ui::AttachmentsEdit)
|
|
|
|
, m_model(nullptr)
|
2015-04-22 19:33:53 +02:00
|
|
|
{
|
|
|
|
// setup UI and model
|
|
|
|
m_ui->setupUi(this);
|
|
|
|
m_model = new AttachmentsModel(this);
|
|
|
|
m_ui->treeView->setModel(m_model);
|
|
|
|
// connect signals and slots
|
|
|
|
connect(m_ui->restorePushButton, &QPushButton::clicked, this, &AttachmentsEdit::restore);
|
|
|
|
connect(m_ui->clearPushButton, &QPushButton::clicked, this, &AttachmentsEdit::clear);
|
|
|
|
connect(m_ui->addPushButton, &QPushButton::clicked, this, &AttachmentsEdit::showFileSelection);
|
|
|
|
connect(m_ui->extractPushButton, &QPushButton::clicked, this, &AttachmentsEdit::extractSelected);
|
|
|
|
connect(m_ui->treeView->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &AttachmentsEdit::selectionChanged);
|
|
|
|
// load specified file
|
|
|
|
setFileInfo(fileInfo, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
AttachmentsEdit::~AttachmentsEdit()
|
2018-03-07 01:18:01 +01:00
|
|
|
{
|
|
|
|
}
|
2015-04-22 19:33:53 +02:00
|
|
|
|
2018-03-06 23:10:13 +01:00
|
|
|
void AttachmentsEdit::setFileInfo(TagParser::MediaFileInfo *fileInfo, bool updateUi)
|
2015-04-22 19:33:53 +02:00
|
|
|
{
|
|
|
|
m_fileInfo = fileInfo;
|
|
|
|
m_currentAttachments.clear();
|
2018-03-07 01:18:01 +01:00
|
|
|
if (fileInfo && fileInfo->areAttachmentsSupported()) {
|
|
|
|
if (AbstractContainer *container = fileInfo->container()) {
|
2015-04-22 19:33:53 +02:00
|
|
|
auto count = container->attachmentCount();
|
2021-03-20 21:59:49 +01:00
|
|
|
m_currentAttachments.reserve(static_cast<decltype(m_currentAttachments)::size_type>(count));
|
2018-03-07 01:18:01 +01:00
|
|
|
for (size_t i = 0; i < count; ++i) {
|
2015-04-22 19:33:53 +02:00
|
|
|
m_currentAttachments << container->attachment(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-03-07 01:18:01 +01:00
|
|
|
if (updateUi) {
|
2015-04-22 19:33:53 +02:00
|
|
|
setEnabled(fileInfo && fileInfo->areAttachmentsSupported());
|
|
|
|
setupUi();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AttachmentsEdit::clear()
|
|
|
|
{
|
|
|
|
m_model->repealSelection();
|
|
|
|
}
|
|
|
|
|
|
|
|
void AttachmentsEdit::restore()
|
|
|
|
{
|
|
|
|
m_model->revert();
|
|
|
|
}
|
|
|
|
|
|
|
|
void AttachmentsEdit::apply()
|
|
|
|
{
|
|
|
|
m_model->submit();
|
|
|
|
}
|
|
|
|
|
|
|
|
void AttachmentsEdit::invalidate()
|
|
|
|
{
|
|
|
|
// clear UI status
|
|
|
|
// TODO
|
|
|
|
// re-setup UI
|
|
|
|
setupUi();
|
|
|
|
}
|
|
|
|
|
2015-10-06 22:41:02 +02:00
|
|
|
void AttachmentsEdit::addFile(const QString &path)
|
2015-04-22 19:33:53 +02:00
|
|
|
{
|
2018-03-07 01:18:01 +01:00
|
|
|
if (!fileInfo() || fileInfo()->attachmentsParsingStatus() != ParsingStatus::Ok || !fileInfo()->container()) {
|
2015-10-06 22:41:02 +02:00
|
|
|
throw Failure();
|
2015-04-22 19:33:53 +02:00
|
|
|
}
|
2018-03-06 02:04:35 +01:00
|
|
|
// create and add attachment
|
|
|
|
auto *const attachment = fileInfo()->container()->createAttachment();
|
|
|
|
attachment->setIgnored(true);
|
|
|
|
Diagnostics diag;
|
2021-02-04 23:22:43 +01:00
|
|
|
AbortableProgressFeedback progress; // FIXME: actually use the progress object
|
|
|
|
attachment->setFile(toNativeFileName(path).data(), diag, progress);
|
2018-03-06 02:04:35 +01:00
|
|
|
// TODO: show diag messages
|
|
|
|
m_addedAttachments << attachment;
|
|
|
|
m_model->addAttachment(-1, attachment, true, path);
|
2015-04-22 19:33:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void AttachmentsEdit::showFileSelection()
|
|
|
|
{
|
|
|
|
auto path = QFileDialog::getOpenFileName(this, tr("Select a file to attach"));
|
2018-03-07 01:18:01 +01:00
|
|
|
if (!path.isEmpty()) {
|
2015-10-06 22:41:02 +02:00
|
|
|
try {
|
|
|
|
addFile(path);
|
2018-03-07 01:18:01 +01:00
|
|
|
} catch (const Failure &) {
|
|
|
|
QMessageBox::warning(this, QApplication::applicationName(),
|
|
|
|
tr("The file couldn't be added because the attachments of the file could not be parsed successfully."));
|
2019-03-13 19:07:51 +01:00
|
|
|
} catch (const std::ios_base::failure &failure) {
|
|
|
|
QMessageBox::warning(this, QApplication::applicationName(),
|
2021-07-03 19:38:27 +02:00
|
|
|
tr("The file couldn't be added because an IO error occurred: ") + QString::fromLocal8Bit(failure.what()));
|
2015-04-22 19:33:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AttachmentsEdit::extractSelected()
|
|
|
|
{
|
|
|
|
auto selectedRows = m_ui->treeView->selectionModel()->selectedRows();
|
2018-03-07 01:18:01 +01:00
|
|
|
if (selectedRows.size() == 1) {
|
|
|
|
if (auto *attachment = m_model->attachment(selectedRows.front())) {
|
|
|
|
if (attachment->data() && attachment->data()->size()) {
|
2015-04-22 19:33:53 +02:00
|
|
|
auto fileName = QFileDialog::getSaveFileName(this, tr("Select where to store the extracted file"));
|
2018-03-07 01:18:01 +01:00
|
|
|
if (!fileName.isEmpty()) {
|
2015-04-22 19:33:53 +02:00
|
|
|
auto *data = attachment->data();
|
|
|
|
auto &input = attachment->data()->stream();
|
2016-12-19 23:53:12 +01:00
|
|
|
NativeFileStream file;
|
2015-04-22 19:33:53 +02:00
|
|
|
file.exceptions(ios_base::badbit | ios_base::failbit);
|
|
|
|
try {
|
2021-03-20 21:59:49 +01:00
|
|
|
input.seekg(static_cast<std::streamoff>(data->startOffset()), std::ios_base::beg);
|
2016-12-19 23:53:12 +01:00
|
|
|
file.open(toNativeFileName(fileName).data(), ios_base::out | ios_base::binary);
|
2015-04-22 19:33:53 +02:00
|
|
|
CopyHelper<0x1000> helper;
|
|
|
|
helper.copy(input, file, data->size());
|
2019-03-13 19:07:51 +01:00
|
|
|
} catch (const std::ios_base::failure &failure) {
|
|
|
|
QMessageBox::warning(this, QApplication::applicationName(),
|
2021-07-03 19:38:27 +02:00
|
|
|
tr("An IO error occurred when extracting the attached file: ") + QString::fromLocal8Bit(failure.what()));
|
2015-04-22 19:33:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
QMessageBox::warning(this, QApplication::applicationName(), tr("There must be exactly one attachment selected."));
|
|
|
|
}
|
|
|
|
|
|
|
|
void AttachmentsEdit::selectionChanged(const QModelIndex ¤t, const QModelIndex &)
|
|
|
|
{
|
|
|
|
m_ui->extractPushButton->setEnabled(current.isValid());
|
|
|
|
}
|
|
|
|
|
|
|
|
void AttachmentsEdit::setupUi()
|
|
|
|
{
|
|
|
|
static const QString currentlyAttached(tr("currently attached"));
|
|
|
|
m_model->setAttachments(m_currentAttachments, true, currentlyAttached);
|
|
|
|
}
|
|
|
|
|
2018-03-07 01:18:01 +01:00
|
|
|
} // namespace QtGui
|