File indexing completed on 2024-05-12 17:07:35
0001 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0002 // SPDX-FileCopyrightText: 2018 Alexis Lopes Zubeta <contact@azubieta.net> 0003 // SPDX-FileCopyrightText: 2020 Tomaz Canabrava <tcanabrava@kde.org> 0004 0005 #include "conectionsmodel.h" 0006 0007 #include <QDebug> 0008 0009 #include <KLocalizedString> 0010 0011 #include "netstatclient.h" 0012 0013 ConnectionsModel::ConnectionsModel(QObject *parent) 0014 : QAbstractListModel(parent) 0015 { 0016 connect(&m_netstatHelper, &NetstatHelper::queryFinished, this, &ConnectionsModel::refreshConnections); 0017 connect(&timer, &QTimer::timeout, &m_netstatHelper, &NetstatHelper::query); 0018 timer.setInterval(10500); 0019 } 0020 0021 void ConnectionsModel::start() 0022 { 0023 m_busy = true; 0024 Q_EMIT busyChanged(); 0025 timer.start(); 0026 QTimer::singleShot(0, &m_netstatHelper, &NetstatHelper::query); 0027 } 0028 0029 void ConnectionsModel::stop() 0030 { 0031 timer.stop(); 0032 } 0033 0034 int ConnectionsModel::rowCount(const QModelIndex &parent) const 0035 { 0036 if (parent.isValid()) { 0037 return 0; 0038 } 0039 0040 return m_connectionsData.size(); 0041 } 0042 0043 bool ConnectionsModel::busy() const 0044 { 0045 return m_busy; 0046 } 0047 0048 QVariant ConnectionsModel::data(const QModelIndex &index, int role) const 0049 { 0050 const auto checkIndexFlags = QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::ParentIsInvalid; 0051 0052 if (!checkIndex(index, checkIndexFlags)) { 0053 return {}; 0054 } 0055 0056 ConnectionsData data = m_connectionsData.at(index.row()); 0057 switch (role) { 0058 case ProtocolRole: 0059 return data.protocol; 0060 case LocalAddressRole: 0061 return data.localAddress; 0062 case ForeignAddressRole: 0063 return data.foreignAddress; 0064 case StatusRole: 0065 return data.status; 0066 case PidRole: 0067 return data.pid; 0068 case ProgramRole: 0069 // HACK. Firefox reports as MainThread 0070 if (data.program == QLatin1String("MainThread")) { 0071 return "Firefox"; 0072 } else { 0073 return data.program; 0074 } 0075 } 0076 return {}; 0077 } 0078 0079 QHash<int, QByteArray> ConnectionsModel::roleNames() const 0080 { 0081 return { 0082 {ProtocolRole, "protocol"}, 0083 {LocalAddressRole, "localAddress"}, 0084 {ForeignAddressRole, "foreignAddress"}, 0085 {StatusRole, "status"}, 0086 {PidRole, "pid"}, 0087 {ProgramRole, "program"}, 0088 }; 0089 } 0090 0091 void ConnectionsModel::refreshConnections(const QVector<QStringList> &result) 0092 { 0093 if (m_netstatHelper.hasError()) { 0094 Q_EMIT showErrorMessage(i18n("Failed to get connections: %1", m_netstatHelper.errorString())); 0095 return; 0096 } 0097 0098 const auto oldConnectionsData = m_connectionsData; 0099 QVector<ConnectionsData> newConnectionsData; 0100 0101 beginResetModel(); 0102 m_connectionsData.clear(); 0103 for (const auto &connection : result) { 0104 ConnectionsData conn{.protocol = connection.at(0), 0105 .localAddress = connection.at(1), 0106 .foreignAddress = connection.at(2), 0107 .status = connection.at(3), 0108 .pid = connection.at(4), 0109 .program = connection.at(5)}; 0110 0111 if (conn.status == QLatin1String("UNCONN")) { 0112 conn.status = i18n("Not Connected"); 0113 } else if (conn.status == QLatin1String("ESTAB")) { 0114 conn.status = i18n("Established"); 0115 } else if (conn.status == QLatin1String("LISTEN")) { 0116 conn.status = i18n("Listening"); 0117 } 0118 0119 newConnectionsData.append(conn); 0120 } 0121 0122 if (newConnectionsData != oldConnectionsData) { 0123 beginResetModel(); 0124 m_connectionsData = newConnectionsData; 0125 endResetModel(); 0126 } 0127 0128 if (newConnectionsData.count() != oldConnectionsData.count()) { 0129 Q_EMIT countChanged(); 0130 } 0131 0132 if (m_busy) { 0133 m_busy = false; 0134 Q_EMIT busyChanged(); 0135 } 0136 }