#################
XML Format plugin
#################

XML can be used as a method of importing_ or exporting_ `config items`_ to and from a device database.

************
Config Items
************

Each config item is one or more pieces of a single type of target device specific data and can be initalised by a combination of XML attributes and XML elements.  Config items are often called config attributes but this document uses attributes to refer only to XML attributes in order to reduce confusion.

.. _importing:

**********
XML Import
**********

Configuration item definitions and display formatting can be imported directly from an XML file at the file menu or from a device specific XML file when a device is selected from the ``Choose Device`` wizard.  The XML file can optionally use Kajiki_ XML templating to provide sequence, selection and iteration processing and to inject and expand symbolic property values prior to XML parsing.

.. _schema:

The Schema
==========

The relatively simple XSD schema can be found in the XML format plugin.  It's location varies by platform and version, but a typical windows path would be:

``C:\Program Files (x86)\QualcommDeviceConfigTool\pyenv36\Lib\site-packages\config_xml\qconf_xml_1_0.xsd``

The schema will detect, and the tool will report, most XML problems before the XML import is attempted, but it is far from foolproof and many errors can only be detected and reported during config tree creation.  Kajiki XML template expansion occurs before XSD schema validation and is therefore also validated by the schema.

XML Attributes
==============

This is the full list of legal XML attributes.  Not all XML attributes are applicable to all XML elements, but many XML elements share the same XML attributes so they are listed together here for brevity.

  ============== ==== =====
  Attribute Name Type Description
  ============== ==== =====
  Id_            str  The internal XML name of a definition which can be referenced by a``uses`` attribute or element; this is the only XML attribute which does not affect a config item
  name_          str  The display name of a domain or config item.  This appears next to a config item or as a column header in tables.
  description_   str  The display description of a domain or config item in html, restructured or plain text
  key_           str  The unique key of a config item visible as a widget tooltip on mouseover
  default_       any  The default value of a config item
  view_          str  The widget name used to display a config item
  max_value      num  The maximum value of numeric config items
  min_value      num  The minimum value of numeric config items
  wraps          bool Allows numeric config item spinboxes to wrap max<->min
  precision      byte Decimal places in a floating point config item
  hexdigits      byte Number of hex characters for a hex integer config item
  choices_       str  The name of a choice list for enum config items
  item_count_    byte The minimum number of rows in a table or table item
  visibility_key str  A config item key whose truthiness makes the config item visible
  enablement_key str  A config item key whose truthiness makes the config item modifiable
  metadata_      str  Any information needed by the device plug-in
  css_           str  A ``;``-separated string of CSS properties to be applied to the default or selected view
  tags           str  Unused
  locked         bool Attribute of Defines whose meaning differs by usage
  ============== ==== =====

.. _key:

Using ``key`` in XML and config items
-------------------------------------

Each config item (not domain) must have a unique ``key`` when expanded, this can be easily achieved using relative key definitions.

Absolute
^^^^^^^^

To define a key as absolute, start it with any character except ".";  A ``<Define`` with an absolute key can only ever be ``use`` d once without causing a duplicate key error.

Relative
^^^^^^^^

To define a key as relative use ``".key"``.  The eventual key will become ``"root.key"`` where ``root`` will be the key of the parent config domain or table or struct which uses the config item.

.. _description:

Descriptions
------------

Descriptions are the best way to document your `config domains`_, tables_, structures_ and `config items`_.  They can contain html, plain or restructured text and should be as helpful as possible this is your chance to document your config item.  Descriptions can be specified as an attribute with a single string or as restructured text using a `description block`_.

.. _name:

Names
-----

This is the short ``name`` for the config item, it need not be unique.  If it is not supplied it will inherit the ``key`` value.  Tables will use a config item's ``name`` to label the column.

.. _default:

Values
------

The "value" of a config item is set using the ``default`` attribute.  On initial load a config items value will be set to it's default.

.. _view:

Views
=====

There is a default ``view`` for each config item type, but the config item data and the tool presentation are completely separate so many config items have alternative view types and extra views can be added for a specific device type if needed.  Consult device plug-in documentation for device specific views.

All config items support the special value ``view="none"``.  Using ``none`` causes a config item to be imported into the tool with a default value and sent to the device but remains invisible and unconfigurable to the tool user.

.. _Id:

XML Elements
============

Each ``<Define`` element must have a unique ``Id``.  The ``Id`` is not part of the config item and can be used unlimited times so a ``<DefineChoices`` list can be ``use`` d in many ``<DefineEnum`` elements or a text item with ``Id="config_page"`` and ``key=".config_page"`` can be used in every ``<ConfigDomain``.

This is the full list of XML elements which are accepted by the schema_.

 ================= ====
 Element           Description
 ================= ====
 <ConfigRoot>      The XML root node
 <ConfigDomain_>   A subdomain of root or another ConfigDomain
 <DefineChoices_>  A key-value pair list of enum choices
 <DefineEnum_>     A config item which has a limited number of defined choices
 <DefineText_>     A config item with a text value
 <DefineInt_>      A config item with an integer value
 <DefineFloat_>    A config item with a floating point value
 <DefineTable_>    A table of ints, floats, texts, enums
 <DefineStruct_>   An indexed collection of structs
 <elem_>           Used to initialise config items
 <choice_>         Used to initialise a choice list
 <uses_>           Add an attribute ``Id`` to a struct, table or ConfigDomain 
 <struct_>         A collection of tables, ints, floats, texts and enums
 <description_>    A multi-line description supporting restructured text which overrides the ``description`` attribute
 <metadata_>       Multi-line metadata which overrides the ``metadata`` attribute
 ================= ====

The following sections explain the usage of each XML Element.  To clarify usage the prefixes (M)andatory meaning exactly one, (O)ptional meaning 1 or 0, (+) meaning 1 or more and (*) meaning 0 or more are used to define the accepted occurrences of an XML attribute or sub-element.

.. _ConfigDomain:
.. _config domains:
.. _domains:

Domains
-------

The hierarchy of the configuration tree is determined by ConfigDomain elements.  The ``key`` attribute does not need to be unique, this allows multiple domains to configure the same namespace when combined with config item relative keys.

.. code::

 <ConfigDomain
   (M) key=""
   (O) name=""
   (O) description="">
   (*) <Define .../>
   (*) <uses .../>
   (*) <ConfigDomain .../>
   (O) <description>...</description>
 </ConfigDomain>

.. _config items:
.. _definitions:

Config item definitions
-----------------------

.. _DefineInt:

Integers
^^^^^^^^

Int config items represent one or more 32 bit signed integer values

.. code::

 <DefineInt
   (M) Id=""
   (M) key=""
   (O) name=""        (default:key)
   (O) description="" (default:name)
   (O) default=""     (default:"0")
   (O) view=""        (default:"qtspinbox")
   (O) max_value=""   (default:"100")
   (O) min_Value=""   (default:"0")
   (O) wraps=""       (default:"false")
   (O) locked=""      (default:"false")
   (O) hex_digits=""
   (O) item_count=""
   (O) enablement_key=""
   (O) visibility_key=""
   (O) metadata=""
   (O) css="">
   (*) <elem .../>
   (O) <metadata>...</metadata>
   (O) <description>...</description>
 </DefineInt>

Other views for integers include "qthexspinbox", "qtslider", "qtvslider"

.. _DefineFloat:

Floats
^^^^^^

Float config items represent one or more signed double floating point values

.. code::

 <_DefineFloat
   (M) Id=""
   (M) key=""
   (O) name=""        (default:key)
   (O) description="" (default:name)
   (O) default=""     (default:"0.0")
   (O) view=""        (default:"qtdoublespinbox")
   (O) max_value=""   (default:"100.0")
   (O) min_Value=""   (default:"0.0")
   (O) precision=""   (default:"1")
   (O) wraps=""       (default:"false")
   (O) locked=""      (default:"false")
   (O) item_count=""
   (O) enablement_key=""
   (O) visibility_key=""
   (O) metadata=""
   (O) css="">
   (*) <elem .../>
   (O) <metadata>...</metadata>
   (O) <description>...</description>
 </DefineFloat>

.. _DefineText:

Text
^^^^

Text config items represent one or more blocks of character data.

.. code::

 <DefineText
   (M) Id=""
   (M) key=""
   (O) name=""        (default:key)
   (O) description="" (default:name)
   (O) default=""     (default:"")
   (O) view=""        (default:"qtlineedit")
   (O) locked=""      (default:"false")
   (O) item_count=""
   (O) enablement_key=""
   (O) visibility_key=""
   (O) metadata=""
   (O) css="">
   (*) <elem .../>
   (O) <metadata>...</metadata>
   (O) <description>...</description>
 </DefineText>

Other views for text include "qtcolorpicker", "qtlabel", and "qttextedit".

.. _DefineBool:

Boolean
^^^^^^^

Bool config items represent one or more True/False values.

.. code::

 <DefineBool
   (M) Id=""
   (M) key=""
   (O) name=""        (default:key)
   (O) description="" (default:name)
   (O) default=""     (default:"false")
   (O) view=""        (default:"qtcheckbox")
   (O) locked=""      (default:"false")
   (O) item_count=""
   (O) enablement_key=""
   (O) visibility_key=""
   (O) metadata=""
   (O) css="">
   (*) <elem .../>
   (O) <metadata>...</metadata>
   (O) <description>...</description>
 </DefineBool>

.. _DefineEnum:
.. _DefineChoices:
.. _choices:
.. _choice:

Enums
^^^^^

Enumerated items have a two-part definition where choice lists are defined separately from the enumerated config items.  The tool will display the key and emit the selected value(s), if the internal value is the same as the key, the value can be omitted.

.. code::

 <DefineChoices
   (M) Id=""/>
   (+) <choice 
      (M) key=""
      (O) value=""/>
 </DefineChoices>

.. code::

 <DefineEnum
   (M) Id=""
   (M) key=""
   (M) choices=""
   (O) name=""        (default:key)
   (O) description="" (default:name)
   (O) default=""     (default:first item in choice list)
   (O) view=""        (default:"qtcombobox")
   (O) locked=""      (default:"false")
   (O) item_count=""
   (O) enablement_key=""
   (O) visibility_key=""
   (O) metadata=""
   (O) css="">
   (*) <elem .../>
   (O) <metadata>...</metadata>
   (O) <description>...</description>
 </DefineEnum>

.. _DefineTable:
.. _item_count:
.. _tables:

Tables
^^^^^^

Tables store multiple instances of basic config items in tabular form.  Each row will contain a separate instance of the column's config item with an indenpendent value.  Columns are fixed but rows can be added, deleted and moved.

.. code::

 <DefineTable
   (M) Id=""
   (M) key=""
   (O) name=""        (default:key)
   (O) description="" (default:name)
   (O) item_count=""  (default:"0")
   (O) metadata="">
   (+) <uses=""/>
   (*) <elem .. />
   (O) <metadata>...</metadata>
   (O) <description>...</description>
 </DefineTable>


- In tables, each config item in a column is automatically indexed so a 2x2 table with ``key=".table"`` using two integers with keys ``".int1"`` and ``".int2"`` would create ``table.int1.0``, ``table.int1.1``, ``table.int2.0`` and ``table.int2.1``.  In some devices an automatic ``.count`` key is emitted as a row count leading to the key ``table.count`` being created too.

- Tables can use any basic defined config item, but not other tables or structs.

- When a config item is used in a table it will be resized to the smallest length possible to contain either the largest defined ``item_count`` of the table or table item, or the largest initialised index of all the table items - This may result in a zero-length table if no values are defined and the table has no ``item_count``.

- The rows of a table with attribute ``locked="true"`` cannot be moved, added to or deleted.

- The ``name`` property of ``uses`` attributes will be used to label each column.  A ';' can be placed in the name to split the column title over 2 or more lines if desired.

- If the first ``uses`` attribute has ``view="qtlabel"`` then the attribute value will be used to label each row.

- *NOTE* Device plugins control how their output keys are emitted so for instance a device could choose to use infix indices e.g. ``table.int.0`` is emitted as ``table.0.int`` or to remove key content before a special character e.g. ``audio:table.int.0``.  Refer to the device plug-in for guidance.

.. _DefineStruct:
.. _struct:
.. _structures:

Structures
^^^^^^^^^^

A struct is a structure or object-like store of multiple config item types.  Each structure instance appears in a different indexed tab and by default structures can be cloned or deleted.  Different tabs can also contain different data collections, but the structure index is incremental by tab so this may not be a good idea!

.. code::

  <DefineStruct
    (M) Id=""
    (O) name=""
    (O) key=""/>
    (+) <struct>
      (+) <uses=""/>
        </struct>
  </DefineStruct>

Structs can use any defined config item including tables but cannot use other structures.

In structs, each tab's content is automatically indexed, so a 2 tabbed structure with ``key="mystruct"`` which uses an integer of ``key=".myint"`` in both structs would generate keys ``mystruct.0.myint`` and ``mystruct.1.myint``

The tabs of a struct with attribute ``locked="true"`` cannot be cloned or deleted.

.. _elem:

Config item initialisation using ``<elem ../>`` XML element
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The ``<elem>`` XML element is used to define config item values.

.. code::

 <elem 
   (O) i=""
   (O) value="">
   (O) ""
 </elem>

It has 3 useful formats, the first one relates to defining multiple values for table items

.. code::

 <!-- Set 4th amd 10th items in the table let the rest be default -->
 <elem i="4" value="45.35"\>
 <elem i="10" value="12472.0"\>

The last two are only necessary for multi-line values, other values can be set using the first form of ``elem`` or the item's ``default`` attribute

.. code-block:: xml

 <!-- Set 0th item in a table to multi-line value "one\ntwo" -->
 <elem i="0">one
 two</elem>

.. code-block:: xml

 <!-- Set the default value of a config parameter to "\"this\" &\n 'that'" -->
 <elem>&quot;this&quot; &amp;
 &apos;that&apos;</elem>

.. _uses:

Config item display with the ``<uses ../>`` XML element
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The ``uses`` element can appear in domains, tables and structures. It has exactly one attribute which references the ``Id`` of a defined int, float, enum, bool, text, table or struct.

.. code::

 <uses
 	(M) (int|float|enum|bool|text|table|struct)=""/>

In a ``ConfigDomain`` this causes a config item to appear in the config pane

In a ``table`` this causes a config item to become a table item and a column to be appended to the table definition which will become visible when the ``table`` is used in a ``ConfigDomain``

In a ``struct`` this adds a config item to the ``struct`` instance which will become visible once the ``struct`` is added to a ``ConfigDomain``

.. _metadata:

Metadata
^^^^^^^^

The content of this optional element is entirely defined by your device plugin.  The tool will store metadata content with the config item and provide it to the device plug-in for processing, please refer to the device plug-in documentation for further documentation.

.. code-block:: xml

 <metadata>
   (+) ""
 </metadata>

.. _description block:

Description blocks
^^^^^^^^^^^^^^^^^^

This optional element replaces the content of the description attribute when present.  The string content can be used to supply restructured text formatted attribute documentation.

.. code-block:: xml

 <description>
   (+) ""
 </description>

.. _css:

Cascading Style Sheet (CSS) properties
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Attribute views will attempt to apply the CSS properties provided.  An attributes CSS property will be applied to the view of the attribute which defines the CSS string only.  Defining an attribute CSS property will override any global theme default for the same property, but may be replaced or ignored if that property is used explicitly by the chosen attribute view.  Supported CSS properties can be found at http://doc.qt.io/qt-5/stylesheet-reference.html

examples:

.. code-block:: xml

  css="color: red; background-color: white"

  css="min-width: 72px"

  css="font: bold italic large &quot;Times New Roman&quot;"

  css="max-height:20px;margin:8px;margin-top:20px"

Suggested Layout
================

The XML file order is not especially important, definitions_ are extracted first then domains_ are imported in the order and depth they are defined. To aid maintainability the following is a useful template for a device XML file repeating components, sub-components, features and sub-features as needed.  As noted elsewhere ``Id`` and ``key`` values (when resolved) should be unique.

.. code-block:: xml

 <ConfigRoot>
 
   <!-- Kajiki definitions -->
   <?python my_text="edit me!" ?>
 
   <!-- Component XYZ -->
   <ConfigDomain
     key="XYZ"
     name="component_XYZ_name"
     description="component_XYZ_description">
 
     <!-- Define Elements for this Component -->
     <DefineInt Id="abc:anint" key=".myint"/>
     <DefineText Id="abc:thistext" key=".mytext" default="$my_text"/>
     <DefineTable Id="abc:thattable" key=".mytable" item_count="12">
       <uses int="abc:anint"/>
       <uses text="abc:thistext"/>
     </DefineTable>
 
     <!-- Sub-component abc -->
     <ConfigDomain
       key="XYZ:abc"
       name="subcomponent_abc_name"
       description="subcomponent_abc_description">
       <uses int="abc:anint"/>
       <uses text="abc:thistext"/>
  
       <!-- Feature 123 -->
       <ConfigDomain
         key=".123"
         name="feature_123"
         description="feature_123_description">
         <uses int="abc:anint"/>
         <uses table="abc:thattable"/>
       </ConfigDomain>
 
     </ConfigDomain>
   </ConfigDomain>
 </ConfigRoot>


Using Kajiki_
=============

.. _Kajiki: https://kajiki.readthedocs.io/en/latest/xml-templates.html

Kajiki_ XML templates can make your imported XML more maintainable and readable by:

 - wrapping CDATA
 - substituting repeated text
 - generating pattern-based elements
 - conditionally modiifying or including config items or domains based on device properties
 - importing component XML files
 - and much, much more.

examples:

.. code-block:: xml

 <py:include href="domain/wifi.xml"/>

could be used to import the wifi ``ConfigDomain`` from a domain subdirectory in the device XML file's directory.

.. _exporting:

**********
XML Export
**********

A device database can be exported to XML from the File menu.  This will *not* recreate the original XML source if XML was the original source, but it will create an XML file that will faithfully recreate the current state of the device database.

Notes:
 - ``Id`` attributes will be automatically named from the config item's ``key`` attribute
 - ``DefineChoice`` ``Id`` attributes are automatically named by the hash of their content
 - All Kajiki_ template content will be fully expanded to raw XML
 - Any config items which have been updated will have their ``default`` attribute set to the current value or for table items an elem_ initialiser will be created.
 - The generated file will reorder the content in the following manner:

 .. code-block:: xml

   <ConfigRoot>
     <!-- Auto-generated Configuration Item Definitions -->
     <DefineStuff />
     <!-- Auto-generated Configuration Layout Starts Here -->
     <ConfigDomain />
   </ConfigRoot>
