Page MenuHome GnuPG

No OneTemporary

diff --git a/src/widgets/messageviewer.cpp b/src/widgets/messageviewer.cpp
index 13ddeba..f334475 100644
--- a/src/widgets/messageviewer.cpp
+++ b/src/widgets/messageviewer.cpp
@@ -1,393 +1,394 @@
// SPDX-FileCopyrightText: 2023 Carl Schwan <carl.schwan@gnupg.com>
// SPDX-License-Identifier: LGPL-2.0-or-later
#include "messageviewer.h"
#include "attachmentview_p.h"
#include "messagecontainerwidget_p.h"
#include "mimetreeparser_widgets_debug.h"
#include "urlhandler_p.h"
#include <KCalendarCore/Event>
#include <KCalendarCore/ICalFormat>
#include <KLocalizedString>
#include <KMessageWidget>
#include <MimeTreeParserCore/AttachmentModel>
#include <MimeTreeParserCore/MessageParser>
#include <MimeTreeParserCore/ObjectTreeParser>
#include <MimeTreeParserCore/PartModel>
#include <QAction>
#include <QFileDialog>
#include <QFormLayout>
#include <QGroupBox>
#include <QLabel>
#include <QMenu>
#include <QScrollArea>
#include <QSplitter>
#include <QStandardPaths>
#include <QVBoxLayout>
using namespace MimeTreeParser::Widgets;
class MessageViewer::Private
{
public:
Private(MessageViewer *q_ptr)
: q{q_ptr}
, messageWidget(new KMessageWidget(q_ptr))
{
createActions();
messageWidget->setCloseButtonVisible(true);
messageWidget->hide();
}
MessageViewer *q;
QVBoxLayout *layout = nullptr;
KMime::Message::Ptr message;
MessageParser parser;
QScrollArea *scrollArea = nullptr;
QFormLayout *formLayout = nullptr;
AttachmentView *attachmentView = nullptr;
MimeTreeParser::MessagePart::List selectedParts;
UrlHandler *urlHandler = nullptr;
KMessageWidget *const messageWidget = nullptr;
QAction *saveAttachmentAction = nullptr;
QAction *openAttachmentAction = nullptr;
QAction *importPublicKeyAction = nullptr;
void createActions()
{
saveAttachmentAction = new QAction(QIcon::fromTheme(QStringLiteral("document-save-as")), i18n("&Save Attachment As..."), q);
connect(saveAttachmentAction, &QAction::triggered, q, [this]() {
saveSelectedAttachments();
});
openAttachmentAction = new QAction(i18nc("to open", "Open"), q);
connect(openAttachmentAction, &QAction::triggered, q, [this]() {
openSelectedAttachments();
});
importPublicKeyAction = new QAction(i18nc("@action:inmenu", "Import public key"), q);
connect(importPublicKeyAction, &QAction::triggered, q, [this]() {
importPublicKey();
});
}
void openSelectedAttachments();
void saveSelectedAttachments();
void selectionChanged();
void showContextMenu();
void importPublicKey();
void recursiveBuildViewer(PartModel *parts, QVBoxLayout *layout, const QModelIndex &parent);
};
void MessageViewer::Private::openSelectedAttachments()
{
Q_ASSERT(selectedParts.count() >= 1);
for (const auto &part : std::as_const(selectedParts)) {
parser.attachments()->openAttachment(part);
}
}
void MessageViewer::Private::saveSelectedAttachments()
{
Q_ASSERT(selectedParts.count() >= 1);
for (const auto &part : std::as_const(selectedParts)) {
QString pname = part->filename();
if (pname.isEmpty()) {
pname = i18nc("Fallback when file has no name", "unnamed");
}
const QString path = QFileDialog::getSaveFileName(q, i18n("Save Attachment As"), pname);
parser.attachments()->saveAttachmentToPath(part, path);
}
}
void MessageViewer::Private::importPublicKey()
{
Q_ASSERT(selectedParts.count() == 1);
parser.attachments()->importPublicKey(selectedParts[0]);
}
void MessageViewer::Private::showContextMenu()
{
const int numberOfParts(selectedParts.count());
QMenu menu;
if (numberOfParts == 1) {
const QString mimetype = QString::fromLatin1(selectedParts.first()->mimeType());
if (mimetype == QLatin1String("application/pgp-keys")) {
menu.addAction(importPublicKeyAction);
}
}
menu.addAction(openAttachmentAction);
menu.addAction(saveAttachmentAction);
menu.exec(QCursor::pos());
}
void MessageViewer::Private::selectionChanged()
{
const QModelIndexList selectedRows = attachmentView->selectionModel()->selectedRows();
MimeTreeParser::MessagePart::List selectedParts;
selectedParts.reserve(selectedRows.count());
for (const QModelIndex &index : selectedRows) {
auto part = attachmentView->model()->data(index, AttachmentModel::AttachmentPartRole).value<MimeTreeParser::MessagePart::Ptr>();
selectedParts.append(part);
}
this->selectedParts = selectedParts;
}
MessageViewer::MessageViewer(QWidget *parent)
: QSplitter(Qt::Vertical, parent)
, d(std::make_unique<MessageViewer::Private>(this))
{
setObjectName(QStringLiteral("MessageViewerSplitter"));
setChildrenCollapsible(false);
setSizes({0});
addWidget(d->messageWidget);
auto headersArea = new QWidget(this);
headersArea->setSizePolicy(sizePolicy().horizontalPolicy(), QSizePolicy::Expanding);
addWidget(headersArea);
d->urlHandler = new UrlHandler(this);
d->formLayout = new QFormLayout(headersArea);
auto widget = new QWidget(this);
d->layout = new QVBoxLayout(widget);
d->layout->setSizeConstraint(QLayout::SetMinAndMaxSize);
d->layout->setObjectName(QStringLiteral("PartLayout"));
d->scrollArea = new QScrollArea(this);
d->scrollArea->setWidget(widget);
d->scrollArea->setWidgetResizable(true);
d->scrollArea->setBackgroundRole(QPalette::Base);
addWidget(d->scrollArea);
setStretchFactor(2, 2);
d->attachmentView = new AttachmentView(this);
+ d->attachmentView->setProperty("_breeze_borders_sides", QVariant::fromValue(QFlags{Qt::BottomEdge}));
d->attachmentView->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
addWidget(d->attachmentView);
connect(d->attachmentView, &AttachmentView::contextMenuRequested, this, [this] {
d->selectionChanged();
d->showContextMenu();
});
setMinimumSize(600, 600);
}
MessageViewer::~MessageViewer()
{
QLayoutItem *child;
while ((child = d->layout->takeAt(0)) != nullptr) {
delete child->widget();
delete child;
}
}
KMime::Message::Ptr MessageViewer::message() const
{
return d->parser.message();
}
void MessageViewer::Private::recursiveBuildViewer(PartModel *parts, QVBoxLayout *layout, const QModelIndex &parent)
{
for (int i = 0, count = parts->rowCount(parent); i < count; i++) {
const auto type = static_cast<PartModel::Types>(parts->data(parts->index(i, 0, parent), PartModel::TypeRole).toUInt());
const auto content = parts->data(parts->index(i, 0, parent), PartModel::ContentRole).toString();
const auto signatureInfo = parts->data(parts->index(i, 0, parent), PartModel::SignatureDetails).value<SignatureInfo>();
const auto isSigned = parts->data(parts->index(i, 0, parent), PartModel::IsSignedRole).toBool();
const auto signatureSecurityLevel =
static_cast<PartModel::SecurityLevel>(parts->data(parts->index(i, 0, parent), PartModel::SignatureSecurityLevelRole).toInt());
const auto encryptionInfo = parts->data(parts->index(i, 0, parent), PartModel::EncryptionDetails).value<SignatureInfo>();
const auto isEncrypted = parts->data(parts->index(i, 0, parent), PartModel::IsEncryptedRole).toBool();
const auto encryptionSecurityLevel =
static_cast<PartModel::SecurityLevel>(parts->data(parts->index(i, 0, parent), PartModel::EncryptionSecurityLevelRole).toInt());
const auto displayEncryptionInfo =
i == 0 || parts->data(parts->index(i - 1, 0, parent), PartModel::EncryptionDetails).value<SignatureInfo>().keyId != encryptionInfo.keyId;
const auto displaySignatureInfo =
i == 0 || parts->data(parts->index(i - 1, 0, parent), PartModel::SignatureDetails).value<SignatureInfo>().keyId != signatureInfo.keyId;
switch (type) {
case PartModel::Types::Plain: {
auto container = new MessageWidgetContainer(isSigned,
signatureInfo,
signatureSecurityLevel,
displaySignatureInfo,
isEncrypted,
encryptionInfo,
encryptionSecurityLevel,
displayEncryptionInfo,
urlHandler);
auto label = new QLabel(content);
label->setTextInteractionFlags(Qt::TextSelectableByMouse);
label->setWordWrap(true);
container->layout()->addWidget(label);
layout->addWidget(container);
break;
}
case PartModel::Types::Ical: {
auto container = new MessageWidgetContainer(isSigned,
signatureInfo,
signatureSecurityLevel,
displaySignatureInfo,
isEncrypted,
encryptionInfo,
encryptionSecurityLevel,
displayEncryptionInfo,
urlHandler);
KCalendarCore::ICalFormat format;
auto incidence = format.fromString(content);
auto widget = new QGroupBox(container);
widget->setTitle(i18n("Invitation"));
auto incidenceLayout = new QFormLayout(widget);
incidenceLayout->addRow(i18n("&Summary:"), new QLabel(incidence->summary()));
incidenceLayout->addRow(i18n("&Organizer:"), new QLabel(incidence->organizer().fullName()));
if (incidence->location().length() > 0) {
incidenceLayout->addRow(i18n("&Location:"), new QLabel(incidence->location()));
}
incidenceLayout->addRow(i18n("&Start date:"), new QLabel(incidence->dtStart().toLocalTime().toString()));
if (const auto event = incidence.dynamicCast<KCalendarCore::Event>()) {
incidenceLayout->addRow(i18n("&End date:"), new QLabel(event->dtEnd().toLocalTime().toString()));
}
if (incidence->description().length() > 0) {
incidenceLayout->addRow(i18n("&Details:"), new QLabel(incidence->description()));
}
container->layout()->addWidget(widget);
layout->addWidget(container);
break;
}
case PartModel::Types::Encapsulated: {
auto container = new MessageWidgetContainer(isSigned,
signatureInfo,
signatureSecurityLevel,
displaySignatureInfo,
isEncrypted,
encryptionInfo,
encryptionSecurityLevel,
displayEncryptionInfo,
urlHandler);
auto groupBox = new QGroupBox(container);
groupBox->setSizePolicy(QSizePolicy::MinimumExpanding, q->sizePolicy().verticalPolicy());
groupBox->setTitle(i18n("Encapsulated email"));
auto encapsulatedLayout = new QVBoxLayout(groupBox);
auto header = new QWidget(groupBox);
auto headerLayout = new QFormLayout(header);
const auto from = parts->data(parts->index(i, 0, parent), PartModel::SenderRole).toString();
const auto date = parts->data(parts->index(i, 0, parent), PartModel::DateRole).toDateTime();
headerLayout->addRow(i18n("From:"), new QLabel(from));
headerLayout->addRow(i18n("Date:"), new QLabel(date.toLocalTime().toString()));
encapsulatedLayout->addWidget(header);
recursiveBuildViewer(parts, encapsulatedLayout, parts->index(i, 0, parent));
container->layout()->addWidget(groupBox);
layout->addWidget(container);
break;
}
case PartModel::Types::Error: {
const auto errorString = parts->data(parts->index(i, 0, parent), PartModel::ErrorString).toString();
auto errorWidget = new KMessageWidget(i18n("Error: %1", errorString));
errorWidget->setMessageType(KMessageWidget::MessageType::Error);
layout->addWidget(errorWidget);
break;
}
default:
qCWarning(MIMETREEPARSER_WIDGET_LOG) << parts->data(parts->index(i, 0, parent), PartModel::ContentRole) << type;
}
}
}
void MessageViewer::setMessage(const KMime::Message::Ptr message)
{
setUpdatesEnabled(false);
d->parser.setMessage(message);
connect(d->parser.attachments(), &AttachmentModel::info, this, [this](const QString &message) {
d->messageWidget->setMessageType(KMessageWidget::Information);
d->messageWidget->setText(message);
d->messageWidget->animatedShow();
});
connect(d->parser.attachments(), &AttachmentModel::errorOccurred, this, [this](const QString &message) {
d->messageWidget->setMessageType(KMessageWidget::Error);
d->messageWidget->setText(message);
d->messageWidget->animatedShow();
});
for (int i = d->formLayout->rowCount() - 1; i >= 0; i--) {
d->formLayout->removeRow(i);
}
if (!d->parser.subject().isEmpty()) {
d->formLayout->addRow(i18n("&Subject:"), new QLabel(d->parser.subject()));
}
if (!d->parser.from().isEmpty()) {
d->formLayout->addRow(i18n("&From:"), new QLabel(d->parser.from()));
}
if (!d->parser.sender().isEmpty() && d->parser.from() != d->parser.sender()) {
d->formLayout->addRow(i18n("&Sender:"), new QLabel(d->parser.sender()));
}
if (!d->parser.to().isEmpty()) {
d->formLayout->addRow(i18n("&To:"), new QLabel(d->parser.to()));
}
if (!d->parser.cc().isEmpty()) {
d->formLayout->addRow(i18n("&CC:"), new QLabel(d->parser.cc()));
}
if (!d->parser.bcc().isEmpty()) {
d->formLayout->addRow(i18n("&BCC:"), new QLabel(d->parser.bcc()));
}
const auto parts = d->parser.parts();
QLayoutItem *child;
while ((child = d->layout->takeAt(0)) != nullptr) {
delete child->widget();
delete child;
}
d->recursiveBuildViewer(parts, d->layout, {});
d->layout->addStretch();
d->attachmentView->setModel(d->parser.attachments());
d->attachmentView->setVisible(d->parser.attachments()->rowCount() > 0);
connect(d->attachmentView->selectionModel(), &QItemSelectionModel::selectionChanged, this, [this] {
d->selectionChanged();
});
setUpdatesEnabled(true);
}
void MessageViewer::print(QPainter *painter, int width)
{
const auto oldSize = size();
resize(width - 30, oldSize.height());
d->scrollArea->setFrameShape(QFrame::NoFrame);
render(painter);
d->scrollArea->setFrameShape(QFrame::StyledPanel);
resize(oldSize);
}
diff --git a/src/widgets/messageviewerdialog.cpp b/src/widgets/messageviewerdialog.cpp
index 7cb9073..b2390f3 100644
--- a/src/widgets/messageviewerdialog.cpp
+++ b/src/widgets/messageviewerdialog.cpp
@@ -1,302 +1,302 @@
// SPDX-FileCopyrightText: 2023 g10 Code GmbH
// SPDX-FileContributor: Carl Schwan <carl.schwan@gnupg.com>
// SPDX-License-Identifier: GPL-2.0-or-later
#include "messageviewerdialog.h"
#include "messageviewer.h"
#include "mimetreeparser_widgets_debug.h"
#include <MimeTreeParserCore/CryptoHelper>
#include <MimeTreeParserCore/FileOpener>
#include <KLocalizedString>
#include <KMessageBox>
#include <KMessageWidget>
#include <KMime/Message>
#include <QDialogButtonBox>
#include <QFileDialog>
#include <QMenuBar>
#include <QPainter>
#include <QPrintDialog>
#include <QPrintPreviewDialog>
#include <QPrinter>
#include <QPushButton>
#include <QRegularExpression>
#include <QSaveFile>
#include <QStandardPaths>
#include <QStyle>
#include <QToolBar>
#include <QVBoxLayout>
#include <memory>
using namespace MimeTreeParser::Widgets;
namespace
{
/// On windows, force the filename to end with .eml
/// On Linux, do nothing as this is handled by the file picker
inline QString changeExtension(const QString &fileName)
{
#ifdef Q_OS_WIN
auto renamedFileName = fileName;
renamedFileName.replace(QRegularExpression(QStringLiteral("\\.(mbox|p7m|asc)$")), QStringLiteral(".eml"));
// In case the file name didn't contain any of the expected extension: mbox, p7m, asc and eml
// or doesn't contains an extension at all.
if (!renamedFileName.endsWith(QStringLiteral(".eml"))) {
renamedFileName += QStringLiteral(".eml");
}
return renamedFileName;
#else
// Handled automatically by the file picker on linux
return fileName;
#endif
}
}
class MessageViewerDialog::Private
{
public:
int currentIndex = 0;
QList<KMime::Message::Ptr> messages;
QString fileName;
MimeTreeParser::Widgets::MessageViewer *messageViewer = nullptr;
QAction *nextAction = nullptr;
QAction *previousAction = nullptr;
void setCurrentIndex(int currentIndex);
QMenuBar *createMenuBar(QWidget *parent);
private:
void save(QWidget *parent);
void saveDecrypted(QWidget *parent);
void print(QWidget *parent);
void printPreview(QWidget *parent);
void printInternal(QPrinter *printer);
};
void MessageViewerDialog::Private::setCurrentIndex(int index)
{
Q_ASSERT(index >= 0);
Q_ASSERT(index < messages.count());
currentIndex = index;
messageViewer->setMessage(messages[currentIndex]);
previousAction->setEnabled(currentIndex != 0);
nextAction->setEnabled(currentIndex != messages.count() - 1);
}
QMenuBar *MessageViewerDialog::Private::createMenuBar(QWidget *parent)
{
const auto menuBar = new QMenuBar(parent);
// File menu
const auto fileMenu = menuBar->addMenu(i18nc("@action:inmenu", "&File"));
const auto saveAction = new QAction(QIcon::fromTheme(QStringLiteral("document-save")), i18nc("@action:inmenu", "&Save"));
QObject::connect(saveAction, &QAction::triggered, parent, [parent, this] {
save(parent);
});
fileMenu->addAction(saveAction);
const auto saveDecryptedAction = new QAction(QIcon::fromTheme(QStringLiteral("document-save")), i18nc("@action:inmenu", "Save Decrypted"));
QObject::connect(saveDecryptedAction, &QAction::triggered, parent, [parent, this] {
saveDecrypted(parent);
});
fileMenu->addAction(saveDecryptedAction);
const auto printPreviewAction = new QAction(QIcon::fromTheme(QStringLiteral("document-print-preview")), i18nc("@action:inmenu", "Print Preview"));
QObject::connect(printPreviewAction, &QAction::triggered, parent, [parent, this] {
printPreview(parent);
});
fileMenu->addAction(printPreviewAction);
const auto printAction = new QAction(QIcon::fromTheme(QStringLiteral("document-print")), i18nc("@action:inmenu", "&Print"));
QObject::connect(printAction, &QAction::triggered, parent, [parent, this] {
print(parent);
});
fileMenu->addAction(printAction);
// Navigation menu
const auto navigationMenu = menuBar->addMenu(i18nc("@action:inmenu", "&Navigation"));
previousAction = new QAction(QIcon::fromTheme(QStringLiteral("go-previous")), i18nc("@action:button Previous email", "Previous Message"), parent);
previousAction->setEnabled(false);
navigationMenu->addAction(previousAction);
nextAction = new QAction(QIcon::fromTheme(QStringLiteral("go-next")), i18nc("@action:button Next email", "Next Message"), parent);
nextAction->setEnabled(false);
navigationMenu->addAction(nextAction);
return menuBar;
}
void MessageViewerDialog::Private::save(QWidget *parent)
{
const QString location = QFileDialog::getSaveFileName(parent,
i18nc("@title:window", "Save File"),
changeExtension(fileName),
i18nc("File dialog accepted files", "Email files (*.eml *.mbox)"));
QSaveFile file(location);
if (!file.open(QIODevice::WriteOnly)) {
KMessageBox::error(parent, i18n("File %1 could not be created.", location), i18n("Error saving message"));
return;
}
file.write(messages[currentIndex]->encodedContent());
file.commit();
}
void MessageViewerDialog::Private::saveDecrypted(QWidget *parent)
{
const QString location = QFileDialog::getSaveFileName(parent,
i18nc("@title:window", "Save Decrypted File"),
changeExtension(fileName),
i18nc("File dialog accepted files", "Email files (*.eml *.mbox)"));
QSaveFile file(location);
if (!file.open(QIODevice::WriteOnly)) {
KMessageBox::error(parent, i18nc("Error message", "File %1 could not be created.", location), i18n("Error saving message"));
return;
}
auto message = messages[currentIndex];
bool wasEncrypted = false;
auto decryptedMessage = CryptoUtils::decryptMessage(message, wasEncrypted);
if (!wasEncrypted) {
decryptedMessage = message;
}
file.write(decryptedMessage->encodedContent());
file.commit();
}
void MessageViewerDialog::Private::print(QWidget *parent)
{
QPrinter printer;
QPrintDialog dialog(&printer, parent);
dialog.setWindowTitle(i18nc("@title:window", "Print Document"));
if (dialog.exec() != QDialog::Accepted)
return;
printInternal(&printer);
}
void MessageViewerDialog::Private::printPreview(QWidget *parent)
{
auto dialog = new QPrintPreviewDialog(parent);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->resize(800, 750);
dialog->setWindowTitle(i18nc("@title:window", "Print Document"));
QObject::connect(dialog, &QPrintPreviewDialog::paintRequested, parent, [this](QPrinter *printer) {
printInternal(printer);
});
dialog->open();
}
void MessageViewerDialog::Private::printInternal(QPrinter *printer)
{
QPainter painter;
painter.begin(printer);
const auto pageLayout = printer->pageLayout();
const auto pageRect = pageLayout.paintRectPixels(printer->resolution());
const double xscale = pageRect.width() / double(messageViewer->width());
const double yscale = pageRect.height() / double(messageViewer->height());
const double scale = qMin(qMin(xscale, yscale), 1.);
painter.translate(pageRect.x(), pageRect.y());
painter.scale(scale, scale);
messageViewer->print(&painter, pageRect.width());
}
MessageViewerDialog::MessageViewerDialog(const QList<KMime::Message::Ptr> &messages, QWidget *parent)
: QDialog(parent)
, d(std::make_unique<Private>())
{
d->messages += messages;
initGUI();
}
MessageViewerDialog::MessageViewerDialog(const QString &fileName, QWidget *parent)
: QDialog(parent)
, d(std::make_unique<Private>())
{
d->fileName = fileName;
d->messages += MimeTreeParser::Core::FileOpener::openFile(fileName);
initGUI();
}
void MessageViewerDialog::initGUI()
{
const auto mainLayout = new QVBoxLayout(this);
mainLayout->setContentsMargins({});
const auto layout = new QVBoxLayout;
- layout->setContentsMargins(style()->pixelMetric(QStyle::PM_LayoutLeftMargin, nullptr, this),
- style()->pixelMetric(QStyle::PM_LayoutTopMargin, nullptr, this),
- style()->pixelMetric(QStyle::PM_LayoutRightMargin, nullptr, this),
- style()->pixelMetric(QStyle::PM_LayoutBottomMargin, nullptr, this));
const auto menuBar = d->createMenuBar(this);
mainLayout->setMenuBar(menuBar);
if (d->messages.isEmpty()) {
auto errorMessage = new KMessageWidget(this);
errorMessage->setMessageType(KMessageWidget::Error);
errorMessage->setText(i18nc("@info", "Unable to read file"));
layout->addWidget(errorMessage);
return;
}
const bool multipleMessages = d->messages.length() > 1;
if (multipleMessages) {
const auto toolBar = new QToolBar(this);
#ifdef Q_OS_UNIX
toolBar->setToolButtonStyle(Qt::ToolButtonFollowStyle);
#else
// on other platforms the default is IconOnly which is bad for
// accessibility and can't be changed by the user.
toolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
#endif
toolBar->addAction(d->previousAction);
connect(d->previousAction, &QAction::triggered, this, [this] {
d->setCurrentIndex(d->currentIndex - 1);
});
const auto spacer = new QWidget(this);
spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
toolBar->addWidget(spacer);
toolBar->addAction(d->nextAction);
connect(d->nextAction, &QAction::triggered, this, [this] {
d->setCurrentIndex(d->currentIndex + 1);
});
d->nextAction->setEnabled(true);
mainLayout->addWidget(toolBar);
}
mainLayout->addLayout(layout);
d->messageViewer = new MimeTreeParser::Widgets::MessageViewer(this);
d->messageViewer->setMessage(d->messages[0]);
layout->addWidget(d->messageViewer);
auto buttonBox = new QDialogButtonBox(this);
+ buttonBox->setContentsMargins(style()->pixelMetric(QStyle::PM_LayoutLeftMargin, nullptr, this),
+ style()->pixelMetric(QStyle::PM_LayoutTopMargin, nullptr, this),
+ style()->pixelMetric(QStyle::PM_LayoutRightMargin, nullptr, this),
+ style()->pixelMetric(QStyle::PM_LayoutBottomMargin, nullptr, this));
auto closeButton = buttonBox->addButton(QDialogButtonBox::Close);
connect(closeButton, &QPushButton::pressed, this, &QDialog::accept);
layout->addWidget(buttonBox);
}
MessageViewerDialog::~MessageViewerDialog() = default;
QList<KMime::Message::Ptr> MessageViewerDialog::messages() const
{
return d->messages;
}
#include "moc_messageviewerdialog.cpp"

File Metadata

Mime Type
text/x-diff
Expires
Mon, Dec 8, 11:08 AM (1 d, 19 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
97/55/0c65a82e4423820e9a24eaec10cd

Event Timeline