File indexing completed on 2024-11-24 04:53:15
0001 /* Copyright (C) 2006 - 2014 Jan Kundrát <jkt@flaska.net> 0002 0003 This file is part of the Trojita Qt IMAP e-mail client, 0004 http://trojita.flaska.net/ 0005 0006 This program is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU General Public License as 0008 published by the Free Software Foundation; either version 2 of 0009 the License or (at your option) version 3 or any later version 0010 accepted by the membership of KDE e.V. (or its successor approved 0011 by the membership of KDE e.V.), which shall act as a proxy 0012 defined in Section 14 of version 3 of the license. 0013 0014 This program is distributed in the hope that it will be useful, 0015 but WITHOUT ANY WARRANTY; without even the implied warranty of 0016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0017 GNU General Public License for more details. 0018 0019 You should have received a copy of the GNU General Public License 0020 along with this program. If not, see <http://www.gnu.org/licenses/>. 0021 */ 0022 #include <QDebug> 0023 #include <QStringList> 0024 #include <QTimer> 0025 0026 #include "MsgPartNetworkReply.h" 0027 #include "Imap/Model/ItemRoles.h" 0028 #include "Imap/Model/MailboxTree.h" 0029 #include "Imap/Model/Model.h" 0030 #include "Imap/Network/MsgPartNetAccessManager.h" 0031 0032 namespace Imap 0033 { 0034 0035 namespace Network 0036 { 0037 0038 MsgPartNetworkReply::MsgPartNetworkReply(MsgPartNetAccessManager *parent, const QPersistentModelIndex &part): 0039 QNetworkReply(parent), part(part) 0040 { 0041 QUrl url; 0042 url.setScheme(QStringLiteral("trojita-imap")); 0043 url.setHost(QStringLiteral("msg")); 0044 url.setPath(part.data(Imap::Mailbox::RolePartPathToPart).toString()); 0045 setUrl(url); 0046 0047 setOpenMode(QIODevice::ReadOnly | QIODevice::Unbuffered); 0048 Q_ASSERT(part.isValid()); 0049 0050 connect(part.model(), &QAbstractItemModel::dataChanged, this, &MsgPartNetworkReply::slotModelDataChanged); 0051 0052 // We have to ask for contents before we check whether it's already fetched 0053 part.data(Imap::Mailbox::RolePartData); 0054 0055 // The part data might be already unavailable or already fetched 0056 QTimer::singleShot(0, this, SLOT(slotMyDataChanged())); 0057 0058 QByteArray* bufferPtr = part.data(Imap::Mailbox::RolePartBufferPtr).value<QByteArray*>(); 0059 Q_ASSERT(bufferPtr); 0060 buffer.setBuffer(bufferPtr); 0061 buffer.open(QIODevice::ReadOnly); 0062 } 0063 0064 /** @short Check to see whether the data which concern this object has arrived already */ 0065 void MsgPartNetworkReply::slotModelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) 0066 { 0067 Q_UNUSED(bottomRight); 0068 // FIXME: use bottomRight as well! 0069 if (topLeft.model() != part.model()) { 0070 return; 0071 } 0072 if (topLeft == part) { 0073 slotMyDataChanged(); 0074 } 0075 } 0076 0077 /** @short Data for the current message part are available now */ 0078 void MsgPartNetworkReply::slotMyDataChanged() 0079 { 0080 if (part.data(Mailbox::RoleIsUnavailable).toBool()) { 0081 if (!part.data(Mailbox::RoleIsNetworkOffline).isValid()) { 0082 setError(UnknownProxyError, tr("Cannot access data")); 0083 } else { 0084 if (part.data(Mailbox::RoleIsNetworkOffline).toBool()) { 0085 setError(TimeoutError, tr("Uncached data not available when offline")); 0086 } else { 0087 setError(ContentNotFoundError, tr("Error downloading data")); 0088 } 0089 } 0090 setFinished(true); 0091 emit errorOccurred(error()); 0092 emit finished(); 0093 return; 0094 } 0095 0096 if (!part.data(Mailbox::RoleIsFetched).toBool()) 0097 return; 0098 0099 MsgPartNetAccessManager *netAccess = qobject_cast<MsgPartNetAccessManager*>(manager()); 0100 Q_ASSERT(netAccess); 0101 QString mimeType = netAccess->translateToSupportedMimeType(part.data(Mailbox::RolePartMimeType).toString()); 0102 QString charset = part.data(Mailbox::RolePartCharset).toString(); 0103 if (mimeType.startsWith(QLatin1String("text/"))) { 0104 setHeader(QNetworkRequest::ContentTypeHeader, 0105 charset.isEmpty() ? mimeType : QStringLiteral("%1; charset=%2").arg(mimeType, charset) 0106 ); 0107 } else { 0108 setHeader(QNetworkRequest::ContentTypeHeader, mimeType); 0109 } 0110 setFinished(true); 0111 emit readyRead(); 0112 emit finished(); 0113 } 0114 0115 /** @short QIODevice compatibility */ 0116 void MsgPartNetworkReply::abort() 0117 { 0118 close(); 0119 } 0120 0121 /** @short QIODevice compatibility */ 0122 void MsgPartNetworkReply::close() 0123 { 0124 disconnectBufferIfVanished(); 0125 buffer.close(); 0126 } 0127 0128 /** @short QIODevice compatibility */ 0129 qint64 MsgPartNetworkReply::bytesAvailable() const 0130 { 0131 disconnectBufferIfVanished(); 0132 return buffer.bytesAvailable() + QNetworkReply::bytesAvailable(); 0133 } 0134 0135 /** @short QIODevice compatibility */ 0136 qint64 MsgPartNetworkReply::readData(char *data, qint64 maxSize) 0137 { 0138 disconnectBufferIfVanished(); 0139 return buffer.read(data, maxSize); 0140 } 0141 0142 0143 /** @short Cut the buffer connection in case the message got removed */ 0144 void MsgPartNetworkReply::disconnectBufferIfVanished() const 0145 { 0146 if (!part.isValid()) { 0147 buffer.close(); 0148 buffer.setBuffer(0); 0149 } 0150 } 0151 0152 } 0153 }