From 18f24e03abf0343d3a4292b35b2e251625879e71 Mon Sep 17 00:00:00 2001 From: Aaron Rainbolt Date: Mon, 23 Oct 2023 21:50:26 -0500 Subject: [PATCH] Initial import (main window mostly implemented) --- CMakeLists.txt | 85 +++++++++ ethernetsettings.cpp | 15 ++ ethernetsettings.h | 22 +++ ethernetsettings.ui | 19 ++ lubuntu-connection-editor_en_US.ts | 3 + main.cpp | 23 +++ networkcreator.cpp | 14 ++ networkcreator.h | 22 +++ networkcreator.ui | 19 ++ networkdeleter.cpp | 15 ++ networkdeleter.h | 22 +++ networkdeleter.ui | 18 ++ networkselector.cpp | 280 +++++++++++++++++++++++++++++ networkselector.h | 53 ++++++ networkselector.ui | 55 ++++++ 15 files changed, 665 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 ethernetsettings.cpp create mode 100644 ethernetsettings.h create mode 100644 ethernetsettings.ui create mode 100644 lubuntu-connection-editor_en_US.ts create mode 100644 main.cpp create mode 100644 networkcreator.cpp create mode 100644 networkcreator.h create mode 100644 networkcreator.ui create mode 100644 networkdeleter.cpp create mode 100644 networkdeleter.h create mode 100644 networkdeleter.ui create mode 100644 networkselector.cpp create mode 100644 networkselector.h create mode 100644 networkselector.ui diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..08d2452 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,85 @@ +cmake_minimum_required(VERSION 3.16) + +project(lubuntu-connection-editor VERSION 0.1 LANGUAGES CXX) + +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +set(KF5_MIN_VERSION "5.102.0") + +find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE) +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH}) + +find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Network LinguistTools) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Network LinguistTools) +find_package(KF5 ${KF5_MIN_VERSION} REQUIRED NetworkManagerQt) + +set(TS_FILES lubuntu-connection-editor_en_US.ts) + +set(PROJECT_SOURCES + main.cpp + networkselector.cpp + networkselector.h + networkselector.ui + ethernetsettings.h + ethernetsettings.cpp + ethernetsettings.ui + networkcreator.h + networkcreator.cpp + networkcreator.ui + networkdeleter.h + networkdeleter.cpp + networkdeleter.ui + ${TS_FILES} +) + +if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) + qt_add_executable(lubuntu-connection-editor + MANUAL_FINALIZATION + ${PROJECT_SOURCES} + ) +# Define target properties for Android with Qt 6 as: +# set_property(TARGET lubuntu-connection-editor APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR +# ${CMAKE_CURRENT_SOURCE_DIR}/android) +# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation + + qt_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES}) +else() + if(ANDROID) + add_library(lubuntu-connection-editor SHARED + ${PROJECT_SOURCES} + ) +# Define properties for Android with Qt 5 after find_package() calls as: +# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android") + else() + add_executable(lubuntu-connection-editor + ${PROJECT_SOURCES} + ) + endif() + + qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES}) +endif() + +target_link_libraries(lubuntu-connection-editor PRIVATE Qt${QT_VERSION_MAJOR}::Widgets KF5::NetworkManagerQt) + +set_target_properties(lubuntu-connection-editor PROPERTIES + MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com + MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} + MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} + MACOSX_BUNDLE TRUE + WIN32_EXECUTABLE TRUE +) + +install(TARGETS lubuntu-connection-editor + BUNDLE DESTINATION . + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) + +if(QT_VERSION_MAJOR EQUAL 6) + qt_finalize_executable(lubuntu-connection-editor) +endif() diff --git a/ethernetsettings.cpp b/ethernetsettings.cpp new file mode 100644 index 0000000..8786c63 --- /dev/null +++ b/ethernetsettings.cpp @@ -0,0 +1,15 @@ +#include "ethernetsettings.h" +#include "ui_ethernetsettings.h" + +EthernetSettings::EthernetSettings(QString title, QWidget *parent) : + QDialog(parent), + ui(new Ui::EthernetSettings) +{ + ui->setupUi(this); + this->setWindowTitle(title); +} + +EthernetSettings::~EthernetSettings() +{ + delete ui; +} diff --git a/ethernetsettings.h b/ethernetsettings.h new file mode 100644 index 0000000..4c3628b --- /dev/null +++ b/ethernetsettings.h @@ -0,0 +1,22 @@ +#ifndef ETHERNETSETTINGS_H +#define ETHERNETSETTINGS_H + +#include + +namespace Ui { +class EthernetSettings; +} + +class EthernetSettings : public QDialog +{ + Q_OBJECT + +public: + explicit EthernetSettings(QString title, QWidget *parent = nullptr); + ~EthernetSettings(); + +private: + Ui::EthernetSettings *ui; +}; + +#endif // ETHERNETSETTINGS_H diff --git a/ethernetsettings.ui b/ethernetsettings.ui new file mode 100644 index 0000000..851ba4a --- /dev/null +++ b/ethernetsettings.ui @@ -0,0 +1,19 @@ + + + EthernetSettings + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + diff --git a/lubuntu-connection-editor_en_US.ts b/lubuntu-connection-editor_en_US.ts new file mode 100644 index 0000000..edd0d34 --- /dev/null +++ b/lubuntu-connection-editor_en_US.ts @@ -0,0 +1,3 @@ + + + diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..0f03959 --- /dev/null +++ b/main.cpp @@ -0,0 +1,23 @@ +#include "networkselector.h" + +#include +#include +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + + QTranslator translator; + const QStringList uiLanguages = QLocale::system().uiLanguages(); + for (const QString &locale : uiLanguages) { + const QString baseName = "lubuntu-connection-editor_" + QLocale(locale).name(); + if (translator.load(":/i18n/" + baseName)) { + a.installTranslator(&translator); + break; + } + } + NetworkSelector w; + w.show(); + return a.exec(); +} diff --git a/networkcreator.cpp b/networkcreator.cpp new file mode 100644 index 0000000..4e647e0 --- /dev/null +++ b/networkcreator.cpp @@ -0,0 +1,14 @@ +#include "networkcreator.h" +#include "ui_networkcreator.h" + +NetworkCreator::NetworkCreator(QWidget *parent) : + QDialog(parent), + ui(new Ui::NetworkCreator) +{ + ui->setupUi(this); +} + +NetworkCreator::~NetworkCreator() +{ + delete ui; +} diff --git a/networkcreator.h b/networkcreator.h new file mode 100644 index 0000000..553f974 --- /dev/null +++ b/networkcreator.h @@ -0,0 +1,22 @@ +#ifndef NETWORKCREATOR_H +#define NETWORKCREATOR_H + +#include + +namespace Ui { +class NetworkCreator; +} + +class NetworkCreator : public QDialog +{ + Q_OBJECT + +public: + explicit NetworkCreator(QWidget *parent = nullptr); + ~NetworkCreator(); + +private: + Ui::NetworkCreator *ui; +}; + +#endif // NETWORKCREATOR_H diff --git a/networkcreator.ui b/networkcreator.ui new file mode 100644 index 0000000..8abf0ff --- /dev/null +++ b/networkcreator.ui @@ -0,0 +1,19 @@ + + + NetworkCreator + + + + 0 + 0 + 400 + 300 + + + + Create New Connection... + + + + + diff --git a/networkdeleter.cpp b/networkdeleter.cpp new file mode 100644 index 0000000..9c9dc1c --- /dev/null +++ b/networkdeleter.cpp @@ -0,0 +1,15 @@ +#include "networkdeleter.h" +#include "ui_networkdeleter.h" + +NetworkDeleter::NetworkDeleter(QString networkName, QString networkUuidStr, QWidget *parent) : + QDialog(parent), + ui(new Ui::NetworkDeleter) +{ + ui->setupUi(this); + this->setWindowTitle("Delete connection " + networkName + "?"); +} + +NetworkDeleter::~NetworkDeleter() +{ + delete ui; +} diff --git a/networkdeleter.h b/networkdeleter.h new file mode 100644 index 0000000..7688248 --- /dev/null +++ b/networkdeleter.h @@ -0,0 +1,22 @@ +#ifndef NETWORKDELETER_H +#define NETWORKDELETER_H + +#include + +namespace Ui { +class NetworkDeleter; +} + +class NetworkDeleter : public QDialog +{ + Q_OBJECT + +public: + explicit NetworkDeleter(QString networkName, QString networkUuidStr, QWidget *parent = nullptr); + ~NetworkDeleter(); + +private: + Ui::NetworkDeleter *ui; +}; + +#endif // NETWORKDELETER_H diff --git a/networkdeleter.ui b/networkdeleter.ui new file mode 100644 index 0000000..89d6ba1 --- /dev/null +++ b/networkdeleter.ui @@ -0,0 +1,18 @@ + + NetworkDeleter + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + diff --git a/networkselector.cpp b/networkselector.cpp new file mode 100644 index 0000000..f4c8661 --- /dev/null +++ b/networkselector.cpp @@ -0,0 +1,280 @@ +#include "networkselector.h" +#include "./ui_networkselector.h" +#include + +NetworkSelector::NetworkSelector(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::NetworkSelector) +{ + ui->setupUi(this); + regenConnTree(); + ui->modifyConnButton->setEnabled(false); + connect(ui->connTree, &QTreeView::clicked, this, &NetworkSelector::onTreeSingleClicked); + connect(ui->connTree, &QTreeView::doubleClicked, this, &NetworkSelector::onTreeDoubleClicked); + connect(ui->createConnButton, &QPushButton::clicked, this, &NetworkSelector::onCreateClicked); + connect(ui->deleteConnButton, &QPushButton::clicked, this, &NetworkSelector::onDeleteClicked); + connect(ui->modifyConnButton, &QPushButton::clicked, this, &NetworkSelector::onModifyClicked); +} + +NetworkSelector::~NetworkSelector() +{ + delete ui; + delete connTreeModel; +} + +void NetworkSelector::onTreeSingleClicked(QModelIndex index) +{ + QVariant connUuid = index.data(Qt::UserRole+1); + if (!connUuid.isValid()) { + ui->modifyConnButton->setEnabled(false); + return; + } + ui->modifyConnButton->setEnabled(true); +} + +void NetworkSelector::onTreeDoubleClicked(QModelIndex index) +{ + modifyConnection(index); +} + +void NetworkSelector::onCreateClicked() +{ + dialogWindow = new NetworkCreator(); + dialogWindow->exec(); + delete dialogWindow; + regenConnTree(); +} + +void NetworkSelector::onDeleteClicked() +{ + QModelIndexList selectedNetworks = ui->connTree->selectionModel()->selectedIndexes(); + if (selectedNetworks.length() == 0) { + return; + } + if (!selectedNetworks[0].data(Qt::UserRole+1).isValid()) { + return; + } + dialogWindow = new NetworkDeleter(selectedNetworks[0].data().toString(), selectedNetworks[0].data(Qt::UserRole+1).toString()); + dialogWindow->exec(); + delete dialogWindow; + regenConnTree(); +} + +void NetworkSelector::onModifyClicked() +{ + QModelIndexList selectedNetworks = ui->connTree->selectionModel()->selectedIndexes(); + if (selectedNetworks.length() == 0) { + return; + } + if (!selectedNetworks[0].data(Qt::UserRole+1).isValid()) { + return; + } + + modifyConnection(selectedNetworks[0]); +} + +QStandardItem *NetworkSelector::connGroupItem(QString itemName) +{ + for (int i = 0;i < connTreeList.length();i++) { + if (connTreeList[i]->text() == itemName) { + return connTreeList[i]; + } + } + return NULL; +} + +void NetworkSelector::regenConnTree() +{ + if (connTreeModel != NULL) { + delete connTreeModel; + } + connTreeList = QList(); + connTreeModel = new QStandardItemModel(0, 2); + connTreeModel->setHeaderData(0, Qt::Orientation::Horizontal, "Connection"); + connTreeModel->setHeaderData(1, Qt::Orientation::Horizontal, "Last used"); + + connList = NetworkManager::listConnections(); + + for (int i = 0;i < connList.length();i++) { + if (connList[i]->name() == "lo") { // don't show the loopback device + continue; + } + + QList infoRow; + infoRow.append(new QStandardItem(connList[i]->name())); + infoRow.append(new QStandardItem(connList[i]->settings()->timestamp().toString("yyyy-MM-dd hh:mm"))); + + // When the user double-clicks a cell in the tree, the double-click handler gets an object that can fetch a data value from the clicked cell. + // We need to identify the exact connection that was double-clicked on in order for this to work, so we bind the connection's UUID to both visible + // cells in the row representing a connection. + infoRow[0]->setData(connList[i]->uuid()); + infoRow[1]->setData(connList[i]->uuid()); + + NetworkManager::ConnectionSettings::ConnectionType connType = connList[i]->settings()->connectionType(); + QStandardItem *targetItem; + switch(connType) { + case NetworkManager::ConnectionSettings::Wired: + targetItem = connGroupItem("Ethernet"); + if (targetItem == NULL) { + targetItem = new QStandardItem("Ethernet"); + connTreeList.append(targetItem); + } + break; + + case NetworkManager::ConnectionSettings::Wireless: + targetItem = connGroupItem("WiFi"); + if (targetItem == NULL) { + targetItem = new QStandardItem("WiFi"); + connTreeList.append(targetItem); + } + break; + + case NetworkManager::ConnectionSettings::Adsl: + case NetworkManager::ConnectionSettings::Pppoe: + targetItem = connGroupItem("DSL"); + if (targetItem == NULL) { + targetItem = new QStandardItem("DSL"); + connTreeList.append(targetItem); + } + break; + + case NetworkManager::ConnectionSettings::Bluetooth: + targetItem = connGroupItem("Bluetooth"); + if (targetItem == NULL) { + targetItem = new QStandardItem("Bluetooth"); + connTreeList.append(targetItem); + } + break; + + case NetworkManager::ConnectionSettings::Bond: + case NetworkManager::ConnectionSettings::Bridge: + case NetworkManager::ConnectionSettings::Vlan: + targetItem = connGroupItem("Virtual"); + if (targetItem == NULL) { + targetItem = new QStandardItem("Virtual"); + connTreeList.append(targetItem); + } + break; + + case NetworkManager::ConnectionSettings::Cdma: + case NetworkManager::ConnectionSettings::Gsm: + targetItem = connGroupItem("Mobile"); + if (targetItem == NULL) { + targetItem = new QStandardItem("Mobile"); + connTreeList.append(targetItem); + } + break; + + case NetworkManager::ConnectionSettings::Infiniband: + targetItem = connGroupItem("Infiniband"); + if (targetItem == NULL) { + targetItem = new QStandardItem("Infiniband"); + connTreeList.append(targetItem); + } + break; + + case NetworkManager::ConnectionSettings::OLPCMesh: + targetItem = connGroupItem("OLPC-Mesh"); + if (targetItem == NULL) { + targetItem = new QStandardItem("OLPC-Mesh"); + connTreeList.append(targetItem); + } + break; + + case NetworkManager::ConnectionSettings::Vpn: + case NetworkManager::ConnectionSettings::Tun: + case NetworkManager::ConnectionSettings::IpTunnel: + case NetworkManager::ConnectionSettings::WireGuard: + targetItem = connGroupItem("VPN"); + if (targetItem == NULL) { + targetItem = new QStandardItem("VPN"); + connTreeList.append(targetItem); + } + break; + + case NetworkManager::ConnectionSettings::Wimax: + targetItem = connGroupItem("WiMAX"); + if (targetItem == NULL) { + targetItem = new QStandardItem("WiMAX"); + connTreeList.append(targetItem); + } + break; + + case NetworkManager::ConnectionSettings::Team: + targetItem = connGroupItem("Team"); + if (targetItem == NULL) { + targetItem = new QStandardItem("Team"); + connTreeList.append(targetItem); + } + break; + + case NetworkManager::ConnectionSettings::Generic: + targetItem = connGroupItem("Generic"); + if (targetItem == NULL) { + targetItem = new QStandardItem("Generic"); + connTreeList.append(targetItem); + } + break; + + case NetworkManager::ConnectionSettings::Unknown: + targetItem = connGroupItem("Unknown"); + if (targetItem == NULL) { + targetItem = new QStandardItem("Unknown"); + connTreeList.append(targetItem); + } + break; + } + + targetItem->appendRow(infoRow); + } + + for (int i = 0;i < connTreeList.length();i++) { + QList currentItemWrap; + currentItemWrap.append(connTreeList[i]); + connTreeModel->appendRow(currentItemWrap); + } + + ui->connTree->setModel(connTreeModel); + ui->connTree->setColumnWidth(0, 500); +} + +void NetworkSelector::modifyConnection(QModelIndex index) +{ + QVariant connUuid = index.data(Qt::UserRole+1); + if (!connUuid.isValid()) { + return; + } + + for (int i = 0;i < connList.length();i++) { + if (connUuid.toString() == connList[i]->uuid()) { + NetworkManager::ConnectionSettings::ConnectionType connType = connList[i]->settings()->connectionType(); + switch(connType) { + case NetworkManager::ConnectionSettings::Wired: + dialogWindow = new EthernetSettings(index.data().toString()); + dialogWindow->exec(); + delete dialogWindow; + break; + case NetworkManager::ConnectionSettings::Wireless: + case NetworkManager::ConnectionSettings::Adsl: + case NetworkManager::ConnectionSettings::Pppoe: + case NetworkManager::ConnectionSettings::Bluetooth: + case NetworkManager::ConnectionSettings::Bond: + case NetworkManager::ConnectionSettings::Bridge: + case NetworkManager::ConnectionSettings::Vlan: + case NetworkManager::ConnectionSettings::Cdma: + case NetworkManager::ConnectionSettings::Gsm: + case NetworkManager::ConnectionSettings::Infiniband: + case NetworkManager::ConnectionSettings::OLPCMesh: + case NetworkManager::ConnectionSettings::Vpn: + case NetworkManager::ConnectionSettings::Tun: + case NetworkManager::ConnectionSettings::IpTunnel: + case NetworkManager::ConnectionSettings::WireGuard: + case NetworkManager::ConnectionSettings::Wimax: + case NetworkManager::ConnectionSettings::Team: + case NetworkManager::ConnectionSettings::Generic: + case NetworkManager::ConnectionSettings::Unknown: + ; + } + } + } +} diff --git a/networkselector.h b/networkselector.h new file mode 100644 index 0000000..0a0a388 --- /dev/null +++ b/networkselector.h @@ -0,0 +1,53 @@ +#ifndef NETWORKSELECTOR_H +#define NETWORKSELECTOR_H + +#include "ethernetsettings.h" +#include "networkcreator.h" +#include "networkdeleter.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE +namespace Ui { class NetworkSelector; } +QT_END_NAMESPACE + +class NetworkSelector : public QMainWindow +{ + Q_OBJECT + +public: + NetworkSelector(QWidget *parent = nullptr); + ~NetworkSelector(); + +private slots: + void onTreeSingleClicked(QModelIndex index); + void onTreeDoubleClicked(QModelIndex index); + void onCreateClicked(); + void onDeleteClicked(); + void onModifyClicked(); + +private: + QStandardItem *connGroupItem(QString itemName); + void regenConnTree(); + void modifyConnection(QModelIndex index); + + Ui::NetworkSelector *ui; + QStandardItemModel *connTreeModel; + QList connTreeList; + NetworkManager::Connection::List connList; + + QDialog *dialogWindow; +}; +#endif // NETWORKSELECTOR_H diff --git a/networkselector.ui b/networkselector.ui new file mode 100644 index 0000000..aba0561 --- /dev/null +++ b/networkselector.ui @@ -0,0 +1,55 @@ + + + NetworkSelector + + + + 0 + 0 + 800 + 600 + + + + NetworkSelector + + + + + + + QAbstractItemView::NoEditTriggers + + + + + + + + + Create + + + + + + + Delete + + + + + + + Modify + + + + + + + + + + +