<NME> jasp-qml-guide.md <BEF> Guide to writing an analysis interface in QML ============================================= QML (Qt Modeling Language) is a user interface markup language that JASP uses to show the analysis input panel. In this panel the user can specify what options should be set to what values and thereby change the tables and plots that the analysis computes. QML is a very flexible language that allows us to easily generate checkboxes, dropdowns and other common interface components. To create a more uniform layout and make it easier to add new analyses we have provided a number of standardized components. These components should satisfy most analyses, and are explained in this document. One important pardigm in QML is containment: the implementation of a component is hidden, only public properties (specified by the component self) can be used to manipulate the component. QML uses JavaScript expressions to set values of these properties. Another important paradigm in QML is property binding: this means that when you set a property of a component with a JavaScript expression that uses values of other elements, whenever the values of those elements change, the property value will change automatically: ```qml + [CheckBox](#checkbox) + [RadioButton](#radiobutton) + [DropDown](#dropdown) + [DoubleField](#doublefield) + [IntegerField](#integerfield) + [PercentField](#percentfield) + [TextField](#textfield) * [Variable Specification](#variable-specification) + [availableVariablesList](#availablevariableslist) + [AssignedVariablesList](#assignedvariableslist) + [RepeatedMeasuresFactorsList](#repeatedmeasuresfactorslist) * [Grouping](#grouping) - [DropDown](#dropdown) - [Slider](#slider) - [DoubleField](#doublefield) - [IntegerField](#integerfield) - [PercentField](#percentfield) - [CIField](#cifield) - [TextField](#textfield) - [FormulaField](#formulafield) - [TextArea](#textarea) - [Variable Specification](#variable-specification) - [AvailableVariablesList](#availablevariableslist) ## Components The components can roughly be divided in three classes. One that deals with general inputs (e.g., checkboxes), one that deals with assigning variables and one that groups components together. Each will be covered in the following section. Note that in several examples you may encounter `qsTr()`, it is important that this function wraps all text that will be shown in the interface. It will provide the possibility to translate JASP in the future. Additionally, note that the components described below may generally be nested to an arbitrary level (e.g., a checkbox in a checkbox in a checkbox). ### General Input These components are quite common in questionnaires and input forms on websites, they include the checkbox, radiobutton, dropdown and fields where text may be entered. #### CheckBox Properties - `name`: string identifier (in your R code you will be able to retrieve the value of the checkbox through this identifier) - `label`: text that will be shown to the left of the checkbox - `checked`: [optional, default: `false`] boolean specifying if it should contain a checkmark (often a binding that when evaluated gives a boolean, see the section on [Connecting Multiple Components](#connecting-multiple-components)) - `childrenOnSameRow`: [optional, default: `false`] boolean specifying if components (e.g., other checkboxes, textfields) nested within the checkbox should be shown on the same row or, alternatively, below the checkbox - `columns`: [optional, default: `1`] integer specifying how many columns the nested components should spread out over (e.g., when set to 3, with three nested checkboxes, these three checkboxes will appear side by side on the same horizontal row) <details> <summary>Examples</summary> Some remarks about these components: - They are all QML items, so they automatically get generic QML properties like `enabled` or `visible`. - In several examples you may encounter `qsTr()`, it is important that this function wraps all text that will be shown in the interface. It will provide the possibility to translate JASP in the future. - The components described below may generally be nested to an arbitrary level (e.g., a checkbox in a group in a checkbox). All (well almost all) of these components have a property `name` that is also used in JASP-files to store the value the user selected. That means that whenever you change `name` for a component for a newer version of your analysis/module the stored value will be ignored. To make sure the user entered information isn't lost you can add an [Upgrades.qml to your module](jasp-upgrade-qml.md). ### General Input These components are quite common in questionnaires and input forms on websites, they include the checkbox, radiobutton, dropdown, slider and textfields where text may be entered. #### CheckBox Check button that can be toggled on and off. If some components are nested inside a CheckBox, they are automatically enabled or disabled when the CheckBox is set or not. Properties - `name`: string identifier (in your R code you will be able to retrieve the value of the checkbox through this identifier) - `label`: text that will be shown to the left of the checkbox - `checked`: [optional, default: `false`] boolean specifying if it should be set per default on or not. - `childrenOnSameRow`: [optional, default: `false`] boolean specifying if components (e.g., other checkboxes, textfields) nested within the checkbox should be shown on the same row or, alternatively, below the checkbox - `columns`: [optional, default: `1`] integer specifying how many columns the nested components should occupy (e.g., when set to 3, with three nested checkboxes, these three checkboxes will appear side by side on the same horizontal row) </details> #### RadioButton A single radiobutton is not very useful, and so they must be grouped together. We can do this by putting multiple `RadioButton`s together in a `RadioButtonGroup`. Properties - `name`: string identifier (in your R code you will be able to retrieve the value of the checked radiobutton through this identifier) - `title`: text that is shown above the set of radiobuttons - `RadioButton`: * `value`: the value of the `RadioButtonGroup` that is send to R when this radiobutton is checked * `label`: the text that is shown to the right of the radiobutton * `checked`: [optional, default: `false`] boolean specifying if it should contain a checkmark (and thus be the default); one radiobutton should have this property set to `true` * `childrenOnSameRow`: [optional, default: `false`] boolean specifying if components (e.g., checkboxes, textfields) nested within the radiobutton should be shown on the same row or, alternatively, below the radiobutton * `columns`: [optional, default: `1`] integer specifying how many columns the nested components should spread out over (e.g., when set to 3, with three nested checkboxes, these three checkboxes will appear side by side on the same horizontal row) <details> <summary>Examples</summary> </details> #### RadioButton A RadioButton is used with other RadioButton's inside a `RadioButtonGroup`. Contrary to CheckBox, only 1 RadioButton can be checked at the same time. RadioButtonGroup properties: - `name`: string identifier (in your R code you will be able to retrieve the value of the checked radiobutton through this identifier) - `title`: text that is shown above the set of radiobuttons - `radioButtonsOnSameRow`: [optional, default: `false`] per default, the RadioButton's are placed vertically under the title. Set this property to true to place the buttons horizontally. - `columns`: [optional, default: `1`] integer specifying how many columns should be used to display the RadioButton's RadioButton properties: - `value`: the value of the `RadioButtonGroup` that is send to R when this radiobutton is checked - `label`: the text that is shown to the right of the radiobutton - `checked`: [optional, default: `false`] boolean specifying if it should contain a checkmark (and thus be the default); one radiobutton should have this property set to `true` - `childrenOnSameRow`: [optional, default: `false`] boolean specifying if components (e.g., checkboxes, textfields) nested within the radiobutton should be shown on the same row or, alternatively, below the radiobutton - `columns`: [optional, default: `1`] integer specifying how many columns the nested components should occupy (e.g., when set to 3, with three nested checkboxes, these three checkboxes will appear side by side on the same horizontal row) <details> <summary>Examples</summary> ```qml RadioButtonGroup { name: "countProp" title: qsTr("Display") RadioButton { value: "descCounts"; label: qsTr("Counts"); checked: true } RadioButton { value: "descProps"; label: qsTr("Proportions") } } ``` ![Image example](/Docs/development/img/qml-guide/RadioButton_example_1.png) ```qml RadioButtonGroup { name: "steppingMethodCriteriaType" title: qsTr("Stepping Method Criteria") RadioButton { - `label`: [optional, default: `""`] text that will be shown above the dropdown - `values`: array of (named) values that is shown in the dropdown list, in the case of an unnamed array the value and the label are the same, but when a named array is provided the label shown to the user can be different from the value send to R (see example below) - `indexDefaultValue`: [optional, default: `1`] integer specifying the index of the dropdown item that is selected by default, take note that this is zero-based <details> <summary>Examples</summary> value: "useFValue"; label: qsTr("Use F value") columns: 2 DoubleField { name: "steppingMethodCriteriaFEntry"; label: qsTr("Entry"); fieldWidth: 60; defaultValue: 3.84; decimals: 3 } DoubleField { name: "steppingMethodCriteriaFRemoval"; label: qsTr("Removal"); fieldWidth: 60; defaultValue: 2.71; decimals: 3 } } } ``` ![Image example](/Docs/development/img/qml-guide/RadioButton_example_2.png) </details> #### DropDown Properties - `name`: string identifier (in your R code you will be able to retrieve the value of the dropdown through this identifier) - `label`: [optional, default: `""`] text that will be shown above the dropdown - `values`: [optional, default: empty] array of (named) values that is shown in the dropdown list, in the case of an unnamed array the value and the label are the same, but when a named array is provided the label shown to the user can be different from the value send to R (see example below) - `startValue`: [optional, default: ``] string specifying the value of the dropdown item that is selected by default - `currentIndex`, `currentValue`, `currentLabel`: [optional] gives the current index, value or label of the selected item. Can be used to set the current item. - `currentColumnType`: [read-only] if the values of the dropdown are variables of the dataset, then this property gives the type of this variable, i.e. `scale`, `nominal`, `nominalText`, `ordinal`. - `source`: [optional, default: empty] if `values` is empty, you can use the name of a VariablesList or other kind of source (see [Variable Specification](#variable-specification)) to set the values of the DropDown. If `values` and `source` is empty, then all available columns of the dataset are used. - `addEmptyValue`: [optional, default: `false`] if `true`, add an empty value with a place holder (see `placeHolderText`) as first element of the dropdown list - `placeHolderText`: [optional, default: `<no choice>`] name used if an ampty value is added in the dropdown list - `addScrollBar`: [optional, default: `false`] add a scrollbar when the list is displayed. <details> </details> #### DoubleField Properties - `name`: string identifier (in your R code you will be able to retrieve the value of the field through this identifier) - `name`: string identifier (in your R code you will be able to retrieve the value of the slider through this identifier) - `label`: [optional, default: `""`] text that will be shown above the slider - `value`: [optional, default: `0.5`] default value - `min`: [optional, default: `0`] minimum value - `max`: [optional, default: `1`] maximum value - `vertical`: [optional, default: `true`] set whether the slider should be displayed vertically or horizontally - `decimals`: [optional, default: `2`] set the number of decimals the value gets <details> <summary>Examples</summary> ```qml Slider { name: "highlight" label: qsTr("Highlight") value: 0.4 } ``` ![Image example](/Docs/development/img/qml-guide/Slider_example_1.png) </details> #### DoubleField Properties - `name`: string identifier (in your R code you will be able to retrieve the value of the field through this identifier) - `label`: [optional, default: `""`] text that will be shown to the left of the field - `afterLabel`: [optional, default: `""`] text that will be shown to the right of the field - `defaultValue`: [optional, default: `0`] numeric specifying the default value shown; can be an integer or a decimal value, just be sure to use a dot and not a comma - `negativeValues`: [optional, default: `false`] specifies if the user should be able to input negative values (works only when the `min` argument is omitted) - `min`: [optional, default: `0` if negativeValues is `false`, otherwise `-Infinity`] numeric specifying the minimum value a user can enter - `max`: [optional, default: `Infinity`] numeric specifying the maximum value a user can enter - `inclusive`: [optional, default: `JASP.MinMax`, possible values: `JASP.MinMax`, `JASP.MinOnly`, `JASP.MaxOnly`, `JASP.None`] specify whether the `min` and `max` parameters are inclusive or not. For example if `min` is `1` and `inclusive` is `JASP.MinMax` or `JASP.MinOnly` then value `1` is allowed. - `decimals`: [optional, default: `3`] integer specifying how many decimals the user can enter - `fieldWidth`: [optional, default: `40`] in pixels how wide should the field be <details> <summary>Examples</summary> ```qml DoubleField { name: "eigenValuesBox" label: qsTr("Eigenvalues above") defaultValue: 1 decimals: 1 } ``` ![Image example](/Docs/development/img/qml-guide/DoubleField_example_1.png) ```qml DoubleField { name: "priorFixedEffects" label: qsTr("r scale fixed effects") defaultValue: 0.5 fieldWidth: 50 max: 2 decimals: 1 } ``` ![Image example](/Docs/development/img/qml-guide/DoubleField_example_2.png) </details> #### IntegerField Properties - `name`: string identifier (in your R code you will be able to retrieve the value of the field through this identifier) - `label`: [optional, default: `""`] text that will be shown to the left of the field - `afterLabel`: [optional, default: `""`] text that will be shown to the right of the field - `defaultValue`: [optional, default: `0`] integer specifying the default value shown - `negativeValues`: [optional, default: `false`] specifies if the user should be able to input negative values (works only when the `min` argument is omitted) - `min`: [optional, default: `0` if negativeValues is `false`, otherwise `-Infinity`] integer specifying the minimum value a user can enter - `max`: [optional, default: `Infinity`] integer specifying the maximum value a user can enter - `inclusive`: [optional, default: `yes`, possible values: `yes`, `minOnly`, `maxOnly`, `no`] specify whether the `min` and `max` parameters are inclusive or not. For example if `min` is `1` and `inclusive` is `yes` or `minOnly` then value `1` is allowed. - `fieldWidth`: [optional, default: `40`] in pixels how wide should the field be - `label`: text that will be shown to the left of the field - `defaultValue`: [optional, default: `50`] integer specifying the default percentage shown - `fieldWidth`: [optional, default: `40`] in pixels how wide should the field be <details> <summary>Examples</summary> name: "fixedSamplesNumber" label: qsTr("No. samples") defaultValue: 10000 fieldWidth: 60 } ``` ![Image example](/Docs/development/img/qml-guide/IntegerField_example_1.png) ```qml IntegerField - `name`: string identifier (in your R code you will be able to retrieve the value of the field through this identifier) - `label`: [optional, default: `""`] text that will be shown to the left of the field - `afterLabel`: [optional, default: `""`] text that will be shown to the right of the field - `defaultValue`: [optional, default: `""`] default text before the user enters anything - `placeholderText`: [optional, default: `""`] text shown as a placeholder until a user enters something, will not be send to R if left unchanged by the user (mutually exclusive with `defaultValue`) - `fieldWidth`: [optional, default: `40`] in pixels how wide should the field be ``` ![Image example](/Docs/development/img/qml-guide/IntegerField_example_2.png) </details> #### PercentField Properties - `name`: string identifier (in your R code you will be able to retrieve the value of the field through this identifier) - `label`: text that will be shown to the left of the field - `afterLabel`: [optional, default `%`] text that will be shown to the right of the field - `defaultValue`: [optional, default: `50`] integer specifying the default percentage shown - `fieldWidth`: [optional, default: `40`] in pixels how wide should the field be - `decimals`: [optional, default: `0`] integer specifying how many decimals the user can enter <details> <summary>Examples</summary> - `name`: identifier of the variables list, this is never send to R - `label`: [optional, default: `""`] text that will be shown above the variable field - `source`: [optional] can be set to the `name` of an `AssignedVariablesList`, when omitted variables are taken from the dataset (example usage: you have a second `availableVariablesList` for plotting the variables that are assigned to an `AssignedVariablesList`; see also the example) - `width`: [optional, default: ±`230`] in pixels how wide should the field be Note: `height` should be defined on `VariablesForm` itself. #### CIField ```qml VariablesForm { AssignedVariablesList { name: "fixedFactors" label: qsTr("Fixed Factors") allowedColumns: ["ordinal", "nominal"] } } VariablesForm { height: 200 AvailableVariablesList { name: "postHocTestsAvailable" source: "fixedFactors" } } ``` ![Image example](/Docs/development/img/qml-guide/availableVariablesList_example_1_1.png) - `placeholderText`: [optional, default: `""`] text shown as a placeholder until a user enters something, will not be send to R if left unchanged by the user (mutually exclusive with `defaultValue`) - `fieldWidth`: [optional, default: `40`] in pixels how wide should the field be <details> <summary>Examples</summary> ```qml TextField { name: "labelYAxis"; label: qsTr("Label y-axis"); fieldWidth: 200 } ``` - `singleVariable`: [optional, default: `false`] boolean specifying if this field will accept a maximum of one variable - `listViewType`: [optional] string that specifies the type of `AssignedVariablesList`, when omitted we get a normal list, options are `"Layers"` (see Contingency Tables), `"Pairs"` (see Paired Samples T-Test), `"Interaction"` (see ANOVA) and `"RepeatedMeasures"` (see Repeated Measures ANOVA) - `ExtraControlColumn`: [optional] addititional general input component (e.g., `"CheckBox"`) which is added to each variable and can be used to add extra control (e.g., you can specify the status of the variable within a linear model, see example below) - `width`: [optional, default: ±`230`] in pixels how wide should the field be - `height`: [optional, default: `350`] in pixels how heigh should the field be <details> <summary>Examples</summary> - `min`: [optional, default `-Infinity`] minimum value that the result of the formula can give. ```qml VariablesForm { AssignedVariablesList { name: "dependent" label: qsTr("Dependent Variable") allowedColumns: ["scale"] singleVariable: true } } ``` ![Image example](/Docs/development/img/qml-guide/AssignedVariablesList_example_1.png) - `separator`, `separators`: [optional, default: `"\n"`] string or array of strings used to split the string of a `source` TextArea ```qml VariablesForm { AssignedVariablesList { name: "modelTerms" - `name`: identifier of the variables list, this is never send to R - `label`: [optional, default: `""`] text that will be shown above the variable field - `source`: [optional, default: `""`] this can be set to the `id` or the `name` (or a list of id or names) of one or more Variables Lists. If no source is specified, then all variables of the data file are used as source. To specify several sources, you need to use an array: `["source1", "source2"]`. If you want to specify what you want to read from the source, you can add extra attributes:<br> * `use` attribute: if you want to read the levels of a `singleVariable` Variables List source, type: `source: [{name: "splitby", use: "levels"}]`. If you want only some variables with some types, type: `[{name: "source", use: "type=nominal|ordinal"}]` * `discard` attribute: if you want to discard some of the values of the source, set the discard attribute to another source or values. For example `source: [{ name: "modelTerms", discard: "covariates" }]` * `condition` attribute: if a Variables List source has some components, and you want to retrieve the variables whose components have some specific values, type: `[ { name: "contrasts", condition: "contrast.currentValue == 'custom'" } ]` where `contrast` is the name of a DropDown component (added in the `contrasts` Variables List). In this example only variables with contrast having `custom` as value will be read from the source `contrasts`. * `values` attribute: if you want to add specific values to the list, you can add them in this way `source: [ { values: ["one", "two"] }, "myvariables" ]`. Here the values `one` and `two` are prepend to the names of the variables of the Variables List `myvariables`. If you want to display a label (that can be translated) different from the value used in the analysis, use: `source: [ { values: [ { label: qsTr("One"), value: "one" }, { label: qsTr("Two"), value: "two" } ], "myvariables" ]` (qsTr is the function you need to use if you want the string to be translatable). * `rSource`: name of a R source. This source should be generated in R with the jaspQmlSource function. * `combineTerms` attribute: if you want to combine the variables of the source, you can set this attribute. Per default this is JASP.NoCombination, but it can be set to JASP.CombinationCross (all combinations), JASP.CombinationInteraction (gives only one term with all variables of the source, eg. var1 * var2 * var3), Combination2Way (all combinations of 2 variables), Combination3Way (all combinations of 3 variables), Combination4Way (all combinations of 4 variables), Combination5Way (all combinations of 5 variables) * if you want to display not the variable names of the source, but the values of some component of this list, use the syntax `name.component`. For example, if the source `myvariables` has a TextField named `field`, a Variables List with source `source: "myvariables.field"` will display all values of the TextField component in place of the variable names.<br> - `values`: [optional, default: `""`] this is a shortcut: in place of writing `source: [ values: ["one", "two"] ]`, type `values: ["one", "two"]`. If you want to display labels different from the values used by the analysis, use the same syntax as in the `source` property. You can also use an integer n: in this case the values are just [1, 2, ... n] - `rSource`: [optional, default: `""`] this is a shortcut: in place of writing `source: [ { rSource: "myRSource" } ]`, type `rSource: "myRSource"]`. - `width`: [optional, default: 2/5 of the VariablesForm width] in pixels how wide should the field be - `count`: [read-only integer] Gives the number of rows of the list. Note: `height` should be defined on `VariablesForm` itself. <details> <summary>Examples</summary> ```qml VariablesForm { AvailableVariablesList { name: "allVariables" } AssignedVariablesList { name: "fixedFactors"; label: qsTr("Fixed Factors"); allowedColumns: ["ordinal", "nominal"] } } VariablesForm { height: 200 AvailableVariablesList { name: "postHocTestsAvailable"; source: "fixedFactors"; rowComponent: CheckBox { name: "check" } } AssignedVariablesList { name: "postHocTestsVariables" } } VariablesForm { height: 200 AvailableVariablesList { name: "checkedPostHocAvailable"; source: [ name: "postHocTestsVariables", condition: "check.checked" ] } AssignedVariablesList { name: "checkedPostHoc" } } ``` ![Image example](/Docs/development/img/qml-guide/availableVariablesList_example_1_1.png) ![Image example](/Docs/development/img/qml-guide/availableVariablesList_example_1_2.png) </details> #### AssignedVariablesList Properties - `name`: identifier of the particular variable field (in your R code you will be able to retrieve the assigned variable(s) through this identifier) - `label`: [optional, default: `""`] text that will be shown above the variable field - `columns`: [optional, default: 1] number of columns of the list. - `allowedColumns`: [optional, default: empty, possible values: `["scale", "ordinal", "nominal"]` ] array specifying the allowed column types - `suggestedColumns`: [optional, default: empty, possible values: `["scale", "ordinal", "nominal"]` ] array specifying the suggested column types. These types will be displayed as icons at the bottom-right of the AssignedVariablesList. If `suggestedColumns` is empty and `allowedColumns` is specified, then `suggestedColumns` get automatically the value of `allowedColumns`. If `allowedColumns` is empty and `suggestedColumns` is specified, then the following rules apply: * `scale` allows Nominal Integer and Ordinal columns #### Group Properties - `title`: text shown above the grouped input components - `columns`: [optional, default: `1`] integer specifying how many columns the grouped components should spread out over <details> <summary>Examples</summary> - `height`: [optional] in pixels how heigh should the field be. Per default, it is set so that all AssignedVariablesList's fit the VariablesForm. If you set the height for 1 AssignedVariablesList, it will try to set height of the other AssignedVariablesLists's so that they all fit the heigth of the VariablesForm. - `count`: [read-only integer] Gives the number of rows of the list. - `rowComponentTitle`: [optional, default '']: title for rowComponent. It will be added at the right side above the list. - `rowComponent`: It is possible to add one or more components for each assigned variable. To do this, add the `rowComponent` property. If you want to add just one extra component, a CheckBox for example, just add it here: <br> ```qml rowComponent: CheckBox { name: "enableNumber"; checked: true } ``` If you want several components, then wrap it with a `Row` item, like this: ```qml rowComponent: Row { CheckBox { name: "enableNumber"; checked: true } TextField { name: "myField"; value: rowValue } } ``` ![Image example](/Docs/development/img/qml-guide/RowComponents_example.png) You can use so-called context properties in the components: * rowIndex: gives the row number in the list * rowValue: gives the name of the variable in the same row - `optionKey`: [optional, default: 'variable' (for Interaction type, default is 'components'] If there is no rowComponent, the values are just given as an array of strings. But if one or more components are specified, the values are more complex: it is also an array, but each element of the array contains the name of the variable with as key the value of this `optionKey`, and the values of each component with as key the name of the component. #### ExpanderButton Properties - `title`: text shown in the button that controls the collapse of an entire section - `columns`: [optional, default: `2`] integer specifying how many columns the grouped components should spread out over <details> <summary>Examples</summary> AvailableVariablesList { name: "allVariables" } AssignedVariablesList { name: "dependent" label: qsTr("Dependent Variable") allowedColumns: ["scale"] singleVariable: true } } } ``` ![Image example](/Docs/development/img/qml-guide/AssignedVariablesList_example_1.png) ```qml VariablesForm { AvailableVariablesList { name: "allVariables" } AssignedVariablesList { name: "modelTerms" label: qsTr("Model terms") listViewType: JASP.Interaction rowComponentTitle: "Add to null model" rowComponent: CheckBox { name: "isNuisance" } } } ``` ![Image example](/Docs/development/img/qml-guide/AssignedVariablesList_example_2.png) </details> #### FactorLevelList With this component, the user can set names of factors, and for each factor, the names of its levels. This is used in Repeated Measures ANOVA. Properties - `name`: identifier of the particular variable field (in your R code you will be able to retrieve the assigned variable(s) through this identifier) - `label`: [optional, default: `""`] text that will be shown above the variable field - `width`: [optional, default: ±`230`] in pixels how wide should the field be - `height`: [optional, default: `350`] in pixels how heigh should the field be - `factorName`: [optional, default: `Factor`] default name of the factor. - `levelName`: [optional, default: `Level`] default name of the level. - `minFactors`: [optional, default: `1`] minimum number of factors. - `minLevels`: [optional, default: `2`] minimum numbe of levels. <details> <summary>Examples</summary> ```qml VariablesForm { FactorLevelList { name: "repeatedMeasuresFactors" label: qsTr("Repeated Measures Factors") height: 180 factorName: qsTr("RM Factor") } AssignedVariablesList { name: "repeatedMeasuresCells" label: qsTr("Repeated Measures Cells") allowedColumns: ["scale"] listViewType: JASP.MeasuresCells source: "repeatedMeasuresFactors" height: 140 } } ``` ![Image example](/Docs/development/img/qml-guide/RepeatedMeasuresFactorsList_example_1.png) </details> ### Complex components ComponentsList, TabView, InputListView and TableView are complex components that allow to view a variable number of input or other components #### ComponentsList This allows to displays a list of components either from a source or from user input. - `name`: identifier of this component (in your R code you will be able to retrieve the text value(s) through this identifier) - `title`: [optional, default: `""`] text that will be shown above this component - `rowComponent`: as for the Variables List, you can specify all the components that will be repeated for each row. - `source`: [optional, default: empty] as for Variables List you can specify any kind of source (see [Variable Specification]). It a source is used, the number of rows will automatically depends on the number of elements of this source. You can then also use the `rowValue` context property if you want to use the value of the source in one of the component. - `values`: [optional, default: empty] In place of a source, you can specify direcly a list of values or value/label list as in the DropDown component. - `addItemManually`: [optional, default 'false' if `source` and `values` are empty, else 'true'] If this is true, then it displays a '+' icon so that the user can add new rows, and a 'X' icon to delete a row. ## Connecting Multiple Components In `AvailableVariablesList` we showed that through its `source` property, we can establish a link between two components. There are other ways of connecting components and they are not limited to a `VariableList` (although they are a little different, only a `VariableList` uses the `name` property). QML allows us to do this is by adding an `id` to one component and then referencing this `id` in a different component. Note that the `id` can be any string, but it must be unique. An example is enabling a checkbox if one of two different checkboxes is checked. <p><details> <summary>Implementation</summary> ```qml CheckBox { name: "checkboxA"; label: qsTr("Some label"), id: "A"} CheckBox { name: "checkboxB"; label: qsTr("Some label"), id: "B"} CheckBox { name: "checkboxC"; label: qsTr("Some Label too"); enabled: A.checked || B.checked } ``` </details></p> Here we make use of a JavaScript expression to evaluate if either CheckBox A or CheckBox B has been checked and if this is the case we enable CheckBox C. It may be a bit confusing that we didn't cover `enabled` as a property of a `CheckBox`, this is simply one of the many properties that QML adds without our help. Another example would be setting the visibility of some textfield to invisible if a checkbox is not checked. ```qml InputListView { name : "groupNames" { name: "checkboxA" label: qsTr("Some label") id: "A" TextField { name: "textfieldA"; afterlabel: qsTr("x"); visible: A.checked} } ``` </details> ## An Example We'll create a simple analysis input panel to show the workflow. ### 1. Setting up the QML Watcher It is, of course, much easier to create a working product when you can test it along the way. This was made easy when the QML watcher was introduced to JASP. To use it: 1. Open JASP 2. Click on the menu in the top left corner 3. Navigate to 'Preferences' 4. Navigate to 'Advanced' 5. Place a checkmark before 'Developer mode' 6. Enter the path where the QML file you want to make can be found Now every time you save a change in your QML file it will immediately be reflected in the input panel of your analysis. ### 2. Specifying Imports We can begin actual work on the QML file, first we have to tell the engine where to find our resources. To do so, we add a number of imports to the top of our file. ### Grouping In order to add more structure to the input panel you can group components together. There are 2 levels of grouping: Section and Group. A Section can hide a group of components under a button. A Group is a smaller logical unit. #### Group Properties - `title`: text shown above the grouped input components - `columns`: [optional, default: `1`] integer specifying how many columns the grouped components should occupy <details> <summary>Examples</summary> ```qml Group { title: qsTr("Output") CheckBox { name: "effects"; label: qsTr("Effects") RadioButtonGroup { name: "effectsType" RadioButton { value: "allModels"; label: qsTr("Across all models"); checked: true } RadioButton { value: "matchedModels"; label: qsTr("Across matched models") } } } CheckBox { name: "descriptives"; label: qsTr("Descriptives") } } ``` ![Image example](/Docs/development/img/qml-guide/Group_example_1.png) </details> #### Section A Section sets components (or groups of components) under a button. By clicking the button, you can hide or display these components. Properties - `title`: text shown in the button that controls the collapse of an entire section - `columns`: [optional, default: `2`] integer specifying how many columns the grouped components should occupy <details> <summary>Examples</summary> ```qml Section { title: qsTr("Advanced Options") RadioButtonGroup { title: qsTr("Missing Values") name: "missingValues" RadioButton { value: "excludeCasesListwise"; label: qsTr("Exclude cases listwise"); checked: true } RadioButton { value: "excludeCasesPairwise"; label: qsTr("Exclude cases pairwise") } } Group { title: qsTr("Confidence Interval") enabled: chronbach.checked CheckBox { name: "confAlpha" label: qsTr("Cronbach's α analytical") PercentField { name: "confAlphaLevel"; label: qsTr("Confidence"); defaultValue: 95 } } } } ``` ![Image example](/Docs/development/img/qml-guide/ExpanderButton_example_1.png) </details> ## Layout of Components By default JASP creates a two column grid that is filled row-wise. So each component you place in your QML file will be added to the input panel left to right, top to bottom. We will demonstrate what this means by the use of a table. Imagine a simple table with two columns and two rows. We have three components (CheckBox A, B and C) and each must go in their own cell. When these components are added row-wise we get A in the top left cell, then next to it B and on its own row C: | | <column 1> | <column 2> | |---------|------------|------------| | <row 1> | CheckBox A | CheckBox B | | <row 2> | CheckBox C | | #### Layout.rowSpan The above works great, but it definitely helps that the checkboxes are the same size. We could also add a RadioButtonGroup that is much taller than a simple checkbox. If we again imagine three components (but this time CheckBox A and B and RadioButtonGroup A) that go in the table in the same way: | | <column 1> | <column 2> | |---------|------------|--------------------| | <row 1> | CheckBox A | RadioButtonGroup A | | | | RadioButtonGroup A | | <row 2> | CheckBox B | | We notice that there is a lot of space between CheckBox A and CheckBox B. The reason for this is that CheckBox B is placed in the next available row. Fortunately we can remedy this with the property `Layout.rowSpan`; all we need to do is set `Layout.rowSpan: 2` in RadioButtonGroup A. This tells the engine that the component spans two rows and therefore CheckBox B will fit snuggly under CheckBox A: | | <column 1> | <column 2> | |---------|------------|--------------------| | <row 1> | CheckBox A | RadioButtonGroup A | | <row 2> | CheckBox B | RadioButtonGroup A | #### Layout.columnSpan Now imagine we really wanted to put the RadioButtonGroup in the top left cell and the two checkboxes below it on the same height as one another: | | <column 1> | <column 2> | |---------|--------------------|------------| | <row 1> | RadioButtonGroup A | | | | RadioButtonGroup A | | | <row 2> | CheckBox A | CheckBox B | However, if we simply added the components we would end up with this situation: | | <column 1> | <column 2> | |---------|--------------------|------------| | <row 1> | RadioButtonGroup A | CheckBox A | | | RadioButtonGroup A | | | <row 2> | CheckBox B | | To accomplish this we can set `Layout.columnSpan: 2` on RadioButtonGroup A. This results in the following situation: | | <column 1> | <column 2> | |---------|--------------------|--------------------| | <row 1> | RadioButtonGroup A | RadioButtonGroup A | | | RadioButtonGroup A | RadioButtonGroup A | | <row 2> | CheckBox A | CheckBox B | ## Connecting Multiple Components In `AvailableVariablesList` we showed that through its `source` property, we can establish a link between two components. There are other ways of connecting components and they are not limited to a `VariableList` (although they are a little different, only a `VariableList` uses the `name` property). QML allows us to do this is by adding an `id` to one component and then referencing this `id` in a different component. Note that the `id` can be any string starting with a lowercase, but it must be unique. An example is enabling a checkbox if one of two different checkboxes is checked. <p><details> <summary>Implementation</summary> ```qml CheckBox { name: "checkboxA"; label: qsTr("Some label"), id: checkA} CheckBox { name: "checkboxB"; label: qsTr("Some label"), id: checkB} CheckBox { name: "checkboxC"; label: qsTr("Some Label too"); enabled: checkA.checked || checkB.checked } ``` </details></p> Here we make use of a JavaScript expression to evaluate if either CheckBox A or CheckBox B has been checked and if this is the case we enable CheckBox C. This JavaScript expression will be automatically updated each time that the checked values of checkA and checkB changes. Another example would be setting the visibility of some textfield to invisible if a checkbox is not checked. <details> <summary>Implementation</summary> ```qml CheckBox { name: "checkboxA" label: qsTr("Some label") id: checkA TextField { name: "textfieldA"; afterlabel: qsTr("x"); visible: checkA.checked} } ``` </details> Any property can be set with an expression. A title of a Section for example: <details> <summary>Implementation</summary> ```qml DropDown { id: estimator name: "estimator" label: qsTr("Estimator") values: ["EBICglasso", "cor", "pcor", "IsingFit", "IsingSampler", "huge", "adalasso", "mgm"] } Section { title: qsTr("Analysis Options - ") + estimator.currentText .... } ``` </details> ## An Example We'll create a simple analysis input panel to show the workflow. Read first the Guide to adding a module in JASP. In this way, when you edit your QML file, the changes made will be automatically seen in JASP. You can play with the components and their properties, and see immediately the output in JASP. ### 1. Specifying Imports We can begin actual work on the QML file, first we have to tell the engine where to find our resources. To do so, we add a number of imports to the top of our file. <details> <summary>Code</summary> ```qml import QtQuick 2.11 import QtQuick.Layouts 1.3 import JASP.Controls 1.0 import JASP.Widgets 1.0 ``` If you want to import QML components from another jasp module, you can! Have a look at [custom imports](#custom-imports). </details> In the future, we will require using qualified namespace for the import statements for the JASP QML modules [see here](https://doc.qt.io/qt-5/qtqml-syntax-imports.html#importing-into-a-qualified-local-namespace). <details> <summary>Code</summary> ```qml import QtQuick 2.11 import QtQuick.Layouts 1.3 import JASP.Controls 1.0 as JC import JASP.Theme 1.0 as JT import JASP.Widgets 1.0 as JW ``` </details> This means that a JASP control, theme or a widget needs to be prepended with the qualifier, e.g., `JC.CheckBox` instead of just `CheckBox`. ### 2. Adding the Form At this point we add a `Form` which will hold all our input components: <details> <summary>Code</summary> ```qml import QtQuick 2.11 import QtQuick.Layouts 1.3 import JASP.Controls 1.0 import JASP.Widgets 1.0 Form { } ``` </details> ### 3. Adding the Components It's now a matter of mixing and matching the previously shown components to create a form to our liking. Of course, if something isn't quite possible, you can also use QML features that were not covered here. <details> <summary>Code</summary> ```qml import QtQuick 2.11 import QtQuick.Layouts 1.3 import JASP.Controls 1.0 import JASP.Widgets 1.0 Form { VariablesForm { AssignedVariablesList { name: "variables"; allowedColumns: ["ordinal", "nominal"] } } RadioButtonGroup { Layout.rowSpan: 2 name: "hypothesis" title: qsTr("Hypothesis") RadioButton { value: "notEqualToTestValue"; label: qsTr("≠ Test value"); checked: true } RadioButton { value: "greaterThanTestValue"; label: qsTr("> Test value") } RadioButton { value: "lessThanTestValue"; label: qsTr("< Test value") } } DoubleField { name: "testValue"; label: qsTr("Test value: "); defaultValue: 0.5 ; max: 1; decimals: 2} Group { title: qsTr("Plots") CheckBox { name: "descriptivesPlots" label: qsTr("Descriptive plots") PercentField { name: "descriptivesPlotsConfidenceInterval"; label: qsTr("Confidence Interval"); defaultValue: 95 } } } } ``` ![Image example](/Docs/development/img/qml-guide/general_example.png) </details> ## Advanced Usage QML is a very flexible format, besides giving you access to all of the built-in components and our JASP-components that are detailed under [components](#components) you can also add your own components! If you add a qml-file to the [qml directory](#jasp-adding-module.md#qml), for instance `Example.qml`, then it will be treated as a component by all other files in the directory. Make sure to give the file an actual capital as first letter though, otherwise qml will not see it as a component. Then you can use it in another qml file simply by adding `Example { id: yourExampleComponent }` and set any of the properties the root-component of your component if desired. This will give you the opportunity to create reusable parts, for instance, each of your analyses might share a common core. You could add this to a `Core.qml` and then this could be part of each analysis and be exactly the same everywhere. If you then also make sure to have a common function in R that uses the options specified in the `Core.qml`-component you can reuse that as well. The possibilities here are rather extended and possibly even endless. See [the Qt QML tutorials](https://doc.qt.io/qt-5/qml-tutorial.html) or the [official documentation](https://doc.qt.io/qt-5/qtqml-index.html) for more information on this. ## Custom Imports To allow other jasp modules to reuse your qml code you need to turn it into a "QML Module" and you do this by adding a textfile to you `inst` folder called `qmldir`. This file specifies which qml-components your module makes available to other modules. For instance, suppose you want to share the entire `Descriptives` analysisform with other modules you can create `jaspDescriptives/qmldir` and that should contain: ``` module <jaspDescriptives> Descriptives 1.0 qml/Descriptives.qml ``` And then suppose you want to use it in any other module you can simply do `import jaspDescriptives 1.0` and use it directly as `Descriptives {}`. There is only small thing to keep in mind, when your module is loaded in JASP it can only use qml modules from jasp modules that are installed in jasp. This means that if your jasp module depends on another, like the above `jaspDescriptives`, you will get the r-code from the dependency-rpkg. But the qml will come from the loaded `jaspDescriptives` in JASP. This is far from ideal because it can lead to conflicts between the r-code and qml. There is sadly no way around this at the moment though. But this can be worked around once we have an online module library. Then we can just force the dependencies to be installed fully. If it turns out it is too much of a problem we could also consider using multiple qml-engines or something, but for now that seems overkill. <MSG> Update jasp-qml-guide.md <DFF> @@ -9,12 +9,13 @@ Table of Contents: + [CheckBox](#checkbox) + [RadioButton](#radiobutton) + [DropDown](#dropdown) + + [Slider](#slider) + [DoubleField](#doublefield) + [IntegerField](#integerfield) + [PercentField](#percentfield) + [TextField](#textfield) * [Variable Specification](#variable-specification) - + [availableVariablesList](#availablevariableslist) + + [AvailableVariablesList](#availablevariableslist) + [AssignedVariablesList](#assignedvariableslist) + [RepeatedMeasuresFactorsList](#repeatedmeasuresfactorslist) * [Grouping](#grouping) @@ -32,18 +33,24 @@ Table of Contents: ## Components -The components can roughly be divided in three classes. One that deals with general inputs (e.g., checkboxes), one that deals with assigning variables and one that groups components together. Each will be covered in the following section. Note that in several examples you may encounter `qsTr()`, it is important that this function wraps all text that will be shown in the interface. It will provide the possibility to translate JASP in the future. Additionally, note that the components described below may generally be nested to an arbitrary level (e.g., a checkbox in a checkbox in a checkbox). +The components can roughly be divided in three classes. One that deals with general inputs (e.g., checkboxes), one that deals with assigning variables and one that groups components together. Each will be covered in the following section. +Some remarks about these components: +- They are all QML items, so they automatically get generic QML properties like `enabled` or `visible`. +- The properties of the components can be set directly with a value. You can use also a JavaScript expression so that the value will depend on other components (see the section on [Connecting Multiple Components](#connecting-multiple-components)). +- In several examples you may encounter `qsTr()`, it is important that this function wraps all text that will be shown in the interface. It will provide the possibility to translate JASP in the future. +- The components described below may generally be nested to an arbitrary level (e.g., a checkbox in a group in a checkbox). ### General Input -These components are quite common in questionnaires and input forms on websites, they include the checkbox, radiobutton, dropdown and fields where text may be entered. +These components are quite common in questionnaires and input forms on websites, they include the checkbox, radiobutton, dropdown, slider and textfields where text may be entered. #### CheckBox +Check button that can be toggled on and off. If some components are nested inside a CheckBox, they are automatically enabled or disabled when the CheckBox is set or not. Properties - `name`: string identifier (in your R code you will be able to retrieve the value of the checkbox through this identifier) - `label`: text that will be shown to the left of the checkbox -- `checked`: [optional, default: `false`] boolean specifying if it should contain a checkmark (often a binding that when evaluated gives a boolean, see the section on [Connecting Multiple Components](#connecting-multiple-components)) +- `checked`: [optional, default: `false`] boolean specifying if it should be set per default on or not. - `childrenOnSameRow`: [optional, default: `false`] boolean specifying if components (e.g., other checkboxes, textfields) nested within the checkbox should be shown on the same row or, alternatively, below the checkbox -- `columns`: [optional, default: `1`] integer specifying how many columns the nested components should spread out over (e.g., when set to 3, with three nested checkboxes, these three checkboxes will appear side by side on the same horizontal row) +- `columns`: [optional, default: `1`] integer specifying how many columns the nested components should occupy (e.g., when set to 3, with three nested checkboxes, these three checkboxes will appear side by side on the same horizontal row) <details> <summary>Examples</summary> @@ -69,17 +76,20 @@ Properties </details> #### RadioButton -A single radiobutton is not very useful, and so they must be grouped together. We can do this by putting multiple `RadioButton`s together in a `RadioButtonGroup`. +A RadioButton is used with other RadioButton's inside a `RadioButtonGroup`. Contrary to CheckBox, only 1 RadioButton can be checked at the same time. -Properties +RadioButtonGroup properties: - `name`: string identifier (in your R code you will be able to retrieve the value of the checked radiobutton through this identifier) - `title`: text that is shown above the set of radiobuttons -- `RadioButton`: - * `value`: the value of the `RadioButtonGroup` that is send to R when this radiobutton is checked - * `label`: the text that is shown to the right of the radiobutton - * `checked`: [optional, default: `false`] boolean specifying if it should contain a checkmark (and thus be the default); one radiobutton should have this property set to `true` - * `childrenOnSameRow`: [optional, default: `false`] boolean specifying if components (e.g., checkboxes, textfields) nested within the radiobutton should be shown on the same row or, alternatively, below the radiobutton - * `columns`: [optional, default: `1`] integer specifying how many columns the nested components should spread out over (e.g., when set to 3, with three nested checkboxes, these three checkboxes will appear side by side on the same horizontal row) +- `placeRadioButtonsOnSameRow`: [optional, default: `false`] per default, the RadioButton's are placed vertically under the title. Set this property to true to place the buttons horizontally. +- `columns`: [optional, default: `1`] integer specifying how many columns should be used to display the RadioButton's + +RadioButton properties: +- `value`: the value of the `RadioButtonGroup` that is send to R when this radiobutton is checked +- `label`: the text that is shown to the right of the radiobutton +- `checked`: [optional, default: `false`] boolean specifying if it should contain a checkmark (and thus be the default); one radiobutton should have this property set to `true` +- `childrenOnSameRow`: [optional, default: `false`] boolean specifying if components (e.g., checkboxes, textfields) nested within the radiobutton should be shown on the same row or, alternatively, below the radiobutton +- `columns`: [optional, default: `1`] integer specifying how many columns the nested components should occupy (e.g., when set to 3, with three nested checkboxes, these three checkboxes will appear side by side on the same horizontal row) <details> <summary>Examples</summary> @@ -126,6 +136,7 @@ Properties - `label`: [optional, default: `""`] text that will be shown above the dropdown - `values`: array of (named) values that is shown in the dropdown list, in the case of an unnamed array the value and the label are the same, but when a named array is provided the label shown to the user can be different from the value send to R (see example below) - `indexDefaultValue`: [optional, default: `1`] integer specifying the index of the dropdown item that is selected by default, take note that this is zero-based +- `source`: if `values` is empty, you can use the name of a VariablesList (see [Variable Specification](#variable-specification)) to set the source of the values of the DropDown. <details> <summary>Examples</summary> @@ -157,6 +168,32 @@ Properties </details> +#### Slider +Slider is used to select a value by sliding a handle along a track. +Properties +- `name`: string identifier (in your R code you will be able to retrieve the value of the slider through this identifier) +- `label`: [optional, default: `""`] text that will be shown above the slider +- `value`: [optional, default: `0.5`] default value +- `min`: [optional, default: `0`] minimum value +- `max`: [optional, default: `1`] maximum value +- `orientation`: [optional, default: `Qt.Vertical`] set wheter the slider should be displayed vertically (`Qt.Vertical`) or horizontally (`Qt.Horizontal`) + +<details> + <summary>Examples</summary> + + ```qml + Slider + { + name: "highlight" + label: qsTr("Highlight") + value: 0.4 + } + ``` + ![Image example](/Docs/development/img/qml-guide/Slider_example_1.png) + +</details> + + #### DoubleField Properties - `name`: string identifier (in your R code you will be able to retrieve the value of the field through this identifier) @@ -242,6 +279,7 @@ Properties - `label`: text that will be shown to the left of the field - `defaultValue`: [optional, default: `50`] integer specifying the default percentage shown - `fieldWidth`: [optional, default: `40`] in pixels how wide should the field be +- `decimals`: [optional, default: `0`] integer specifying how many decimals the user can enter <details> <summary>Examples</summary> @@ -258,7 +296,7 @@ Properties: - `name`: string identifier (in your R code you will be able to retrieve the value of the field through this identifier) - `label`: [optional, default: `""`] text that will be shown to the left of the field - `afterLabel`: [optional, default: `""`] text that will be shown to the right of the field -- `defaultValue`: [optional, default: `""`] default text before the user enters anything +- `value`: [optional, default: `""`] default text before the user enters anything - `placeholderText`: [optional, default: `""`] text shown as a placeholder until a user enters something, will not be send to R if left unchanged by the user (mutually exclusive with `defaultValue`) - `fieldWidth`: [optional, default: `40`] in pixels how wide should the field be @@ -281,7 +319,7 @@ Properties - `name`: identifier of the variables list, this is never send to R - `label`: [optional, default: `""`] text that will be shown above the variable
{'commit': 'diff --git a/Docs/development/jasp-qml-guide.md b/Docs/development/jasp-qml-guide.md\nindex 95d65d2d7..15450db05 100644\n--- a/Docs/development/jasp-qml-guide.md\n+++ b/Docs/development/jasp-qml-guide.md\n@@ -9,12 +9,13 @@ Table of Contents:\n     + [CheckBox](#checkbox)\n     + [RadioButton](#radiobutton)\n     + [DropDown](#dropdown)\n+    + [Slider](#slider)\n     + [DoubleField](#doublefield)\n     + [IntegerField](#integerfield)\n     + [PercentField](#percentfield)\n     + [TextField](#textfield)\n   * [Variable Specification](#variable-specification)\n-    + [availableVariablesList](#availablevariableslist)\n+    + [AvailableVariablesList](#availablevariableslist)\n     + [AssignedVariablesList](#assignedvariableslist)\n     + [RepeatedMeasuresFactorsList](#repeatedmeasuresfactorslist)\n   * [Grouping](#grouping)\n@@ -32,18 +33,24 @@ Table of Contents:\n \n \n ## Components\n-The components can roughly be divided in three classes. One that deals with general inputs (e.g., checkboxes), one that deals with assigning variables and one that groups components together. Each will be covered in the following section. Note that in several examples you may encounter `qsTr()`, it is important that this function wraps all text that will be shown in the interface. It will provide the possibility to translate JASP in the future. Additionally, note that the components described below may generally be nested to an arbitrary level (e.g., a checkbox in a checkbox in a checkbox).\n+The components can roughly be divided in three classes. One that deals with general inputs (e.g., checkboxes), one that deals with assigning variables and one that groups components together. Each will be covered in the following section.\n+Some remarks about these components:\n+- They are all QML items, so they automatically get generic QML properties like `enabled` or `visible`.\n+- The properties of the components can be set directly with a value. You can use also a JavaScript expression so that the value will depend on other components (see the section on [Connecting Multiple Components](#connecting-multiple-components)).\n+- In several examples you may encounter `qsTr()`, it is important that this function wraps all text that will be shown in the interface. It will provide the possibility to translate JASP in the future.\n+- The components described below may generally be nested to an arbitrary level (e.g., a checkbox in a group in a checkbox).\n \n ### General Input\n-These components are quite common in questionnaires and input forms on websites, they include the checkbox, radiobutton, dropdown and fields where text may be entered.\n+These components are quite common in questionnaires and input forms on websites, they include the checkbox, radiobutton, dropdown, slider and textfields where text may be entered.\n \n #### CheckBox\n+Check button that can be toggled on and off. If some components are nested inside a CheckBox, they are automatically enabled or disabled when the CheckBox is set or not.\n Properties\n - `name`: string identifier (in your R code you will be able to retrieve the value of the checkbox through this identifier)\n - `label`: text that will be shown to the left of the checkbox\n-- `checked`: [optional, default: `false`] boolean specifying if it should contain a checkmark (often a binding that when evaluated gives a boolean, see the section on [Connecting Multiple Components](#connecting-multiple-components))\n+- `checked`: [optional, default: `false`] boolean specifying if it should be set per default on or not.\n - `childrenOnSameRow`: [optional, default: `false`] boolean specifying if components (e.g., other checkboxes, textfields) nested within the checkbox should be shown on the same row or, alternatively, below the checkbox\n-- `columns`: [optional, default: `1`] integer specifying how many columns the nested components should spread out over (e.g., when set to 3, with three nested checkboxes, these three checkboxes will appear side by side on the same horizontal row)\n+- `columns`: [optional, default: `1`] integer specifying how many columns the nested components should occupy (e.g., when set to 3, with three nested checkboxes, these three checkboxes will appear side by side on the same horizontal row)\n \n <details>\n \t<summary>Examples</summary>\n@@ -69,17 +76,20 @@ Properties\n </details>\n \n #### RadioButton\n-A single radiobutton is not very useful, and so they must be grouped together. We can do this by putting multiple `RadioButton`s together in a `RadioButtonGroup`.\n+A RadioButton is used with other RadioButton\'s inside a `RadioButtonGroup`. Contrary to CheckBox, only 1 RadioButton can be checked at the same time.\n \n-Properties\n+RadioButtonGroup properties:\n - `name`: string identifier (in your R code you will be able to retrieve the value of the checked radiobutton through this identifier)\n - `title`: text that is shown above the set of radiobuttons\n-- `RadioButton`: \n-  * `value`: the value of the `RadioButtonGroup` that is send to R when this radiobutton is checked\n-  * `label`: the text that is shown to the right of the radiobutton\n-  * `checked`: [optional, default: `false`] boolean specifying if it should contain a checkmark (and thus be the default); one radiobutton should have this property set to `true`\n-  * `childrenOnSameRow`: [optional, default: `false`] boolean specifying if components (e.g., checkboxes, textfields) nested within the radiobutton should be shown on the same row or, alternatively, below the radiobutton\n-  * `columns`: [optional, default: `1`] integer specifying how many columns the nested components should spread out over (e.g., when set to 3, with three nested checkboxes, these three checkboxes will appear side by side on the same horizontal row)\n+- `placeRadioButtonsOnSameRow`: [optional, default: `false`] per default, the RadioButton\'s are placed vertically under the title. Set this property to true to place the buttons horizontally.\n+- `columns`: [optional, default: `1`] integer specifying how many columns should be used to display the RadioButton\'s\n+\n+RadioButton properties:\n+- `value`: the value of the `RadioButtonGroup` that is send to R when this radiobutton is checked\n+- `label`: the text that is shown to the right of the radiobutton\n+- `checked`: [optional, default: `false`] boolean specifying if it should contain a checkmark (and thus be the default); one radiobutton should have this property set to `true`\n+- `childrenOnSameRow`: [optional, default: `false`] boolean specifying if components (e.g., checkboxes, textfields) nested within the radiobutton should be shown on the same row or, alternatively, below the radiobutton\n+- `columns`: [optional, default: `1`] integer specifying how many columns the nested components should occupy (e.g., when set to 3, with three nested checkboxes, these three checkboxes will appear side by side on the same horizontal row)\n \n <details>\n \t<summary>Examples</summary>\n@@ -126,6 +136,7 @@ Properties\n - `label`: [optional, default: `""`] text that will be shown above the dropdown\n - `values`: array of (named) values that is shown in the dropdown list, in the case of an unnamed array the value and the label are the same, but when a named array is provided the label shown to the user can be different from the value send to R (see example below)\n - `indexDefaultValue`: [optional, default: `1`] integer specifying the index of the dropdown item that is selected by default, take note that this is zero-based\n+- `source`: if `values` is empty, you can use the name of a VariablesList (see [Variable Specification](#variable-specification)) to set the source of the values of the DropDown.\n \n <details>\n \t<summary>Examples</summary>\n@@ -157,6 +168,32 @@ Properties\n   \n </details>\n \n+#### Slider\n+Slider is used to select a value by sliding a handle along a track.\n+Properties\n+- `name`: string identifier (in your R code you will be able to retrieve the value of the slider through this identifier)\n+- `label`: [optional, default: `""`] text that will be shown above the slider\n+- `value`: [optional, default: `0.5`] default value\n+- `min`: [optional, default: `0`] minimum value\n+- `max`: [optional, default: `1`] maximum value\n+- `orientation`: [optional, default: `Qt.Vertical`] set wheter the slider should be displayed vertically (`Qt.Vertical`) or horizontally (`Qt.Horizontal`)\n+\n+<details>\n+\t<summary>Examples</summary>\n+\t\n+  ```qml\n+  Slider\n+  {\n+    name: "highlight"\n+    label: qsTr("Highlight")\n+    value: 0.4\n+  }\n+  ```\n+  ![Image example](/Docs/development/img/qml-guide/Slider_example_1.png)\n+    \n+</details>\n+\n+\n #### DoubleField\n Properties\n - `name`: string identifier (in your R code you will be able to retrieve the value of the field through this identifier)\n@@ -242,6 +279,7 @@ Properties\n - `label`: text that will be shown to the left of the field\n - `defaultValue`: [optional, default: `50`] integer specifying the default percentage shown\n - `fieldWidth`: [optional, default: `40`] in pixels how wide should the field be\n+- `decimals`: [optional, default: `0`] integer specifying how many decimals the user can enter\n \n <details>\n \t<summary>Examples</summary>\n@@ -258,7 +296,7 @@ Properties:\n - `name`: string identifier (in your R code you will be able to retrieve the value of the field through this identifier)\n - `label`: [optional, default: `""`] text that will be shown to the left of the field\n - `afterLabel`: [optional, default: `""`] text that will be shown to the right of the field\n-- `defaultValue`: [optional, default: `""`] default text before the user enters anything\n+- `value`: [optional, default: `""`] default text before the user enters anything\n - `placeholderText`: [optional, default: `""`] text shown as a placeholder until a user enters something, will not be send to R if left unchanged by the user (mutually exclusive with `defaultValue`)\n - `fieldWidth`: [optional, default: `40`] in pixels how wide should the field be\n \n@@ -281,7 +319,7 @@ Properties\n - `name`: identifier of the variables list, this is never send to R\n - `label`: [optional, default: `""`] text that will be shown above the variable field\n - `source`: [optional] can be set to the `name` of an `AssignedVariablesList`, when omitted variables are taken from the dataset (example usage: you have a second `availableVariablesList` for plotting the variables that are assigned to an `AssignedVariablesList`; see also the example)\n-- `width`: [optional, default: ±`230`] in pixels how wide should the field be\n+- `width`: [optional, default: 2/5 of the VariablesForm width] in pixels how wide should the field be\n \n Note: `height` should be defined on `VariablesForm` itself.\n \n@@ -290,23 +328,16 @@ Note: `height` should be defined on `VariablesForm` itself.\n   \n   ```qml\n   VariablesForm\n-\t{\n-    AssignedVariablesList\n-    {\n-      name: "fixedFactors"\n-      label: qsTr("Fixed Factors")\n-      allowedColumns: ["ordinal", "nominal"]\n-    }\n+  {\n+    AvailableVariablesList { name: "allVariables" }\n+    AssignedVariablesList  { name: "fixedFactors"; label: qsTr("Fixed Factors"); allowedColumns: ["ordinal", "nominal"] }\n   }\n \n   VariablesForm\n   {\n     height: 200\n-    AvailableVariablesList\n-    { \n-      name: "postHocTestsAvailable"\n-      source: "fixedFactors"\n-    }\n+    AvailableVariablesList { name: "postHocTestsAvailable"; source: "fixedFactors" }\n+    AssignedVariablesList {  name: "postHocTestsVariables" }\n   }\n   ```\n   ![Image example](/Docs/development/img/qml-guide/availableVariablesList_example_1_1.png)\n@@ -322,8 +353,8 @@ Properties\n - `singleVariable`: [optional, default: `false`] boolean specifying if this field will accept a maximum of one variable\n - `listViewType`: [optional] string that specifies the type of `AssignedVariablesList`, when omitted we get a normal list,  options are `"Layers"` (see Contingency Tables), `"Pairs"` (see Paired Samples T-Test), `"Interaction"` (see ANOVA) and `"RepeatedMeasures"` (see Repeated Measures ANOVA)\n - `ExtraControlColumn`: [optional] addititional general input component (e.g., `"CheckBox"`) which is added to each variable and can be used to add extra control (e.g., you can specify the status of the variable within a linear model, see example below)\n-- `width`: [optional, default: ±`230`] in pixels how wide should the field be\n-- `height`: [optional, default: `350`] in pixels how heigh should the field be\n+- `width`: [optional, default: 2/5 of the VariablesForm width] in pixels how wide should the field be\n+- `height`: [optional] in pixels how heigh should the field be. Per default, it is set so that all AssignedVariablesList\'s fit the VariablesForm. If you set the height for 1 AssignedVariablesList, it will try to set height of the other AssignedVariablesLists\'s so that they all fit the heigth of the VariablesForm.\n \n <details>\n \t<summary>Examples</summary>\n@@ -331,13 +362,15 @@ Properties\n   ```qml\n \tVariablesForm\n \t{\n-    AssignedVariablesList\n-    {\n-      name: "dependent"\n-      label: qsTr("Dependent Variable")\n-      allowedColumns: ["scale"]\n-      singleVariable: true\n-    }\n+\t\tAvailableVariablesList { name: "allVariables" }\n+\t\tAssignedVariablesList\n+\t\t{\n+\t\t\tname: "dependent"\n+\t\t\tlabel: qsTr("Dependent Variable")\n+\t\t\tallowedColumns: ["scale"]\n+\t\t\tsingleVariable: true\n+\t\t}\n+\t}\n   }\n   ```\n   ![Image example](/Docs/development/img/qml-guide/AssignedVariablesList_example_1.png)\n@@ -345,6 +378,7 @@ Properties\n   ```qml\n   VariablesForm\n   {\n+    AvailableVariablesList { name: "allVariables" }\n     AssignedVariablesList\n     {\n       name: "modelTerms"\n@@ -406,7 +440,7 @@ In order to add more structure to the input panel you can group components toget\n #### Group\n Properties\n - `title`: text shown above the grouped input components\n-- `columns`: [optional, default: `1`] integer specifying how many columns the grouped components should spread out over\n+- `columns`: [optional, default: `1`] integer specifying how many columns the grouped components should occupy\n \n <details>\n \t<summary>Examples</summary>\n@@ -435,7 +469,7 @@ Properties\n #### ExpanderButton\n Properties\n - `title`: text shown in the button that controls the collapse of an entire section\n-- `columns`: [optional, default: `2`] integer specifying how many columns the grouped components should spread out over\n+- `columns`: [optional, default: `2`] integer specifying how many columns the grouped components should occupy\n \n <details>\n \t<summary>Examples</summary>\n@@ -525,22 +559,22 @@ To accomplish this we can set `Layout.columnSpan: 2` on RadioButtonGroup A. This\n \n \n ## Connecting Multiple Components\n-In `AvailableVariablesList` we showed that through its `source` property, we can establish a link between two components. There are other ways of connecting components and they are not limited to a `VariableList` (although they are a little different, only a `VariableList` uses the `name` property). QML allows us to do this is by adding an `id` to one component and then referencing this `id` in a different component. Note that the `id` can be any string, but it must be unique.\n+In `AvailableVariablesList` we showed that through its `source` property, we can establish a link between two components. There are other ways of connecting components and they are not limited to a `VariableList` (although they are a little different, only a `VariableList` uses the `name` property). QML allows us to do this is by adding an `id` to one component and then referencing this `id` in a different component. Note that the `id` can be any string starting with a lowercase, but it must be unique.\n \n An example is enabling a checkbox if one of two different checkboxes is checked.\n <p><details>\n \t<summary>Implementation</summary>\n \t\n   ```qml\n-  CheckBox { name: "checkboxA"; label: qsTr("Some label"), id: "A"}\n-  CheckBox { name: "checkboxB"; label: qsTr("Some label"), id: "B"}\n+  CheckBox { name: "checkboxA"; label: qsTr("Some label"), id: checkA}\n+  CheckBox { name: "checkboxB"; label: qsTr("Some label"), id: checkB}\n \n-  CheckBox { name: "checkboxC";\tlabel: qsTr("Some Label too"); enabled: A.checked || B.checked }\n+  CheckBox { name: "checkboxC";\tlabel: qsTr("Some Label too"); enabled: checkA.checked || checkB.checked }\n   ```\n   \n </details></p>\n \n-Here we make use of a JavaScript expression to evaluate if either CheckBox A or CheckBox B has been checked and if this is the case we enable CheckBox C. It may be a bit confusing that we didn\'t cover `enabled` as a property of a `CheckBox`, this is simply one of the many properties that QML adds without our help.\n+Here we make use of a JavaScript expression to evaluate if either CheckBox A or CheckBox B has been checked and if this is the case we enable CheckBox C. This JavaScript expression will be automatically updated each time that the checked values of checkA and checkB changes. \n \n Another example would be setting the visibility of some textfield to invisible if a checkbox is not checked.\n \n@@ -552,28 +586,43 @@ Another example would be setting the visibility of some textfield to invisible i\n   {\n     name: "checkboxA"\n     label: qsTr("Some label")\n-    id: "A"\n-    TextField { name: "textfieldA"; afterlabel: qsTr("x"); visible: A.checked}\n+    id: checkA\n+    TextField { name: "textfieldA"; afterlabel: qsTr("x"); visible: checkA.checked}\n   \n   }\n   ```\n   \n </details>\n \n+Any property can be set with an expression. A title of an ExpanderButton for example:\n+<details>\n+\t<summary>Implementation</summary>\n+\t\n+  ```qml\n+  \n+\tDropDown\n+\t{\n+\t\tid: estimator\n+\t\tname: "estimator"\n+\t\tlabel: qsTr("Estimator")\n+\t\tvalues: ["EBICglasso", "cor", "pcor", "IsingFit", "IsingSampler", "huge", "adalasso", "mgm"]\n+\t}\n+\t\n+\tExpanderButton \n+\t{\n+\t\ttitle: qsTr("Analysis Options - ") + estimator.currentText\n+                ....\n+\t}\n+\n+  ```\n+  \n+</details>\n+\t\n \n ## An Example\n We\'ll create a simple analysis input panel to show the workflow.\n+Read first the Guide to adding a module in JASP. In this way, when you edit your QML file, the changes made will be automatically seen in JASP. You can play with the components and their properties, and see immediately the output in JASP.\n \n-### 1. Setting up the QML Watcher\n-It is, of course, much easier to create a working product when you can test it along the way. This was made easy when the QML watcher was introduced to JASP. To use it:\n-1. Open JASP\n-2. Click on the menu in the top left corner\n-3. Navigate to \'Preferences\'\n-4. Navigate to \'Advanced\'\n-5. Place a checkmark before \'Developer mode\'\n-6. Enter the path where the QML file you want to make can be found\n-\n-Now every time you save a change in your QML file it will immediately be reflected in the input panel of your analysis.\n \n ### 2. Specifying Imports\n We can begin actual work on the QML file, first we have to tell the engine where to find our resources. To do so, we add a number of imports to the top of our file.\n', 'commit_subject': 'Update jasp-qml-guide.md', 'repo_name': 'jasp-stats/jasp-desktop', 'committer': {'name': 'GitHub', 'email': '1505422b2465e9a84f6fdfaa161078890c593f06@github.com', 'time_sec': '1551275394', 'tz_offset': '60', 'date': {'seconds': '1551275394'}}, 'commit_tree': 'bd4122e76b30fdda8c4250af94ffb77052d034e0', 'commit_message': 'Update jasp-qml-guide.md', 'language_name': 'Shell', 'license': 'agpl-3.0', 'hunks': '@@ -9,12 +9,13 @@ Table of Contents:\n     + [CheckBox](#checkbox)\n     + [RadioButton](#radiobutton)\n     + [DropDown](#dropdown)\n+    + [Slider](#slider)\n     + [DoubleField](#doublefield)\n     + [IntegerField](#integerfield)\n     + [PercentField](#percentfield)\n     + [TextField](#textfield)\n   * [Variable Specification](#variable-specification)\n-    + [availableVariablesList](#availablevariableslist)\n+    + [AvailableVariablesList](#availablevariableslist)\n     + [AssignedVariablesList](#assignedvariableslist)\n     + [RepeatedMeasuresFactorsList](#repeatedmeasuresfactorslist)\n   * [Grouping](#grouping)\n@@ -32,18 +33,24 @@ Table of Contents:\n \n \n ## Components\n-The components can roughly be divided in three classes. One that deals with general inputs (e.g., checkboxes), one that deals with assigning variables and one that groups components together. Each will be covered in the following section. Note that in several examples you may encounter `qsTr()`, it is important that this function wraps all text that will be shown in the interface. It will provide the possibility to translate JASP in the future. Additionally, note that the components described below may generally be nested to an arbitrary level (e.g., a checkbox in a checkbox in a checkbox).\n+The components can roughly be divided in three classes. One that deals with general inputs (e.g., checkboxes), one that deals with assigning variables and one that groups components together. Each will be covered in the following section.\n+Some remarks about these components:\n+- They are all QML items, so they automatically get generic QML properties like `enabled` or `visible`.\n+- The properties of the components can be set directly with a value. You can use also a JavaScript expression so that the value will depend on other components (see the section on [Connecting Multiple Components](#connecting-multiple-components)).\n+- In several examples you may encounter `qsTr()`, it is important that this function wraps all text that will be shown in the interface. It will provide the possibility to translate JASP in the future.\n+- The components described below may generally be nested to an arbitrary level (e.g., a checkbox in a group in a checkbox).\n \n ### General Input\n-These components are quite common in questionnaires and input forms on websites, they include the checkbox, radiobutton, dropdown and fields where text may be entered.\n+These components are quite common in questionnaires and input forms on websites, they include the checkbox, radiobutton, dropdown, slider and textfields where text may be entered.\n \n #### CheckBox\n+Check button that can be toggled on and off. If some components are nested inside a CheckBox, they are automatically enabled or disabled when the CheckBox is set or not.\n Properties\n - `name`: string identifier (in your R code you will be able to retrieve the value of the checkbox through this identifier)\n - `label`: text that will be shown to the left of the checkbox\n-- `checked`: [optional, default: `false`] boolean specifying if it should contain a checkmark (often a binding that when evaluated gives a boolean, see the section on [Connecting Multiple Components](#connecting-multiple-components))\n+- `checked`: [optional, default: `false`] boolean specifying if it should be set per default on or not.\n - `childrenOnSameRow`: [optional, default: `false`] boolean specifying if components (e.g., other checkboxes, textfields) nested within the checkbox should be shown on the same row or, alternatively, below the checkbox\n-- `columns`: [optional, default: `1`] integer specifying how many columns the nested components should spread out over (e.g., when set to 3, with three nested checkboxes, these three checkboxes will appear side by side on the same horizontal row)\n+- `columns`: [optional, default: `1`] integer specifying how many columns the nested components should occupy (e.g., when set to 3, with three nested checkboxes, these three checkboxes will appear side by side on the same horizontal row)\n \n <details>\n \t<summary>Examples</summary>\n@@ -69,17 +76,20 @@ Properties\n </details>\n \n #### RadioButton\n-A single radiobutton is not very useful, and so they must be grouped together. We can do this by putting multiple `RadioButton`s together in a `RadioButtonGroup`.\n+A RadioButton is used with other RadioButton\'s inside a `RadioButtonGroup`. Contrary to CheckBox, only 1 RadioButton can be checked at the same time.\n \n-Properties\n+RadioButtonGroup properties:\n - `name`: string identifier (in your R code you will be able to retrieve the value of the checked radiobutton through this identifier)\n - `title`: text that is shown above the set of radiobuttons\n-- `RadioButton`: \n-  * `value`: the value of the `RadioButtonGroup` that is send to R when this radiobutton is checked\n-  * `label`: the text that is shown to the right of the radiobutton\n-  * `checked`: [optional, default: `false`] boolean specifying if it should contain a checkmark (and thus be the default); one radiobutton should have this property set to `true`\n-  * `childrenOnSameRow`: [optional, default: `false`] boolean specifying if components (e.g., checkboxes, textfields) nested within the radiobutton should be shown on the same row or, alternatively, below the radiobutton\n-  * `columns`: [optional, default: `1`] integer specifying how many columns the nested components should spread out over (e.g., when set to 3, with three nested checkboxes, these three checkboxes will appear side by side on the same horizontal row)\n+- `placeRadioButtonsOnSameRow`: [optional, default: `false`] per default, the RadioButton\'s are placed vertically under the title. Set this property to true to place the buttons horizontally.\n+- `columns`: [optional, default: `1`] integer specifying how many columns should be used to display the RadioButton\'s\n+\n+RadioButton properties:\n+- `value`: the value of the `RadioButtonGroup` that is send to R when this radiobutton is checked\n+- `label`: the text that is shown to the right of the radiobutton\n+- `checked`: [optional, default: `false`] boolean specifying if it should contain a checkmark (and thus be the default); one radiobutton should have this property set to `true`\n+- `childrenOnSameRow`: [optional, default: `false`] boolean specifying if components (e.g., checkboxes, textfields) nested within the radiobutton should be shown on the same row or, alternatively, below the radiobutton\n+- `columns`: [optional, default: `1`] integer specifying how many columns the nested components should occupy (e.g., when set to 3, with three nested checkboxes, these three checkboxes will appear side by side on the same horizontal row)\n \n <details>\n \t<summary>Examples</summary>\n@@ -126,6 +136,7 @@ Properties\n - `label`: [optional, default: `""`] text that will be shown above the dropdown\n - `values`: array of (named) values that is shown in the dropdown list, in the case of an unnamed array the value and the label are the same, but when a named array is provided the label shown to the user can be different from the value send to R (see example below)\n - `indexDefaultValue`: [optional, default: `1`] integer specifying the index of the dropdown item that is selected by default, take note that this is zero-based\n+- `source`: if `values` is empty, you can use the name of a VariablesList (see [Variable Specification](#variable-specification)) to set the source of the values of the DropDown.\n \n <details>\n \t<summary>Examples</summary>\n@@ -157,6 +168,32 @@ Properties\n   \n </details>\n \n+#### Slider\n+Slider is used to select a value by sliding a handle along a track.\n+Properties\n+- `name`: string identifier (in your R code you will be able to retrieve the value of the slider through this identifier)\n+- `label`: [optional, default: `""`] text that will be shown above the slider\n+- `value`: [optional, default: `0.5`] default value\n+- `min`: [optional, default: `0`] minimum value\n+- `max`: [optional, default: `1`] maximum value\n+- `orientation`: [optional, default: `Qt.Vertical`] set wheter the slider should be displayed vertically (`Qt.Vertical`) or horizontally (`Qt.Horizontal`)\n+\n+<details>\n+\t<summary>Examples</summary>\n+\t\n+  ```qml\n+  Slider\n+  {\n+    name: "highlight"\n+    label: qsTr("Highlight")\n+    value: 0.4\n+  }\n+  ```\n+  ![Image example](/Docs/development/img/qml-guide/Slider_example_1.png)\n+    \n+</details>\n+\n+\n #### DoubleField\n Properties\n - `name`: string identifier (in your R code you will be able to retrieve the value of the field through this identifier)\n@@ -242,6 +279,7 @@ Properties\n - `label`: text that will be shown to the left of the field\n - `defaultValue`: [optional, default: `50`] integer specifying the default percentage shown\n - `fieldWidth`: [optional, default: `40`] in pixels how wide should the field be\n+- `decimals`: [optional, default: `0`] integer specifying how many decimals the user can enter\n \n <details>\n \t<summary>Examples</summary>\n@@ -258,7 +296,7 @@ Properties:\n - `name`: string identifier (in your R code you will be able to retrieve the value of the field through this identifier)\n - `label`: [optional, default: `""`] text that will be shown to the left of the field\n - `afterLabel`: [optional, default: `""`] text that will be shown to the right of the field\n-- `defaultValue`: [optional, default: `""`] default text before the user enters anything\n+- `value`: [optional, default: `""`] default text before the user enters anything\n - `placeholderText`: [optional, default: `""`] text shown as a placeholder until a user enters something, will not be send to R if left unchanged by the user (mutually exclusive with `defaultValue`)\n - `fieldWidth`: [optional, default: `40`] in pixels how wide should the field be\n \n@@ -281,7 +319,7 @@ Properties\n - `name`: identifier of the variables list, this is never send to R\n - `label`: [optional, default: `""`] text that will be shown above the variable field\n - `source`: [optional] can be set to the `name` of an `AssignedVariablesList`, when omitted variables are taken from the dataset (example usage: you have a second `availableVariablesList` for plotting the variables that are assigned to an `AssignedVariablesList`; see also the example)\n-- `width`: [optional, default: ±`230`] in pixels how wide should the field be\n+- `width`: [optional, default: 2/5 of the VariablesForm width] in pixels how wide should the field be\n \n Note: `height` should be defined on `VariablesForm` itself.\n \n@@ -290,23 +328,16 @@ Note: `height` should be defined on `VariablesForm` itself.\n   \n   ```qml\n   VariablesForm\n-\t{\n-    AssignedVariablesList\n-    {\n-      name: "fixedFactors"\n-      label: qsTr("Fixed Factors")\n-      allowedColumns: ["ordinal", "nominal"]\n-    }\n+  {\n+    AvailableVariablesList { name: "allVariables" }\n+    AssignedVariablesList  { name: "fixedFactors"; label: qsTr("Fixed Factors"); allowedColumns: ["ordinal", "nominal"] }\n   }\n \n   VariablesForm\n   {\n     height: 200\n-    AvailableVariablesList\n-    { \n-      name: "postHocTestsAvailable"\n-      source: "fixedFactors"\n-    }\n+    AvailableVariablesList { name: "postHocTestsAvailable"; source: "fixedFactors" }\n+    AssignedVariablesList {  name: "postHocTestsVariables" }\n   }\n   ```\n   ![Image example](/Docs/development/img/qml-guide/availableVariablesList_example_1_1.png)\n@@ -322,8 +353,8 @@ Properties\n - `singleVariable`: [optional, default: `false`] boolean specifying if this field will accept a maximum of one variable\n - `listViewType`: [optional] string that specifies the type of `AssignedVariablesList`, when omitted we get a normal list,  options are `"Layers"` (see Contingency Tables), `"Pairs"` (see Paired Samples T-Test), `"Interaction"` (see ANOVA) and `"RepeatedMeasures"` (see Repeated Measures ANOVA)\n - `ExtraControlColumn`: [optional] addititional general input component (e.g., `"CheckBox"`) which is added to each variable and can be used to add extra control (e.g., you can specify the status of the variable within a linear model, see example below)\n-- `width`: [optional, default: ±`230`] in pixels how wide should the field be\n-- `height`: [optional, default: `350`] in pixels how heigh should the field be\n+- `width`: [optional, default: 2/5 of the VariablesForm width] in pixels how wide should the field be\n+- `height`: [optional] in pixels how heigh should the field be. Per default, it is set so that all AssignedVariablesList\'s fit the VariablesForm. If you set the height for 1 AssignedVariablesList, it will try to set height of the other AssignedVariablesLists\'s so that they all fit the heigth of the VariablesForm.\n \n <details>\n \t<summary>Examples</summary>\n@@ -331,13 +362,15 @@ Properties\n   ```qml\n \tVariablesForm\n \t{\n-    AssignedVariablesList\n-    {\n-      name: "dependent"\n-      label: qsTr("Dependent Variable")\n-      allowedColumns: ["scale"]\n-      singleVariable: true\n-    }\n+\t\tAvailableVariablesList { name: "allVariables" }\n+\t\tAssignedVariablesList\n+\t\t{\n+\t\t\tname: "dependent"\n+\t\t\tlabel: qsTr("Dependent Variable")\n+\t\t\tallowedColumns: ["scale"]\n+\t\t\tsingleVariable: true\n+\t\t}\n+\t}\n   }\n   ```\n   ![Image example](/Docs/development/img/qml-guide/AssignedVariablesList_example_1.png)\n@@ -345,6 +378,7 @@ Properties\n   ```qml\n   VariablesForm\n   {\n+    AvailableVariablesList { name: "allVariables" }\n     AssignedVariablesList\n     {\n       name: "modelTerms"\n@@ -406,7 +440,7 @@ In order to add more structure to the input panel you can group components toget\n #### Group\n Properties\n - `title`: text shown above the grouped input components\n-- `columns`: [optional, default: `1`] integer specifying how many columns the grouped components should spread out over\n+- `columns`: [optional, default: `1`] integer specifying how many columns the grouped components should occupy\n \n <details>\n \t<summary>Examples</summary>\n@@ -435,7 +469,7 @@ Properties\n #### ExpanderButton\n Properties\n - `title`: text shown in the button that controls the collapse of an entire section\n-- `columns`: [optional, default: `2`] integer specifying how many columns the grouped components should spread out over\n+- `columns`: [optional, default: `2`] integer specifying how many columns the grouped components should occupy\n \n <details>\n \t<summary>Examples</summary>\n@@ -525,22 +559,22 @@ To accomplish this we can set `Layout.columnSpan: 2` on RadioButtonGroup A. This\n \n \n ## Connecting Multiple Components\n-In `AvailableVariablesList` we showed that through its `source` property, we can establish a link between two components. There are other ways of connecting components and they are not limited to a `VariableList` (although they are a little different, only a `VariableList` uses the `name` property). QML allows us to do this is by adding an `id` to one component and then referencing this `id` in a different component. Note that the `id` can be any string, but it must be unique.\n+In `AvailableVariablesList` we showed that through its `source` property, we can establish a link between two components. There are other ways of connecting components and they are not limited to a `VariableList` (although they are a little different, only a `VariableList` uses the `name` property). QML allows us to do this is by adding an `id` to one component and then referencing this `id` in a different component. Note that the `id` can be any string starting with a lowercase, but it must be unique.\n \n An example is enabling a checkbox if one of two different checkboxes is checked.\n <p><details>\n \t<summary>Implementation</summary>\n \t\n   ```qml\n-  CheckBox { name: "checkboxA"; label: qsTr("Some label"), id: "A"}\n-  CheckBox { name: "checkboxB"; label: qsTr("Some label"), id: "B"}\n+  CheckBox { name: "checkboxA"; label: qsTr("Some label"), id: checkA}\n+  CheckBox { name: "checkboxB"; label: qsTr("Some label"), id: checkB}\n \n-  CheckBox { name: "checkboxC";\tlabel: qsTr("Some Label too"); enabled: A.checked || B.checked }\n+  CheckBox { name: "checkboxC";\tlabel: qsTr("Some Label too"); enabled: checkA.checked || checkB.checked }\n   ```\n   \n </details></p>\n \n-Here we make use of a JavaScript expression to evaluate if either CheckBox A or CheckBox B has been checked and if this is the case we enable CheckBox C. It may be a bit confusing that we didn\'t cover `enabled` as a property of a `CheckBox`, this is simply one of the many properties that QML adds without our help.\n+Here we make use of a JavaScript expression to evaluate if either CheckBox A or CheckBox B has been checked and if this is the case we enable CheckBox C. This JavaScript expression will be automatically updated each time that the checked values of checkA and checkB changes. \n \n Another example would be setting the visibility of some textfield to invisible if a checkbox is not checked.\n \n@@ -552,28 +586,43 @@ Another example would be setting the visibility of some textfield to invisible i\n   {\n     name: "checkboxA"\n     label: qsTr("Some label")\n-    id: "A"\n-    TextField { name: "textfieldA"; afterlabel: qsTr("x"); visible: A.checked}\n+    id: checkA\n+    TextField { name: "textfieldA"; afterlabel: qsTr("x"); visible: checkA.checked}\n   \n   }\n   ```\n   \n </details>\n \n+Any property can be set with an expression. A title of an ExpanderButton for example:\n+<details>\n+\t<summary>Implementation</summary>\n+\t\n+  ```qml\n+  \n+\tDropDown\n+\t{\n+\t\tid: estimator\n+\t\tname: "estimator"\n+\t\tlabel: qsTr("Estimator")\n+\t\tvalues: ["EBICglasso", "cor", "pcor", "IsingFit", "IsingSampler", "huge", "adalasso", "mgm"]\n+\t}\n+\t\n+\tExpanderButton \n+\t{\n+\t\ttitle: qsTr("Analysis Options - ") + estimator.currentText\n+                ....\n+\t}\n+\n+  ```\n+  \n+</details>\n+\t\n \n ## An Example\n We\'ll create a simple analysis input panel to show the workflow.\n+Read first the Guide to adding a module in JASP. In this way, when you edit your QML file, the changes made will be automatically seen in JASP. You can play with the components and their properties, and see immediately the output in JASP.\n \n-### 1. Setting up the QML Watcher\n-It is, of course, much easier to create a working product when you can test it along the way. This was made easy when the QML watcher was introduced to JASP. To use it:\n-1. Open JASP\n-2. Click on the menu in the top left corner\n-3. Navigate to \'Preferences\'\n-4. Navigate to \'Advanced\'\n-5. Place a checkmark before \'Developer mode\'\n-6. Enter the path where the QML file you want to make can be found\n-\n-Now every time you save a change in your QML file it will immediately be reflected in the input panel of your analysis.\n \n ### 2. Specifying Imports\n We can begin actual work on the QML file, first we have to tell the engine where to find our resources. To do so, we add a number of imports to the top of our file.\n', 'addition_count': 104, 'deletion_count': 55, 'src_file': 'a/Docs/development/jasp-qml-guide.md', 'tgt_file': 'b/Docs/development/jasp-qml-guide.md', 'file_extension': '.md', 'before_file': 'Guide to writing an analysis interface in QML\n=============================================\n\nQML (Qt Modeling Language) is a user interface markup language that JASP uses to show the analysis input panel. In this panel the user can specify what options should be set to what values and thereby change the tables and plots that the analysis computes. QML is a very flexible language that allows us to easily generate checkboxes, dropdowns and other common interface components.  \nTo create a more uniform layout and make it easier to add new analyses we have provided a number of standardized components. These components should satisfy most analyses, and are explained in this document.  \nOne important pardigm in QML is containment: the implementation of a component is hidden, only public properties (specified by the component self) can be used to manipulate the component.  \nQML uses JavaScript expressions to set values of these properties. Another important paradigm in QML is property binding: this means that when you set a property of a component with a JavaScript expression that uses values of other elements, whenever the values of those elements change, the property value will change automatically:\n  ```qml\n    + [CheckBox](#checkbox)\n    + [RadioButton](#radiobutton)\n    + [DropDown](#dropdown)\n    + [DoubleField](#doublefield)\n    + [IntegerField](#integerfield)\n    + [PercentField](#percentfield)\n    + [TextField](#textfield)\n  * [Variable Specification](#variable-specification)\n    + [availableVariablesList](#availablevariableslist)\n    + [AssignedVariablesList](#assignedvariableslist)\n    + [RepeatedMeasuresFactorsList](#repeatedmeasuresfactorslist)\n  * [Grouping](#grouping)\n      - [DropDown](#dropdown)\n      - [Slider](#slider)\n      - [DoubleField](#doublefield)\n      - [IntegerField](#integerfield)\n      - [PercentField](#percentfield)\n      - [CIField](#cifield)\n      - [TextField](#textfield)\n      - [FormulaField](#formulafield)\n      - [TextArea](#textarea)\n    - [Variable Specification](#variable-specification)\n      - [AvailableVariablesList](#availablevariableslist)\n\n\n## Components\nThe components can roughly be divided in three classes. One that deals with general inputs (e.g., checkboxes), one that deals with assigning variables and one that groups components together. Each will be covered in the following section. Note that in several examples you may encounter `qsTr()`, it is important that this function wraps all text that will be shown in the interface. It will provide the possibility to translate JASP in the future. Additionally, note that the components described below may generally be nested to an arbitrary level (e.g., a checkbox in a checkbox in a checkbox).\n\n### General Input\nThese components are quite common in questionnaires and input forms on websites, they include the checkbox, radiobutton, dropdown and fields where text may be entered.\n\n#### CheckBox\nProperties\n- `name`: string identifier (in your R code you will be able to retrieve the value of the checkbox through this identifier)\n- `label`: text that will be shown to the left of the checkbox\n- `checked`: [optional, default: `false`] boolean specifying if it should contain a checkmark (often a binding that when evaluated gives a boolean, see the section on [Connecting Multiple Components](#connecting-multiple-components))\n- `childrenOnSameRow`: [optional, default: `false`] boolean specifying if components (e.g., other checkboxes, textfields) nested within the checkbox should be shown on the same row or, alternatively, below the checkbox\n- `columns`: [optional, default: `1`] integer specifying how many columns the nested components should spread out over (e.g., when set to 3, with three nested checkboxes, these three checkboxes will appear side by side on the same horizontal row)\n\n<details>\n\t<summary>Examples</summary>\nSome remarks about these components:\n- They are all QML items, so they automatically get generic QML properties like `enabled` or `visible`.\n- In several examples you may encounter `qsTr()`, it is important that this function wraps all text that will be shown in the interface. It will provide the possibility to translate JASP in the future.\n- The components described below may generally be nested to an arbitrary level (e.g., a checkbox in a group in a checkbox).\n\nAll (well almost all) of these components have a property `name` that is also used in JASP-files to store the value the user selected. That means that whenever you change `name` for a component for a newer version of your analysis/module the stored value will be ignored. To make sure the user entered information isn\'t lost you can add an [Upgrades.qml to your module](jasp-upgrade-qml.md).\n\n### General Input\nThese components are quite common in questionnaires and input forms on websites, they include the checkbox, radiobutton, dropdown, slider and textfields where text may be entered.\n\n#### CheckBox\nCheck button that can be toggled on and off. If some components are nested inside a CheckBox, they are automatically enabled or disabled when the CheckBox is set or not.\nProperties\n- `name`: string identifier (in your R code you will be able to retrieve the value of the checkbox through this identifier)\n- `label`: text that will be shown to the left of the checkbox\n- `checked`: [optional, default: `false`] boolean specifying if it should be set per default on or not.\n- `childrenOnSameRow`: [optional, default: `false`] boolean specifying if components (e.g., other checkboxes, textfields) nested within the checkbox should be shown on the same row or, alternatively, below the checkbox\n- `columns`: [optional, default: `1`] integer specifying how many columns the nested components should occupy (e.g., when set to 3, with three nested checkboxes, these three checkboxes will appear side by side on the same horizontal row)\n\n</details>\n\n#### RadioButton\nA single radiobutton is not very useful, and so they must be grouped together. We can do this by putting multiple `RadioButton`s together in a `RadioButtonGroup`.\n\nProperties\n- `name`: string identifier (in your R code you will be able to retrieve the value of the checked radiobutton through this identifier)\n- `title`: text that is shown above the set of radiobuttons\n- `RadioButton`: \n  * `value`: the value of the `RadioButtonGroup` that is send to R when this radiobutton is checked\n  * `label`: the text that is shown to the right of the radiobutton\n  * `checked`: [optional, default: `false`] boolean specifying if it should contain a checkmark (and thus be the default); one radiobutton should have this property set to `true`\n  * `childrenOnSameRow`: [optional, default: `false`] boolean specifying if components (e.g., checkboxes, textfields) nested within the radiobutton should be shown on the same row or, alternatively, below the radiobutton\n  * `columns`: [optional, default: `1`] integer specifying how many columns the nested components should spread out over (e.g., when set to 3, with three nested checkboxes, these three checkboxes will appear side by side on the same horizontal row)\n\n<details>\n\t<summary>Examples</summary>\n\n</details>\n\n#### RadioButton\nA RadioButton is used with other RadioButton\'s inside a `RadioButtonGroup`. Contrary to CheckBox, only 1 RadioButton can be checked at the same time.\n\nRadioButtonGroup properties:\n- `name`: string identifier (in your R code you will be able to retrieve the value of the checked radiobutton through this identifier)\n- `title`: text that is shown above the set of radiobuttons\n- `radioButtonsOnSameRow`: [optional, default: `false`] per default, the RadioButton\'s are placed vertically under the title. Set this property to true to place the buttons horizontally.\n- `columns`: [optional, default: `1`] integer specifying how many columns should be used to display the RadioButton\'s\n\nRadioButton properties:\n- `value`: the value of the `RadioButtonGroup` that is send to R when this radiobutton is checked\n- `label`: the text that is shown to the right of the radiobutton\n- `checked`: [optional, default: `false`] boolean specifying if it should contain a checkmark (and thus be the default); one radiobutton should have this property set to `true`\n- `childrenOnSameRow`: [optional, default: `false`] boolean specifying if components (e.g., checkboxes, textfields) nested within the radiobutton should be shown on the same row or, alternatively, below the radiobutton\n- `columns`: [optional, default: `1`] integer specifying how many columns the nested components should occupy (e.g., when set to 3, with three nested checkboxes, these three checkboxes will appear side by side on the same horizontal row)\n\n<details>\n\t<summary>Examples</summary>\n\n  ```qml\n  RadioButtonGroup\n  {\n    name: "countProp"\n    title: qsTr("Display")\n    RadioButton { value: "descCounts"; label: qsTr("Counts"); checked: true }\n    RadioButton { value: "descProps"; label: qsTr("Proportions") }\n  }\n  ```\n  ![Image example](/Docs/development/img/qml-guide/RadioButton_example_1.png)\n\n  ```qml\n  RadioButtonGroup\n  {\n    name: "steppingMethodCriteriaType"\n    title: qsTr("Stepping Method Criteria")\n    RadioButton\n    {\n- `label`: [optional, default: `""`] text that will be shown above the dropdown\n- `values`: array of (named) values that is shown in the dropdown list, in the case of an unnamed array the value and the label are the same, but when a named array is provided the label shown to the user can be different from the value send to R (see example below)\n- `indexDefaultValue`: [optional, default: `1`] integer specifying the index of the dropdown item that is selected by default, take note that this is zero-based\n\n<details>\n\t<summary>Examples</summary>\n      value: "useFValue"; label: qsTr("Use F value")\n      columns: 2\n      DoubleField { name: "steppingMethodCriteriaFEntry";\t\tlabel: qsTr("Entry");\tfieldWidth: 60; defaultValue: 3.84; decimals: 3 }\n      DoubleField { name: "steppingMethodCriteriaFRemoval";\tlabel: qsTr("Removal");\tfieldWidth: 60; defaultValue: 2.71; decimals: 3 }\n    }\n  }\n  ```\n  ![Image example](/Docs/development/img/qml-guide/RadioButton_example_2.png)\n\n</details>\n\n#### DropDown\nProperties\n- `name`: string identifier (in your R code you will be able to retrieve the value of the dropdown through this identifier)\n- `label`: [optional, default: `""`] text that will be shown above the dropdown\n- `values`: [optional, default: empty] array of (named) values that is shown in the dropdown list, in the case of an unnamed array the value and the label are the same, but when a named array is provided the label shown to the user can be different from the value send to R (see example below)\n- `startValue`: [optional, default: ``] string specifying the value of the dropdown item that is selected by default\n- `currentIndex`, `currentValue`, `currentLabel`: [optional] gives the current index, value or label of the selected item. Can be used to set the current item.\n- `currentColumnType`: [read-only] if the values of the dropdown are variables of the dataset, then this property gives the type of this variable, i.e. `scale`, `nominal`, `nominalText`, `ordinal`.\n- `source`: [optional, default: empty] if `values` is empty, you can use the name of a VariablesList or other kind of source (see [Variable Specification](#variable-specification)) to set the values of the DropDown. If `values` and `source` is empty, then all available columns of the dataset are used.\n- `addEmptyValue`: [optional, default: `false`] if `true`, add an empty value with a place holder (see `placeHolderText`) as first element of the dropdown list\n- `placeHolderText`: [optional, default: `<no choice>`] name used if an ampty value is added in the dropdown list\n- `addScrollBar`: [optional, default: `false`] add a scrollbar when the list is displayed.\n\n<details>\n  \n</details>\n\n#### DoubleField\nProperties\n- `name`: string identifier (in your R code you will be able to retrieve the value of the field through this identifier)\n- `name`: string identifier (in your R code you will be able to retrieve the value of the slider through this identifier)\n- `label`: [optional, default: `""`] text that will be shown above the slider\n- `value`: [optional, default: `0.5`] default value\n- `min`: [optional, default: `0`] minimum value\n- `max`: [optional, default: `1`] maximum value\n- `vertical`: [optional, default: `true`] set whether the slider should be displayed vertically or horizontally\n- `decimals`: [optional, default: `2`] set the number of decimals the value gets\n\n\n<details>\n\t<summary>Examples</summary>\n\n  ```qml\n  Slider\n  {\n    name: "highlight"\n    label: qsTr("Highlight")\n    value: 0.4\n  }\n  ```\n  ![Image example](/Docs/development/img/qml-guide/Slider_example_1.png)\n\n</details>\n\n\n#### DoubleField\nProperties\n- `name`: string identifier (in your R code you will be able to retrieve the value of the field through this identifier)\n- `label`: [optional, default: `""`] text that will be shown to the left of the field\n- `afterLabel`: [optional, default: `""`] text that will be shown to the right of the field\n- `defaultValue`: [optional, default: `0`] numeric specifying the default value shown; can be an integer or a decimal value, just be sure to use a dot and not a comma\n- `negativeValues`: [optional, default: `false`] specifies if the user should be able to input negative values (works only when the `min` argument is omitted)\n- `min`: [optional, default: `0` if negativeValues is `false`, otherwise `-Infinity`] numeric specifying the minimum value a user can enter\n- `max`: [optional, default: `Infinity`] numeric specifying the maximum value a user can enter\n- `inclusive`: [optional, default: `JASP.MinMax`, possible values: `JASP.MinMax`, `JASP.MinOnly`, `JASP.MaxOnly`, `JASP.None`] specify whether the `min` and `max` parameters are inclusive or not. For example if `min` is `1` and `inclusive` is `JASP.MinMax` or `JASP.MinOnly` then value `1` is allowed.\n- `decimals`: [optional, default: `3`] integer specifying how many decimals the user can enter\n- `fieldWidth`: [optional, default: `40`] in pixels how wide should the field be\n\n\n<details>\n\t<summary>Examples</summary>\n\n  ```qml\n  DoubleField\n  {\n    name: "eigenValuesBox"\n    label: qsTr("Eigenvalues above")\n    defaultValue: 1\n    decimals: 1\n  }\n  ```\n  ![Image example](/Docs/development/img/qml-guide/DoubleField_example_1.png)\n\n  ```qml\n  DoubleField\n  {\n    name: "priorFixedEffects"\n    label: qsTr("r scale fixed effects")\n    defaultValue: 0.5\n    fieldWidth: 50\n    max: 2\n    decimals: 1\n  }\n  ```\n  ![Image example](/Docs/development/img/qml-guide/DoubleField_example_2.png)\n\n</details>\n\n#### IntegerField\nProperties\n- `name`: string identifier (in your R code you will be able to retrieve the value of the field through this identifier)\n- `label`: [optional, default: `""`] text that will be shown to the left of the field\n- `afterLabel`: [optional, default: `""`] text that will be shown to the right of the field\n- `defaultValue`: [optional, default: `0`] integer specifying the default value shown\n- `negativeValues`: [optional, default: `false`] specifies if the user should be able to input negative values (works only when the `min` argument is omitted)\n- `min`: [optional, default: `0` if negativeValues is `false`, otherwise `-Infinity`] integer specifying the minimum value a user can enter\n- `max`: [optional, default: `Infinity`] integer specifying the maximum value a user can enter\n- `inclusive`: [optional, default: `yes`, possible values: `yes`, `minOnly`, `maxOnly`, `no`] specify whether the `min` and `max` parameters are inclusive or not. For example if `min` is `1` and `inclusive` is `yes` or `minOnly` then value `1` is allowed.\n- `fieldWidth`: [optional, default: `40`] in pixels how wide should the field be\n- `label`: text that will be shown to the left of the field\n- `defaultValue`: [optional, default: `50`] integer specifying the default percentage shown\n- `fieldWidth`: [optional, default: `40`] in pixels how wide should the field be\n\n<details>\n\t<summary>Examples</summary>\n    name: "fixedSamplesNumber"\n    label: qsTr("No. samples")\n    defaultValue: 10000\n    fieldWidth: 60\n  }\n  ```\n  ![Image example](/Docs/development/img/qml-guide/IntegerField_example_1.png)\n\n  ```qml\n  IntegerField\n- `name`: string identifier (in your R code you will be able to retrieve the value of the field through this identifier)\n- `label`: [optional, default: `""`] text that will be shown to the left of the field\n- `afterLabel`: [optional, default: `""`] text that will be shown to the right of the field\n- `defaultValue`: [optional, default: `""`] default text before the user enters anything\n- `placeholderText`: [optional, default: `""`] text shown as a placeholder until a user enters something, will not be send to R if left unchanged by the user (mutually exclusive with `defaultValue`)\n- `fieldWidth`: [optional, default: `40`] in pixels how wide should the field be\n\n  ```\n  ![Image example](/Docs/development/img/qml-guide/IntegerField_example_2.png)\n\n</details>\n\n#### PercentField\nProperties\n- `name`: string identifier (in your R code you will be able to retrieve the value of the field through this identifier)\n- `label`: text that will be shown to the left of the field\n- `afterLabel`: [optional, default `%`] text that will be shown to the right of the field\n- `defaultValue`: [optional, default: `50`] integer specifying the default percentage shown\n- `fieldWidth`: [optional, default: `40`] in pixels how wide should the field be\n- `decimals`: [optional, default: `0`] integer specifying how many decimals the user can enter\n\n<details>\n\t<summary>Examples</summary>\n- `name`: identifier of the variables list, this is never send to R\n- `label`: [optional, default: `""`] text that will be shown above the variable field\n- `source`: [optional] can be set to the `name` of an `AssignedVariablesList`, when omitted variables are taken from the dataset (example usage: you have a second `availableVariablesList` for plotting the variables that are assigned to an `AssignedVariablesList`; see also the example)\n- `width`: [optional, default: ±`230`] in pixels how wide should the field be\n\nNote: `height` should be defined on `VariablesForm` itself.\n\n\n#### CIField\n  \n  ```qml\n  VariablesForm\n\t{\n    AssignedVariablesList\n    {\n      name: "fixedFactors"\n      label: qsTr("Fixed Factors")\n      allowedColumns: ["ordinal", "nominal"]\n    }\n  }\n\n  VariablesForm\n  {\n    height: 200\n    AvailableVariablesList\n    { \n      name: "postHocTestsAvailable"\n      source: "fixedFactors"\n    }\n  }\n  ```\n  ![Image example](/Docs/development/img/qml-guide/availableVariablesList_example_1_1.png)\n- `placeholderText`: [optional, default: `""`] text shown as a placeholder until a user enters something, will not be send to R if left unchanged by the user (mutually exclusive with `defaultValue`)\n- `fieldWidth`: [optional, default: `40`] in pixels how wide should the field be\n\n<details>\n\t<summary>Examples</summary>\n\n  ```qml\n  TextField { name: "labelYAxis"; label: qsTr("Label y-axis"); fieldWidth: 200 }\n  ```\n- `singleVariable`: [optional, default: `false`] boolean specifying if this field will accept a maximum of one variable\n- `listViewType`: [optional] string that specifies the type of `AssignedVariablesList`, when omitted we get a normal list,  options are `"Layers"` (see Contingency Tables), `"Pairs"` (see Paired Samples T-Test), `"Interaction"` (see ANOVA) and `"RepeatedMeasures"` (see Repeated Measures ANOVA)\n- `ExtraControlColumn`: [optional] addititional general input component (e.g., `"CheckBox"`) which is added to each variable and can be used to add extra control (e.g., you can specify the status of the variable within a linear model, see example below)\n- `width`: [optional, default: ±`230`] in pixels how wide should the field be\n- `height`: [optional, default: `350`] in pixels how heigh should the field be\n\n<details>\n\t<summary>Examples</summary>\n- `min`: [optional, default `-Infinity`] minimum value that the result of the formula can give.\n  ```qml\n\tVariablesForm\n\t{\n    AssignedVariablesList\n    {\n      name: "dependent"\n      label: qsTr("Dependent Variable")\n      allowedColumns: ["scale"]\n      singleVariable: true\n    }\n  }\n  ```\n  ![Image example](/Docs/development/img/qml-guide/AssignedVariablesList_example_1.png)\n- `separator`, `separators`: [optional, default: `"\\n"`] string or array of strings used to split the string of a `source` TextArea\n  ```qml\n  VariablesForm\n  {\n    AssignedVariablesList\n    {\n      name: "modelTerms"\n- `name`: identifier of the variables list, this is never send to R\n- `label`: [optional, default: `""`] text that will be shown above the variable field\n- `source`: [optional, default: `""`] this can be set to the `id` or the `name` (or a list of id or names) of one or more Variables Lists. If no source is specified, then all variables of the data file are used as source. To specify several sources, you need to use an array: `["source1", "source2"]`. If you want to specify what you want to read from the source, you can add extra attributes:<br>\n  * `use` attribute: if you want to read the levels of a `singleVariable` Variables List source, type: `source: [{name: "splitby", use: "levels"}]`. If you want only some variables with some types, type: `[{name: "source", use: "type=nominal|ordinal"}]`\n  * `discard` attribute: if you want to discard some of the values of the source, set the discard attribute to another source or values. For example `source: [{ name: "modelTerms", discard: "covariates" }]`\n  * `condition` attribute: if a Variables List source has some components, and you want to retrieve the variables whose components have some specific values, type: `[ { name: "contrasts", condition: "contrast.currentValue == \'custom\'" } ]` where `contrast` is the name of a DropDown component (added in the `contrasts` Variables List). In this example only variables with contrast having `custom` as value will be read from the source `contrasts`.\n  * `values` attribute: if you want to add specific values to the list, you can add them in this way `source: [ { values: ["one", "two"] }, "myvariables" ]`. Here the values `one` and `two` are prepend to the names of the variables of the Variables List `myvariables`. If you want to display a label (that can be translated) different from the value used in the analysis, use: `source: [ { values: [ { label: qsTr("One"), value: "one" }, { label: qsTr("Two"), value: "two" } ], "myvariables" ]` (qsTr is the function you need to use if you want the string to be translatable).\n  * `rSource`: name of a R source. This source should be generated in R with the jaspQmlSource function.\n  * `combineTerms` attribute: if you want to combine the variables of the source, you can set this attribute. Per default this is JASP.NoCombination, but it can be set to JASP.CombinationCross (all combinations), JASP.CombinationInteraction (gives only one term with all variables of the source, eg. var1 * var2 * var3), Combination2Way (all combinations of 2 variables), Combination3Way (all combinations of 3 variables), Combination4Way (all combinations of 4 variables), Combination5Way (all combinations of 5 variables)\n  * if you want to display not the variable names of the source, but the values of some component of this list, use the syntax `name.component`. For example, if the source `myvariables` has a TextField named `field`, a Variables List with source `source: "myvariables.field"` will display all values of the TextField component in place of the variable names.<br>\n\n- `values`: [optional, default: `""`] this is a shortcut: in place of writing `source: [ values: ["one", "two"] ]`, type `values: ["one", "two"]`. If you want to display labels different from the values used by the analysis, use the same syntax as in the `source` property. You can also use an integer n: in this case the values are just [1, 2, ... n]\n- `rSource`: [optional, default: `""`] this is a shortcut: in place of writing `source: [ { rSource: "myRSource" } ]`, type `rSource: "myRSource"]`.\n- `width`: [optional, default: 2/5 of the VariablesForm width] in pixels how wide should the field be\n- `count`: [read-only integer] Gives the number of rows of the list.\n\nNote: `height` should be defined on `VariablesForm` itself.\n\n<details>\n\t<summary>Examples</summary>\n\n  ```qml\n  VariablesForm\n  {\n    AvailableVariablesList { name: "allVariables" }\n    AssignedVariablesList  { name: "fixedFactors"; label: qsTr("Fixed Factors"); allowedColumns: ["ordinal", "nominal"] }\n  }\n\n  VariablesForm\n  {\n    height: 200\n    AvailableVariablesList { name: "postHocTestsAvailable"; source: "fixedFactors"; rowComponent: CheckBox { name: "check" } }\n    AssignedVariablesList {  name: "postHocTestsVariables" }\n  }\n\n   VariablesForm\n  {\n    height: 200\n    AvailableVariablesList { name: "checkedPostHocAvailable"; source: [ name: "postHocTestsVariables", condition: "check.checked" ] }\n    AssignedVariablesList { name: "checkedPostHoc" }\n  }\n  ```\n  ![Image example](/Docs/development/img/qml-guide/availableVariablesList_example_1_1.png)\n  ![Image example](/Docs/development/img/qml-guide/availableVariablesList_example_1_2.png)\n\n</details>\n\n#### AssignedVariablesList\nProperties\n- `name`: identifier of the particular variable field (in your R code you will be able to retrieve the assigned variable(s) through this identifier)\n- `label`: [optional, default: `""`] text that will be shown above the variable field\n- `columns`: [optional, default: 1] number of columns of the list.\n- `allowedColumns`: [optional, default: empty, possible values: `["scale", "ordinal", "nominal"]` ] array specifying the allowed column types\n- `suggestedColumns`: [optional, default: empty, possible values: `["scale", "ordinal", "nominal"]` ] array specifying the suggested column types. These types will be displayed as icons at the bottom-right of the AssignedVariablesList. If `suggestedColumns` is empty and `allowedColumns` is specified, then `suggestedColumns` get automatically the value of `allowedColumns`. If `allowedColumns` is empty and `suggestedColumns` is specified, then the following rules apply:\n    * `scale` allows Nominal Integer and Ordinal columns\n#### Group\nProperties\n- `title`: text shown above the grouped input components\n- `columns`: [optional, default: `1`] integer specifying how many columns the grouped components should spread out over\n\n<details>\n\t<summary>Examples</summary>\n- `height`: [optional] in pixels how heigh should the field be. Per default, it is set so that all AssignedVariablesList\'s fit the VariablesForm. If you set the height for 1 AssignedVariablesList, it will try to set height of the other AssignedVariablesLists\'s so that they all fit the heigth of the VariablesForm.\n- `count`: [read-only integer] Gives the number of rows of the list.\n- `rowComponentTitle`: [optional, default \'\']: title for rowComponent. It will be added at the right side above the list.\n- `rowComponent`: It is possible to add one or more components for each assigned variable. To do this, add the `rowComponent` property. If you want to add just one extra component, a CheckBox for example, just add it here: <br>\n    ```qml\n    rowComponent:  CheckBox { name: "enableNumber"; checked: true }\n\t```\n\t\n    If you want several components, then wrap it with a `Row` item, like this:\n\t```qml\n\trowComponent: Row \n    {\n        CheckBox { name: "enableNumber"; checked: true }\n        TextField { name: "myField"; value: rowValue }\n    }\n\t```\n\t![Image example](/Docs/development/img/qml-guide/RowComponents_example.png)\n\n    You can use so-called context properties in the components:\n    * rowIndex: gives the row number in the list\n    * rowValue: gives the name of the variable in the same row\n- `optionKey`: [optional, default: \'variable\' (for Interaction type, default is \'components\'] If there is no rowComponent, the values are just given as an array of strings. But if one or more components are specified, the values are more complex: it is also an array, but each element of the array contains the name of the variable with as key the value of this `optionKey`, and the values of each component with as key the name of the component. \n#### ExpanderButton\nProperties\n- `title`: text shown in the button that controls the collapse of an entire section\n- `columns`: [optional, default: `2`] integer specifying how many columns the grouped components should spread out over\n\n<details>\n\t<summary>Examples</summary>\n                AvailableVariablesList { name: "allVariables" }\n                AssignedVariablesList\n                {\n                        name: "dependent"\n                        label: qsTr("Dependent Variable")\n                        allowedColumns: ["scale"]\n                        singleVariable: true\n                }\n        }\n  }\n  ```\n  ![Image example](/Docs/development/img/qml-guide/AssignedVariablesList_example_1.png)\n\n  ```qml\n  VariablesForm\n  {\n    AvailableVariablesList { name: "allVariables" }\n    AssignedVariablesList\n    {\n      name: "modelTerms"\n      label: qsTr("Model terms")\n      listViewType: JASP.Interaction\n\n      rowComponentTitle: "Add to null model"\n      rowComponent: CheckBox { name: "isNuisance" }\n    }\n  }\n  ```\n  ![Image example](/Docs/development/img/qml-guide/AssignedVariablesList_example_2.png)\n\n</details>\n\n#### FactorLevelList\nWith this component, the user can set names of factors, and for each factor, the names of its levels. This is used in Repeated Measures ANOVA.\nProperties\n- `name`: identifier of the particular variable field (in your R code you will be able to retrieve the assigned variable(s) through this identifier)\n- `label`: [optional, default: `""`] text that will be shown above the variable field\n- `width`: [optional, default: ±`230`] in pixels how wide should the field be\n- `height`: [optional, default: `350`] in pixels how heigh should the field be\n- `factorName`: [optional, default: `Factor`] default name of the factor.\n- `levelName`: [optional, default: `Level`] default name of the level.\n- `minFactors`: [optional, default: `1`] minimum number of factors.\n- `minLevels`: [optional, default: `2`] minimum numbe of levels.\n\n<details>\n\t<summary>Examples</summary>\n\n  ```qml\n  VariablesForm\n  {\n\tFactorLevelList\n    {\n\t  name: "repeatedMeasuresFactors"\n      label: qsTr("Repeated Measures Factors")\n      height: 180\n\t  factorName: qsTr("RM Factor")\n    }\n    AssignedVariablesList\n    {\n      name: "repeatedMeasuresCells"\n      label: qsTr("Repeated Measures Cells")\n      allowedColumns: ["scale"]\n      listViewType: JASP.MeasuresCells\n      source: "repeatedMeasuresFactors"\n      height: 140\n    }\n  }\n  ```\n  ![Image example](/Docs/development/img/qml-guide/RepeatedMeasuresFactorsList_example_1.png)\n\n</details>\n\n### Complex components\nComponentsList, TabView, InputListView and TableView are complex components that allow to view a variable number of input or other components\n\n#### ComponentsList\nThis allows to displays a list of components either from a source or from user input.\n- `name`: identifier of this component (in your R code you will be able to retrieve the text value(s) through this identifier)\n- `title`: [optional, default: `""`] text that will be shown above this component\n- `rowComponent`: as for the Variables List, you can specify all the components that will be repeated for each row.\n- `source`: [optional, default: empty] as for Variables List you can specify any kind of source (see [Variable Specification]). It a source is used, the number of rows will automatically depends on the number of elements of this source. You can then also use the `rowValue` context property if you want to use the value of the source in one of the component.\n- `values`: [optional, default: empty] In place of a source, you can specify direcly a list of values or value/label list as in the DropDown component.\n- `addItemManually`: [optional, default \'false\' if `source` and `values` are empty, else \'true\'] If this is true, then it displays a \'+\' icon so that the user can add new rows, and a \'X\' icon to delete a row.\n\n\n## Connecting Multiple Components\nIn `AvailableVariablesList` we showed that through its `source` property, we can establish a link between two components. There are other ways of connecting components and they are not limited to a `VariableList` (although they are a little different, only a `VariableList` uses the `name` property). QML allows us to do this is by adding an `id` to one component and then referencing this `id` in a different component. Note that the `id` can be any string, but it must be unique.\n\nAn example is enabling a checkbox if one of two different checkboxes is checked.\n<p><details>\n\t<summary>Implementation</summary>\n\t\n  ```qml\n  CheckBox { name: "checkboxA"; label: qsTr("Some label"), id: "A"}\n  CheckBox { name: "checkboxB"; label: qsTr("Some label"), id: "B"}\n\n  CheckBox { name: "checkboxC";\tlabel: qsTr("Some Label too"); enabled: A.checked || B.checked }\n  ```\n  \n</details></p>\n\nHere we make use of a JavaScript expression to evaluate if either CheckBox A or CheckBox B has been checked and if this is the case we enable CheckBox C. It may be a bit confusing that we didn\'t cover `enabled` as a property of a `CheckBox`, this is simply one of the many properties that QML adds without our help.\n\nAnother example would be setting the visibility of some textfield to invisible if a checkbox is not checked.\n\n\n  ```qml\n  InputListView\n  {\n      name                  : "groupNames"\n  {\n    name: "checkboxA"\n    label: qsTr("Some label")\n    id: "A"\n    TextField { name: "textfieldA"; afterlabel: qsTr("x"); visible: A.checked}\n  \n  }\n  ```\n  \n</details>\n\n\n## An Example\nWe\'ll create a simple analysis input panel to show the workflow.\n\n### 1. Setting up the QML Watcher\nIt is, of course, much easier to create a working product when you can test it along the way. This was made easy when the QML watcher was introduced to JASP. To use it:\n1. Open JASP\n2. Click on the menu in the top left corner\n3. Navigate to \'Preferences\'\n4. Navigate to \'Advanced\'\n5. Place a checkmark before \'Developer mode\'\n6. Enter the path where the QML file you want to make can be found\n\nNow every time you save a change in your QML file it will immediately be reflected in the input panel of your analysis.\n\n### 2. Specifying Imports\nWe can begin actual work on the QML file, first we have to tell the engine where to find our resources. To do so, we add a number of imports to the top of our file.\n\n\n### Grouping\nIn order to add more structure to the input panel you can group components together. There are 2 levels of grouping: Section and Group. A Section can hide a group of components under a button. A Group is a smaller logical unit.\n\n#### Group\nProperties\n- `title`: text shown above the grouped input components\n- `columns`: [optional, default: `1`] integer specifying how many columns the grouped components should occupy\n\n<details>\n\t<summary>Examples</summary>\n\n  ```qml\n  Group\n  {\n    title: qsTr("Output")\n    CheckBox\n    {\n      name: "effects"; label: qsTr("Effects")\n      RadioButtonGroup\n      {\n        name: "effectsType"\n        RadioButton { value: "allModels"; label: qsTr("Across all models"); checked: true }\n        RadioButton { value: "matchedModels"; label: qsTr("Across matched models") }\n      }\n    }\n    CheckBox { name: "descriptives"; label: qsTr("Descriptives") }\n  }\n  ```\n  ![Image example](/Docs/development/img/qml-guide/Group_example_1.png)\n\n</details>\n\n#### Section\nA Section sets components (or groups of components) under a button. By clicking the button, you can hide or display these components.\nProperties\n- `title`: text shown in the button that controls the collapse of an entire section\n- `columns`: [optional, default: `2`] integer specifying how many columns the grouped components should occupy\n\n<details>\n\t<summary>Examples</summary>\n\n  ```qml\n  Section\n  {\n    title: qsTr("Advanced Options")\n\n    RadioButtonGroup\n    {\n      title: qsTr("Missing Values")\n      name: "missingValues"\n      RadioButton { value: "excludeCasesListwise"; label: qsTr("Exclude cases listwise"); checked: true }\n      RadioButton { value: "excludeCasesPairwise"; label: qsTr("Exclude cases pairwise") }\n    }\n\n    Group\n    {\n      title: qsTr("Confidence Interval")\n      enabled: chronbach.checked\n      CheckBox\n      {\n        name: "confAlpha"\n        label: qsTr("Cronbach\'s α analytical")\n        PercentField { name: "confAlphaLevel"; label: qsTr("Confidence"); defaultValue: 95 }\n      }\n    }\n  }\n  ```\n  ![Image example](/Docs/development/img/qml-guide/ExpanderButton_example_1.png)\n\n</details>\n\n\n## Layout of Components\nBy default JASP creates a two column grid that is filled row-wise. So each component you place in your QML file will be added to the input panel left to right, top to bottom. We will demonstrate what this means by the use of a table.\n\nImagine a simple table with two columns and two rows. We have three components (CheckBox A, B and C) and each must go in their own cell. When these components are added row-wise we get A in the top left cell, then next to it B and on its own row C:\n\n|         | <column 1> | <column 2> |\n|---------|------------|------------|\n| <row 1> | CheckBox A | CheckBox B |\n| <row 2> | CheckBox C |            |\n\n#### Layout.rowSpan\nThe above works great, but it definitely helps that the checkboxes are the same size. We could also add a RadioButtonGroup that is much taller than a simple checkbox. If we again imagine three components (but this time CheckBox A and B and RadioButtonGroup A) that go in the table in the same way:\n\n|         | <column 1> | <column 2>         |\n|---------|------------|--------------------|\n| <row 1> | CheckBox A | RadioButtonGroup A |\n|         |            | RadioButtonGroup A |\n| <row 2> | CheckBox B |                    |\n\nWe notice that there is a lot of space between CheckBox A and CheckBox B. The reason for this is that CheckBox B is placed in the next available row. Fortunately we can remedy this with the property `Layout.rowSpan`; all we need to do is set `Layout.rowSpan: 2` in RadioButtonGroup A. This tells the engine that the component spans two rows and therefore CheckBox B will fit snuggly under CheckBox A:\n\n|         | <column 1> | <column 2>         |\n|---------|------------|--------------------|\n| <row 1> | CheckBox A | RadioButtonGroup A |\n| <row 2> | CheckBox B | RadioButtonGroup A |\n\n\n#### Layout.columnSpan\nNow imagine we really wanted to put the RadioButtonGroup in the top left cell and the two checkboxes below it on the same height as one another:\n\n|         | <column 1>         | <column 2> |\n|---------|--------------------|------------|\n| <row 1> | RadioButtonGroup A |            |\n|         | RadioButtonGroup A |            |\n| <row 2> | CheckBox A         | CheckBox B |\n\nHowever, if we simply added the components we would end up with this situation:\n\n|         | <column 1>         | <column 2> |\n|---------|--------------------|------------|\n| <row 1> | RadioButtonGroup A | CheckBox A |\n|         | RadioButtonGroup A |            |\n| <row 2> | CheckBox B         |            |\n\nTo accomplish this we can set `Layout.columnSpan: 2` on RadioButtonGroup A. This results in the following situation:\n\n|         | <column 1>         | <column 2>         |\n|---------|--------------------|--------------------|\n| <row 1> | RadioButtonGroup A | RadioButtonGroup A |\n|         | RadioButtonGroup A | RadioButtonGroup A |\n| <row 2> | CheckBox A         | CheckBox B         |\n\n\n## Connecting Multiple Components\nIn `AvailableVariablesList` we showed that through its `source` property, we can establish a link between two components. There are other ways of connecting components and they are not limited to a `VariableList` (although they are a little different, only a `VariableList` uses the `name` property). QML allows us to do this is by adding an `id` to one component and then referencing this `id` in a different component. Note that the `id` can be any string starting with a lowercase, but it must be unique.\n\nAn example is enabling a checkbox if one of two different checkboxes is checked.\n<p><details>\n\t<summary>Implementation</summary>\n\n  ```qml\n  CheckBox { name: "checkboxA"; label: qsTr("Some label"), id: checkA}\n  CheckBox { name: "checkboxB"; label: qsTr("Some label"), id: checkB}\n\n  CheckBox { name: "checkboxC";\tlabel: qsTr("Some Label too"); enabled: checkA.checked || checkB.checked }\n  ```\n\n</details></p>\n\nHere we make use of a JavaScript expression to evaluate if either CheckBox A or CheckBox B has been checked and if this is the case we enable CheckBox C. This JavaScript expression will be automatically updated each time that the checked values of checkA and checkB changes.\n\nAnother example would be setting the visibility of some textfield to invisible if a checkbox is not checked.\n\n<details>\n\t<summary>Implementation</summary>\n\n  ```qml\n  CheckBox\n  {\n    name: "checkboxA"\n    label: qsTr("Some label")\n    id: checkA\n    TextField { name: "textfieldA"; afterlabel: qsTr("x"); visible: checkA.checked}\n\n  }\n  ```\n\n</details>\n\nAny property can be set with an expression. A title of a Section for example:\n<details>\n\t<summary>Implementation</summary>\n\n  ```qml\n\n        DropDown\n        {\n                id: estimator\n                name: "estimator"\n                label: qsTr("Estimator")\n                values: ["EBICglasso", "cor", "pcor", "IsingFit", "IsingSampler", "huge", "adalasso", "mgm"]\n        }\n\n        Section\n        {\n                title: qsTr("Analysis Options - ") + estimator.currentText\n                ....\n        }\n\n  ```\n\n</details>\n\n\n## An Example\nWe\'ll create a simple analysis input panel to show the workflow.\nRead first the Guide to adding a module in JASP. In this way, when you edit your QML file, the changes made will be automatically seen in JASP. You can play with the components and their properties, and see immediately the output in JASP.\n\n\n### 1. Specifying Imports\nWe can begin actual work on the QML file, first we have to tell the engine where to find our resources. To do so, we add a number of imports to the top of our file.\n\n<details>\n\t<summary>Code</summary>\n\n  ```qml\n  import QtQuick 2.11\n  import QtQuick.Layouts 1.3\n  import JASP.Controls 1.0\n  import JASP.Widgets 1.0\n  ```\n\n  If you want to import QML components from another jasp module, you can! \n  Have a look at [custom imports](#custom-imports).\n\n</details>\n\nIn the future, we will require using qualified namespace for the import statements for the JASP QML modules [see here](https://doc.qt.io/qt-5/qtqml-syntax-imports.html#importing-into-a-qualified-local-namespace).\n\n<details>\n\t<summary>Code</summary>\n\n  ```qml\n  import QtQuick          2.11\n  import QtQuick.Layouts  1.3\n  import JASP.Controls    1.0 as JC\n  import JASP.Theme\t      1.0 as JT\n  import JASP.Widgets     1.0 as JW\n  ```\n</details>\n\nThis means that a JASP control, theme or a widget needs to be prepended with the qualifier, e.g., `JC.CheckBox` instead of just `CheckBox`.\n\n### 2. Adding the Form\nAt this point we add a `Form` which will hold all our input components:\n\n<details>\n\t<summary>Code</summary>\n\n  ```qml\n  import QtQuick 2.11\n  import QtQuick.Layouts 1.3\n  import JASP.Controls 1.0\n  import JASP.Widgets 1.0\n\n  Form\n  {\n\n  }\n  ```\n\n</details>\n\n### 3. Adding the Components\nIt\'s now a matter of mixing and matching the previously shown components to create a form to our liking. Of course, if something isn\'t quite possible, you can also use QML features that were not covered here.\n\n<details>\n\t<summary>Code</summary>\n\n  ```qml\n  import QtQuick 2.11\n  import QtQuick.Layouts 1.3\n  import JASP.Controls 1.0\n  import JASP.Widgets 1.0\n\n  Form\n  {\n    VariablesForm\n    {\n      AssignedVariablesList { name: "variables"; allowedColumns: ["ordinal", "nominal"] }\n    }\n\n    RadioButtonGroup\n    {\n      Layout.rowSpan: 2\n      name: "hypothesis"\n      title: qsTr("Hypothesis")\n      RadioButton { value: "notEqualToTestValue"; label: qsTr("≠ Test value"); checked: true }\n      RadioButton { value: "greaterThanTestValue"; label: qsTr("> Test value") }\n      RadioButton { value: "lessThanTestValue"; label: qsTr("< Test value") }\n    }\n\n    DoubleField { name: "testValue"; label: qsTr("Test value: "); defaultValue: 0.5 ; max: 1; decimals: 2}\n\n    Group\n    {\n      title: qsTr("Plots")\n      CheckBox\n      {\n        name: "descriptivesPlots"\n        label: qsTr("Descriptive plots")\n        PercentField { name: "descriptivesPlotsConfidenceInterval"; label: qsTr("Confidence Interval"); defaultValue: 95 }\n      }\n    }\n  }\n  ```\n  ![Image example](/Docs/development/img/qml-guide/general_example.png)\n\n</details>\n\n## Advanced Usage\nQML is a very flexible format, besides giving you access to all of the built-in components and our JASP-components that are detailed under [components](#components) you can also add your own components! If you add a qml-file to the [qml directory](#jasp-adding-module.md#qml), for instance `Example.qml`, then it will be treated as a component by all other files in the directory. Make sure to give the file an actual capital as first letter though, otherwise qml will not see it as a component. Then you can use it in another qml file simply by adding `Example { id: yourExampleComponent }` and set any of the properties the root-component of your component if desired.\n\nThis will give you the opportunity to create reusable parts, for instance, each of your analyses might share a common core. You could add this to a `Core.qml` and then this could be part of each analysis and be exactly the same everywhere. If you then also make sure to have a common function in R that uses the options specified in the `Core.qml`-component you can reuse that as well.\n\nThe possibilities here are rather extended and possibly even endless. See [the Qt QML tutorials](https://doc.qt.io/qt-5/qml-tutorial.html) or the [official documentation](https://doc.qt.io/qt-5/qtqml-index.html) for more information on this.\n\n\n## Custom Imports\nTo allow other jasp modules to reuse your qml code you need to turn it into a "QML Module" and you do this by adding a textfile to you `inst` folder called `qmldir`.\nThis file specifies which qml-components your module makes available to other modules.\n\nFor instance, suppose you want to share the entire `Descriptives` analysisform with other modules you can create `jaspDescriptives/qmldir` and that should contain:\n```\nmodule <jaspDescriptives>\nDescriptives 1.0 qml/Descriptives.qml\n```\n\nAnd then suppose you want to use it in any other module you can simply do `import jaspDescriptives 1.0` and use it directly as `Descriptives {}`.\n\nThere is only small thing to keep in mind, when your module is loaded in JASP it can only use qml modules from jasp modules that are installed in jasp.\nThis means that if your jasp module depends on another, like the above `jaspDescriptives`, you will get the r-code from the dependency-rpkg.\nBut the qml will come from the loaded `jaspDescriptives` in JASP. This is far from ideal because it can lead to conflicts between the r-code and qml.\n\nThere is sadly no way around this at the moment though. But this can be worked around once we have an online module library. Then we can just force the dependencies to be installed fully.\nIf it turns out it is too much of a problem we could also consider using multiple qml-engines or something, but for now that seems overkill.\n', 'message': 'Update jasp-qml-guide.md', 'author_name': 'GitHub', 'lang': 'md'}