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 }