diff --git a/src/Gui/PartWidget.cpp b/src/Gui/PartWidget.cpp index f73bd665..bb27604d 100644 --- a/src/Gui/PartWidget.cpp +++ b/src/Gui/PartWidget.cpp @@ -1,486 +1,506 @@ /* Copyright (C) 2006 - 2014 Jan Kundrát This file is part of the Trojita Qt IMAP e-mail client, http://trojita.flaska.net/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License or (at your option) version 3 or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of version 3 of the license. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "PartWidget.h" #include #include #include #include #include #include #include #include #include "EnvelopeView.h" #include "LoadablePartWidget.h" #include "MessageView.h" #include "Common/InvokeMethod.h" #include "Cryptography/MessageModel.h" #include "Gui/Util.h" #include "Imap/Model/ItemRoles.h" #include "Imap/Model/MailboxTree.h" +#include "Imap/Parser/Message.h" #include "UiUtils/IconLoader.h" namespace { /** @short Unset flags which only make sense for one level of nesting */ UiUtils::PartLoadingOptions filteredForEmbedding(const UiUtils::PartLoadingOptions options) { return options & UiUtils::MASK_PROPAGATE_WHEN_EMBEDDING; } } namespace Gui { QString quoteMeHelper(const QObjectList &children) { QStringList res; for (QObjectList::const_iterator it = children.begin(); it != children.end(); ++it) { const AbstractPartWidget *w = dynamic_cast(*it); if (w) res += w->quoteMe(); } return res.join(QStringLiteral("\n")); } bool searchDialogRequestedHelper(const QObjectList &children) { for (QObject *obj : children) { AbstractPartWidget *w = dynamic_cast(obj); if (w && w->searchDialogRequested()) return true; } return false; } MultipartAlternativeWidget::MultipartAlternativeWidget(QWidget *parent, PartWidgetFactory *factory, const QModelIndex &partIndex, const int recursionDepth, const UiUtils::PartLoadingOptions options): QTabWidget(parent) { setContentsMargins(0,0,0,0); const bool plaintextIsPreferred = options & UiUtils::PART_PREFER_PLAINTEXT_OVER_HTML; // Which "textual, boring part" should be shown? int preferredTextIndex = -1; // Some part which is "strange", i.e. something to draw the user's attention to int someSuspiciousIndex = -1; // First loop iteration is used to find out what MIME type to show. // Two iterations are needed because we have to know about whether we're shown or hidden when creating child widgets. for (int i = 0; i < partIndex.model()->rowCount(partIndex); ++i) { QModelIndex anotherPart = partIndex.child(i, 0); Q_ASSERT(anotherPart.isValid()); QString mimeType = anotherPart.data(Imap::Mailbox::RolePartMimeType).toString(); const bool isPlainText = mimeType == QLatin1String("text/plain"); const bool isHtml = mimeType == QLatin1String("text/html"); // At first, check whether this is one of the textual parts which we like if (isPlainText && plaintextIsPreferred) { preferredTextIndex = i; } else if (isHtml && !plaintextIsPreferred) { preferredTextIndex = i; } if (!isPlainText && !isHtml && someSuspiciousIndex == -1) { someSuspiciousIndex = i; } } // Show that part which is "the most important". The choice is usually between text/plain and text/html, one of them will win, // depending on the user's preferences. If there are additional parts, the user will be alerted about them later on, and some // of these suspicious parts wins the race. // As usual, the later parts win in general. int preferredIndex = someSuspiciousIndex == -1 ? (preferredTextIndex == -1 ? partIndex.model()->rowCount(partIndex) - 1 : preferredTextIndex) : someSuspiciousIndex; // The second loop actually creates the widgets for (int i = 0; i < partIndex.model()->rowCount(partIndex); ++i) { QModelIndex anotherPart = partIndex.child(i, 0); Q_ASSERT(anotherPart.isValid()); // TODO: This is actually not perfect, the preferred part of a multipart/alternative // which is nested as a non-preferred part of another multipart/alternative actually gets loaded here. // I can live with that. QWidget *item = factory->walk(anotherPart, recursionDepth + 1, filteredForEmbedding(i == preferredIndex ? options : options | UiUtils::PART_IS_HIDDEN)); QString mimeType = anotherPart.data(Imap::Mailbox::RolePartMimeType).toString(); const bool isPlainText = mimeType == QLatin1String("text/plain"); const bool isHtml = mimeType == QLatin1String("text/html"); + const bool isCalendar = mimeType == QLatin1String("text/calendar"); if (isPlainText) { //: Translators: use something very short, perhaps even "text". Don't describe this as "Clear text". //: This string is used as a caption of a tab showing the plaintext part of a mail which is e.g. //: sent in both plaintext and HTML formats. mimeType = tr("Plaintext"); } else if (isHtml) { //: Translators: caption of the tab which shows a HTML version of the mail. Use some short, compact text here. mimeType = tr("HTML"); + } else if (isCalendar) { + using bodyFldParam_t = Imap::Message::AbstractMessage::bodyFldParam_t; + const auto bodyFldParam = anotherPart.data(Imap::Mailbox::RolePartBodyFldParam).value(); + auto method = bodyFldParam[QByteArray("METHOD")].toUpper(); + if (method == "CANCEL") { + mimeType = tr("Cancelled Event"); + } else if (method == "REQUEST") { + mimeType = tr("Meeting Request"); + } else if (method == "PUBLISH") { + mimeType = tr("Calendar Event"); + } else if (method == "REPLY") { + mimeType = tr("Calendar Reply"); + } else if (method == "ADD") { + mimeType = tr("New Meeting"); + } + // We do not handle REFRESH, COUNTER or DECLINECOUNTER because they are "too specific" for now } addTab(item, mimeType); // Bug 332950: some items nested within a multipart/alternative message are not exactly an alternative. // One such example is a text/calendar right next to a text/html and a text/plain. - if (!isPlainText && !isHtml) { + if (isCalendar) { + setTabIcon(i, UiUtils::loadIcon(QStringLiteral("text-calendar"))); + } else if (!isPlainText && !isHtml) { // Unfortunately we cannot change the tab background with current Qt (Q1 2014), // see https://bugreports.qt-project.org/browse/QTBUG-840 for details setTabIcon(i, UiUtils::loadIcon(QStringLiteral("emblem-important"))); } } setCurrentIndex(preferredIndex); tabBar()->installEventFilter(this); } QString MultipartAlternativeWidget::quoteMe() const { const AbstractPartWidget *w = dynamic_cast(currentWidget()); return w ? w->quoteMe() : QString(); } bool MultipartAlternativeWidget::searchDialogRequested() { AbstractPartWidget *w = dynamic_cast(currentWidget()); return w && w->searchDialogRequested(); } bool MultipartAlternativeWidget::eventFilter(QObject *o, QEvent *e) { if (e->type() == QEvent::Wheel && qobject_cast(o)) { // don't alter part while wheeling e->ignore(); return true; } return false; } PartStatusWidget::PartStatusWidget(QWidget *parent) : QFrame(parent) , m_icon(new QLabel(this)) , m_text(new QLabel(this)) , m_details(new QLabel(this)) , m_seperator(new QFrame(this)) , m_detailButton(new QPushButton(tr("Show Details"), this)) { connect(m_detailButton, &QAbstractButton::clicked, this, &PartStatusWidget::showDetails); hide(); setAutoFillBackground(true); setBackgroundRole(QPalette::ToolTipBase); setForegroundRole(QPalette::ToolTipText); QGridLayout *layout = new QGridLayout(this); layout->addWidget(m_icon, 0, 0); layout->addWidget(m_text, 0, 1); layout->setColumnStretch(1, 1); layout->addWidget(m_detailButton, 0, 2); m_detailButton->hide(); m_seperator->setFrameStyle(QFrame::HLine); layout->addWidget(m_seperator, 1, 0, 1, 3); m_seperator->hide(); layout->addWidget(m_details, 2, 0, 1, 3); layout->setAlignment(m_details, 0); m_details->hide(); m_text->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); m_details->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); m_details->setWordWrap(true); m_details->setTextInteractionFlags(Qt::TextSelectableByMouse); } void PartStatusWidget::showStatus(const QString &icon, const QString &status, const QString &details) { m_icon->setPixmap(UiUtils::loadIcon(icon).pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize))); m_text->setText(status); m_details->setText(details); if (!details.isEmpty() && !m_detailButton->isVisible()) { m_detailButton->show(); } else if (details.isEmpty() && m_detailButton->isVisible()) { m_detailButton->hide(); } show(); } void PartStatusWidget::showDetails() { if (m_details->isVisible()) { m_details->hide(); m_seperator->hide(); m_detailButton->setText(tr("Show Details")); } else { m_details->show(); m_seperator->show(); m_detailButton->setText(tr("Hide Details")); } } AsynchronousPartWidget::AsynchronousPartWidget(QWidget *parent, PartWidgetFactory *factory, const QModelIndex &partIndex, const int recursionDepth, const UiUtils::PartLoadingOptions options) : QFrame(parent) , m_factory(factory) , m_partIndex(partIndex) , m_recursionDepth(recursionDepth) , m_options(options) { Q_ASSERT(partIndex.isValid()); auto model = qobject_cast(partIndex.model()); Q_ASSERT(model); connect(model, &QAbstractItemModel::rowsInserted, this, &AsynchronousPartWidget::handleRowsInserted); connect(model, &QAbstractItemModel::layoutChanged, this, &AsynchronousPartWidget::handleLayoutChanged); connect(model, &Cryptography::MessageModel::error, this, &AsynchronousPartWidget::handleError); connect(model, &QAbstractItemModel::dataChanged, this, &AsynchronousPartWidget::handleDataChanged); setContentsMargins(0, 0, 0, 0); QVBoxLayout *layout = new QVBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); m_statusWidget = new PartStatusWidget(this); layout->addWidget(m_statusWidget); // We have to call updateStatusIndicator from the derived classes here, // but dynamic binding does not work inside ctors. // The easiest way to make this work is a roundtrip through the event loop by using CALL_LATER CALL_LATER_NOARG(this, updateStatusIndicator); if (partIndex.model()->rowCount(partIndex)) { CALL_LATER(this, handleRowsInserted, Q_ARG(QModelIndex, partIndex), Q_ARG(int, 0), Q_ARG(int, partIndex.model()->rowCount(partIndex))); } } void AsynchronousPartWidget::handleRowsInserted(const QModelIndex &parent, int first, int last) { Q_UNUSED(first) Q_UNUSED(last) if (parent == m_partIndex) { buildWidgets(); // Trigger recalculation of the layout after adding children adjustSize(); } } void AsynchronousPartWidget::handleLayoutChanged(const QList &parents) { if ((parents.isEmpty() || parents.contains(m_partIndex.parent())) && m_partIndex.model()->rowCount(m_partIndex) > 0) { buildWidgets(); adjustSize(); } } void AsynchronousPartWidget::handleError(const QModelIndex &parent, const QString &status, const QString &details) { if (parent == m_partIndex) { disconnect(m_partIndex.model(), &QAbstractItemModel::rowsInserted, this, &AsynchronousPartWidget::handleRowsInserted); disconnect(m_partIndex.model(), &QAbstractItemModel::layoutChanged, this, &AsynchronousPartWidget::handleLayoutChanged); m_statusWidget->showStatus(QStringLiteral("dialog-error"), status, details); } } void AsynchronousPartWidget::buildWidgets() { Q_ASSERT(m_partIndex.isValid()); // The row count might be empty, maybe because the IMAP server refused to provide us // with valid cryptotext data for the individual encrypted parts disconnect(m_partIndex.model(), &QAbstractItemModel::rowsInserted, this, &MultipartSignedEncryptedWidget::handleRowsInserted); disconnect(m_partIndex.model(), &QAbstractItemModel::layoutChanged, this, &MultipartSignedEncryptedWidget::handleLayoutChanged); for (int i = 0; i < m_partIndex.model()->rowCount(m_partIndex); ++i) { QModelIndex anotherPart = m_partIndex.child(i, 0); Q_ASSERT(anotherPart.isValid()); QWidget *res = addingOneWidget(anotherPart, filteredForEmbedding(m_options)); layout()->addWidget(res); res->show(); } } QWidget *AsynchronousPartWidget::addingOneWidget(const QModelIndex &index, UiUtils::PartLoadingOptions options) { return m_factory->walk(index, m_recursionDepth + 1, options); } void AsynchronousPartWidget::handleDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { Q_ASSERT(topLeft == bottomRight); Q_UNUSED(bottomRight); if (topLeft == m_partIndex || !m_partIndex.isValid()) updateStatusIndicator(); } MultipartSignedEncryptedWidget::MultipartSignedEncryptedWidget(QWidget *parent, PartWidgetFactory *factory, const QModelIndex &partIndex, const int recursionDepth, const UiUtils::PartLoadingOptions loadingOptions) : AsynchronousPartWidget(parent, factory, partIndex, recursionDepth, loadingOptions) { setFrameStyle(QFrame::Box); } void MultipartSignedEncryptedWidget::updateStatusIndicator() { using namespace Imap::Mailbox; auto tldr = m_partIndex.data(RolePartCryptoTLDR); if (tldr.isValid()) { m_statusWidget->showStatus( m_partIndex.data(RolePartCryptoStatusIconName).toString(), tldr.toString(), m_partIndex.data(RolePartCryptoDetailedMessage).toString() ); } else { setFrameStyle(QFrame::NoFrame); } } QString MultipartSignedEncryptedWidget::quoteMe() const { return quoteMeHelper(children()); } bool MultipartSignedEncryptedWidget::searchDialogRequested() { return searchDialogRequestedHelper(children()); } QWidget *MultipartSignedEncryptedWidget::addingOneWidget(const QModelIndex &index, UiUtils::PartLoadingOptions options) { auto parent = index.parent(); if (parent.isValid() && parent.model()->rowCount(parent) == 2) { if (parent.data(Imap::Mailbox::RolePartMimeType).toByteArray() == "multipart/signed" && index.row() == 1) { // do not expand the signature options |= UiUtils::PART_IGNORE_INLINE; } else if (parent.data(Imap::Mailbox::RolePartMimeType).toByteArray() == "multipart/encrypted") { // click-to-show for everything within an encrypted message options |= UiUtils::PART_IGNORE_INLINE; } } return AsynchronousPartWidget::addingOneWidget(index, options); } GenericMultipartWidget::GenericMultipartWidget(QWidget *parent, PartWidgetFactory *factory, const QModelIndex &partIndex, int recursionDepth, const UiUtils::PartLoadingOptions options): QWidget(parent) { setContentsMargins(0, 0, 0, 0); // multipart/mixed or anything else, as mandated by RFC 2046, Section 5.1.3 QVBoxLayout *layout = new QVBoxLayout(this); layout->setSpacing(0); for (int i = 0; i < partIndex.model()->rowCount(partIndex); ++i) { using namespace Imap::Mailbox; QModelIndex anotherPart = partIndex.child(i, 0); Q_ASSERT(anotherPart.isValid()); // guaranteed by the MVC QWidget *res = factory->walk(anotherPart, recursionDepth + 1, filteredForEmbedding(options)); layout->addWidget(res); } } QString GenericMultipartWidget::quoteMe() const { return quoteMeHelper(children()); } bool GenericMultipartWidget::searchDialogRequested() { return searchDialogRequestedHelper(children()); } Message822Widget::Message822Widget(QWidget *parent, PartWidgetFactory *factory, const QModelIndex &partIndex, int recursionDepth, const UiUtils::PartLoadingOptions options): QWidget(parent) { QVBoxLayout *layout = new QVBoxLayout(this); layout->setSpacing(0); EnvelopeView *envelope = new EnvelopeView(0, factory->context()); envelope->setMessage(partIndex); layout->addWidget(envelope); for (int i = 0; i < partIndex.model()->rowCount(partIndex); ++i) { using namespace Imap::Mailbox; QModelIndex anotherPart = partIndex.child(i, 0); Q_ASSERT(anotherPart.isValid()); // guaranteed by the MVC QWidget *res = factory->walk(anotherPart, recursionDepth + 1, filteredForEmbedding(options)); layout->addWidget(res); } } QString Message822Widget::quoteMe() const { return quoteMeHelper(children()); } bool Message822Widget::searchDialogRequested() { return searchDialogRequestedHelper(children()); } #define IMPL_PART_FORWARD_ONE_METHOD(CLASS, METHOD) \ void CLASS::METHOD() \ {\ /*qDebug() << metaObject()->className() << children().size();*/\ Q_FOREACH( QObject* const obj, children() ) {\ /*qDebug() << obj->metaObject()->className();*/\ AbstractPartWidget* w = dynamic_cast( obj );\ if ( w ) {\ /*qDebug() << METHOD ":" << w;*/\ w->METHOD();\ }\ }\ } #define IMPL_PART_FORWARDED_METHODS(CLASS) \ IMPL_PART_FORWARD_ONE_METHOD(CLASS, reloadContents) \ IMPL_PART_FORWARD_ONE_METHOD(CLASS, zoomIn) \ IMPL_PART_FORWARD_ONE_METHOD(CLASS, zoomOut) \ IMPL_PART_FORWARD_ONE_METHOD(CLASS, zoomOriginal) IMPL_PART_FORWARDED_METHODS(MultipartSignedEncryptedWidget) IMPL_PART_FORWARDED_METHODS(GenericMultipartWidget) IMPL_PART_FORWARDED_METHODS(Message822Widget) #undef IMPL_PART_FORWARD_ONE_METHOD #define IMPL_PART_FORWARD_ONE_METHOD(CLASS, METHOD) \ void CLASS::METHOD() \ {\ if (count()) { \ for (int i = 0; i < count(); ++i) { \ AbstractPartWidget *w = dynamic_cast(widget(i)); \ if (w) { \ w->METHOD(); \ } \ } \ } \ } IMPL_PART_FORWARDED_METHODS(MultipartAlternativeWidget) #undef IMPL_PART_FORWARD_ONE_METHOD #undef IMPL_PART_FORWARDED_METHODS } diff --git a/src/Imap/Model/ItemRoles.h b/src/Imap/Model/ItemRoles.h index a5475500..4588d4d0 100644 --- a/src/Imap/Model/ItemRoles.h +++ b/src/Imap/Model/ItemRoles.h @@ -1,262 +1,262 @@ /* Copyright (C) 2006 - 2014 Jan Kundrát This file is part of the Trojita Qt IMAP e-mail client, http://trojita.flaska.net/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License or (at your option) version 3 or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of version 3 of the license. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef IMAP_MODEL_ITEMROLES_H #define IMAP_MODEL_ITEMROLES_H #include namespace Imap { namespace Mailbox { /** @short Custom item data roles for IMAP */ enum { /** @short A "random" offset */ RoleBase = Qt::UserRole + 666, /** @short Is the item already fetched? */ RoleIsFetched, /** @short The item is not available -- perhaps we're offline and it isn't cached */ RoleIsUnavailable, /** @short Are we working in an offline mode? This role only works on a top-level item in a model. */ RoleIsNetworkOffline, /** @short Name of the mailbox */ RoleMailboxName, /** @short Short name of the mailbox */ RoleShortMailboxName, /** @short Separator for mailboxes at the current level */ RoleMailboxSeparator, /** @short Total number of messages in a mailbox */ RoleTotalMessageCount, /** @short Number of unread messages in a mailbox */ RoleUnreadMessageCount, /** @short Number of recent messages in a mailbox */ RoleRecentMessageCount, /** @short The mailbox in question is the INBOX */ RoleMailboxIsINBOX, /** @short The mailbox can be selected */ RoleMailboxIsSelectable, /** @short The mailbox has child mailboxes */ RoleMailboxHasChildMailboxes, /** @short Information about whether the number of messages in the mailbox has already been loaded */ RoleMailboxNumbersFetched, /** @short Is anything still loading for this mailbox? */ RoleMailboxItemsAreLoading, /** @short Current UIDVALIDITY of a mailbox */ RoleMailboxUidValidity, /** @short Is the mailbox subscribed? If the server doesn't support RFC5258, this can return wrong answer. */ RoleMailboxIsSubscribed, /** @short UID of the message */ RoleMessageUid, /** @short Subject of the message */ RoleMessageSubject, /** @short The From addresses */ RoleMessageFrom, /** @short The To addresses */ RoleMessageTo, /** @short The Cc addresses */ RoleMessageCc, /** @short The Bcc: addresses */ RoleMessageBcc, /** @short The Sender: header */ RoleMessageSender, /** @short The Reply-To: header */ RoleMessageReplyTo, /** @short The Message-Id: header */ RoleMessageMessageId, /** @short The In-Reply-To: header */ RoleMessageInReplyTo, /** @short The message timestamp as determined from IMAP's ENVELOPE, ie. from the RFC2822 headers */ RoleMessageDate, /** @short Timestamp of when the message was delivered to the mailbox (ie. IMAP's INTERNALDATE) */ RoleMessageInternalDate, /** @short Size of the message */ RoleMessageSize, /** @short Status of the \\Seen flag */ RoleMessageIsMarkedRead, /** @short Was unread when mailbox opened, or has been marked unread. This flag is transient and is recalculated * when switching mailboxes. */ RoleMessageWasUnread, /** @short Status of the \\Deleted flag */ RoleMessageIsMarkedDeleted, /** @short Was the message forwarded? */ RoleMessageIsMarkedForwarded, /** @short Was the message replied to? */ RoleMessageIsMarkedReplied, /** @short Is the message marked as a recent one? */ RoleMessageIsMarkedRecent, /** @short Is the message markes as flagged? */ RoleMessageIsMarkedFlagged, /** @short Is the message markes as junk? */ RoleMessageIsMarkedJunk, /** @short Is the message markes as notjunk? */ RoleMessageIsMarkedNotJunk, /** @short IMAP flags of a message */ RoleMessageFlags, /** @short Is the current item a root of thread with unread messages */ RoleThreadRootWithUnreadMessages, /** @short Aggregated flags from the thread */ RoleThreadAggregatedFlags, /** @short Fuzzy date of a particular message; useful for rough navigation */ RoleMessageFuzzyDate, /** @short List of message IDs from the message's References header */ RoleMessageHeaderReferences, /** @short The List-Post header from RFC 2369 */ RoleMessageHeaderListPost, /** @short Is the List-Post set to a special value of "NO"? */ RoleMessageHeaderListPostNo, /** @short A full message envelope */ RoleMessageEnvelope, /** @short Is this a mail with at least one attachment? The returned value might be a bit fuzzy. */ RoleMessageHasAttachments, /** @short Contents of a message part */ RolePartData, /** @short Unicode text, i.e. RolePartData already decoded */ RolePartUnicodeText, /** @short MIME type of a message part */ RolePartMimeType, /** @short Charset of a message part */ RolePartCharset, /** @short The format= parameter of the message part's Content-Type */ RolePartContentFormat, /** @short The delsp= parameter of the message part's Content-Type */ RolePartContentDelSp, /** @short Content-Transfer-Encoding of a message part */ RolePartTransferEncoding, /** @short The body-fld-id field from BODYSTRUCTURE */ RolePartBodyFldId, /** @short The Content-Disposition of a message part */ RolePartBodyDisposition, /** @short The file name for a message part */ RolePartFileName, /** @short The size of this part, as determined from BODYSTRUCTURE */ RolePartOctets, /** @short Access to the partId() function */ RolePartId, /** @short Access to the partToPath() function */ RolePartPathToPart, /** @short CID of the main part of a multipart/related message */ RolePartMultipartRelatedMainCid, /** @short Is this a top-level multipart, i.e. a multipart/... and a child of a message/rfc822? See isTopLevelMultipart. */ RolePartIsTopLevelMultipart, - /** @short Return the body-fld-param from BODUSTRUCTURE, which usually contains some optional MIME parameters about this part */ + /** @short Return the body-fld-param from BODYSTRUCTURE, which usually contains some optional MIME parameters about this part */ RolePartBodyFldParam, /** @short Fetch a part from the cache if it's available, but do not request it from the server */ RolePartForceFetchFromCache, /** @short Pointer to the internal buffer */ RolePartBufferPtr, /** @short QModelIndex of the message a part is associated to */ RolePartMessageIndex, /** @short A relative IMAP URL pointing to this message or part, if available */ RoleIMAPRelativeUrl, /** @short Is the format of this particular multipart/signed supported for signature verification? A multipart/signed could use some unrecognized or unsupported algorithm, in which case we won't even try to verify the signature. If this is role returns true, it means that there will be just one child item and that that child's validity will be checked by the crypto operation. This role does not imply anything about the validity of the actual signature, though. */ RolePartSignatureVerifySupported, /** @short Is the format of this particular multipart/encrypted supported and recognized? See RolePartSignatureVerifySupported, this is an equivalent. */ RolePartDecryptionSupported, /** @short Is there any point in waiting longer? If true, this means that the crypto code is either waiting for data from the network, or that there is a crypto operation in progress. */ RolePartCryptoNotFinishedYet, /** @short Was there a failure in some cryptography operation which affected the ability to show the message? "Failure" means that something went wrong. Maybe some system component failed, or the message arrived too damaged to be decrypted. This state has nothing to do with, say, a message whose signature failed to verify. */ RolePartCryptoDecryptionFailed, /** @short Short message about the status/result of a crypto operation This is suitable for an immediate presentation to the user. The text should be short enough to not distract the user too much, but also descriptive enough to make sense on its own, without having to consult the longer, more detailed status message. */ RolePartCryptoTLDR, /** @short Longer information about the status/result of a crypto operation This can be shown to the user when they ask for more details. It could possibly be a very long text, including some cryptic output from gpg's stderr, for example. */ RolePartCryptoDetailedMessage, /** @short Icon name for showing the result of a crypto operation */ RolePartCryptoStatusIconName, /** @short Is this a valid signature subject to all checks, whatever they are? */ RolePartSignatureValidTrusted, /** @short Is this a technically valid signature without taking the trust level and other policies into account? */ RolePartSignatureValidDisregardingTrust, /** @short Who made the signature */ RolePartSignatureSignerName, /** @short When was the signature made */ RolePartSignatureSignDate, /** @short True if the item in the tasks list is actually a ParserState This role is *not* used or implemented by the IMAP models, but only by the TaskPresentationModel. */ RoleTaskIsParserState, /** @short True if the task shall be visible in the user-facing list of current activities This role is *not* used or implemented by the IMAP models, but only by the TaskPresentationModel and VisibleTasksModel. */ RoleTaskIsVisible, /** @short A short explanaiton of the task -- what is it doing? */ RoleTaskCompactName, /** @short Content-Disposition (inline or attachment) of an attachment within MessageComposer The enum value is converted to int. */ RoleAttachmentContentDispositionMode, /** @short The very last role */ RoleInvalidLastOne }; } } #endif // IMAP_MODEL_ITEMROLES_H