1 /*
2   clientnetworkreplymodel.cpp
3 
4   This file is part of GammaRay, the Qt application inspection and
5   manipulation tool.
6 
7   Copyright (C) 2019-2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
8   Author: Volker Krause <volker.krause@kdab.com>
9 
10   Licensees holding valid commercial KDAB GammaRay licenses may use this file in
11   accordance with GammaRay Commercial License Agreement provided with the Software.
12 
13   Contact info@kdab.com if any conditions of this licensing are not clear to you.
14 
15   This program is free software; you can redistribute it and/or modify
16   it under the terms of the GNU General Public License as published by
17   the Free Software Foundation, either version 2 of the License, or
18   (at your option) any later version.
19 
20   This program is distributed in the hope that it will be useful,
21   but WITHOUT ANY WARRANTY; without even the implied warranty of
22   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23   GNU General Public License for more details.
24 
25   You should have received a copy of the GNU General Public License
26   along with this program.  If not, see <http://www.gnu.org/licenses/>.
27 */
28 
29 #include "clientnetworkreplymodel.h"
30 #include "networkreplymodeldefs.h"
31 
32 #include <ui/uiresources.h>
33 
34 #include <QApplication>
35 #include <QIcon>
36 #include <QNetworkAccessManager>
37 #include <QPalette>
38 #include <QStyle>
39 
40 using namespace GammaRay;
41 
ClientNetworkReplyModel(QObject * parent)42 ClientNetworkReplyModel::ClientNetworkReplyModel(QObject* parent)
43     : QIdentityProxyModel(parent)
44 {
45 }
46 
47 ClientNetworkReplyModel::~ClientNetworkReplyModel() = default;
48 
data(const QModelIndex & index,int role) const49 QVariant ClientNetworkReplyModel::data(const QModelIndex& index, int role) const
50 {
51     if (role == Qt::DisplayRole && index.column() == NetworkReplyModelColumn::OpColumn) {
52         const auto op = QIdentityProxyModel::data(index, role).toInt();
53         switch (op) {
54             case QNetworkAccessManager::HeadOperation: return QStringLiteral("HEAD");
55             case QNetworkAccessManager::GetOperation: return QStringLiteral("GET");
56             case QNetworkAccessManager::PutOperation: return QStringLiteral("PUT");
57             case QNetworkAccessManager::PostOperation: return QStringLiteral("POST");
58             case QNetworkAccessManager::DeleteOperation: return QStringLiteral("DELETE");
59             case QNetworkAccessManager::CustomOperation: return tr("Custom");
60         }
61     }
62 
63     if (role == Qt::ForegroundRole) {
64         const auto state = QIdentityProxyModel::data(index.sibling(index.row(), NetworkReplyModelColumn::ObjectColumn), NetworkReplyModelRole::ReplyStateRole).toInt();
65         if (state & NetworkReply::Deleted) {
66             return QGuiApplication::palette().color(QPalette::Disabled, QPalette::Text);
67         }
68         if (state & NetworkReply::Error) {
69             return QColor(Qt::red);
70         }
71     }
72 
73     if (role == Qt::DecorationRole && index.parent().isValid()) {
74         const auto state = QIdentityProxyModel::data(index.sibling(index.row(), NetworkReplyModelColumn::ObjectColumn), NetworkReplyModelRole::ReplyStateRole).toInt();
75         switch (index.column()) {
76             case NetworkReplyModelColumn::ObjectColumn:
77                 if (state & NetworkReply::Error) {
78                     return QApplication::style()->standardIcon(QStyle::SP_DialogCancelButton);
79                 } else if (state & NetworkReply::Finished) {
80                     return QApplication::style()->standardIcon(QStyle::SP_DialogOkButton);
81                 }
82                 return QApplication::style()->standardIcon(QStyle::SP_BrowserReload);
83             case NetworkReplyModelColumn::UrlColumn:
84             {
85                 const auto url = QIdentityProxyModel::data(index, Qt::DisplayRole).toString();
86                 if ((state & NetworkReply::Encrypted) || ((state & NetworkReply::Unencrypted) == 0 && url.startsWith(QLatin1String("https")))) {
87                     return UIResources::themedIcon(QLatin1String("lock.png"));
88                 }
89                 return UIResources::themedIcon(QLatin1String("lock-open.png"));
90             }
91         }
92     }
93 
94     if (role == Qt::ToolTipRole) {
95         if (index.column() == NetworkReplyModelColumn::UrlColumn) {
96             return index.data(Qt::DisplayRole);
97         }
98 
99         const auto errMsgs = QIdentityProxyModel::data(index.sibling(index.row(), NetworkReplyModelColumn::ObjectColumn), NetworkReplyModelRole::ReplyErrorRole).toStringList();
100         if (errMsgs.isEmpty()) {
101             return {};
102         }
103         if (errMsgs.size() == 1) {
104             return errMsgs.at(0);
105         }
106         QString tt;
107         for (const auto &msg : errMsgs) {
108             tt += QLatin1String("<li>") + msg + QLatin1String("</li>");
109         }
110         return tt;
111     }
112 
113     return QIdentityProxyModel::data(index, role);
114 }
115 
headerData(int section,Qt::Orientation orientation,int role) const116 QVariant ClientNetworkReplyModel::headerData(int section, Qt::Orientation orientation, int role) const
117 {
118     if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
119         switch (section) {
120             case NetworkReplyModelColumn::ObjectColumn: return tr("Reply");
121             case NetworkReplyModelColumn::OpColumn: return tr("Operation");
122             case NetworkReplyModelColumn::TimeColumn: return tr("Duration");
123             case NetworkReplyModelColumn::SizeColumn: return tr("Size");
124             case NetworkReplyModelColumn::UrlColumn: return tr("URL");
125         }
126     }
127 
128     return QIdentityProxyModel::headerData(section, orientation, role);
129 }
130