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 <KIO/Global>
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, &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(KIO::convertSize(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(KIO::convertSize(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"
AttachmentPropertiesDialog(const AttachmentPart::Ptr &part, bool readOnly=false, QWidget *parent=nullptr)
Creates a new attachment properties dialog.
virtual void reject()
void setShortcut(const QKeySequence &key)
QCA_EXPORT void init()
void setEncryptEnabled(bool enabled)
Sets whether the encryption status of the attachment can be changed.
void clicked(bool checked)
QIcon fromTheme(const QString &name)
KCALUTILS_EXPORT QString mimeType()
KIOFILEWIDGETS_EXPORT QStringList list(const QString &fileClass)
~AttachmentPropertiesDialog() override
Destroys the attachment properties dialog.
A job to load an attachment from a mime content.
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
bool isSignEnabled() const
Returns whether the signature status of the attachment can be changed.
QString i18n(const char *text, const TYPE &arg...)
bool isEncryptEnabled() const
Returns whether the encryption status of the attachment can be changed.
QMimeType mimeTypeForName(const QString &nameOrAlias) const const
void currentTextChanged(const QString &text)
AttachmentPart::Ptr attachmentPart() const
Returns the modified attachment.
void setWindowTitle(const QString &)
virtual void accept()
static KAboutData applicationData()
A dialog for editing attachment properties.
Key_Return
PM_MessageBoxIconSize
QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) const const
QPushButton * button(QDialogButtonBox::StandardButton which) const const
QString fromLatin1(const char *str, int size)
QString name(StandardShortcut id)
void setSignEnabled(bool enabled)
Sets whether the signature status of the attachment can be changed.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
void setDefault(bool)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Sun Mar 26 2023 04:08:10 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.