/*! * * Copyright (c) 2021-2023 Diality Inc. - All Rights Reserved. * \copyright * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * \file VNetworkModel.cpp * \author (last) Behrouz NematiPour * \date (last) 02-Feb-2023 * \author (original) Behrouz NematiPour * \date (original) 11-May-2021 * */ // Qt #include // Project #include "VNetworkModel.h" #include "WifiInterface.h" #include "Logger.h" using namespace View; VNetworkModel::VNetworkModel(QAbstractListModel *parent) : QAbstractListModel(parent) { startTimer(_interval); initConnections(); } /*! * \brief VNetworkModel::initConnections * Makes the necessary connections. Called inside VIEW_DEF_CLASS */ void VNetworkModel::initConnections() { // incoming connect(&_WifiInterface, SIGNAL(didAddNetwork (const WifiNetworkData &)), this, SLOT( onAddNetwork (const WifiNetworkData &))); connect(&_WifiInterface, SIGNAL(didScanStatusChanged(bool)), this, SLOT( onScanStatusChanged(bool))); connect(&_WifiInterface, SIGNAL( didConnectToNetwork(const WifiNetworkData &)), this, SLOT( onConnectToNetwork(const WifiNetworkData &))); connect(&_WifiInterface, SIGNAL(didDisconnectNetwork(const WifiNetworkData &)), this, SLOT( onDisconnectNetwork(const WifiNetworkData &))); connect(&_WifiInterface, SIGNAL( didError (const QString &)), this, SLOT(onStatusChanged (const QString &))); connect(&_WifiInterface, SIGNAL(didStatusChanged (const QString &)), this, SLOT( onStatusChanged (const QString &))); // incoming - static IP address assignment connect(&_WifiInterface, SIGNAL(didSetStaticIPAddress ()), this, SLOT( onSetStaticIPAddressSuccess())); connect(&_WifiInterface, SIGNAL(didSetGateway ()), this, SLOT( onSetGatewaySuccess())); connect(&_WifiInterface, SIGNAL(didSetSubnetMask ()), this, SLOT( onSetSubnetMaskSuccess())); connect(&_WifiInterface, SIGNAL(didSetDNS ()), this, SLOT( onSetDNSSuccess())); // outgoing connect(this, SIGNAL(didScan()), &_WifiInterface, SLOT( doScan())); connect(this, SIGNAL(didJoinNetwork (const WifiNetworkData &, const QString &)), &_WifiInterface, SLOT( doJoinNetwork (const WifiNetworkData &, const QString &))); connect(this, SIGNAL(didDisconnectNetwork(const WifiNetworkData &)), &_WifiInterface, SLOT( doDisconnectNetwork(const WifiNetworkData &))); connect(this, SIGNAL(didRequestIPSettings()), &_WifiInterface, SLOT( doRequestIPSettings())); // outgoing - static IP address assignment connect(this, SIGNAL(didRequestSetIPAddress (const QString &)), &_WifiInterface, SLOT( doRequestSetIPAddress (const QString &))); connect(this, SIGNAL(didRequestSetGateway (const QString &)), &_WifiInterface, SLOT( doRequestSetGateway (const QString &))); connect(this, SIGNAL(didRequestSetSubnetMask (const QString &)), &_WifiInterface, SLOT( doRequestSetSubnetMask (const QString &))); connect(this, SIGNAL(didRequestSetDNS (const QString &)), &_WifiInterface, SLOT( doRequestSetDNS (const QString &))); } /*! * \brief VNetworkModel::addNetwork * Adds a network to the network model * \param network (Network) - the network to add to the model */ void VNetworkModel::addNetwork(const WifiNetworkData &vNetwork) { LOG_DEBUG(QString("Adding network with SSID: %1").arg(vNetwork.ssid())); beginInsertRows(QModelIndex(), rowCount(), rowCount()); _networks << vNetwork; endInsertRows(); // For testing w/out a display: in main.qml call doScan() using Component.onCompleted, // then call doJoinNetwork here when the desired network's mac address has been detected } /*! * \brief VNetworkModel::removeRows * Removes all rows from the model */ void VNetworkModel::removeAllRows() { beginRemoveRows(QModelIndex(), 0, rowCount()); _networks.clear(); endRemoveRows(); } /*! * \brief VNetworkModel::doInit * \details Initializes the view or what needs to be done when for example getting into the WiFi setting screen (do scan for now). */ void VNetworkModel::doInit() { doScan(); } /*! * \brief VNetworkModel::rowCount * Gets the number of networks * \param parent - (QModelIndex) the parent QModelIndex * \return (int) - the number of networks */ int VNetworkModel::rowCount(const QModelIndex & parent) const { Q_UNUSED(parent); return _networks.count(); } /*! * \brief VNetworkModel::data * Returns the network properties at the specified index * \param index (QModelIndex) contains the row of data to lookup * \param role - (int) the property index to return. See NetworkDataRole * \return (QVariant) - the value for the specified network property */ QVariant VNetworkModel::data(const QModelIndex & index, int role) const { if (index.row() < 0 || index.row() >= _networks.count()) return QVariant(); const WifiNetworkData &network = _networks[index.row()]; switch (role) { case MacAddressRole: return network.macAddress(); case SSIDRole: return network.ssid(); case SecurityTypesRole: return MWifiNetwork::securityTypesToStringList(network.securityTypes()).join("/"); case StatusRole: return network.status(); case SignalLevelRole: return network.signalLevel(); case NetworkSupportedRole: { bool isSecurityTypeSupported = (!network.securityTypes().contains(MWifiNetwork::SECURITY_TYPE::WEP) && !network.securityTypes().contains(MWifiNetwork::SECURITY_TYPE::UNSUPPORTED)); bool isPasswordProtected = network.requirePassword(); return isSecurityTypeSupported && isPasswordProtected; } } return QVariant(); } /*! * \brief VNetworkModel::roleNames * Translates how to access specific properties of the data for QML from the NetworkDataRole enum * \return (QHash) - maps enums to property names */ QHash VNetworkModel::roleNames() const { QHash roles; roles[MacAddressRole] = "macAddress"; roles[SSIDRole] = "ssid"; roles[SecurityTypesRole] = "securityTypes"; roles[StatusRole] = "status"; roles[SignalLevelRole] = "signalLevel"; roles[NetworkSupportedRole] = "isNetworkSupported"; return roles; } /*! * \brief VNetworkModel::doScan * Handles when a user clicks the Scan button */ void VNetworkModel::doScan() { LOG_DEBUG("Clearing networks before re-scanning."); removeAllRows(); status(tr("Scanning...")); emit didScan(); } /*! * \brief VNetworkModel::onAddNetwork * Slot that receives a request to add a new network * \param vNetwork - (Network) the new network to add */ void VNetworkModel::onAddNetwork(const WifiNetworkData &vNetwork) { if (!_networks.contains(vNetwork)) { LOG_DEBUG(QString("Adding network with SSID: %1.").arg(vNetwork.ssid())); addNetwork(vNetwork); } else { LOG_DEBUG(QString("Skipping adding network with SSID: %1. It already exists").arg(vNetwork.ssid())); } } /*! * \brief VNetworkModel::onScanStatusChanged * Called when the scan status changes. Updates QML with the current state * \param vScanning - (bool) true if scanning, false otherwise */ void VNetworkModel::onScanStatusChanged(const bool &vScanning) { if (!vScanning) status(tr("Scan Finished")); scanInProgress(vScanning); } /*! * \brief VNetworkModel::doCheckIfConnected * Checks whether the network specified by the mac address is connected or not * \param vMacAddress - (QString) the unique mac address for the network */ bool VNetworkModel::doCheckIfConnected(const QString &vMacAddress) { if (vMacAddress == macAddress()) return true; return false; } /*! * \brief VNetworkModel::doJoinNetwork * Handles request from qml to join a network * \param vMacAddress - (QString) the mac address of the network to join * \param vPassword - (QString) the password for the network provided by the user */ void VNetworkModel::doJoinNetwork(const QString &vMacAddress, const QString &vPassword) { clearSelectedNetwork(); for (const WifiNetworkData &network : _networks) { if (network.macAddress() == vMacAddress) { status(tr("Connecting to %1...").arg(network.ssid())); emit didJoinNetwork(network, vPassword); return; } } } /*! * \brief VNetworkModel::doDisconnectNetwork * Handles request from qml to disconnect from a network * \param vMacAddress - (QString) the mac address of the network to disconnect from */ void VNetworkModel::doDisconnectNetwork(const QString &vMacAddress) { for (const WifiNetworkData &network : _networks) { if (network.macAddress() == vMacAddress) { status(tr("Disconnecting from %1...").arg(network.ssid())); emit didDisconnectNetwork(network); return; } } } /*! * \brief VNetworkModel::onConnectedToNetwork * Called when we have connected to a network. * \param vNetwork - (Network) the network we have connected to */ void VNetworkModel::onConnectToNetwork(const WifiNetworkData &vNetwork) { LOG_DEBUG(QString("Connected to %1.").arg(vNetwork.ssid())); ipAddress(vNetwork.mIPSettings.mIPAddress.trimmed()); gateway(vNetwork.mIPSettings.mGateway.trimmed()); subnetMask(vNetwork.mIPSettings.mSubnetMask.trimmed()); dns(vNetwork.mIPSettings.mDNS.trimmed()); ssid(vNetwork.ssid().trimmed()); macAddress(vNetwork.macAddress().trimmed()); status(tr("Connected to %1.").arg(vNetwork.ssid()).trimmed()); } /*! * \brief VNetworkModel::onDisconnectedNetwork * Called when we have disconnected from a network. * \param vNetwork - (Network) the network we have disconnected from */ void VNetworkModel::onDisconnectNetwork(const WifiNetworkData &vNetwork) { LOG_DEBUG(QString("Disconnected from %1.").arg(vNetwork.ssid())); clearSelectedNetwork(); status(tr("Disconnected from %1.").arg(vNetwork.ssid())); } /*! * \brief VNetworkModel::doRequestIPSettings * Called when QML requests the IP settings */ void VNetworkModel::doRequestIPSettings() { emit didRequestIPSettings(); } /*! * \brief VNetworkModel::onStatusChanged * Called when the wifi interface status changes * \param vMessage - (QString) the error message */ void VNetworkModel::onStatusChanged(const QString &vMessage) { status(vMessage); } /*! * \brief VNetworkModel::doSetIPAddress * \param vIPAddress (QString) the ip address */ void VNetworkModel::doSetIPAddress(const QString &vIPAddress) { emit didRequestSetIPAddress(vIPAddress.trimmed()); } /*! * \brief VNetworkModel::doSetGateway * \param vGateway (QString) the gateway */ void VNetworkModel::doSetGateway(const QString &vGateway) { emit didRequestSetGateway(vGateway.trimmed()); } /*! * \brief VNetworkModel::doSetSubnetMask * \param vSubnetMask (QString) the subnet mask */ void VNetworkModel::doSetSubnetMask(const QString &vSubnetMask) { emit didRequestSetSubnetMask(vSubnetMask.trimmed()); } /*! * \brief VNetworkModel::doSetDNS * \param vDNS (QString) the DNS */ void VNetworkModel::doSetDNS(const QString &vDNS) { emit didRequestSetDNS(vDNS.trimmed()); } /*! * \brief VNetworkModel::timerEvent * \details The overloaded parent QObject timer event handler function */ void VNetworkModel::timerEvent(QTimerEvent *) { checkEthernet(); checkWireless(); } /*! * \brief VNetworkModel::clearWifiSettings * Clears the selected network settings */ void VNetworkModel::clearSelectedNetwork() { ipAddress(""); gateway(""); subnetMask(""); dns(""); ssid(""); macAddress(""); } /*! * \brief VNetworkModel::checkEthernet * \details check for Ethernet using VNetworkModel::checkDevNet */ void VNetworkModel::checkEthernet() { const QNetworkInterface dev = QNetworkInterface::interfaceFromName(_devEth); QString devIP = tr("No Ethernet"); if ( dev.isValid() ) { auto addresses = dev.addressEntries(); if ( addresses.count() ) { devIP = addresses.first().ip().toString(); } } _ethernetIP = devIP; emit ethernetIPChanged( _ethernetIP ); } /*! * \brief VNetworkModel::checkWireless * \details check for Ethernet using VNetworkModel::checkDevNet */ void VNetworkModel::checkWireless() { const QNetworkInterface dev = QNetworkInterface::interfaceFromName(_devWlan); QString devIP = tr("No WiFi"); if ( dev.isValid() ) { auto addresses = dev.addressEntries(); if ( addresses.count() ) { if ( dev.flags().testFlag(QNetworkInterface::IsUp) && dev.flags().testFlag(QNetworkInterface::IsRunning) ) { devIP = addresses.first().ip().toString(); } else { devIP = tr("WiFi Disconnect"); } } } _wirelessIP = devIP; emit wirelessIPChanged( _wirelessIP ); } /*! * \brief VNetworkModel::onSetIPAddressSuccess * Called when the IP address has been set */ void VNetworkModel::onSetStaticIPAddressSuccess() { status(tr("Successfully set the IP address.")); } /*! * \brief VNetworkModel::onSetGatewaySuccess * Called when the gateway has been set */ void VNetworkModel::onSetGatewaySuccess() { status(tr("Successfully set the gateway.")); } /*! * \brief VNetworkModel::onSetSubnetMaskSuccess * Called when the subnet mask has been set */ void VNetworkModel::onSetSubnetMaskSuccess() { status(tr("Successfully set the subnet mask.")); } /*! * \brief VNetworkModel::onSetDNSSuccess * Called when the DNS has been set */ void VNetworkModel::onSetDNSSuccess() { status(tr("Successfully set the DNS.")); }