Warning, /pim/kube/docs/design.md is written in an unsupported language. File is not indexed.

0001 # Architecture / Design
0002 
0003 ## Overview
0004 Kube is supposed to be a small and concise codebase that is easy to modify and evolve.
0005 
0006 It's following a reactive model, where in one direction we have actions generating modifications, and in the other direction models updating themselves on changes.
0007 
0008 The overall architecture is split into three layers; Ui, Domain Logic and Infrastructure.
0009 
0010 ```
0011 +----------------------------+
0012 |        UI Components       |
0013 +----------------------------+
0014 |                            |
0015 |        Domain Logic        |
0016 |        Fabric/Models       |
0017 |                            |
0018 +--------------+------+------+
0019 |              |      |      |
0020 |    Sink      |Config| ...  |
0021 |              |      |      |
0022 +--------------+------+------+
0023 ```
0024 
0025 The UI Layer consists of views (mostly written in QML), view-models (models that are view specific and potentially implement user interaction details), and the glue code to use various models and actions from the interface. Different UI layers may exist for different form factors.
0026 
0027 The domain logic layer holds the application state. It povides models to access data and actions to act upon it. The domain logic is by definition Kube specific and not sharable with other applications, as it needs to be taylored exactly according to the requirements of Kube.
0028 
0029 The infrastructure layer provides:
0030 
0031 * Data access (Sink)
0032 * Configuration (Config files, etc.)
0033 * Various functionality provided by libraries (email sending, ldap, iTip handling, iCal implementation (kcalcore), vCard implementation, ...)
0034 Various bits of the infrastructure layer may be exchanged on different platforms, to i.e. integrate into native infrastructure providers on a platform.
0035 
0036 ## UI / Application
0037 The UI / Application layer contains all the view components, and their composition, that make up the application.
0038 All the interactions between the different components are defined here.
0039 
0040 ## Components
0041 The application consists of various application components. A component could be a maillist, an event-editor or the complete kube-mail application. Each component is instantiable on it's own, and has an API to interact with it. The API i.e. allows to set a folder for the maillist, or an event for the event-editor. Components can be nested (a component can instantiate another component)
0042 
0043 A component primarily is a QML UI.
0044 
0045 The QML UI is built on top of:
0046 
0047 * One or more models that are instantiated to provide the data.
0048 * The fabric to interconnect the components.
0049 
0050 ## Component interaction / Fabric
0051 The application is made up of various nested components that often need to interact with each other.
0052 
0053 This interaction is wired up using the Fabric.
0054 
0055 The fabric is a pub/sub messagebus that is orthogonal to the visual hierarchy, that can be used to wire up varius parts of the UI
0056 where a regular property binding would become problematic.
0057 
0058 For more information see: https://cmollekopf.wordpress.com/2017/06/06/kubefabric/
0059 
0060 If we look at the example of the org.kube.mail component:
0061 1. The folderlist-component posts to the fabric that current folder has changed. The maillist reacts to that change and sets it's parentFolder property to display the mails of the currently selected folder.
0062 2. The "add-note" message might either switch to the org.kube.note application as currently displayed component, or it might just display a quick-note widget directly inline.
0063 
0064 This makes it possible for i.e. a maillist to display a note-widget directly inline, or letting the parent component handle the action to show a full note editor. If nothing handles the action, the root component (the shell)can switch to the note application component.
0065 
0066 ## Third party users of components
0067 Since components are self contained and made available as QML plugins, external applications can load fully functional Kube components.
0068 
0069 For example, the KDE calendar plasmoid could load the Kube Event Viewer component when available, and thus provide Kube's full functionality of that component, including all actions etc, without having to reimplement the Domain Logic (as is the case if only data access is provided through Sink).
0070 
0071 ## Domain Logic
0072 
0073 ### Models
0074 Self-updating models are used to implement the read-only part of the application.
0075 By using QAbstractItemModels we can reuse the existing update mechanism, have something that works well with QML, and avoid implementing a boatload of boilerplate code for hand-coded domain objects.
0076 
0077 Models should always be reactive and configured with a query, so they are asynchronous.
0078 
0079 By implementing everything according to that model we can later on achieve lazy-loading of properties and zero-copy (or at least close to zero-copy) directly from storage without modifying anything besides data access.
0080 
0081 Models are self contained and have an API to set i.e. a query for what to load. Models can load data from anywhere. Typically models are implemented in C++ to interface with the rest of the system, but some models may also be implemented directly in QML.
0082 
0083 ### Controller
0084 Controllers are used to interact with the system. The controller is a QObject with a QObject-property for every property that should be editable, and a QValidator for every property, so editors can easily be built using property binding while providing property-level validation and feedback.
0085 
0086 The domain object is exposed as an opaque QVariant. This way details from the infrastructure layer don't leak to the UI layer
0087 
0088 Controllers may interact with infrastructure directly or via the fabric.
0089 
0090 ### Notifications
0091 The system will provide notifications from various sources.
0092 
0093 Notifications could be:
0094 
0095 * New mails arrived
0096 * An error occurred
0097 * A synchronization is in progress
0098 * ...
0099 
0100 Notifications can be displayed in various places of the application and are transported over the Fabric.
0101 
0102 ## Infrastructure
0103 The infrastructure layer interfaces with the rest of the system. It is the place where we can integrate with various native infrastructure parts.
0104 The interface of the infrastructure layer, that is used by the domain logic, may not expose any implementation details of any infrastructure part, to ensure that all infrastructure parts are exchangable.
0105 
0106 ### Sink
0107 Sink is used for primary data access and handles all synchronization.
0108 
0109 Interactions with Sink involve:
0110 
0111 * Adding/removing/configuring resources
0112 * Triggering synchronization
0113 * Querying of data
0114 * Creating/Modifying/Removing entities
0115 
0116 ### Configuration
0117 Configuration as traditionally stored in config files in ~/.config
0118 
0119 ### Notification
0120 Notifications for the system.
0121 
0122 ### Files
0123 Store/Load/Shared stuff (attachments, events, ....)
0124 * Additional to the basic store/load stuff that may need further abstraction for mobile platforms beyond what qt provides.
0125 * Android Intents/Libpurpose (share with various applications etc).
0126 
0127 ### Import/Export
0128 Same as files? Import/Export calendar data
0129 
0130 ### RFC implementations
0131 * iCal: KCalendarCore
0132 * vCard: KContacts
0133 * iTip: extract from kdepim repo
0134 * SMTP: based on libcurl
0135 
0136 ### Cryptography
0137 
0138 Encryption is based on GpgME and uses the systems gpg keyring.
0139 Please note that Kube does not currently manage your key, and retrieves a key matching your email address (gpg2 --list-secret-keys youremail@example.com)
0140 
0141 ### MIME-Message parsing
0142 * KMime
0143 
0144 ## Testing
0145 
0146 TBD
0147 
0148 ## Configuration and Accounts
0149 Kube is a groupware application, so one of its most important features is being able to work with various remote backends. We live in a world of multiple devies and applications, so it is interesting to share as much state and configuration accross all different devices and applications, which is why we try to store as much of that in the backend.
0150 
0151 From the perspective of Kube we are working with different "Accounts". Each account represents a different backend, such as your personal IMAP or Kolab server, or a hosted offering such as GMail or Kolab Now. Each of those accounts may interact with various protocols such as imap, smtp, ldap, caldav etc.
0152 
0153 To add support for a new backend thus means that a new account type has to be added to Kube.
0154 
0155 An account consists of:
0156 
0157 * One or more sink resources to access the remote data
0158 * A configuration UI in QML that can be embedded in the accounts setup
0159 * Potentially custom action handlers if the default action handlers are not sufficient.
0160 * A configuration controller to modify and access the data
0161 * A set of action pre-handler to supply the configuration to actions
0162 
0163 ### Configuration Controller
0164 The configuraton controller is not only used in the configuration UI to provide the data, but it is also used by the rest of the system to access configuration of this account.
0165 
0166 This allows the account to retrieve configruation data on a property-by-property basis i.e. from Sink or a local config file.
0167 
0168 ### Accounts-Plugin
0169 The account is supplied as a plugin. The plugin is loaded into kube directly from QML. The plugin registers it's configuration controller and potentially actions.
0170 
0171 Note: We could have a plugin mechanism that discovers account-plugins should that become necessary at some point.
0172 
0173 ## Application Context
0174 Various parts of the system are context sensitive. I.e. the currently selected account affects which transport is used to send an email, or which folders are currently visble.
0175 
0176 In future iterations that context can be expanded i.e. with projects that affect prioritization of various data items.
0177 
0178 The application context is globally available, although it may be altered locally.
0179 
0180 ## Focus handling
0181 This section lines out how we deal with focus throughout the application.
0182 The aim is to have consistent behaviour across controls and other elements.
0183 
0184 The focus handling needs to take into account:
0185 
0186 * Mouse navigation
0187 * Keyboard navigation
0188 * Touch input
0189 
0190 The primary indicator for focus is the "activeFocus" property (or if available, "visualFocus"). The "focus" property is used for requesting focus and thus not what should be used for detecting focus.
0191 
0192 There are the following different focus states:
0193 * An element can be selected (if selectable). This includes i.e. a text editor that has focus, or a selectable element in a list view.
0194 * An element can be hovered. This is only available with mouse pointers and indicates that the element can be clicked.
0195 * An element can have keyboard focus. This is only available with keyboard navigation and indicates which element currently has keyboard focus.
0196 
0197 With touch input only the selected state is relevant.
0198 
0199 The following indicators are available to visualize selection:
0200 * Highlight: A overlay over the item in the highlight color.
0201 * Border: A border around the item in highlight color.
0202 * Underlined text
0203 
0204 It is important that a selected element can still show focus, otherwise the focus during keyboard navigation simply disappears if it moves to the selected element.
0205 
0206 The following controls need to deal with focus:
0207 * Buttons, IconButtons
0208 * ListView, TreeView, GridView
0209 * TextFields
0210 * Copyable elements
0211 
0212 We're indicating focus as follows:
0213 * Active focus is indicated with a border. This is used for both hovering and keyboard focus.
0214 * A selected element is highlighted.
0215 
0216 ### FocusScope
0217 In order to be able to deal with focus on a local scope (which is important for reusable components), a FocusScope is required to establish a border for focus handling. Internally you can set the focus as required within the focus scope, and externally you can just give focus to the FocusScope, ignoring what's going to happen internally. The FocusScope will automatically forward focus (when it receives it), to whatever element requested focus internally.
0218 
0219 ### Tab focus chain
0220 Set "activeFocusOnTab: true" on all elements that should be included in the tab focus chain.