PageRenderTime 37ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/src/app/devtools/networklogger/qgsnetworkloggernode.cpp

http://github.com/qgis/Quantum-GIS
C++ | 627 lines | 484 code | 88 blank | 55 comment | 56 complexity | 21dad3303f790a7316643baa8e8da4f6 MD5 | raw file
Possible License(s): LGPL-2.0, GPL-3.0, GPL-2.0, CC-BY-SA-3.0, MIT, 0BSD, BSD-3-Clause
  1. /***************************************************************************
  2. qgsnetworkloggernode.cpp
  3. -------------------------
  4. begin : March 2020
  5. copyright : (C) 2020 by Nyall Dawson
  6. email : nyall dot dawson at gmail dot com
  7. ***************************************************************************
  8. * *
  9. * This program is free software; you can redistribute it and/or modify *
  10. * it under the terms of the GNU General Public License as published by *
  11. * the Free Software Foundation; either version 2 of the License, or *
  12. * (at your option) any later version. *
  13. * *
  14. ***************************************************************************/
  15. #include "qgsnetworkloggernode.h"
  16. #include "qgis.h"
  17. #include "qgsjsonutils.h"
  18. #include <QUrlQuery>
  19. #include <QColor>
  20. #include <QBrush>
  21. #include <QFont>
  22. #include <QAction>
  23. #include <QDesktopServices>
  24. #include <QApplication>
  25. #include <QClipboard>
  26. #include <nlohmann/json.hpp>
  27. //
  28. // QgsNetworkLoggerNode
  29. //
  30. QgsNetworkLoggerNode::QgsNetworkLoggerNode() = default;
  31. QgsNetworkLoggerNode::~QgsNetworkLoggerNode() = default;
  32. //
  33. // QgsNetworkLoggerGroup
  34. //
  35. QgsNetworkLoggerGroup::QgsNetworkLoggerGroup( const QString &title )
  36. : mGroupTitle( title )
  37. {
  38. }
  39. void QgsNetworkLoggerGroup::addChild( std::unique_ptr<QgsNetworkLoggerNode> child )
  40. {
  41. if ( !child )
  42. return;
  43. Q_ASSERT( !child->mParent );
  44. child->mParent = this;
  45. mChildren.emplace_back( std::move( child ) );
  46. }
  47. int QgsNetworkLoggerGroup::indexOf( QgsNetworkLoggerNode *child ) const
  48. {
  49. Q_ASSERT( child->mParent == this );
  50. auto it = std::find_if( mChildren.begin(), mChildren.end(), [&]( const std::unique_ptr<QgsNetworkLoggerNode> &p )
  51. {
  52. return p.get() == child;
  53. } );
  54. if ( it != mChildren.end() )
  55. return std::distance( mChildren.begin(), it );
  56. return -1;
  57. }
  58. QgsNetworkLoggerNode *QgsNetworkLoggerGroup::childAt( int index )
  59. {
  60. Q_ASSERT( static_cast< std::size_t >( index ) < mChildren.size() );
  61. return mChildren[ index ].get();
  62. }
  63. void QgsNetworkLoggerGroup::clear()
  64. {
  65. mChildren.clear();
  66. }
  67. QVariant QgsNetworkLoggerGroup::data( int role ) const
  68. {
  69. switch ( role )
  70. {
  71. case Qt::DisplayRole:
  72. return mGroupTitle;
  73. default:
  74. break;
  75. }
  76. return QVariant();
  77. }
  78. QVariant QgsNetworkLoggerGroup::toVariant() const
  79. {
  80. QVariantMap res;
  81. for ( const std::unique_ptr< QgsNetworkLoggerNode > &child : mChildren )
  82. {
  83. if ( const QgsNetworkLoggerValueNode *valueNode = dynamic_cast< const QgsNetworkLoggerValueNode *>( child.get() ) )
  84. {
  85. res.insert( valueNode->key(), valueNode->value() );
  86. }
  87. }
  88. return res;
  89. }
  90. //
  91. // QgsNetworkLoggerRootNode
  92. //
  93. QgsNetworkLoggerRootNode::QgsNetworkLoggerRootNode()
  94. : QgsNetworkLoggerGroup( QString() )
  95. {
  96. }
  97. QVariant QgsNetworkLoggerRootNode::data( int ) const
  98. {
  99. return QVariant();
  100. }
  101. void QgsNetworkLoggerRootNode::removeRow( int row )
  102. {
  103. mChildren.erase( mChildren.begin() + row );
  104. }
  105. QVariant QgsNetworkLoggerRootNode::toVariant() const
  106. {
  107. QVariantList res;
  108. for ( const std::unique_ptr< QgsNetworkLoggerNode > &child : mChildren )
  109. res << child->toVariant();
  110. return res;
  111. }
  112. //
  113. // QgsNetworkLoggerValueNode
  114. //
  115. QgsNetworkLoggerValueNode::QgsNetworkLoggerValueNode( const QString &key, const QString &value, const QColor &color )
  116. : mKey( key )
  117. , mValue( value )
  118. , mColor( color )
  119. {
  120. }
  121. QVariant QgsNetworkLoggerValueNode::data( int role ) const
  122. {
  123. switch ( role )
  124. {
  125. case Qt::DisplayRole:
  126. case Qt::ToolTipRole:
  127. {
  128. return QStringLiteral( "%1: %2" ).arg( mKey.leftJustified( 30, ' ' ), mValue );
  129. }
  130. case Qt::ForegroundRole:
  131. {
  132. if ( mColor.isValid() )
  133. return QBrush( mColor );
  134. break;
  135. }
  136. default:
  137. break;
  138. }
  139. return QVariant();
  140. }
  141. //
  142. // QgsNetworkLoggerGroup
  143. //
  144. void QgsNetworkLoggerGroup::addKeyValueNode( const QString &key, const QString &value, const QColor &color )
  145. {
  146. addChild( qgis::make_unique< QgsNetworkLoggerValueNode >( key, value, color ) );
  147. }
  148. //
  149. // QgsNetworkLoggerRequestGroup
  150. //
  151. QgsNetworkLoggerRequestGroup::QgsNetworkLoggerRequestGroup( const QgsNetworkRequestParameters &request )
  152. : QgsNetworkLoggerGroup( QString() )
  153. , mUrl( request.request().url() )
  154. , mRequestId( request.requestId() )
  155. , mOperation( request.operation() )
  156. , mData( request.content() )
  157. {
  158. const QList<QByteArray> headers = request.request().rawHeaderList();
  159. for ( const QByteArray &header : headers )
  160. {
  161. mHeaders.append( qMakePair( QString( header ), QString( request.request().rawHeader( header ) ) ) );
  162. }
  163. std::unique_ptr< QgsNetworkLoggerRequestDetailsGroup > detailsGroup = qgis::make_unique< QgsNetworkLoggerRequestDetailsGroup >( request );
  164. mDetailsGroup = detailsGroup.get();
  165. addChild( std::move( detailsGroup ) );
  166. mTimer.start();
  167. }
  168. QVariant QgsNetworkLoggerRequestGroup::data( int role ) const
  169. {
  170. switch ( role )
  171. {
  172. case Qt::DisplayRole:
  173. return QStringLiteral( "%1 %2 %3" ).arg( QString::number( mRequestId ),
  174. operationToString( mOperation ),
  175. mUrl.url() );
  176. case Qt::ToolTipRole:
  177. {
  178. QString bytes = QObject::tr( "unknown" );
  179. if ( mBytesTotal != 0 )
  180. {
  181. if ( mBytesReceived > 0 && mBytesReceived < mBytesTotal )
  182. bytes = QStringLiteral( "%1/%2" ).arg( QString::number( mBytesReceived ), QString::number( mBytesTotal ) );
  183. else if ( mBytesReceived > 0 && mBytesReceived == mBytesTotal )
  184. bytes = QString::number( mBytesTotal );
  185. }
  186. // ?? adding <br/> instead of \n after (very long) url seems to break url up
  187. // COMPLETE, Status: 200 - text/xml; charset=utf-8 - 2334 bytes - 657 milliseconds
  188. return QStringLiteral( "%1<br/>%2 - Status: %3 - %4 - %5 bytes - %6 msec - %7 replies" )
  189. .arg( mUrl.url(),
  190. statusToString( mStatus ),
  191. QString::number( mHttpStatus ),
  192. mContentType,
  193. bytes,
  194. mStatus == Status::Pending ? QString::number( mTimer.elapsed() / 1000 ) : QString::number( mTotalTime ),
  195. QString::number( mReplies ) );
  196. }
  197. case RoleStatus:
  198. return static_cast< int >( mStatus );
  199. case RoleId:
  200. return mRequestId;
  201. case Qt::ForegroundRole:
  202. {
  203. if ( mHasSslErrors )
  204. return QBrush( QColor( 180, 65, 210 ) );
  205. switch ( mStatus )
  206. {
  207. case QgsNetworkLoggerRequestGroup::Status::Pending:
  208. case QgsNetworkLoggerRequestGroup::Status::Canceled:
  209. return QBrush( QColor( 0, 0, 0, 100 ) );
  210. case QgsNetworkLoggerRequestGroup::Status::Error:
  211. return QBrush( QColor( 235, 10, 10 ) );
  212. case QgsNetworkLoggerRequestGroup::Status::TimeOut:
  213. return QBrush( QColor( 235, 10, 10 ) );
  214. case QgsNetworkLoggerRequestGroup::Status::Complete:
  215. break;
  216. }
  217. break;
  218. }
  219. case Qt::FontRole:
  220. {
  221. if ( mStatus == Status::Canceled )
  222. {
  223. QFont f;
  224. f.setStrikeOut( true );
  225. return f;
  226. }
  227. break;
  228. }
  229. default:
  230. break;
  231. }
  232. return QVariant();
  233. }
  234. QList<QAction *> QgsNetworkLoggerRequestGroup::actions( QObject *parent )
  235. {
  236. QList< QAction * > res;
  237. QAction *openUrlAction = new QAction( QObject::tr( "Open URL" ), parent );
  238. QObject::connect( openUrlAction, &QAction::triggered, openUrlAction, [ = ]
  239. {
  240. QDesktopServices::openUrl( mUrl );
  241. } );
  242. res << openUrlAction;
  243. QAction *copyUrlAction = new QAction( QObject::tr( "Copy URL" ), parent );
  244. QObject::connect( copyUrlAction, &QAction::triggered, openUrlAction, [ = ]
  245. {
  246. QApplication::clipboard()->setText( mUrl.url() );
  247. } );
  248. res << copyUrlAction;
  249. QAction *copyAsCurlAction = new QAction( QObject::tr( "Copy As cURL" ), parent );
  250. QObject::connect( copyAsCurlAction, &QAction::triggered, copyAsCurlAction, [ = ]
  251. {
  252. QString curlHeaders;
  253. for ( const QPair< QString, QString > &header : qgis::as_const( mHeaders ) )
  254. curlHeaders += QStringLiteral( "-H '%1: %2' " ).arg( header.first, header.second );
  255. QString curlData;
  256. if ( mOperation == QNetworkAccessManager::PostOperation || mOperation == QNetworkAccessManager::PutOperation )
  257. curlData = QStringLiteral( "--data '%1' " ).arg( QString( mData ) );
  258. QString curlCmd = QStringLiteral( "curl '%1' %2 %3--compressed" ).arg(
  259. mUrl.url(),
  260. curlHeaders,
  261. curlData );
  262. QApplication::clipboard()->setText( curlCmd );
  263. } );
  264. res << copyAsCurlAction;
  265. QAction *copyJsonAction = new QAction( QObject::tr( "Copy as JSON" ), parent );
  266. QObject::connect( copyJsonAction, &QAction::triggered, openUrlAction, [ = ]
  267. {
  268. const QVariant value = toVariant();
  269. const QString json = QString::fromStdString( QgsJsonUtils::jsonFromVariant( value ).dump( 2 ) );
  270. QApplication::clipboard()->setText( json );
  271. } );
  272. res << copyJsonAction;
  273. return res;
  274. }
  275. QVariant QgsNetworkLoggerRequestGroup::toVariant() const
  276. {
  277. QVariantMap res;
  278. res.insert( QStringLiteral( "URL" ), mUrl.url() );
  279. res.insert( QStringLiteral( "Total time (ms)" ), mTotalTime );
  280. res.insert( QStringLiteral( "Bytes Received" ), mBytesReceived );
  281. res.insert( QStringLiteral( "Bytes Total" ), mBytesTotal );
  282. res.insert( QStringLiteral( "Replies" ), mReplies );
  283. if ( mDetailsGroup )
  284. {
  285. const QVariantMap detailsMap = mDetailsGroup->toVariant().toMap();
  286. for ( auto it = detailsMap.constBegin(); it != detailsMap.constEnd(); ++it )
  287. res.insert( it.key(), it.value() );
  288. }
  289. if ( mReplyGroup )
  290. {
  291. res.insert( QObject::tr( "Reply" ), mReplyGroup->toVariant() );
  292. }
  293. if ( mSslErrorsGroup )
  294. {
  295. res.insert( QObject::tr( "SSL Errors" ), mSslErrorsGroup->toVariant() );
  296. }
  297. return res;
  298. }
  299. void QgsNetworkLoggerRequestGroup::setReply( const QgsNetworkReplyContent &reply )
  300. {
  301. switch ( reply.error() )
  302. {
  303. case QNetworkReply::OperationCanceledError:
  304. mStatus = Status::Canceled;
  305. break;
  306. case QNetworkReply::NoError:
  307. mStatus = Status::Complete;
  308. break;
  309. default:
  310. mStatus = Status::Error;
  311. break;
  312. }
  313. mTotalTime = mTimer.elapsed();
  314. mHttpStatus = reply.attribute( QNetworkRequest::HttpStatusCodeAttribute ).toInt();
  315. mContentType = reply.rawHeader( "Content - Type" );
  316. std::unique_ptr< QgsNetworkLoggerReplyGroup > replyGroup = qgis::make_unique< QgsNetworkLoggerReplyGroup >( reply ) ;
  317. mReplyGroup = replyGroup.get();
  318. addChild( std::move( replyGroup ) );
  319. }
  320. void QgsNetworkLoggerRequestGroup::setTimedOut()
  321. {
  322. mStatus = Status::TimeOut;
  323. }
  324. void QgsNetworkLoggerRequestGroup::setProgress( qint64 bytesReceived, qint64 bytesTotal )
  325. {
  326. mReplies++;
  327. mBytesReceived = bytesReceived;
  328. mBytesTotal = bytesTotal;
  329. }
  330. void QgsNetworkLoggerRequestGroup::setSslErrors( const QList<QSslError> &errors )
  331. {
  332. mHasSslErrors = !errors.empty();
  333. if ( mHasSslErrors )
  334. {
  335. std::unique_ptr< QgsNetworkLoggerSslErrorGroup > errorGroup = qgis::make_unique< QgsNetworkLoggerSslErrorGroup >( errors );
  336. mSslErrorsGroup = errorGroup.get();
  337. addChild( std::move( errorGroup ) );
  338. }
  339. }
  340. QString QgsNetworkLoggerRequestGroup::operationToString( QNetworkAccessManager::Operation operation )
  341. {
  342. switch ( operation )
  343. {
  344. case QNetworkAccessManager::HeadOperation:
  345. return QStringLiteral( "HEAD" );
  346. case QNetworkAccessManager::GetOperation:
  347. return QStringLiteral( "GET" );
  348. case QNetworkAccessManager::PutOperation:
  349. return QStringLiteral( "PUT" );
  350. case QNetworkAccessManager::PostOperation:
  351. return QStringLiteral( "POST" );
  352. case QNetworkAccessManager::DeleteOperation:
  353. return QStringLiteral( "DELETE" );
  354. case QNetworkAccessManager::UnknownOperation:
  355. return QStringLiteral( "UNKNOWN" );
  356. case QNetworkAccessManager::CustomOperation:
  357. return QStringLiteral( "CUSTOM" );
  358. }
  359. return QString();
  360. }
  361. QString QgsNetworkLoggerRequestGroup::statusToString( QgsNetworkLoggerRequestGroup::Status status )
  362. {
  363. switch ( status )
  364. {
  365. case QgsNetworkLoggerRequestGroup::Status::Pending:
  366. return QObject::tr( "Pending" );
  367. case QgsNetworkLoggerRequestGroup::Status::Complete:
  368. return QObject::tr( "Complete" );
  369. case QgsNetworkLoggerRequestGroup::Status::Error:
  370. return QObject::tr( "Error" );
  371. case QgsNetworkLoggerRequestGroup::Status::TimeOut:
  372. return QObject::tr( "Timeout" );
  373. case QgsNetworkLoggerRequestGroup::Status::Canceled:
  374. return QObject::tr( "Canceled" );
  375. }
  376. return QString();
  377. }
  378. QString QgsNetworkLoggerRequestGroup::cacheControlToString( QNetworkRequest::CacheLoadControl control )
  379. {
  380. switch ( control )
  381. {
  382. case QNetworkRequest::AlwaysNetwork:
  383. return QObject::tr( "Always load from network, do not check cache" );
  384. case QNetworkRequest::PreferNetwork:
  385. return QObject::tr( "Load from the network if the cached entry is older than the network entry" );
  386. case QNetworkRequest::PreferCache:
  387. return QObject::tr( "Load from cache if available, otherwise load from network" );
  388. case QNetworkRequest::AlwaysCache:
  389. return QObject::tr( "Only load from cache, error if no cached entry available" );
  390. }
  391. return QString();
  392. }
  393. //
  394. // QgsNetworkLoggerRequestDetailsGroup
  395. //
  396. QgsNetworkLoggerRequestDetailsGroup::QgsNetworkLoggerRequestDetailsGroup( const QgsNetworkRequestParameters &request )
  397. : QgsNetworkLoggerGroup( QObject::tr( "Request" ) )
  398. {
  399. addKeyValueNode( QObject::tr( "Operation" ), QgsNetworkLoggerRequestGroup::operationToString( request.operation() ) );
  400. addKeyValueNode( QObject::tr( "Thread" ), request.originatingThreadId() );
  401. addKeyValueNode( QObject::tr( "Initiator" ), request.initiatorClassName().isEmpty() ? QObject::tr( "unknown" ) : request.initiatorClassName() );
  402. if ( request.initiatorRequestId().isValid() )
  403. addKeyValueNode( QObject::tr( "ID" ), request.initiatorRequestId().toString() );
  404. addKeyValueNode( QObject::tr( "Cache (control)" ), QgsNetworkLoggerRequestGroup::cacheControlToString( static_cast< QNetworkRequest::CacheLoadControl >( request.request().attribute( QNetworkRequest::CacheLoadControlAttribute ).toInt() ) ) );
  405. addKeyValueNode( QObject::tr( "Cache (save)" ), request.request().attribute( QNetworkRequest::CacheSaveControlAttribute ).toBool() ? QObject::tr( "Can store result in cache" ) : QObject::tr( "Result cannot be stored in cache" ) );
  406. if ( !QUrlQuery( request.request().url() ).queryItems().isEmpty() )
  407. {
  408. std::unique_ptr< QgsNetworkLoggerRequestQueryGroup > queryGroup = qgis::make_unique< QgsNetworkLoggerRequestQueryGroup >( request.request().url() );
  409. mQueryGroup = queryGroup.get();
  410. addChild( std::move( queryGroup ) );
  411. }
  412. std::unique_ptr< QgsNetworkLoggerRequestHeadersGroup > requestHeadersGroup = qgis::make_unique< QgsNetworkLoggerRequestHeadersGroup >( request );
  413. mRequestHeaders = requestHeadersGroup.get();
  414. addChild( std::move( requestHeadersGroup ) );
  415. switch ( request.operation() )
  416. {
  417. case QNetworkAccessManager::PostOperation:
  418. case QNetworkAccessManager::PutOperation:
  419. {
  420. std::unique_ptr< QgsNetworkLoggerPostContentGroup > postContentGroup = qgis::make_unique< QgsNetworkLoggerPostContentGroup >( request );
  421. mPostContent = postContentGroup.get();
  422. addChild( std::move( postContentGroup ) );
  423. break;
  424. }
  425. case QNetworkAccessManager::GetOperation:
  426. case QNetworkAccessManager::HeadOperation:
  427. case QNetworkAccessManager::DeleteOperation:
  428. case QNetworkAccessManager::UnknownOperation:
  429. case QNetworkAccessManager::CustomOperation:
  430. break;
  431. }
  432. }
  433. QVariant QgsNetworkLoggerRequestDetailsGroup::toVariant() const
  434. {
  435. QVariantMap res = QgsNetworkLoggerGroup::toVariant().toMap();
  436. if ( mQueryGroup )
  437. res.insert( QObject::tr( "Query" ), mQueryGroup->toVariant() );
  438. if ( mRequestHeaders )
  439. res.insert( QObject::tr( "Headers" ), mRequestHeaders->toVariant() );
  440. if ( mPostContent )
  441. res.insert( QObject::tr( "Content" ), mPostContent->toVariant() );
  442. return res;
  443. }
  444. //
  445. // QgsNetworkLoggerRequestQueryGroup
  446. //
  447. QgsNetworkLoggerRequestQueryGroup::QgsNetworkLoggerRequestQueryGroup( const QUrl &url )
  448. : QgsNetworkLoggerGroup( QObject::tr( "Query" ) )
  449. {
  450. QUrlQuery query( url );
  451. const QList<QPair<QString, QString> > queryItems = query.queryItems();
  452. for ( const QPair< QString, QString > &query : queryItems )
  453. {
  454. addKeyValueNode( query.first, query.second );
  455. }
  456. }
  457. //
  458. // QgsNetworkLoggerRequestHeadersGroup
  459. //
  460. QgsNetworkLoggerRequestHeadersGroup::QgsNetworkLoggerRequestHeadersGroup( const QgsNetworkRequestParameters &request )
  461. : QgsNetworkLoggerGroup( QObject::tr( "Headers" ) )
  462. {
  463. const QList<QByteArray> headers = request.request().rawHeaderList();
  464. for ( const QByteArray &header : headers )
  465. {
  466. addKeyValueNode( header, request.request().rawHeader( header ) );
  467. }
  468. }
  469. //
  470. // QgsNetworkLoggerPostContentGroup
  471. //
  472. QgsNetworkLoggerPostContentGroup::QgsNetworkLoggerPostContentGroup( const QgsNetworkRequestParameters &parameters )
  473. : QgsNetworkLoggerGroup( QObject::tr( "Content" ) )
  474. {
  475. addKeyValueNode( QObject::tr( "Data" ), parameters.content() );
  476. }
  477. //
  478. // QgsNetworkLoggerReplyGroup
  479. //
  480. QgsNetworkLoggerReplyGroup::QgsNetworkLoggerReplyGroup( const QgsNetworkReplyContent &reply )
  481. : QgsNetworkLoggerGroup( QObject::tr( "Reply" ) )
  482. {
  483. addKeyValueNode( QObject::tr( "Status" ), reply.attribute( QNetworkRequest::HttpStatusCodeAttribute ).toString() );
  484. if ( reply.error() != QNetworkReply::NoError )
  485. {
  486. addKeyValueNode( QObject::tr( "Error Code" ), QString::number( static_cast< int >( reply.error() ) ) );
  487. addKeyValueNode( QObject::tr( "Error" ), reply.errorString() );
  488. }
  489. addKeyValueNode( QObject::tr( "Cache (result)" ), reply.attribute( QNetworkRequest::SourceIsFromCacheAttribute ).toBool() ? QObject::tr( "Used entry from cache" ) : QObject::tr( "Read from network" ) );
  490. std::unique_ptr< QgsNetworkLoggerReplyHeadersGroup > headersGroup = qgis::make_unique< QgsNetworkLoggerReplyHeadersGroup >( reply );
  491. mReplyHeaders = headersGroup.get();
  492. addChild( std::move( headersGroup ) );
  493. }
  494. QVariant QgsNetworkLoggerReplyGroup::toVariant() const
  495. {
  496. QVariantMap res = QgsNetworkLoggerGroup::toVariant().toMap();
  497. if ( mReplyHeaders )
  498. {
  499. res.insert( QObject::tr( "Headers" ), mReplyHeaders->toVariant() );
  500. }
  501. return res;
  502. }
  503. //
  504. // QgsNetworkLoggerReplyHeadersGroup
  505. //
  506. QgsNetworkLoggerReplyHeadersGroup::QgsNetworkLoggerReplyHeadersGroup( const QgsNetworkReplyContent &reply )
  507. : QgsNetworkLoggerGroup( QObject::tr( "Headers" ) )
  508. {
  509. const QList<QByteArray> headers = reply.rawHeaderList();
  510. for ( const QByteArray &header : headers )
  511. {
  512. addKeyValueNode( header, reply.rawHeader( header ) );
  513. }
  514. }
  515. //
  516. // QgsNetworkLoggerSslErrorGroup
  517. //
  518. QgsNetworkLoggerSslErrorGroup::QgsNetworkLoggerSslErrorGroup( const QList<QSslError> &errors )
  519. : QgsNetworkLoggerGroup( QObject::tr( "SSL errors" ) )
  520. {
  521. for ( const QSslError &error : errors )
  522. {
  523. addKeyValueNode( QObject::tr( "Error" ), error.errorString(), QColor( 180, 65, 210 ) );
  524. }
  525. }
  526. QVariant QgsNetworkLoggerSslErrorGroup::data( int role ) const
  527. {
  528. if ( role == Qt::ForegroundRole )
  529. return QBrush( QColor( 180, 65, 210 ) );
  530. return QgsNetworkLoggerGroup::data( role );
  531. }
  532. QList<QAction *> QgsNetworkLoggerNode::actions( QObject * )
  533. {
  534. return QList< QAction * >();
  535. }
  536. QVariant QgsNetworkLoggerNode::toVariant() const
  537. {
  538. return QVariant();
  539. }