DESIGN

Split system

i) KCModule performs connection configuration

ii) Settings service exists on the system bus and provides information to NetworkManager

iii) Plasmoid gives user feedback i
      Notifications
      Status in popup
    and connection control
      Calls DBUS methods on manager, passing references to objects supplied by the setings service
    launches KCModule on request


Directory structure of project
./libs                      Headers shared by all code
./libs/storage              Storage layer shared library (libknmstorage) for loading and saving NM settings
./libs/ui                   UI shared library (libknmui) for settings config widgets
./settings                  (Any source code in this directory is unused)
./settings/service          Settings service using libknmstorage
./settings/config           KCM for configuring settings using libknmstorage and libknmui
./settings/configshell      New connection helper app that shows only a new connection dialog when the user clicks an 
                            unconfigured network
./settings/test             (Unused test code, scheduled for merging/moving)
./tests                     Proof-of-concept code, not proper unit tests yet
./applet                    Plasmoid sources
./widgets                   OBSOLETE Components for the plasmoid


PLASMOID
Functions
* Show current merged connection status
* Show any in-progress operations
* List currently appropriate connections
  * For wireless, when there are no appropriate connections, list networks that are seen
* Allow activation of appropriate connections
* Show status of current connections
* Allow disconnect of active connections
* Allow user to select flight mode
* Allow user to select offline mode
* Allow user to launch configuration interface
* Show extended connection information
* Perform notifications

Implementation
* Plasmoid shows overall system status when in panel, by deciding which interface is most interesting and showing
  its status
* On click, popup graphicswidget (instead of context menu) for control
* Popup contains InterfaceGroups of like interfaces, and auxiliary controls
** Manage.. button shows KCM
** Toggle wireless
** Toggle overall networking
* InterfaceGroups consist of InterfaceItems and ConnectionItems.  1 InterfaceItem per physical interface.  1 ConnectionItem shown per /appropriate/ connection.
* "Appropriate" means that the ConnectionItem could be activated at the present time - the network interface is active, and any connection-specific requirements are filled; for example, wireless connections' access points are detected
* InterfaceGroups hide inappropriate ConnectionItems
* Subclasses for wireless and serial interfaces exist, and for wireless connections.  These show interface-specific connection information
* WirelessInterfaceItems maintain a WirelessEnvironment object.  This models the wireless environment visible to that
  network interface.   Solid::Control::AccessPoints in the same ESSID are grouped into WirelessNetwork objects, since
  NetworkManager does not do this for us.  WirelessNetwork objects' are managed by the WirelessEnvironment, and users
  should connect to their deleted() or disappeared() signals to avoid dangling pointers (same behaviour as Solid objects)
* NetworkManagerSettings objects represent the UserSettings and SystemSettings services, and give access to their connection objects.  Signals indicate when connections are added or removed or if the service itself terminates, and the connection lists in the popup are updated.
* VPN connections are displayed in an InterfaceGroup without any InterfaceItems.  If only one networkinterface is active, the VPN connection is activated on that interface.  If multiple interfaces are active, the one with the default route is used for the VPN connection.

KCM
Functions
* Show currently configured connections
** show name, type, date of last use
* Allow import of system connections
* Add new connection
** Save connection data to kconfig and kwallet
* Edit existing connection
** Read connection data from kconfig and kwallet
* Delete existing connection
* Secrets may not be stored at all for extreme security, provide kioskable setting for this
* Show warning label if NM is not running.

Implementation:
* List connections by type in main KCM DONE
  * Store connectionId using KTreeWidgetItem::setData() DONE
* There is only one KCM plugin; the other widgets are KCMs (to take advantage of KCModule's good KConfigSkeleton integration) but are not loaded as plugins DONE
* Pass connectionId to connection specific KCM for new or edited connections DONE
* Connect up non-trivial UI to save settings (esp wireless security, 802.1x and ppp)
* Connect up wireless security type combo to tabWidget
* Delete connections deletes config file DONE
  * and wallet entries

Connection types (as used in nm-applet)
wired: connection wired 8021x ipv4
wireless: connection wireless wirelesssecurity ipv4 8021x
mobilebb:
  cdma: cdma ppp
  gsm: gsm ppp
vpn: connection ipv4 vpn
dsl: connection dsl wired ppp

Characteristics
* Use storage layer shared with service.

SERVICE
Functions
* Provide service on system dbus containing configured connections
* Update configured connections following configuration changes
* Emit NewConnection on dbus as needed
* Provide dbus settings objects that provide org.freedesktop.NetworkManagerSettings.Connection and org.freedesktop.NetworkManagerSettings.Connection.Secrets
* Request secrets if required
* Persist changed secrets to kwallet

Characteristics
* Lives in kded
* Watches config file for changes or has simple dbus api with configure() method like kscreensaver
* Uses storage layer shared with KCM
** Added connections
** Updated connections (how? dbus signal? sequence number in config file?)
** Removed connections (compare list of configured connections with active connections)

Implementation
* kded module
* readConfiguration (KConfigToService::init())
** Read central knetworkmanagerrc for connection IDs - DONE
** Read connections from apps/knetworkmanager/connections - DONE
** Read config schemas from apps knetworkmanager/configschema - DONE 
** per-setting group helper class for complex settings, where needed. DONE for ipv4 config read
*** How to figure out whether these are needed at runtime? put in shlib to use with kcm, but separate from UI.
*** ipv4 (really only ipv4 afaics)
* configure method accessible over dbus DONE
** calls rereadConfiguration (KConfigToService::update()) DONE
* GetSecrets. will be received by Connection. emit signal received by NetworkSettings, relayed up ( NetworkSettings knows nothing of storage).  Catch in KConfigToService and ask each configxml for that setting's groups to get secrets?

STORAGE LAYER
Functions

Characteristics
Serializer converts between kconfig storage and qvariantmapmaps
and between kconfig storage and UI contents (like kconfigdialog).
and kwallet

Uses a .kcfg file to define settings.  Since .kcfg allows multiple groups should be able to define all in one .kcfg file.

Use nested groups in rcfile.

Load kcfg, create in memory representation - ConfigXml

Flag passed to ConfigXml controls whether it should load secrets or skip this (for the dbus service, which should not open the wallet until queried by the NM daemon)

READ
Open rcfile.
enumerate connections (top level value).
For each connection:
  get ID
  enumerate settings:
  For each setting:
    pass setting to handler
    enumerate values:
	For each value:
	  lookup name(entry) for setting(group) in kcfg
	  lookup value of entry
	  lookup type for entry
	  lookup min, max if present (or if numeric type)
      pass these to appropriate handler for type
      if a secret=true entry, create an Item that reads KWallet instead of KConfig

handler settings:
  map handler: create new qvariantmap, insert it using setting name, set this on the map handler as current map.
  ui handler: locate child widget called "$name_setting_widget", set it on the ui handler as current widget
handler values:
  map handler: insert qvariant into setting's map with name
  ui handler: locate child widget named "$name_item_widget" and set value, min, max using methods appropriate to widget type 

The UI case is nearly the same as what KConfigXT already does, the difference is that it operates on a top level group only instead of the whole file. We use KConfigDialogManager with a custom KConfigSkeleton (ConfigXml)

All of this is already done, using ConfigXml from Plasma.  Our copy adds support for KWallet and storing byte arrays.

I thought that KConfigDialog only allows a single managed widget but KConfigDialog can handle an arbitrary number of widgets and their children.  Still might have to use the Manager directly to work on a widget in a KCM.

WRITE
From ui:
Each Connection type has its own ConnectionPreferences subclass.  ConnectionPreferences in turn subclasses KCModule, so all write operations are carried out in ConnectionPreferences::save() (a reimpl). {

First KCModule::save() is called, which triggers the KConfigDialogManager automatic persistence of changed widgets' contents using ConfigXml

Secondly, each SettingWidget's SettingsInterface::writeConfig() reimplementation is called, which performs any custom save work necessary.

Many settings are too complex (either the UI does not map to the simple widgets supported by KConfigSkeleton, or there is no 1:1 mapping between the contents of the UI and what NetworkManager expects to receive.

To read and write these settings, reimplement SettingsInterface::writeConfig(), access the config group for the widget with KConfigGroup group(configXml()->config(), settingName());  Then use normal KConfigGroup api to save your settings.  The call to KConfig::sync() is done at the end of ConnectionPreferences::save().

ASSESSMENT OF CURRENT STORAGE LAYER
PROBLEMS
Interface of connections is too simple and under-elaborated - doing settings map lookups to find out things about a connection is tiresome.  
Since there is no Connection class, code to interface with the outside world has to be in other classes. 
Currently we have no place to do custom DBus marshalling of internal connection maps to QVariantMaps which are valid Connections to put on the bus.

NEW STORAGE LAYER
Statically generate classes representing connection settings.  These are managed by a Connection
object.
Per class, have a <classname>Persistence object responsible for reading/writing KConfig and KWallet, and a <classname>Dbus object that marshals to and from dbus a{sa{sv} nested maps.
The code (all 3 classes per Setting) is generated by a hacked version of kconfig_compiler.
It is hand edited after generation so the developer can implement non-trivial settings, so the code is not generated at build time, but generated manually, copied into the source tree and committed.

Secrets should be saveable in KWallet or KConfig.  
KWallet usage should use KWallet's map type instead of individual keys.
SecretStorageHelper and ConnectionSecretsJob will need modifying
SSH does writes and reads synchronously.
SSH is being used in ConfigXml to write secrets individually, and to read secrets there, but read is disabled in the service by passing in false to the ConfigXml ctor.  In the KCM it is enabled so the wallet is access synchronously
CSJ is being used in settings/service/connection.cpp external to ConfigXml to fetch secrets and then update the (already marshalled maps) from restoreConnection

Consider moving CSJ inside *Persistence and calling Setting-specific converters to do things like key hashing so toSecretsMap() (?) can return a finished set of secrets.
Add bool secretsLoaded() accessor.  Make $class a QObject, getSecrets/gotSecrets async pair.  Do fetch inside Persistence.  On gotSecrets, actual dbus object can use Dbus to marshal them (including any hashing).

* <Settingname>DBus may be a bad name since it is just a marshaller, not a dbus object itself

MINI TODO
Move special cases from KConfigToService to ConnectionDbus.
WPA-EAP Non Peap/TTLS types
GSM

