1 /*
2 networkconfigurationmodel.cpp
3
4 This file is part of GammaRay, the Qt application inspection and
5 manipulation tool.
6
7 Copyright (C) 2017-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 "networkconfigurationmodel.h"
30
31 #include <core/varianthandler.h>
32
33 #include <QNetworkConfigurationManager>
34 #include <QTimer>
35
36 using namespace GammaRay;
37
NetworkConfigurationModel(QObject * parent)38 NetworkConfigurationModel::NetworkConfigurationModel(QObject *parent)
39 : QAbstractTableModel(parent)
40 , m_mgr(nullptr)
41 {
42 }
43
44 NetworkConfigurationModel::~NetworkConfigurationModel() = default;
45
columnCount(const QModelIndex & parent) const46 int NetworkConfigurationModel::columnCount(const QModelIndex& parent) const
47 {
48 Q_UNUSED(parent);
49 return 8;
50 }
51
rowCount(const QModelIndex & parent) const52 int NetworkConfigurationModel::rowCount(const QModelIndex& parent) const
53 {
54 // delayed lazy loading, not just for performance, creating QNetworkConfigurationManager
55 // has tons of side-effects such as D-Bus communication on Linux, that will possibly
56 // fail when holding the Probe::objectLock
57 if (!m_mgr) {
58 QTimer::singleShot(0, this, &NetworkConfigurationModel::init);
59 return 0;
60 }
61
62 if (parent.isValid())
63 return 0;
64 return m_configs.size();
65 }
66
flags(const QModelIndex & index) const67 Qt::ItemFlags NetworkConfigurationModel::flags(const QModelIndex& index) const
68 {
69 const auto baseFlags = QAbstractTableModel::flags(index);
70 #if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
71 if (index.column() == 3)
72 return baseFlags | Qt::ItemIsEditable;
73 #endif
74 return baseFlags;
75 }
76
data(const QModelIndex & index,int role) const77 QVariant NetworkConfigurationModel::data(const QModelIndex& index, int role) const
78 {
79 if (!m_mgr || !index.isValid())
80 return QVariant();
81
82 const auto conf = m_configs.at(index.row());
83 if (role == Qt::DisplayRole) {
84 switch (index.column()) {
85 case 0:
86 return conf.name();
87 case 1:
88 return conf.identifier();
89 case 2:
90 return conf.bearerTypeName();
91 case 3:
92 #if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
93 return conf.connectTimeout();
94 #else
95 return QStringLiteral("?");
96 #endif
97 case 4:
98 return conf.isRoamingAvailable();
99 case 5:
100 return VariantHandler::displayString(QVariant::fromValue(conf.purpose()));
101 case 6:
102 return VariantHandler::displayString(QVariant::fromValue(conf.state()));
103 case 7:
104 return VariantHandler::displayString(QVariant::fromValue(conf.type()));
105 }
106 } else if (role == Qt::EditRole && index.column() == 3) {
107 #if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
108 return conf.connectTimeout();
109 #endif
110 } else if (role == NetworkConfigurationModelRoles::DefaultConfigRole && index.column() == 0) {
111 if (conf == m_mgr->defaultConfiguration())
112 return true;
113 }
114
115 return QVariant();
116 }
117
setData(const QModelIndex & index,const QVariant & value,int role)118 bool NetworkConfigurationModel::setData(const QModelIndex& index, const QVariant& value, int role)
119 {
120 if (!m_mgr || !index.isValid() || role != Qt::EditRole || index.column() != 3 || value.isNull())
121 return false;
122
123 #if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
124 auto conf = m_configs[index.row()];
125 conf.setConnectTimeout(value.toInt());
126 #endif
127 emit dataChanged(index, index);
128 return true;
129 }
130
init()131 void NetworkConfigurationModel::init()
132 {
133 if (m_mgr)
134 return;
135
136 beginResetModel();
137 m_mgr = new QNetworkConfigurationManager(this);
138 const auto configs = m_mgr->allConfigurations();
139 m_configs.reserve(configs.size());
140 std::copy(configs.begin(), configs.end(), std::back_inserter(m_configs));
141
142 connect(m_mgr, &QNetworkConfigurationManager::configurationAdded, this, &NetworkConfigurationModel::configurationAdded);
143 connect(m_mgr, &QNetworkConfigurationManager::configurationChanged, this, &NetworkConfigurationModel::configurationChanged);
144 connect(m_mgr, &QNetworkConfigurationManager::configurationRemoved, this, &NetworkConfigurationModel::configurationRemoved);
145 endResetModel();
146 }
147
configurationAdded(const QNetworkConfiguration & config)148 void NetworkConfigurationModel::configurationAdded(const QNetworkConfiguration& config)
149 {
150 const auto it = std::find(m_configs.begin(), m_configs.end(), config);
151 if (it != m_configs.end())
152 return;
153 beginInsertRows(QModelIndex(), m_configs.size(), m_configs.size());
154 m_configs.push_back(config);
155 endInsertRows();
156 }
157
configurationChanged(const QNetworkConfiguration & config)158 void NetworkConfigurationModel::configurationChanged(const QNetworkConfiguration& config)
159 {
160 const auto it = std::find(m_configs.begin(), m_configs.end(), config);
161 if (it == m_configs.end())
162 return;
163 const auto idx = std::distance(m_configs.begin(), it);
164 emit dataChanged(index(idx, 0), index(idx, columnCount() - 1));
165 }
166
configurationRemoved(const QNetworkConfiguration & config)167 void NetworkConfigurationModel::configurationRemoved(const QNetworkConfiguration& config)
168 {
169 const auto it = std::find(m_configs.begin(), m_configs.end(), config);
170 if (it == m_configs.end())
171 return;
172 const auto idx = std::distance(m_configs.begin(), it);
173 beginRemoveRows(QModelIndex(), idx, idx);
174 m_configs.erase(it);
175 endRemoveRows();
176 }
177