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