File indexing completed on 2024-05-05 04:48:36

0001 /***************************************************************************
0002  *   Copyright (C) 2009, 2010 by Richard J. Moore <rich@kde.org>           *
0003  *                                                                         *
0004  *   This program is free software; you can redistribute it and/or modify  *
0005  *   it under the terms of the GNU General Public License as published by  *
0006  *   the Free Software Foundation; either version 2 of the License, or     *
0007  *   (at your option) any later version.                                   *
0008  *                                                                         *
0009  *   This program is distributed in the hope that it will be useful,       *
0010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0012  *   GNU General Public License for more details.                          *
0013  *                                                                         *
0014  *   You should have received a copy of the GNU General Public License     *
0015  *   along with this program; if not, write to the                         *
0016  *   Free Software Foundation, Inc.,                                       *
0017  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
0018  ***************************************************************************/
0019 
0020 #include "NetworkAccessViewer.h"
0021 
0022 #include "core/support/Debug.h"
0023 
0024 #include <QNetworkReply>
0025 #include <QNetworkRequest>
0026 #include <QSignalMapper>
0027 
0028 NetworkAccessViewer::NetworkAccessViewer( QWidget *parent )
0029     : QObject( parent )
0030 {
0031     dialog = new QDialog( parent );
0032     networkRequestsDialog = new Ui::NetworkRequestsDialog;
0033     networkRequestsDialog->setupUi(dialog);
0034 
0035     mapper = new QSignalMapper(this);
0036     connect( mapper, QOverload<QObject*>::of(&QSignalMapper::mapped),
0037              this, &NetworkAccessViewer::requestFinished );
0038 
0039     connect( networkRequestsDialog->requestList, &QTreeWidget::currentItemChanged, this, &NetworkAccessViewer::showItemDetails );
0040     connect( networkRequestsDialog->clearButton, &QPushButton::clicked, this, &NetworkAccessViewer::clear );
0041 }
0042 
0043 NetworkAccessViewer::~NetworkAccessViewer()
0044 {
0045     delete networkRequestsDialog;
0046 }
0047 
0048 void NetworkAccessViewer::addRequest( QNetworkAccessManager::Operation op, const QNetworkRequest&req, QIODevice *outgoingData, QNetworkReply *reply )
0049 {
0050     Q_UNUSED( outgoingData )
0051     // Add to list of requests
0052     QStringList cols;
0053     switch( op ) {
0054     case   QNetworkAccessManager::HeadOperation:
0055         cols << QString::fromLatin1("HEAD");
0056         break;
0057     case   QNetworkAccessManager::GetOperation:
0058         cols << QString::fromLatin1("GET");
0059         break;
0060     case   QNetworkAccessManager::PutOperation:
0061         cols << QString::fromLatin1("PUT");
0062         break;
0063     case   QNetworkAccessManager::PostOperation:
0064         cols << QString::fromLatin1("POST");
0065         break;
0066     default:
0067         qWarning() << "Unknown network operation";
0068     }
0069     cols << req.url().toString();
0070     cols << tr("Pending");
0071 
0072     QTreeWidgetItem *item = new QTreeWidgetItem( cols );
0073     networkRequestsDialog->requestList->addTopLevelItem( item );
0074     networkRequestsDialog->requestList->scrollToItem( item );
0075 
0076     // Add to maps
0077     requestMap.insert( reply, req );
0078     itemMap.insert( reply, item );
0079     itemRequestMap.insert( item, req );
0080 
0081     mapper->setMapping( reply, reply );
0082     connect( reply, &QNetworkReply::finished,
0083              mapper, QOverload<>::of(&QSignalMapper::map) );
0084 }
0085 
0086 void NetworkAccessViewer::show()
0087 {
0088     dialog->show();
0089 }
0090 
0091 void NetworkAccessViewer::hide()
0092 {
0093     dialog->hide();
0094 }
0095 
0096 void NetworkAccessViewer::clear()
0097 {
0098     requestMap.clear();
0099     itemMap.clear();
0100     itemReplyMap.clear();
0101     itemRequestMap.clear();
0102     networkRequestsDialog->requestList->clear();
0103     networkRequestsDialog->requestDetails->clear();
0104     networkRequestsDialog->responseDetails->clear();
0105 }
0106 
0107 void NetworkAccessViewer::requestFinished( QObject *replyObject )
0108 {
0109     QNetworkReply *reply = qobject_cast<QNetworkReply *>( replyObject );
0110     if( !reply )
0111     {
0112         warning() << __PRETTY_FUNCTION__ << "Failed to downcast reply";
0113         return;
0114     }
0115     QTreeWidgetItem *item = itemMap.value( reply );
0116     if( !item )
0117     {
0118         warning() << __PRETTY_FUNCTION__ << "null item";
0119         return;
0120     }
0121 
0122     // Record the reply headers
0123     QList<QByteArray> headerValues;
0124     foreach( const QByteArray &header, reply->rawHeaderList() ) {
0125         headerValues += reply->rawHeader( header );
0126     }
0127     QPair< QList<QByteArray>, QList<QByteArray> > replyHeaders;
0128     replyHeaders.first = reply->rawHeaderList();
0129     replyHeaders.second = headerValues;
0130     itemReplyMap[item] = replyHeaders;
0131 
0132     // Display the request
0133     int status = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute ).toInt();
0134     QString reason = reply->attribute( QNetworkRequest::HttpReasonPhraseAttribute ).toString();
0135     item->setText( 2, tr("%1 %2").arg(status).arg(reason) );
0136 
0137     QString length = reply->header( QNetworkRequest::ContentLengthHeader ).toString();
0138     item->setText( 3, length );
0139 
0140     QString contentType = reply->header( QNetworkRequest::ContentTypeHeader ).toString();
0141     item->setText( 4, contentType );
0142 
0143     if ( status == 302 ) {
0144         QUrl target = reply->attribute( QNetworkRequest::RedirectionTargetAttribute ).toUrl();
0145         item->setText( 5, tr("Redirect: %1").arg( target.toString() ) );
0146     }
0147 }
0148 
0149 void NetworkAccessViewer::showItemDetails( QTreeWidgetItem *item )
0150 {
0151     // Show request details
0152     QTreeWidget *reqTree = networkRequestsDialog->requestDetails;
0153     reqTree->clear();
0154 
0155     QNetworkRequest req = itemRequestMap[item];
0156     QByteArray header;
0157     foreach( header, req.rawHeaderList() ) {
0158         QTreeWidgetItem *item = new QTreeWidgetItem();
0159         item->setText( 0, QString::fromLatin1( header ) );
0160         item->setText( 1, QString::fromLatin1( req.rawHeader( header ) ) );
0161         reqTree->addTopLevelItem( item );
0162     }
0163 
0164     // Show reply headers
0165     QTreeWidget *respTree = networkRequestsDialog->responseDetails;
0166     respTree->clear();
0167 
0168     QPair< QList<QByteArray>, QList<QByteArray> > replyHeaders = itemReplyMap[item];
0169     for ( int i = 0; i < replyHeaders.first.count(); i++ ) {
0170         QTreeWidgetItem *item = new QTreeWidgetItem();
0171         item->setText( 0, QString::fromLatin1( replyHeaders.first[i] ) );
0172         item->setText( 1, QString::fromLatin1( replyHeaders.second[i] ) );
0173         respTree->addTopLevelItem( item );
0174     }
0175 }