File indexing completed on 2024-04-28 05:11:32
0001 /* 0002 SPDX-FileCopyrightText: 2010 Bertjan Broeksema <broeksema@kde.org> 0003 SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "incidenceattachment.h" 0009 #include "attachmenteditdialog.h" 0010 #include "attachmenticonview.h" 0011 #include "ui_dialogdesktop.h" 0012 0013 #include <CalendarSupport/UriHandler> 0014 0015 #include <KContacts/VCardDrag> 0016 0017 #include <KMime/Message> 0018 0019 #include <KActionCollection> 0020 #include <KIO/FileCopyJob> 0021 #include <KIO/JobUiDelegate> 0022 #include <KIO/JobUiDelegateFactory> 0023 #include <KIO/OpenUrlJob> 0024 #include <KIO/StoredTransferJob> 0025 #include <KJobWidgets> 0026 #include <KLocalizedString> 0027 #include <KMessageBox> 0028 #include <KProtocolManager> 0029 #include <QAction> 0030 #include <QFileDialog> 0031 #include <QIcon> 0032 #include <QMenu> 0033 #include <QUrl> 0034 0035 #include <QClipboard> 0036 #include <QMimeData> 0037 #include <QMimeDatabase> 0038 #include <QMimeType> 0039 0040 using namespace IncidenceEditorNG; 0041 0042 IncidenceAttachment::IncidenceAttachment(Ui::EventOrTodoDesktop *ui) 0043 : IncidenceEditor(nullptr) 0044 , mUi(ui) 0045 , mPopupMenu(new QMenu) 0046 { 0047 setupActions(); 0048 setupAttachmentIconView(); 0049 setObjectName(QLatin1StringView("IncidenceAttachment")); 0050 0051 connect(mUi->mAddButton, &QPushButton::clicked, this, &IncidenceAttachment::addAttachment); 0052 connect(mUi->mRemoveButton, &QPushButton::clicked, this, &IncidenceAttachment::removeSelectedAttachments); 0053 } 0054 0055 IncidenceAttachment::~IncidenceAttachment() 0056 { 0057 delete mPopupMenu; 0058 } 0059 0060 void IncidenceAttachment::load(const KCalendarCore::Incidence::Ptr &incidence) 0061 { 0062 mLoadedIncidence = incidence; 0063 mAttachmentView->clear(); 0064 0065 KCalendarCore::Attachment::List attachments = incidence->attachments(); 0066 for (KCalendarCore::Attachment::List::ConstIterator it = attachments.constBegin(), end = attachments.constEnd(); it != end; ++it) { 0067 new AttachmentIconItem((*it), mAttachmentView); 0068 } 0069 0070 mWasDirty = false; 0071 } 0072 0073 void IncidenceAttachment::save(const KCalendarCore::Incidence::Ptr &incidence) 0074 { 0075 incidence->clearAttachments(); 0076 0077 for (int itemIndex = 0; itemIndex < mAttachmentView->count(); ++itemIndex) { 0078 QListWidgetItem *item = mAttachmentView->item(itemIndex); 0079 auto attitem = dynamic_cast<AttachmentIconItem *>(item); 0080 Q_ASSERT(item); 0081 incidence->addAttachment(attitem->attachment()); 0082 } 0083 } 0084 0085 bool IncidenceAttachment::isDirty() const 0086 { 0087 if (mLoadedIncidence) { 0088 if (mAttachmentView->count() != mLoadedIncidence->attachments().count()) { 0089 return true; 0090 } 0091 0092 KCalendarCore::Attachment::List origAttachments = mLoadedIncidence->attachments(); 0093 for (int itemIndex = 0; itemIndex < mAttachmentView->count(); ++itemIndex) { 0094 QListWidgetItem *item = mAttachmentView->item(itemIndex); 0095 Q_ASSERT(dynamic_cast<AttachmentIconItem *>(item)); 0096 0097 const KCalendarCore::Attachment listAttachment = static_cast<AttachmentIconItem *>(item)->attachment(); 0098 0099 for (int i = 0; i < origAttachments.count(); ++i) { 0100 const KCalendarCore::Attachment attachment = origAttachments.at(i); 0101 0102 if (attachment == listAttachment) { 0103 origAttachments.remove(i); 0104 break; 0105 } 0106 } 0107 } 0108 // All attachments are removed from the list, meaning, the items in mAttachmentView 0109 // are equal to the attachments set on mLoadedIncidence. 0110 return !origAttachments.isEmpty(); 0111 } else { 0112 // No incidence loaded, so if the user added attachments we're dirty. 0113 return mAttachmentView->count() != 0; 0114 } 0115 } 0116 0117 int IncidenceAttachment::attachmentCount() const 0118 { 0119 return mAttachmentView->count(); 0120 } 0121 0122 /// Private slots 0123 0124 void IncidenceAttachment::addAttachment() 0125 { 0126 QPointer<QObject> that(this); 0127 auto item = new AttachmentIconItem(KCalendarCore::Attachment(), mAttachmentView); 0128 0129 QPointer<AttachmentEditDialog> dialog(new AttachmentEditDialog(item, mAttachmentView)); 0130 dialog->setWindowTitle(i18nc("@title", "Add Attachment")); 0131 auto dialogResult = dialog->exec(); 0132 if (!that) { 0133 return; 0134 } 0135 0136 if (dialogResult == QDialog::Rejected) { 0137 delete item; 0138 } else { 0139 Q_EMIT attachmentCountChanged(mAttachmentView->count()); 0140 } 0141 delete dialog; 0142 0143 checkDirtyStatus(); 0144 } 0145 0146 void IncidenceAttachment::copyToClipboard() 0147 { 0148 #ifndef QT_NO_CLIPBOARD 0149 QApplication::clipboard()->setMimeData(mAttachmentView->mimeData(), QClipboard::Clipboard); 0150 #endif 0151 } 0152 0153 void IncidenceAttachment::openURL(const QUrl &url) 0154 { 0155 QString uri = url.url(); 0156 CalendarSupport::UriHandler::process(uri); 0157 } 0158 0159 void IncidenceAttachment::pasteFromClipboard() 0160 { 0161 #ifndef QT_NO_CLIPBOARD 0162 handlePasteOrDrop(QApplication::clipboard()->mimeData()); 0163 #endif 0164 } 0165 0166 void IncidenceAttachment::removeSelectedAttachments() 0167 { 0168 QList<QListWidgetItem *> selected; 0169 QStringList labels; 0170 selected.reserve(mAttachmentView->count()); 0171 labels.reserve(mAttachmentView->count()); 0172 0173 for (int itemIndex = 0; itemIndex < mAttachmentView->count(); ++itemIndex) { 0174 QListWidgetItem *it = mAttachmentView->item(itemIndex); 0175 if (it->isSelected()) { 0176 auto attitem = static_cast<AttachmentIconItem *>(it); 0177 if (attitem) { 0178 const KCalendarCore::Attachment att = attitem->attachment(); 0179 labels << att.label(); 0180 selected << it; 0181 } 0182 } 0183 } 0184 0185 if (selected.isEmpty()) { 0186 return; 0187 } 0188 0189 QString labelsStr = labels.join(QLatin1StringView("<nl/>")); 0190 0191 if (KMessageBox::questionTwoActions(nullptr, 0192 xi18nc("@info", "Do you really want to remove these attachments?<nl/>%1", labelsStr), 0193 i18nc("@title:window", "Remove Attachments?"), 0194 KStandardGuiItem::remove(), 0195 KStandardGuiItem::cancel(), 0196 QStringLiteral("calendarRemoveAttachments")) 0197 != KMessageBox::ButtonCode::PrimaryAction) { 0198 return; 0199 } 0200 0201 for (QList<QListWidgetItem *>::iterator it(selected.begin()), end(selected.end()); it != end; ++it) { 0202 int row = mAttachmentView->row(*it); 0203 QListWidgetItem *next = mAttachmentView->item(++row); 0204 QListWidgetItem *prev = mAttachmentView->item(--row); 0205 if (next) { 0206 next->setSelected(true); 0207 } else if (prev) { 0208 prev->setSelected(true); 0209 } 0210 delete *it; 0211 } 0212 0213 mAttachmentView->update(); 0214 Q_EMIT attachmentCountChanged(mAttachmentView->count()); 0215 checkDirtyStatus(); 0216 } 0217 0218 void IncidenceAttachment::saveAttachment(QListWidgetItem *item) 0219 { 0220 Q_ASSERT(item); 0221 Q_ASSERT(dynamic_cast<AttachmentIconItem *>(item)); 0222 0223 auto attitem = static_cast<AttachmentIconItem *>(item); 0224 if (attitem->attachment().isEmpty()) { 0225 return; 0226 } 0227 0228 KCalendarCore::Attachment att = attitem->attachment(); 0229 0230 // get the saveas file name 0231 const QString saveAsFile = QFileDialog::getSaveFileName(nullptr, i18nc("@title", "Save Attachment"), att.label()); 0232 0233 if (saveAsFile.isEmpty()) { 0234 return; 0235 } 0236 0237 QUrl sourceUrl; 0238 if (att.isUri()) { 0239 sourceUrl = QUrl(att.uri()); 0240 } else { 0241 sourceUrl = attitem->tempFileForAttachment(); 0242 } 0243 // save the attachment url 0244 auto job = KIO::file_copy(sourceUrl, QUrl::fromLocalFile(saveAsFile)); 0245 if (!job->exec() && job->error()) { 0246 KMessageBox::error(nullptr, job->errorString()); 0247 } 0248 } 0249 0250 void IncidenceAttachment::saveSelectedAttachments() 0251 { 0252 for (int itemIndex = 0; itemIndex < mAttachmentView->count(); ++itemIndex) { 0253 QListWidgetItem *item = mAttachmentView->item(itemIndex); 0254 if (item->isSelected()) { 0255 saveAttachment(item); 0256 } 0257 } 0258 } 0259 0260 void IncidenceAttachment::showAttachment(QListWidgetItem *item) 0261 { 0262 Q_ASSERT(item); 0263 Q_ASSERT(dynamic_cast<AttachmentIconItem *>(item)); 0264 auto attitem = static_cast<AttachmentIconItem *>(item); 0265 if (attitem->attachment().isEmpty()) { 0266 return; 0267 } 0268 0269 const KCalendarCore::Attachment att = attitem->attachment(); 0270 if (att.isUri()) { 0271 openURL(QUrl(att.uri())); 0272 } else { 0273 auto job = new KIO::OpenUrlJob(attitem->tempFileForAttachment(), att.mimeType()); 0274 job->setUiDelegate(KIO::createDefaultJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, mAttachmentView)); 0275 job->setDeleteTemporaryFile(true); 0276 job->start(); 0277 } 0278 } 0279 0280 void IncidenceAttachment::showContextMenu(const QPoint &pos) // clazy:exclude=function-args-by-value 0281 { 0282 const bool enable = mAttachmentView->itemAt(pos) != nullptr; 0283 0284 int numSelected = 0; 0285 for (int itemIndex = 0; itemIndex < mAttachmentView->count(); ++itemIndex) { 0286 QListWidgetItem *item = mAttachmentView->item(itemIndex); 0287 if (item->isSelected()) { 0288 numSelected++; 0289 } 0290 } 0291 0292 mOpenAction->setEnabled(enable); 0293 // TODO: support saving multiple attachments into a directory 0294 mSaveAsAction->setEnabled(enable && numSelected == 1); 0295 #ifndef QT_NO_CLIPBOARD 0296 mCopyAction->setEnabled(enable && numSelected == 1); 0297 mCutAction->setEnabled(enable && numSelected == 1); 0298 #endif 0299 mDeleteAction->setEnabled(enable); 0300 mEditAction->setEnabled(enable); 0301 mPopupMenu->exec(mAttachmentView->mapToGlobal(pos)); 0302 } 0303 0304 void IncidenceAttachment::showSelectedAttachments() 0305 { 0306 for (int itemIndex = 0; itemIndex < mAttachmentView->count(); ++itemIndex) { 0307 QListWidgetItem *item = mAttachmentView->item(itemIndex); 0308 if (item->isSelected()) { 0309 showAttachment(item); 0310 } 0311 } 0312 } 0313 0314 void IncidenceAttachment::cutToClipboard() 0315 { 0316 #ifndef QT_NO_CLIPBOARD 0317 copyToClipboard(); 0318 removeSelectedAttachments(); 0319 #endif 0320 } 0321 0322 void IncidenceAttachment::editSelectedAttachments() 0323 { 0324 for (int itemIndex = 0; itemIndex < mAttachmentView->count(); ++itemIndex) { 0325 QListWidgetItem *item = mAttachmentView->item(itemIndex); 0326 if (item->isSelected()) { 0327 Q_ASSERT(dynamic_cast<AttachmentIconItem *>(item)); 0328 0329 auto attitem = static_cast<AttachmentIconItem *>(item); 0330 if (attitem->attachment().isEmpty()) { 0331 return; 0332 } 0333 0334 QPointer<AttachmentEditDialog> dialog(new AttachmentEditDialog(attitem, mAttachmentView, false)); 0335 dialog->setModal(false); 0336 dialog->setAttribute(Qt::WA_DeleteOnClose, true); 0337 dialog->show(); 0338 } 0339 } 0340 } 0341 0342 void IncidenceAttachment::slotItemRenamed(QListWidgetItem *item) 0343 { 0344 Q_ASSERT(item); 0345 Q_ASSERT(dynamic_cast<AttachmentIconItem *>(item)); 0346 static_cast<AttachmentIconItem *>(item)->setLabel(item->text()); 0347 checkDirtyStatus(); 0348 } 0349 0350 void IncidenceAttachment::slotSelectionChanged() 0351 { 0352 bool selected = false; 0353 for (int itemIndex = 0; itemIndex < mAttachmentView->count(); ++itemIndex) { 0354 QListWidgetItem *item = mAttachmentView->item(itemIndex); 0355 if (item->isSelected()) { 0356 selected = true; 0357 break; 0358 } 0359 } 0360 mUi->mRemoveButton->setEnabled(selected); 0361 } 0362 0363 /// Private functions 0364 0365 void IncidenceAttachment::handlePasteOrDrop(const QMimeData *mimeData) 0366 { 0367 if (!mimeData) { 0368 return; 0369 } 0370 QList<QUrl> urls; 0371 bool probablyWeHaveUris = false; 0372 QStringList labels; 0373 0374 if (KContacts::VCardDrag::canDecode(mimeData)) { 0375 KContacts::Addressee::List addressees; 0376 KContacts::VCardDrag::fromMimeData(mimeData, addressees); 0377 urls.reserve(addressees.count()); 0378 labels.reserve(addressees.count()); 0379 const KContacts::Addressee::List::ConstIterator end(addressees.constEnd()); 0380 for (KContacts::Addressee::List::ConstIterator it = addressees.constBegin(); it != end; ++it) { 0381 urls.append(QUrl(QStringLiteral("uid:") + (*it).uid())); 0382 // there is some weirdness about realName(), hence fromUtf8 0383 labels.append(QString::fromUtf8((*it).realName().toLatin1())); 0384 } 0385 probablyWeHaveUris = true; 0386 } else if (mimeData->hasUrls()) { 0387 QMap<QString, QString> metadata; 0388 0389 // QT5 0390 // urls = QList<QUrl>::fromMimeData( mimeData, &metadata ); 0391 probablyWeHaveUris = true; 0392 labels = metadata[QStringLiteral("labels")].split(QLatin1Char(':'), Qt::SkipEmptyParts); 0393 const QStringList::Iterator end(labels.end()); 0394 for (QStringList::Iterator it = labels.begin(); it != end; ++it) { 0395 *it = QUrl::fromPercentEncoding((*it).toLatin1()); 0396 } 0397 } else if (mimeData->hasText()) { 0398 const QString text = mimeData->text(); 0399 QStringList lst = text.split(QLatin1Char('\n'), Qt::SkipEmptyParts); 0400 urls.reserve(lst.count()); 0401 QStringList::ConstIterator end(lst.constEnd()); 0402 for (QStringList::ConstIterator it = lst.constBegin(); it != end; ++it) { 0403 urls.append(QUrl(*it)); 0404 } 0405 probablyWeHaveUris = true; 0406 } 0407 QMenu menu; 0408 QAction *linkAction = nullptr; 0409 QAction *cancelAction = nullptr; 0410 if (probablyWeHaveUris) { 0411 linkAction = menu.addAction(QIcon::fromTheme(QStringLiteral("insert-link")), i18nc("@action:inmenu", "&Link here")); 0412 // we need to check if we can reasonably expect to copy the objects 0413 bool weCanCopy = true; 0414 QList<QUrl>::ConstIterator end(urls.constEnd()); 0415 for (QList<QUrl>::ConstIterator it = urls.constBegin(); it != end; ++it) { 0416 if (!(weCanCopy = KProtocolManager::supportsReading(*it))) { 0417 break; // either we can copy them all, or no copying at all 0418 } 0419 } 0420 if (weCanCopy) { 0421 menu.addAction(QIcon::fromTheme(QStringLiteral("edit-copy")), i18nc("@action:inmenu", "&Copy here")); 0422 } 0423 } else { 0424 menu.addAction(QIcon::fromTheme(QStringLiteral("edit-copy")), i18nc("@action:inmenu", "&Copy here")); 0425 } 0426 0427 menu.addSeparator(); 0428 cancelAction = menu.addAction(QIcon::fromTheme(QStringLiteral("process-stop")), i18nc("@action:inmenu", "C&ancel")); 0429 0430 QByteArray data; 0431 QString mimeType; 0432 QString label; 0433 0434 if (!mimeData->formats().isEmpty() && !probablyWeHaveUris) { 0435 mimeType = mimeData->formats().first(); 0436 data = mimeData->data(mimeType); 0437 QMimeDatabase db; 0438 QMimeType mime = db.mimeTypeForName(mimeType); 0439 if (mime.isValid()) { 0440 label = mime.comment(); 0441 } 0442 } 0443 0444 QAction *ret = menu.exec(QCursor::pos()); 0445 if (linkAction == ret) { 0446 QStringList::ConstIterator jt = labels.constBegin(); 0447 const QList<QUrl>::ConstIterator jtEnd = urls.constEnd(); 0448 for (QList<QUrl>::ConstIterator it = urls.constBegin(); it != jtEnd; ++it) { 0449 addUriAttachment((*it).url(), QString(), (jt == labels.constEnd() ? QString() : *(jt++)), true); 0450 } 0451 } else if (cancelAction != ret) { 0452 if (probablyWeHaveUris) { 0453 QList<QUrl>::ConstIterator end = urls.constEnd(); 0454 for (QList<QUrl>::ConstIterator it = urls.constBegin(); it != end; ++it) { 0455 KIO::Job *job = KIO::storedGet(*it); 0456 // TODO verify if slot exist ! 0457 connect(job, &KIO::Job::result, this, &IncidenceAttachment::downloadComplete); 0458 } 0459 } else { // we take anything 0460 addDataAttachment(data, mimeType, label); 0461 } 0462 } 0463 } 0464 0465 void IncidenceAttachment::downloadComplete(KJob *) 0466 { 0467 // TODO 0468 } 0469 0470 void IncidenceAttachment::setupActions() 0471 { 0472 auto ac = new KActionCollection(this); 0473 // ac->addAssociatedWidget( this ); 0474 0475 mOpenAction = new QAction(QIcon::fromTheme(QStringLiteral("document-open")), i18nc("@action:inmenu open the attachment in a viewer", "&Open"), this); 0476 connect(mOpenAction, &QAction::triggered, this, &IncidenceAttachment::showSelectedAttachments); 0477 ac->addAction(QStringLiteral("view"), mOpenAction); 0478 mPopupMenu->addAction(mOpenAction); 0479 0480 mSaveAsAction = 0481 new QAction(QIcon::fromTheme(QStringLiteral("document-save-as")), i18nc("@action:inmenu save the attachment to a file", "Save As..."), this); 0482 connect(mSaveAsAction, &QAction::triggered, this, &IncidenceAttachment::saveSelectedAttachments); 0483 mPopupMenu->addAction(mSaveAsAction); 0484 mPopupMenu->addSeparator(); 0485 0486 #ifndef QT_NO_CLIPBOARD 0487 mCopyAction = KStandardAction::copy(this, &IncidenceAttachment::copyToClipboard, ac); 0488 mPopupMenu->addAction(mCopyAction); 0489 0490 mCutAction = KStandardAction::cut(this, &IncidenceAttachment::cutToClipboard, ac); 0491 mPopupMenu->addAction(mCutAction); 0492 0493 QAction *action = KStandardAction::paste(this, &IncidenceAttachment::pasteFromClipboard, ac); 0494 mPopupMenu->addAction(action); 0495 mPopupMenu->addSeparator(); 0496 #endif 0497 0498 mDeleteAction = new QAction(QIcon::fromTheme(QStringLiteral("list-remove")), i18nc("@action:inmenu remove the attachment", "&Remove"), this); 0499 connect(mDeleteAction, &QAction::triggered, this, &IncidenceAttachment::removeSelectedAttachments); 0500 ac->addAction(QStringLiteral("remove"), mDeleteAction); 0501 mDeleteAction->setShortcut(Qt::Key_Delete); 0502 mPopupMenu->addAction(mDeleteAction); 0503 mPopupMenu->addSeparator(); 0504 0505 mEditAction = new QAction(QIcon::fromTheme(QStringLiteral("document-properties")), 0506 i18nc("@action:inmenu show a dialog used to edit the attachment", "&Properties..."), 0507 this); 0508 connect(mEditAction, &QAction::triggered, this, &IncidenceAttachment::editSelectedAttachments); 0509 ac->addAction(QStringLiteral("edit"), mEditAction); 0510 mPopupMenu->addAction(mEditAction); 0511 } 0512 0513 void IncidenceAttachment::setupAttachmentIconView() 0514 { 0515 mAttachmentView = new AttachmentIconView; 0516 mAttachmentView->setWhatsThis(i18nc("@info:whatsthis", 0517 "Displays items (files, mail, etc.) that " 0518 "have been associated with this event or to-do.")); 0519 0520 connect(mAttachmentView, &AttachmentIconView::itemDoubleClicked, this, &IncidenceAttachment::showAttachment); 0521 connect(mAttachmentView, &AttachmentIconView::itemChanged, this, &IncidenceAttachment::slotItemRenamed); 0522 connect(mAttachmentView, &AttachmentIconView::itemSelectionChanged, this, &IncidenceAttachment::slotSelectionChanged); 0523 connect(mAttachmentView, &AttachmentIconView::customContextMenuRequested, this, &IncidenceAttachment::showContextMenu); 0524 0525 auto layout = new QGridLayout(mUi->mAttachmentViewPlaceHolder); 0526 layout->setContentsMargins(0, 0, 0, 0); 0527 layout->addWidget(mAttachmentView); 0528 QWidget::setTabOrder(mUi->mAddButton, mAttachmentView); 0529 } 0530 0531 // void IncidenceAttachmentEditor::addAttachment( KCalendarCore::Attachment *attachment ) 0532 // { 0533 // new AttachmentIconItem( attachment, mAttachmentView ); 0534 // } 0535 0536 void IncidenceAttachment::addDataAttachment(const QByteArray &data, const QString &mimeType, const QString &label) 0537 { 0538 auto item = new AttachmentIconItem(KCalendarCore::Attachment(), mAttachmentView); 0539 0540 QString nlabel = label; 0541 if (mimeType == QLatin1StringView("message/rfc822")) { 0542 // mail message. try to set the label from the mail Subject: 0543 KMime::Message msg; 0544 msg.setContent(data); 0545 msg.parse(); 0546 nlabel = msg.subject()->asUnicodeString(); 0547 } 0548 0549 item->setData(data); 0550 item->setLabel(nlabel); 0551 if (mimeType.isEmpty()) { 0552 QMimeDatabase db; 0553 item->setMimeType(db.mimeTypeForData(data).name()); 0554 } else { 0555 item->setMimeType(mimeType); 0556 } 0557 0558 checkDirtyStatus(); 0559 } 0560 0561 void IncidenceAttachment::addUriAttachment(const QString &uri, const QString &mimeType, const QString &label, bool inLine) 0562 { 0563 if (!inLine) { 0564 auto item = new AttachmentIconItem(KCalendarCore::Attachment(), mAttachmentView); 0565 item->setUri(uri); 0566 item->setLabel(label); 0567 if (mimeType.isEmpty()) { 0568 if (uri.startsWith(QLatin1StringView("uid:"))) { 0569 item->setMimeType(QStringLiteral("text/directory")); 0570 } else if (uri.startsWith(QLatin1StringView("kmail:"))) { 0571 item->setMimeType(QStringLiteral("message/rfc822")); 0572 } else if (uri.startsWith(QLatin1StringView("urn:x-ical"))) { 0573 item->setMimeType(QStringLiteral("text/calendar")); 0574 } else if (uri.startsWith(QLatin1StringView("news:"))) { 0575 item->setMimeType(QStringLiteral("message/news")); 0576 } else { 0577 QMimeDatabase db; 0578 item->setMimeType(db.mimeTypeForUrl(QUrl(uri)).name()); 0579 } 0580 } 0581 } else { 0582 auto job = KIO::storedGet(QUrl(uri)); 0583 KJobWidgets::setWindow(job, nullptr); 0584 if (job->exec()) { 0585 const QByteArray data = job->data(); 0586 addDataAttachment(data, mimeType, label); 0587 } 0588 } 0589 } 0590 0591 #include "moc_incidenceattachment.cpp"