Messagelib

attachmentpropertiesdialog.cpp
1 /*
2  SPDX-FileCopyrightText: 2009 Constantin Berzan <[email protected]>
3 
4  Based on KMail code by various authors (kmmsgpartdlg).
5 
6  SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 #include "attachmentpropertiesdialog.h"
10 
11 #include "attachmentfrommimecontentjob.h"
12 #include "ui_attachmentpropertiesdialog.h"
13 #include "ui_attachmentpropertiesdialog_readonly.h"
14 
15 #include "messagecore_debug.h"
16 #include <KAboutData>
17 #include <PimCommon/PimUtil>
18 
19 #include <KMime/Content>
20 #include <KMime/Headers>
21 
22 #include <KFormat>
23 #include <KLocalizedString>
24 #include <QDialogButtonBox>
25 #include <QMimeDatabase>
26 #include <QMimeType>
27 #include <QPushButton>
28 #include <QVBoxLayout>
29 
30 using namespace MessageCore;
31 
32 class Q_DECL_HIDDEN MessageCore::AttachmentPropertiesDialog::AttachmentPropertiesDialogPrivate
33 {
34 public:
35  AttachmentPropertiesDialogPrivate(AttachmentPropertiesDialog *qq)
36  : q(qq)
37  {
38  }
39 
40  ~AttachmentPropertiesDialogPrivate()
41  {
42  delete ui;
43  delete uiReadOnly;
44  }
45 
46  void init(const AttachmentPart::Ptr &part, bool readOnly);
47  void polishUi();
48  void mimeTypeChanged(const QString &type); // slot
49  void populateEncodings();
50  void populateMimeTypes();
51  void populateWhatsThis();
52  void loadFromPart();
53  void saveToPart();
54 
56  AttachmentPart::Ptr mPart;
57 
58  Ui::AttachmentPropertiesDialog *ui = nullptr;
59  Ui::AttachmentPropertiesDialogReadOnly *uiReadOnly = nullptr;
60  QVBoxLayout *mainLayout = nullptr;
61  bool mReadOnly = false;
62 };
63 
64 void AttachmentPropertiesDialog::AttachmentPropertiesDialogPrivate::init(const AttachmentPart::Ptr &part, bool readOnly)
65 {
66  mReadOnly = readOnly;
67  mPart = part;
68 
69  auto widget = new QWidget(q);
70  mainLayout = new QVBoxLayout;
71  q->setLayout(mainLayout);
72 
73  mainLayout->addWidget(widget);
74  if (mReadOnly) {
75  uiReadOnly = new Ui::AttachmentPropertiesDialogReadOnly;
76  uiReadOnly->setupUi(widget);
77  } else {
78  ui = new Ui::AttachmentPropertiesDialog;
79  ui->setupUi(widget);
80  }
81  polishUi();
82  q->setModal(true);
83 
84  loadFromPart();
85 }
86 
87 void AttachmentPropertiesDialog::AttachmentPropertiesDialogPrivate::polishUi()
88 {
89  // Tweak the dialog, depending on whether it is read-only or not.
90  QDialogButtonBox *buttonBox = nullptr;
91 
92  if (mReadOnly) {
94  } else {
95  // Update the icon when the selected mime type changes.
96 
97  connect(ui->mimeType, qOverload<const QString &>(&QComboBox::currentTextChanged), q, [this](const QString &str) {
98  mimeTypeChanged(str);
99  });
100  populateMimeTypes();
101  populateEncodings();
103  QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
104  okButton->setDefault(true);
105  okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
106  }
107  q->connect(buttonBox->button(QDialogButtonBox::Help), &QAbstractButton::clicked, q, &AttachmentPropertiesDialog::slotHelp);
108  q->connect(buttonBox, &QDialogButtonBox::accepted, q, &QDialog::accept);
109  q->connect(buttonBox, &QDialogButtonBox::rejected, q, &QDialog::reject);
110  mainLayout->addWidget(buttonBox);
111  populateWhatsThis();
112 }
113 
114 void AttachmentPropertiesDialog::AttachmentPropertiesDialogPrivate::mimeTypeChanged(const QString &type)
115 {
116  QMimeDatabase db;
117  const QMimeType mimeType = db.mimeTypeForName(type);
118  QPixmap pix =
119  QIcon::fromTheme(mimeType.iconName(), QIcon::fromTheme(QStringLiteral("unknown"))).pixmap(q->style()->pixelMetric(QStyle::PM_MessageBoxIconSize));
120 
121  if (mReadOnly) {
122  uiReadOnly->mimeIcon->setPixmap(pix);
123  } else {
124  ui->mimeIcon->setPixmap(pix);
125  }
126 }
127 
128 void AttachmentPropertiesDialog::AttachmentPropertiesDialogPrivate::populateWhatsThis()
129 {
130  // FIXME These are such a mess... Make them straightforward and pretty.
131 
132  const QString msgMimeType = i18n(
133  "<p>The <em>MIME type</em> of the file:</p>"
134  "<p>Normally, you do not need to touch this setting, since the "
135  "type of the file is automatically checked; but, sometimes, %1 "
136  "may not detect the type correctly -- here is where you can fix "
137  "that.</p>",
138  KAboutData::applicationData().componentName());
139 
140  const QString msgSize = i18n(
141  "<p>The estimated size of the attachment:</p>"
142  "<p>Note that, in an email message, a binary file encoded with "
143  "base64 will take up four thirds the actual size of the file.</p>");
144 
145  const QString msgName = i18n(
146  "<p>The file name of the part:</p>"
147  "<p>Although this defaults to the name of the attached file, "
148  "it does not specify the file to be attached; rather, it "
149  "suggests a file name to be used by the recipient's mail agent "
150  "when saving the part to disk.</p>");
151 
152  const QString msgDescription = i18n(
153  "<p>A description of the part:</p>"
154  "<p>This is just an informational description of the part, "
155  "much like the Subject is for the whole message; most "
156  "mail agents will show this information in their message "
157  "previews alongside the attachment's icon.</p>");
158 
159  const QString msgEncoding = i18n(
160  "<p>The transport encoding of this part:</p>"
161  "<p>Normally, you do not need to change this, since %1 will use "
162  "a decent default encoding, depending on the MIME type; yet, "
163  "sometimes, you can significantly reduce the size of the "
164  "resulting message, e.g. if a PostScript file does not contain "
165  "binary data, but consists of pure text -- in this case, choosing "
166  "\"quoted-printable\" over the default \"base64\" will save up "
167  "to 25% in resulting message size.</p>",
168  KAboutData::applicationData().componentName());
169 
170  const QString msgAutoDisplay = i18n(
171  "<p>Check this option if you want to suggest to the "
172  "recipient the automatic (inline) display of this part in the "
173  "message preview, instead of the default icon view;</p>"
174  "<p>Technically, this is carried out by setting this part's "
175  "<em>Content-Disposition</em> header field to \"inline\" "
176  "instead of the default \"attachment\".</p>");
177 
178  const QString msgSign = i18n(
179  "<p>Check this option if you want this message part to be "
180  "signed.</p>"
181  "<p>The signature will be made with the key that you associated "
182  "with the currently-selected identity.</p>");
183 
184  const QString msgEncrypt = i18n(
185  "<p>Check this option if you want this message part to be "
186  "encrypted.</p>"
187  "<p>The part will be encrypted for the recipients of this "
188  "message.</p>");
189 
190  if (mReadOnly) {
191  uiReadOnly->size->setWhatsThis(msgSize);
192  uiReadOnly->name->setWhatsThis(msgName);
193  uiReadOnly->encoding->setWhatsThis(msgEncoding);
194  } else {
195  ui->mimeType->setWhatsThis(msgMimeType);
196  ui->size->setWhatsThis(msgSize);
197  ui->name->setWhatsThis(msgName);
198  ui->encrypt->setWhatsThis(msgEncrypt);
199  ui->sign->setWhatsThis(msgSign);
200  ui->autoDisplay->setWhatsThis(msgAutoDisplay);
201  ui->encoding->setWhatsThis(msgEncoding);
202  ui->description->setWhatsThis(msgDescription);
203  }
204 }
205 
206 void AttachmentPropertiesDialog::AttachmentPropertiesDialogPrivate::populateEncodings()
207 {
208  using namespace KMime;
209  using namespace KMime::Headers;
210 
211  ui->encoding->clear();
212  ui->encoding->addItem(nameForEncoding(CE7Bit), int(CE7Bit));
213  ui->encoding->addItem(nameForEncoding(CE8Bit), int(CE8Bit));
214  ui->encoding->addItem(nameForEncoding(CEquPr), int(CEquPr));
215  ui->encoding->addItem(nameForEncoding(CEbase64), int(CEbase64));
216 
217  // TODO 8bit should be disabled if it is disabled in Settings.
218  // Also, if it's a message/* part, base64 and qp should be disabled.
219  // But since this is a dialog for power users anyway, let them shoot
220  // themselves in the foot. (The AttachmentJob will fail when they
221  // try to compose the message.)
222 }
223 
224 void AttachmentPropertiesDialog::AttachmentPropertiesDialogPrivate::populateMimeTypes()
225 {
226  const QStringList list = QStringList() << QStringLiteral("text/html") << QStringLiteral("text/plain") << QStringLiteral("image/gif")
227  << QStringLiteral("image/jpeg") << QStringLiteral("image/png") << QStringLiteral("application/octet-stream")
228  << QStringLiteral("application/x-gunzip") << QStringLiteral("application/zip");
229 
230  ui->mimeType->addItems(list);
231 }
232 
233 void AttachmentPropertiesDialog::AttachmentPropertiesDialogPrivate::loadFromPart()
234 {
235  Q_ASSERT(mPart);
236 
237  if (mReadOnly) {
238  uiReadOnly->mimeType->setText(QString::fromLatin1(mPart->mimeType()));
239  mimeTypeChanged(QString::fromLatin1(mPart->mimeType()));
240  uiReadOnly->size->setText(KFormat().formatByteSize(mPart->size()));
241  uiReadOnly->name->setText(mPart->name().isEmpty() ? mPart->fileName() : mPart->name());
242  if (mPart->description().isEmpty()) {
243  uiReadOnly->description->hide();
244  uiReadOnly->descriptionLabel->hide();
245  } else {
246  uiReadOnly->description->setText(mPart->description());
247  }
248  uiReadOnly->encoding->setText(KMime::nameForEncoding(mPart->encoding()));
249  } else {
250  const QString mimeType = QString::fromLatin1(mPart->mimeType());
251  const int index = ui->mimeType->findText(mimeType);
252  if (index == -1) {
253  ui->mimeType->insertItem(0, mimeType);
254  ui->mimeType->setCurrentIndex(0);
255  } else {
256  ui->mimeType->setCurrentIndex(index);
257  }
258  ui->size->setText(KFormat().formatByteSize(mPart->size()));
259  ui->name->setText(mPart->name().isEmpty() ? mPart->fileName() : mPart->name());
260  ui->description->setText(mPart->description());
261  ui->encoding->setCurrentIndex(int(mPart->encoding()));
262  ui->autoDisplay->setChecked(mPart->isInline());
263  ui->encrypt->setChecked(mPart->isEncrypted());
264  ui->sign->setChecked(mPart->isSigned());
265  }
266 }
267 
268 static QString removeNewlines(const QString &input)
269 {
270  QString ret(input);
271  ret.replace(QLatin1Char('\n'), QLatin1Char(' '));
272  return ret;
273 }
274 
275 void AttachmentPropertiesDialog::AttachmentPropertiesDialogPrivate::saveToPart()
276 {
277  Q_ASSERT(mPart);
278  Q_ASSERT(!mReadOnly);
279 
280  if (mReadOnly) {
281  return;
282  }
283  mPart->setMimeType(ui->mimeType->currentText().toLatin1());
284  const QString name = removeNewlines(ui->name->text());
285  mPart->setName(name);
286  mPart->setFileName(name);
287  mPart->setDescription(removeNewlines(ui->description->text()));
288  mPart->setInline(ui->autoDisplay->isChecked());
289  mPart->setSigned(ui->sign->isChecked());
290  mPart->setEncrypted(ui->encrypt->isChecked());
291  mPart->setInline(ui->autoDisplay->isChecked());
292 
293  if (ui->mimeType->currentText().startsWith(QLatin1String("message")) && ui->encoding->itemData(ui->encoding->currentIndex()) != KMime::Headers::CE7Bit
294  && ui->encoding->itemData(ui->encoding->currentIndex()) != KMime::Headers::CE8Bit) {
295  qCWarning(MESSAGECORE_LOG) << R"(Encoding on message/rfc822 must be "7bit" or "8bit".)";
296  }
297 
298  mPart->setEncoding(KMime::Headers::contentEncoding(ui->encoding->itemData(ui->encoding->currentIndex()).toInt()));
299 }
300 
302  : QDialog(parent)
303  , d(new AttachmentPropertiesDialogPrivate(this))
304 {
305  d->init(part, readOnly);
306  setWindowTitle(i18nc("@title:window", "Attachment Properties"));
307 }
308 
310  : QDialog(parent)
311  , d(new AttachmentPropertiesDialogPrivate(this))
312 {
313  auto job = new AttachmentFromMimeContentJob(content, this);
314  job->exec();
315  if (job->error()) {
316  qCCritical(MESSAGECORE_LOG) << "AttachmentFromMimeContentJob failed." << job->errorString();
317  }
318 
319  const AttachmentPart::Ptr part = job->attachmentPart();
320  d->init(part, true);
321  setWindowTitle(i18nc("@title:window", "Attachment Properties"));
322 }
323 
325 
327 {
328  return d->mPart;
329 }
330 
332 {
333  if (d->ui) {
334  return d->ui->encrypt->isEnabled();
335  }
336  return false;
337 }
338 
340 {
341  if (d->ui) {
342  d->ui->encrypt->setEnabled(enabled);
343  }
344 }
345 
347 {
348  if (d->ui) {
349  return d->ui->sign->isEnabled();
350  }
351  return false;
352 }
353 
355 {
356  if (d->ui) {
357  d->ui->sign->setEnabled(enabled);
358  }
359 }
360 
361 void AttachmentPropertiesDialog::accept()
362 {
363  if (!d->mReadOnly) {
364  d->saveToPart();
365  }
366 
367  QDialog::accept();
368 }
369 
370 void AttachmentPropertiesDialog::slotHelp()
371 {
372  PimCommon::Util::invokeHelp(QStringLiteral("kmail2/the-composer-window.html"), QStringLiteral("attachments"));
373 }
374 
375 #include "moc_attachmentpropertiesdialog.cpp"
virtual void reject()
AttachmentPart::Ptr attachmentPart() const
Returns the modified attachment.
static KAboutData applicationData()
int size() const const
AttachmentPropertiesDialog(const AttachmentPart::Ptr &part, bool readOnly=false, QWidget *parent=nullptr)
Creates a new attachment properties dialog.
const QLatin1String name
A job to load an attachment from a mime content.
void setEncryptEnabled(bool enabled)
Sets whether the encryption status of the attachment can be changed.
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
~AttachmentPropertiesDialog() override
Destroys the attachment properties dialog.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
void clicked(bool checked)
void setShortcut(const QKeySequence &key)
QMimeType mimeTypeForName(const QString &nameOrAlias) const const
virtual void accept()
void currentTextChanged(const QString &text)
QCA_EXPORT void init()
QString i18n(const char *text, const TYPE &arg...)
PM_MessageBoxIconSize
bool isEncryptEnabled() const
Returns whether the encryption status of the attachment can be changed.
void setWindowTitle(const QString &)
A dialog for editing attachment properties.
QString fromLatin1(const char *str, int size)
QPushButton * button(QDialogButtonBox::StandardButton which) const const
QIcon fromTheme(const QString &name)
QString mimeType(Type)
QObject * parent() const const
bool isSignEnabled() const
Returns whether the signature status of the attachment can be changed.
void setDefault(bool)
void setSignEnabled(bool enabled)
Sets whether the signature status of the attachment can be changed.
Key_Return
KIOFILEWIDGETS_EXPORT QStringList list(const QString &fileClass)
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Nov 30 2021 23:05:45 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.