This document describes the implementation of the GlobalProtect VPN plugin for KDE Plasma 5.
All components have been implemented and are ready for testing:
-
Plugin Factory (
gpclientui.h/cpp)- Implements
VpnUiPlugininterface - Provides widget creation and metadata
- Exports
K_PLUGIN_CLASS_WITH_JSONmacro for plugin loading
- Implements
-
Configuration Widget (
gpclientwidget.h/cpp)- Implements
SettingWidgetinterface - Handles loading/saving VPN configuration
- Provides validation (gateway required)
- Implements
-
User Interface (
gpclientwidget.ui)- Qt Designer XML format
- QFormLayout with 3 fields:
- Gateway (QLineEdit)
- Browser (QLineEdit)
- DNS Servers (QLineEdit)
- Tooltips and placeholders for user guidance
-
Plugin Metadata (
plasmanetworkmanagement_gpclientui.json)- KPlugin metadata in JSON format
- Service type:
PlasmaNetworkManagement/VpnUiPlugin - NetworkManager service:
org.freedesktop.NetworkManager.gpclient
-
Service Definition (
plasmanetworkmanagement_gpclientui.desktop)- Desktop entry for plugin discovery
- Compatible with KDE service system
-
Build System (
CMakeLists.txt,build.sh)- CMake configuration with KDE/Qt dependencies
- Automated build script for convenience
GpclientUiPlugin : VpnUiPlugin
└── creates GpclientWidget : SettingWidget
└── uses UI from gpclientwidget.ui
User Input (UI)
↓
GpclientWidget::setting()
↓
QVariantMap with VPN data items
↓
NetworkManager::VpnSetting
↓
NetworkManager (saved to connection)
NetworkManager Connection
↓
NetworkManager::VpnSetting
↓
GpclientWidget::loadConfig()
↓
UI fields populated
Plasma Network Manager discovers plugins through:
- Service Type:
PlasmaNetworkManagement/VpnUiPlugin - Service Name:
org.freedesktop.NetworkManager.gpclient - Plugin Location:
/usr/lib/x86_64-linux-gnu/qt5/plugins/plasma/network/vpn/ - Desktop File:
/usr/share/kservices5/
VPN settings are stored as NetworkManager data items:
| Key | Type | Description | Required |
|---|---|---|---|
gateway |
string | VPN server hostname/IP | Yes |
browser |
string | Browser path for 2FA | No |
dns |
string | Semicolon-separated DNS list | No |
Example stored data:
[vpn]
service-type=org.freedesktop.NetworkManager.gpclient
data=gateway=vpn.company.com;browser=/usr/bin/firefox;dns=8.8.8.8;8.8.4.4Libraries:
- Qt5Core, Qt5Widgets
- KF5::I18n, KF5::Service, KF5::WidgetsAddons
- KF5::NetworkManagerQt
- plasmanm_internal, plasmanm_editor (from plasma-nm)
Build Tools:
- CMake 3.16+
- Extra CMake Modules (ECM)
- C++17 compiler
cd plasma
mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=/usr
make -j$(nproc)
sudo make installPlugin: /usr/lib/x86_64-linux-gnu/qt5/plugins/plasma/network/vpn/
plasmanetworkmanagement_gpclientui.so
Metadata: /usr/lib/x86_64-linux-gnu/qt5/plugins/plasma/network/vpn/
plasmanetworkmanagement_gpclientui.json
Service: /usr/share/kservices5/
plasmanetworkmanagement_gpclientui.desktop
Purpose: Plugin factory and entry point
Key Functions:
widget()- Creates configuration widgetaskUser()- Creates authentication dialog (reuses widget)suggestedFileName()- Suggests export filename
Exports:
K_PLUGIN_CLASS_WITH_JSON(GpclientUiPlugin, "plasmanetworkmanagement_gpclientui.json")
Purpose: Configuration UI and data handling
Key Functions:
loadConfig()- Loads VPN settings into UIsetting()- Converts UI to QVariantMapisValid()- Validates configuration (gateway required)
Signals:
settingChanged()- Emitted on any field change
// Plugin factory registration
K_PLUGIN_CLASS_WITH_JSON(GpclientUiPlugin, "plasmanetworkmanagement_gpclientui.json")
// Widget creation
SettingWidget *GpclientUiPlugin::widget(const NetworkManager::VpnSetting::Ptr &setting, ...)
{
return new GpclientWidget(setting, parent);
}
// Data saving
QVariantMap GpclientWidget::setting() const
{
NetworkManager::VpnSetting setting;
setting.setServiceType("org.freedesktop.NetworkManager.gpclient");
QVariantMap data;
data.insert("gateway", m_ui->gatewayLineEdit->text());
// ... more fields ...
setting.setData(data);
return setting.toMap();
}- Build and install the plugin
- Restart plasmashell:
killall plasmashell && plasmashell & - Open System Settings → Network → Connections
- Add new VPN connection
- Select "GlobalProtect" from VPN types
- Configure and save
- Connect using network applet
# Check plugin file
ls -l /usr/lib/x86_64-linux-gnu/qt5/plugins/plasma/network/vpn/plasmanetworkmanagement_gpclientui.so
# Check desktop file
ls -l /usr/share/kservices5/plasmanetworkmanagement_gpclientui.desktop
# Check if plugin loads
qdbus org.kde.plasmanetworkmanagement
# Test connection
nmcli connection show "My GlobalProtect VPN"
nmcli connection up "My GlobalProtect VPN"# Set Qt debug categories
export QT_LOGGING_RULES="plasma-nm.debug=true"
# View logs
journalctl --user -u plasma-plasmashell -fPlugin not found:
- Check installation paths match CMake configuration
- Verify JSON metadata is valid
- Ensure desktop file has correct service type
Widget not showing:
- Check
widget()returns non-null - Verify UI file was processed by
ki18n_wrap_ui() - Ensure all Qt properties are set correctly
Settings not saving:
- Check
setting()returns valid QVariantMap - Verify service type matches:
org.freedesktop.NetworkManager.gpclient - Ensure data keys match what NetworkManager expects
- KDE Plasma: 5.x series
- Qt: 5.15+
- KF5: 5.80+
- NetworkManager: 1.46+
The plugin should work on any Linux distribution with:
- KDE Plasma 5 desktop
- NetworkManager
- plasma-nm package
Tested distributions:
- Ubuntu 22.04, 24.04
- Fedora 38+
- Arch Linux
- openSUSE Tumbleweed
Possible improvements:
- Authentication Dialog: Implement custom
askUser()for password/2FA prompts - Advanced Options: Add expander for optional settings
- Connection Wizard: Step-by-step setup assistant
- Import/Export: Load .ovpn or similar config files
- Browser Selection: File picker dialog instead of text entry
- DNS Validation: Check DNS server format validity
Based on:
- Plasma Network Manager VPN plugin architecture
- OpenConnect VPN plugin structure
- NetworkManager OpenConnect plugin
This KDE Plasma plugin code was 100% generated by AI (Claude). The author does not have expertise in Qt/KDE/Plasma plugin development and cannot fully verify the correctness of this implementation. The code works in testing but may contain issues. Use at your own risk and please report any bugs.
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL