From c4ca91c4eb13d22f61ce92f0ada2c013bdd0c358 Mon Sep 17 00:00:00 2001 From: Matthias Klumpp Date: Sat, 31 Oct 2020 03:25:09 +0100 Subject: [PATCH 1/4] spec: Specify display_length requires/recommends item --- docs/xml/metainfo-component.xml | 83 +++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/docs/xml/metainfo-component.xml b/docs/xml/metainfo-component.xml index 5e0de54d3..7a07bd21c 100644 --- a/docs/xml/metainfo-component.xml +++ b/docs/xml/metainfo-component.xml @@ -834,6 +834,89 @@ + + <display_length/> + + + Set a relation to the display length defined as an integer value in either millimeters or logical pixels + (device pixels divided by scaling factor, roughly equivalent to 0.26mm (1/96in), also known as device-independent pixels). + To use millimeters, the unit property of this tag needs to be set to value mm, to use logical pixels + its value must be px. If no unit is explicitly defined, px is implicitly assumed. + Setting the side property to either shortest or longest will apply the selected size constraint to + either the shortest or longest side of the display rectangle, with shortest being implicitly assumed if no value is set. + + + About Pixel Dimensions + + One logical pixel (= device independent pixel) roughly corresponds to the visual angle of one pixel on a device with a pixel density of + 96dpi and a distance from the observer of about 52cm, making the physical pixel about 0.26mm in size. + If using logical pixels as unit, they might not always map to exact physical lengths as their exact size is defined by the device providing + the display. + They do however accurately depict the maximum amount of things that can be drawn in a direction on screen. + + + + Relations for the display length can be defined using a compare property as described in . + If this property is not present, a value of ge (greater-or-equal) is implicitly assumed. + + + The display_length tag also accepts one of the following text values. While their exact meaning in terms of pixel-based or physical size + is implementation-defined, the text term must roughly match the screen size of the device class listed next to it in the listing below: + + + xsmall - Very small screens, as used in watches, wearables and other small-display devices (about <= 300px). + small - Small screens often used in handheld devices, such as phone screens, small phablets (about < 600px). + medium - Screens in laptops, tablets (about >= 600px) + large - Bigger computer monitors (about >= 1024px) + xlarge - Television screens, large projected images + + + If a text value is used, the unit and side properties must not be present. For side, shortest + is assumed in this case. + A compare property is permitted and will compare the text placeholder values from smallest (xsmall) to largest (xlarge). + The text values are intended for adaptive applications which only need or want to give a very rough hint as to which display lengths they support, and do + not need fine control over their visibility (as these types of applications will adjust well to most screen sizes at runtime). + If finer control is needed, absolute sizes should be used instead. + + + This tag may appear up to four times to set a minimum and maximum dimension required. It is recommended to not mix different units + (so e.g. a required minimal width is not requested in both px and mm). + If multiple displays are connected to a device, it is acceptable to test against either the largest screen attached to the device, or the combined + amount of display space (depending on what makes sense for the respective device). + + + If used in a requires block, this relation can be used to restrict an application to only be installable on systems which have a minimum + usable display length available for it. If used in a recommends block, the application will still be + installable, but the user may be shown a warning. + + + If no display_length relation is present, a minimum required display (ge) relation + of medium is implicitly assumed to preserve backwards compatibility (so applications capable of running on smaller screens + need to make their support for that configuration explicit). + + + Examples: + + + + 600 + + + + + 80 + 50 + + + + + xlarge + xsmall +]]> + + + From 472181da017ddacc7f0794da7415314d7f75b5a2 Mon Sep 17 00:00:00 2001 From: Matthias Klumpp Date: Sun, 22 Nov 2020 02:34:38 +0100 Subject: [PATCH 2/4] spec: Add tv-remote user input control type --- docs/xml/metainfo-component.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/xml/metainfo-component.xml b/docs/xml/metainfo-component.xml index 7a07bd21c..0b077b292 100644 --- a/docs/xml/metainfo-component.xml +++ b/docs/xml/metainfo-component.xml @@ -807,6 +807,7 @@ console - Control via a console / command-line interface touch - Input by touching a surface with fingers is possible gamepad - The component supports gamepads (any game controller with wheels/buttons/joysticks) + tv-remote - Input via a TV remote (with arrow keys, number pad, other basic inputs) is supported. voice - The software can be controlled via voice recognition/activation vision - The software can be controlled by computer vision / visual object and sign detection From 7ec2df8344781caef6f780a8883f95863a9db90e Mon Sep 17 00:00:00 2001 From: Matthias Klumpp Date: Sun, 22 Nov 2020 02:35:30 +0100 Subject: [PATCH 3/4] spec: Simplify display_length spec, drop absolute lengths for now --- docs/xml/metainfo-component.xml | 48 +++++++++++++++++---------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/docs/xml/metainfo-component.xml b/docs/xml/metainfo-component.xml index 0b077b292..0a9821b3d 100644 --- a/docs/xml/metainfo-component.xml +++ b/docs/xml/metainfo-component.xml @@ -835,14 +835,12 @@ - + <display_length/> - Set a relation to the display length defined as an integer value in either millimeters or logical pixels - (device pixels divided by scaling factor, roughly equivalent to 0.26mm (1/96in), also known as device-independent pixels). - To use millimeters, the unit property of this tag needs to be set to value mm, to use logical pixels - its value must be px. If no unit is explicitly defined, px is implicitly assumed. + Set a relation to the display length defined as an integer value in logical pixels (device pixels divided by scaling factor, + roughly equivalent to 0.26mm (1/96in), also known as device-independent pixels). Setting the side property to either shortest or longest will apply the selected size constraint to either the shortest or longest side of the display rectangle, with shortest being implicitly assumed if no value is set. @@ -851,9 +849,9 @@ One logical pixel (= device independent pixel) roughly corresponds to the visual angle of one pixel on a device with a pixel density of 96dpi and a distance from the observer of about 52cm, making the physical pixel about 0.26mm in size. - If using logical pixels as unit, they might not always map to exact physical lengths as their exact size is defined by the device providing + When using logical pixels as unit, they might not always map to exact physical lengths as their exact size is defined by the device providing the display. - They do however accurately depict the maximum amount of things that can be drawn in a direction on screen. + They do however accurately depict the maximum amount of pixels that can be drawn in the depicted direction on the device's display space. @@ -861,29 +859,39 @@ If this property is not present, a value of ge (greater-or-equal) is implicitly assumed. - The display_length tag also accepts one of the following text values. While their exact meaning in terms of pixel-based or physical size - is implementation-defined, the text term must roughly match the screen size of the device class listed next to it in the listing below: + The display_length tag also accepts one of the following text values. While their exact meaning in terms of pixel-based size + is implementation-defined, the text term will roughly match the screen size of the device class listed next to it in the listing below: - xsmall - Very small screens, as used in watches, wearables and other small-display devices (about <= 300px). - small - Small screens often used in handheld devices, such as phone screens, small phablets (about < 600px). - medium - Screens in laptops, tablets (about >= 600px) + xsmall - Very small screens, as used in watches, wearables and other small-display devices (about <= 360px). + small - Small screens often used in handheld devices, such as phone screens, small phablets (about < 768px). + medium - Screens in laptops, tablets (about >= 768px) large - Bigger computer monitors (about >= 1024px) - xlarge - Television screens, large projected images + xlarge - Television screens, large projected images (about >= 3840px) - If a text value is used, the unit and side properties must not be present. For side, shortest + If a text value is used, the side property must not be present. For side, shortest is assumed in this case. A compare property is permitted and will compare the text placeholder values from smallest (xsmall) to largest (xlarge). The text values are intended for adaptive applications which only need or want to give a very rough hint as to which display lengths they support, and do not need fine control over their visibility (as these types of applications will adjust well to most screen sizes at runtime). If finer control is needed, absolute sizes should be used instead. + + Determining Device Types + + Please note that a display with a lot of vertical space may not be a television screen, but could also be a large gaming monitor. + Similar logic applies to the smaller screen sizes. Therefore, to indicate that an application runs well on a certain device + and not just on a certain display, additional metadata is needed, like the application's supported + input controls as defined via . + + - This tag may appear up to four times to set a minimum and maximum dimension required. It is recommended to not mix different units - (so e.g. a required minimal width is not requested in both px and mm). + This tag may appear up to four times to set a minimum and maximum dimension required. If multiple displays are connected to a device, it is acceptable to test against either the largest screen attached to the device, or the combined - amount of display space (depending on what makes sense for the respective device). + amount of display space (depending on what makes the most sense for the respective device / setup). + A software center application may test for the maximum possible resolution of an attached display, and not the currently set display resolution in case + it wants to check against hardware capability and not be influenced by user configuration. If used in a requires block, this relation can be used to restrict an application to only be installable on systems which have a minimum @@ -903,12 +911,6 @@ 600 - - - 80 - 50 - - From 3571aec0b4963d443f95861b9fa223d6ff777fc0 Mon Sep 17 00:00:00 2001 From: Matthias Klumpp Date: Sun, 22 Nov 2020 04:34:48 +0100 Subject: [PATCH 4/4] Implement support for display_length relation kind --- src/as-relation-private.h | 3 + src/as-relation.c | 306 ++++++++++++++++++++++++++++++++++++-- src/as-relation.h | 72 +++++++-- tests/test-xmldata.c | 37 ++++- tests/test-yamldata.c | 40 ++++- 5 files changed, 432 insertions(+), 26 deletions(-) diff --git a/src/as-relation-private.h b/src/as-relation-private.h index 5c7124ace..1e805e117 100644 --- a/src/as-relation-private.h +++ b/src/as-relation-private.h @@ -47,6 +47,9 @@ void as_relation_emit_yaml (AsRelation *relation, AsContext *ctx, yaml_emitter_t *emitter); +gint as_display_length_kind_to_px (AsDisplayLengthKind kind); +AsDisplayLengthKind as_display_length_kind_from_px (gint px); + #pragma GCC visibility pop G_END_DECLS diff --git a/src/as-relation.c b/src/as-relation.c index 1c25e4fe5..d4eff700e 100644 --- a/src/as-relation.c +++ b/src/as-relation.c @@ -45,6 +45,8 @@ typedef struct gchar *value; gchar *version; + + AsDisplaySideKind display_side_kind; } AsRelationPrivate; G_DEFINE_TYPE_WITH_PRIVATE (AsRelation, as_relation, G_TYPE_OBJECT) @@ -116,6 +118,8 @@ as_relation_item_kind_to_string (AsRelationItemKind kind) return "firmware"; if (kind == AS_RELATION_ITEM_KIND_CONTROL) return "control"; + if (kind == AS_RELATION_ITEM_KIND_DISPLAY_LENGTH) + return "display_length"; return "unknown"; } @@ -144,6 +148,8 @@ as_relation_item_kind_from_string (const gchar *kind_str) return AS_RELATION_ITEM_KIND_FIRMWARE; if (g_strcmp0 (kind_str, "control") == 0) return AS_RELATION_ITEM_KIND_CONTROL; + if (g_strcmp0 (kind_str, "display_length") == 0) + return AS_RELATION_ITEM_KIND_DISPLAY_LENGTH; return AS_RELATION_ITEM_KIND_UNKNOWN; } @@ -315,6 +321,128 @@ as_control_kind_from_string (const gchar *kind_str) return AS_CONTROL_KIND_UNKNOWN; } +/** + * as_display_side_kind_to_string: + * @kind: the #AsDisplaySideKind. + * + * Converts the enumerated value to a text representation. + * + * Returns: string version of @kind + * + * Since: 0.12.12 + **/ +const gchar* +as_display_side_kind_to_string (AsDisplaySideKind kind) +{ + if (kind == AS_DISPLAY_SIDE_KIND_SHORTEST) + return "shortest"; + if (kind == AS_DISPLAY_SIDE_KIND_LONGEST) + return "longest"; + return "unknown"; +} + +/** + * as_display_side_kind_from_string: + * @kind_str: the string. + * + * Converts the text representation to an enumerated value. + * + * Returns: a #AsDisplaySideKind or %AS_DISPLAY_SIDE_KIND_UNKNOWN for unknown + * + * Since: 0.12.12 + **/ +AsDisplaySideKind +as_display_side_kind_from_string (const gchar *kind_str) +{ + if (kind_str == NULL) + return AS_DISPLAY_SIDE_KIND_SHORTEST; + if (g_strcmp0 (kind_str, "shortest") == 0) + return AS_DISPLAY_SIDE_KIND_SHORTEST; + if (g_strcmp0 (kind_str, "longest") == 0) + return AS_DISPLAY_SIDE_KIND_LONGEST; + return AS_DISPLAY_SIDE_KIND_UNKNOWN; +} + +/** + * as_display_length_kind_to_px: + * @kind: the #AsDisplaySideKind. + * + * Converts the rough display length value to an absolute + * logical pixel measurement, roughly matching the shortest + * display size of the respective screen size. + * + * Returns: amount of logical pixels for shortest display edge, or -1 on invalid input. + * + * Since: 0.12.12 + **/ +gint +as_display_length_kind_to_px (AsDisplayLengthKind kind) +{ + if (kind == AS_DISPLAY_LENGTH_KIND_XSMALL) + return 360; + if (kind == AS_DISPLAY_LENGTH_KIND_SMALL) + return 420; + if (kind == AS_DISPLAY_LENGTH_KIND_MEDIUM) + return 760; + if (kind == AS_DISPLAY_LENGTH_KIND_LARGE) + return 900; + if (kind == AS_DISPLAY_LENGTH_KIND_XLARGE) + return 1200; + return -1; +} + +/** + * as_display_length_kind_from_px: + * @kind: the #AsDisplaySideKind. + * + * Classify a logical pixel amount into a display size. + * + * Returns: display size enum. + * + * Since: 0.12.12 + **/ +AsDisplayLengthKind +as_display_length_kind_from_px (gint px) +{ + if (px <= 360 ) + return AS_DISPLAY_LENGTH_KIND_XSMALL; + if (px >= 360 ) + return AS_DISPLAY_LENGTH_KIND_SMALL; + if (px >= 760 ) + return AS_DISPLAY_LENGTH_KIND_MEDIUM; + if (px >= 900 ) + return AS_DISPLAY_LENGTH_KIND_LARGE; + if (px >= 1200 ) + return AS_DISPLAY_LENGTH_KIND_XLARGE; + return AS_DISPLAY_LENGTH_KIND_UNKNOWN; +} + +/** + * as_display_length_kind_from_string: + * @kind_str: the string. + * + * Converts the text representation to an enumerated value. + * + * Returns: a #AsDisplayLengthKind or %AS_DISPLAY_LENGTH_KIND_UNKNOWN for unknown + * + * Since: 0.12.12 + **/ +AsDisplayLengthKind +as_display_length_kind_from_string (const gchar *kind_str) +{ + if (g_strcmp0 (kind_str, "xsmall") == 0) + return AS_DISPLAY_LENGTH_KIND_XSMALL; + if (g_strcmp0 (kind_str, "small") == 0) + return AS_DISPLAY_LENGTH_KIND_SMALL; + if (g_strcmp0 (kind_str, "medium") == 0) + return AS_DISPLAY_LENGTH_KIND_MEDIUM; + if (g_strcmp0 (kind_str, "large") == 0) + return AS_DISPLAY_LENGTH_KIND_LARGE; + if (g_strcmp0 (kind_str, "xlarge") == 0) + return AS_DISPLAY_LENGTH_KIND_XLARGE; + return AS_DISPLAY_LENGTH_KIND_UNKNOWN; +} + /** * as_relation_finalize: **/ @@ -535,6 +663,64 @@ as_relation_get_value_control_kind (AsRelation *relation) return as_control_kind_from_string (priv->value); } +/** + * as_relation_set_value_control_kind: + * @relation: an #AsRelation instance. + * @kind: an #AsControlKind + * + * Set relation item value from an #AsControlKind. + * + * Since: 0.12.12 + **/ +void +as_relation_set_value_control_kind (AsRelation *relation, AsControlKind kind) +{ + as_relation_set_value (relation, as_control_kind_to_string (kind)); +} + +/** + * as_relation_get_value_px: + * @relation: an #AsRelation instance. + * + * In case this #AsRelation is of kind %AS_RELATION_ITEM_KIND_DISPLAY_LENGTH, + * return the set logical pixel amount. + * + * Returns: The logical pixel amount for this display length, value <= 0 on error. + * + * Since: 0.12.12 + **/ +gint +as_relation_get_value_px (AsRelation *relation) +{ + AsRelationPrivate *priv = GET_PRIVATE (relation); + AsDisplayLengthKind dlkind; + if (priv->item_kind != AS_RELATION_ITEM_KIND_DISPLAY_LENGTH) + return -1; + + dlkind = as_display_length_kind_from_string (priv->value); + if (dlkind == AS_DISPLAY_LENGTH_KIND_UNKNOWN) + return g_ascii_strtoll (priv->value, NULL, 10); + return as_display_length_kind_to_px (dlkind); +} + +/** + * as_relation_get_value_display_length_kind: + * @relation: an #AsRelation instance. + * + * In case this #AsRelation is of kind %AS_RELATION_ITEM_KIND_DISPLAY_LENGTH, + * return the #AsDisplayLengthKind. + * + * Returns: The #AsDisplayLengthKind if a placeholder value was set, or %AS_DISPLAY_LENGTH_KIND_UNKNOWN otherwise. + * + * Since: 0.12.12 + **/ +AsDisplayLengthKind +as_relation_get_value_display_length_kind (AsRelation *relation) +{ + AsRelationPrivate *priv = GET_PRIVATE (relation); + return as_display_length_kind_from_string (priv->value); +} + /** * as_relation_set_value: * @relation: an #AsRelation instance. @@ -552,6 +738,40 @@ as_relation_set_value (AsRelation *relation, const gchar *value) priv->value = g_strdup (value); } +/** + * as_relation_get_display_side_kind: + * @relation: an #AsRelation instance. + * + * Gets the display side kind, in case this item is of + * kind %AS_RELATION_ITEM_KIND_DISPLAY_LENGTH + * + * Returns: a #AsDisplaySideKind or %AS_DISPLAY_SIDE_KIND_UNKNOWN + * + * Since: 0.12.12 + **/ +AsDisplaySideKind +as_relation_get_display_side_kind (AsRelation *relation) +{ + AsRelationPrivate *priv = GET_PRIVATE (relation); + return priv->display_side_kind; +} + +/** + * as_relation_set_display_side_kind: + * @relation: an #AsRelation instance. + * @kind: the new #AsDisplaySideKind. + * + * Sets the display side kind, in case this item is of + * kind %AS_RELATION_ITEM_KIND_DISPLAY_LENGTH + * + * Since: 0.12.12 + **/ +void +as_relation_set_display_side_kind (AsRelation *relation, AsDisplaySideKind kind) +{ + AsRelationPrivate *priv = GET_PRIVATE (relation); + priv->display_side_kind = kind; +} /** * as_relation_version_compare: @@ -627,7 +847,7 @@ as_relation_load_from_xml (AsRelation *relation, AsContext *ctx, xmlNode *node, g_free (priv->version); priv->version = (gchar*) xmlGetProp (node, (xmlChar*) "version"); - if (priv->version != NULL) { + if ((priv->version != NULL) || (priv->item_kind == AS_RELATION_ITEM_KIND_DISPLAY_LENGTH)) { g_autofree gchar *compare_str = (gchar*) xmlGetProp (node, (xmlChar*) "compare"); priv->compare = as_relation_compare_from_string (compare_str); } @@ -657,11 +877,21 @@ as_relation_to_xml_node (AsRelation *relation, AsContext *ctx, xmlNode *root) n = xmlNewTextChild (root, NULL, (xmlChar*) as_relation_item_kind_to_string (priv->item_kind), (xmlChar*) priv->value); - if (priv->version != NULL) { + + if (priv->item_kind == AS_RELATION_ITEM_KIND_DISPLAY_LENGTH) { + if ((priv->display_side_kind != AS_DISPLAY_SIDE_KIND_SHORTEST) && (priv->display_side_kind != AS_DISPLAY_SIDE_KIND_UNKNOWN)) + xmlNewProp (n, (xmlChar*) "side", + (xmlChar*) as_display_side_kind_to_string (priv->display_side_kind)); + if (priv->compare != AS_RELATION_COMPARE_GE) + xmlNewProp (n, (xmlChar*) "compare", + (xmlChar*) as_relation_compare_to_string (priv->compare)); + + } else if (priv->item_kind == AS_RELATION_ITEM_KIND_CONTROL) { + } else if (priv->version != NULL) { xmlNewProp (n, (xmlChar*) "version", (xmlChar*) priv->version); xmlNewProp (n, (xmlChar*) "compare", - (xmlChar*) as_relation_compare_to_string (priv->compare)); + (xmlChar*) as_relation_compare_to_string (priv->compare)); } } @@ -690,7 +920,7 @@ as_relation_load_from_yaml (AsRelation *relation, AsContext *ctx, GNode *node, G if (g_strcmp0 (entry, "version") == 0) { g_autofree gchar *compare_str = NULL; - g_autofree gchar *ver_str = g_strdup (as_yaml_node_get_value (n)); + const gchar *ver_str = as_yaml_node_get_value (n); if (strlen (ver_str) <= 2) continue; /* this string is too short to contain any valid version */ compare_str = g_strndup (ver_str, 2); @@ -698,14 +928,39 @@ as_relation_load_from_yaml (AsRelation *relation, AsContext *ctx, GNode *node, G g_free (priv->version); priv->version = g_strdup (ver_str + 2); g_strstrip (priv->version); + } else if (g_strcmp0 (entry, "side") == 0) { + priv->display_side_kind = as_display_side_kind_from_string (as_yaml_node_get_value (n)); } else { AsRelationItemKind kind = as_relation_item_kind_from_string (entry); - if (kind != AS_RELATION_ITEM_KIND_UNKNOWN) { - priv->item_kind = kind; + if (kind == AS_RELATION_ITEM_KIND_UNKNOWN) { + g_debug ("Unknown Requires/Recommends YAML field: %s", entry); + continue; + } + + priv->item_kind = kind; + if (kind == AS_RELATION_ITEM_KIND_DISPLAY_LENGTH) { + g_autofree gchar *compare_str = NULL; + const gchar *len_str = as_yaml_node_get_value (n); + if (strlen (len_str) <= 2) { + /* this string is too short to contain a comparsion operator */ + g_free (priv->value); + priv->value = g_strdup (len_str); + continue; + } + compare_str = g_strndup (len_str, 2); + priv->compare = as_relation_compare_from_string (compare_str); + g_free (priv->value); - priv->value = g_strdup (as_yaml_node_get_value (n)); + if (priv->compare == AS_RELATION_COMPARE_UNKNOWN) { + priv->value = g_strdup (len_str); + priv->compare = AS_RELATION_COMPARE_GE; + } else { + priv->value = g_strdup (len_str + 2); + g_strstrip (priv->value); + } } else { - g_debug ("Unknown Requires/Recommends YAML field: %s", entry); + g_free (priv->value); + priv->value = g_strdup (as_yaml_node_get_value (n)); } } } @@ -731,11 +986,38 @@ as_relation_emit_yaml (AsRelation *relation, AsContext *ctx, yaml_emitter_t *emi as_yaml_mapping_start (emitter); - as_yaml_emit_entry (emitter, - as_relation_item_kind_to_string (priv->item_kind), - priv->value); + if (priv->item_kind == AS_RELATION_ITEM_KIND_DISPLAY_LENGTH) { + if ((priv->compare != AS_RELATION_COMPARE_UNKNOWN) && (priv->compare != AS_RELATION_COMPARE_GE)) { + g_autofree gchar *len_str = g_strdup_printf ("%s %s", + as_relation_compare_to_symbols_string (priv->compare), + priv->value); + as_yaml_emit_entry (emitter, + as_relation_item_kind_to_string (priv->item_kind), + len_str); + } else { + gint ival = as_relation_get_value_int (relation); + if (ival > 0) { + as_yaml_emit_entry_uint64 (emitter, + as_relation_item_kind_to_string (priv->item_kind), + ival); + } else { + as_yaml_emit_entry (emitter, + as_relation_item_kind_to_string (priv->item_kind), + priv->value); + } + } + } else { + as_yaml_emit_entry (emitter, + as_relation_item_kind_to_string (priv->item_kind), + priv->value); + } + + if (priv->item_kind == AS_RELATION_ITEM_KIND_DISPLAY_LENGTH) { + if ((priv->display_side_kind != AS_DISPLAY_SIDE_KIND_SHORTEST) && (priv->display_side_kind != AS_DISPLAY_SIDE_KIND_UNKNOWN)) + as_yaml_emit_entry (emitter, "side", as_display_side_kind_to_string (priv->display_side_kind)); - if (priv->version != NULL) { + } else if (priv->item_kind == AS_RELATION_ITEM_KIND_CONTROL) { + } else if (priv->version != NULL) { g_autofree gchar *ver_str = g_strdup_printf ("%s %s", as_relation_compare_to_symbols_string (priv->compare), priv->version); diff --git a/src/as-relation.h b/src/as-relation.h index c5752ee53..67dc6f590 100644 --- a/src/as-relation.h +++ b/src/as-relation.h @@ -62,13 +62,14 @@ typedef enum { /** * AsRelationItemKind: - * @AS_RELATION_ITEM_KIND_UNKNOWN: Unknown kind - * @AS_RELATION_ITEM_KIND_ID: A component ID - * @AS_RELATION_ITEM_KIND_MODALIAS: A hardware modalias - * @AS_RELATION_ITEM_KIND_KERNEL: An operating system kernel (like Linux) - * @AS_RELATION_ITEM_KIND_MEMORY: A system RAM requirement - * @AS_RELATION_ITEM_KIND_FIRMWARE: A device firmware requirement (used by fwupd) - * @AS_RELATION_ITEM_KIND_CONTROL: An input method for users to control software + * @AS_RELATION_ITEM_KIND_UNKNOWN: Unknown kind + * @AS_RELATION_ITEM_KIND_ID: A component ID + * @AS_RELATION_ITEM_KIND_MODALIAS: A hardware modalias + * @AS_RELATION_ITEM_KIND_KERNEL: An operating system kernel (like Linux) + * @AS_RELATION_ITEM_KIND_MEMORY: A system RAM requirement + * @AS_RELATION_ITEM_KIND_FIRMWARE: A device firmware requirement (used by fwupd) + * @AS_RELATION_ITEM_KIND_CONTROL: An input method for users to control software + * @AS_RELATION_ITEM_KIND_DISPLAY_LENGTH: Display edge length * * Type of the item an #AsRelation is for. **/ @@ -80,6 +81,7 @@ typedef enum { AS_RELATION_ITEM_KIND_MEMORY, AS_RELATION_ITEM_KIND_FIRMWARE, AS_RELATION_ITEM_KIND_CONTROL, + AS_RELATION_ITEM_KIND_DISPLAY_LENGTH, /*< private >*/ AS_RELATION_ITEM_KIND_LAST } AsRelationItemKind; @@ -134,6 +136,44 @@ typedef enum { AS_CONTROL_KIND_LAST } AsControlKind; +/** + * AsDisplaySideKind: + * @AS_DISPLAY_SIDE_KIND_UNKNOWN: Unknown + * @AS_DISPLAY_SIDE_KIND_SHORTEST: Shortest side of the display rectangle. + * @AS_DISPLAY_SIDE_KIND_LONGEST: Longest side of the display rectangle. + * + * Side a display_length requirement is for. + **/ +typedef enum { + AS_DISPLAY_SIDE_KIND_UNKNOWN, + AS_DISPLAY_SIDE_KIND_SHORTEST, + AS_DISPLAY_SIDE_KIND_LONGEST, + /*< private >*/ + AS_DISPLAY_SIDE_KIND_LAST +} AsDisplaySideKind; + +/** + * AsDisplayLengthKind: + * @AS_DISPLAY_LENGTH_KIND_UNKNOWN: Unknown + * @AS_DISPLAY_LENGTH_KIND_XSMALL: Very small display + * @AS_DISPLAY_LENGTH_KIND_SMALL: Small display + * @AS_DISPLAY_LENGTH_KIND_MEDIUM: Medium display + * @AS_DISPLAY_LENGTH_KIND_LARGE: Large display + * @AS_DISPLAY_LENGTH_KIND_XLARGE: Very large display + * + * A rought estimate of how large a given display length is. + **/ +typedef enum { + AS_DISPLAY_LENGTH_KIND_UNKNOWN, + AS_DISPLAY_LENGTH_KIND_XSMALL, + AS_DISPLAY_LENGTH_KIND_SMALL, + AS_DISPLAY_LENGTH_KIND_MEDIUM, + AS_DISPLAY_LENGTH_KIND_LARGE, + AS_DISPLAY_LENGTH_KIND_XLARGE, + /*< private >*/ + AS_DISPLAY_LENGTH_KIND_LAST +} AsDisplayLengthKind; + const gchar *as_relation_kind_to_string (AsRelationKind kind); AsRelationKind as_relation_kind_from_string (const gchar *kind_str); @@ -147,6 +187,11 @@ const gchar *as_relation_compare_to_symbols_string (AsRelationCompare compare); const gchar *as_control_kind_to_string (AsControlKind kind); AsControlKind as_control_kind_from_string (const gchar *kind_str); +const gchar *as_display_side_kind_to_string (AsDisplaySideKind kind); +AsDisplaySideKind as_display_side_kind_from_string (const gchar *kind_str); + +AsDisplayLengthKind as_display_length_kind_from_string (const gchar *kind_str); + AsRelation *as_relation_new (void); AsRelationKind as_relation_get_kind (AsRelation *relation); @@ -166,10 +211,19 @@ void as_relation_set_version (AsRelation *relation, const gchar *version); const gchar *as_relation_get_value (AsRelation *relation); -gint as_relation_get_value_int (AsRelation *relation); -AsControlKind as_relation_get_value_control_kind (AsRelation *relation); void as_relation_set_value (AsRelation *relation, const gchar *value); +gint as_relation_get_value_int (AsRelation *relation); + +AsControlKind as_relation_get_value_control_kind (AsRelation *relation); +void as_relation_set_value_control_kind (AsRelation *relation, + AsControlKind kind); + +AsDisplaySideKind as_relation_get_display_side_kind (AsRelation *relation); +void as_relation_set_display_side_kind (AsRelation *relation, + AsDisplaySideKind kind); +gint as_relation_get_value_px (AsRelation *relation); +AsDisplayLengthKind as_relation_get_value_display_length_kind (AsRelation *relation); gboolean as_relation_version_compare (AsRelation *relation, const gchar *version, diff --git a/tests/test-xmldata.c b/tests/test-xmldata.c index 48674b239..b1f421eb2 100644 --- a/tests/test-xmldata.c +++ b/tests/test-xmldata.c @@ -1295,10 +1295,12 @@ static const gchar *xmldata_recommends_requires = "\n" " \n" " 2500\n" " usb:v1130p0202d*\n" + " 4200\n" " \n" " \n" " Linux\n" " org.example.TestDependency\n" + " small\n" " \n" "\n"; /** @@ -1320,8 +1322,8 @@ test_xml_read_recommends_requires (void) recommends = as_component_get_recommends (cpt); requires = as_component_get_requires (cpt); - g_assert_cmpint (recommends->len, ==, 2); - g_assert_cmpint (requires->len, ==, 2); + g_assert_cmpint (recommends->len, ==, 3); + g_assert_cmpint (requires->len, ==, 3); /* memory relation */ relation = AS_RELATION (g_ptr_array_index (recommends, 0)); @@ -1335,6 +1337,13 @@ test_xml_read_recommends_requires (void) g_assert_cmpint (as_relation_get_item_kind (relation), ==, AS_RELATION_ITEM_KIND_MODALIAS); g_assert_cmpstr (as_relation_get_value (relation), ==, "usb:v1130p0202d*"); + /* display_length relation (REC) */ + relation = AS_RELATION (g_ptr_array_index (recommends, 2)); + g_assert_cmpint (as_relation_get_kind (relation), ==, AS_RELATION_KIND_RECOMMENDS); + g_assert_cmpint (as_relation_get_item_kind (relation), ==, AS_RELATION_ITEM_KIND_DISPLAY_LENGTH); + g_assert_cmpint (as_relation_get_value_px (relation), ==, 4200); + g_assert_cmpint (as_relation_get_compare (relation), ==, AS_RELATION_COMPARE_LE); + /* kernel relation */ relation = AS_RELATION (g_ptr_array_index (requires, 0)); g_assert_cmpint (as_relation_get_kind (relation), ==, AS_RELATION_KIND_REQUIRES); @@ -1350,6 +1359,13 @@ test_xml_read_recommends_requires (void) g_assert_cmpstr (as_relation_get_value (relation), ==, "org.example.TestDependency"); g_assert_cmpstr (as_relation_get_version (relation), ==, "1.2"); g_assert_cmpint (as_relation_get_compare (relation), ==, AS_RELATION_COMPARE_EQ); + + /* display_length relation (REQ) */ + relation = AS_RELATION (g_ptr_array_index (requires, 2)); + g_assert_cmpint (as_relation_get_kind (relation), ==, AS_RELATION_KIND_REQUIRES); + g_assert_cmpint (as_relation_get_item_kind (relation), ==, AS_RELATION_ITEM_KIND_DISPLAY_LENGTH); + g_assert_cmpint (as_relation_get_value_display_length_kind (relation), ==, AS_DISPLAY_LENGTH_KIND_SMALL); + g_assert_cmpint (as_relation_get_compare (relation), ==, AS_RELATION_COMPARE_GE); } /** @@ -1366,6 +1382,8 @@ test_xml_write_recommends_requires (void) g_autoptr(AsRelation) moda_relation = NULL; g_autoptr(AsRelation) kernel_relation = NULL; g_autoptr(AsRelation) id_relation = NULL; + g_autoptr(AsRelation) dl_relation1 = NULL; + g_autoptr(AsRelation) dl_relation2 = NULL; cpt = as_component_new (); as_component_set_id (cpt, "org.example.RelationsTest"); @@ -1374,11 +1392,15 @@ test_xml_write_recommends_requires (void) moda_relation = as_relation_new (); kernel_relation = as_relation_new (); id_relation = as_relation_new (); + dl_relation1 = as_relation_new (); + dl_relation2 = as_relation_new (); as_relation_set_kind (mem_relation, AS_RELATION_KIND_RECOMMENDS); as_relation_set_kind (moda_relation, AS_RELATION_KIND_RECOMMENDS); as_relation_set_kind (kernel_relation, AS_RELATION_KIND_REQUIRES); as_relation_set_kind (id_relation, AS_RELATION_KIND_REQUIRES); + as_relation_set_kind (dl_relation1, AS_RELATION_KIND_RECOMMENDS); + as_relation_set_kind (dl_relation2, AS_RELATION_KIND_REQUIRES); as_relation_set_item_kind (mem_relation, AS_RELATION_ITEM_KIND_MEMORY); as_relation_set_value (mem_relation, "2500"); @@ -1395,10 +1417,21 @@ test_xml_write_recommends_requires (void) as_relation_set_version (id_relation, "1.2"); as_relation_set_compare (id_relation, AS_RELATION_COMPARE_EQ); + as_relation_set_item_kind (dl_relation1, AS_RELATION_ITEM_KIND_DISPLAY_LENGTH); + as_relation_set_value (dl_relation1, "4200"); + as_relation_set_display_side_kind (dl_relation1, AS_DISPLAY_SIDE_KIND_LONGEST); + as_relation_set_compare (dl_relation1, AS_RELATION_COMPARE_LE); + + as_relation_set_item_kind (dl_relation2, AS_RELATION_ITEM_KIND_DISPLAY_LENGTH); + as_relation_set_value (dl_relation2, "small"); + as_relation_set_compare (dl_relation2, AS_RELATION_COMPARE_GE); + as_component_add_relation (cpt, mem_relation); as_component_add_relation (cpt, moda_relation); as_component_add_relation (cpt, kernel_relation); as_component_add_relation (cpt, id_relation); + as_component_add_relation (cpt, dl_relation1); + as_component_add_relation (cpt, dl_relation2); res = as_xml_test_serialize (cpt, AS_FORMAT_STYLE_METAINFO); g_assert (as_xml_test_compare_xml (res, xmldata_recommends_requires)); diff --git a/tests/test-yamldata.c b/tests/test-yamldata.c index 6019caf0d..8b579576c 100644 --- a/tests/test-yamldata.c +++ b/tests/test-yamldata.c @@ -867,11 +867,14 @@ static const gchar *yamldata_requires_recommends_field = "Recommends:\n" "- memory: '2500'\n" "- modalias: usb:v1130p0202d*\n" + "- display_length: <= xlarge\n" + " side: longest\n" "Requires:\n" "- kernel: Linux\n" " version: '>= 4.15'\n" "- id: org.example.TestDependency\n" - " version: == 1.2\n"; + " version: == 1.2\n" + "- display_length: 4200\n"; /** * test_yaml_write_requires_recommends: @@ -887,6 +890,8 @@ test_yaml_write_requires_recommends (void) g_autoptr(AsRelation) moda_relation = NULL; g_autoptr(AsRelation) kernel_relation = NULL; g_autoptr(AsRelation) id_relation = NULL; + g_autoptr(AsRelation) dl_relation1 = NULL; + g_autoptr(AsRelation) dl_relation2 = NULL; cpt = as_component_new (); as_component_set_kind (cpt, AS_COMPONENT_KIND_GENERIC); @@ -896,11 +901,15 @@ test_yaml_write_requires_recommends (void) moda_relation = as_relation_new (); kernel_relation = as_relation_new (); id_relation = as_relation_new (); + dl_relation1 = as_relation_new (); + dl_relation2 = as_relation_new (); as_relation_set_kind (mem_relation, AS_RELATION_KIND_RECOMMENDS); as_relation_set_kind (moda_relation, AS_RELATION_KIND_RECOMMENDS); as_relation_set_kind (kernel_relation, AS_RELATION_KIND_REQUIRES); as_relation_set_kind (id_relation, AS_RELATION_KIND_REQUIRES); + as_relation_set_kind (dl_relation1, AS_RELATION_KIND_RECOMMENDS); + as_relation_set_kind (dl_relation2, AS_RELATION_KIND_REQUIRES); as_relation_set_item_kind (mem_relation, AS_RELATION_ITEM_KIND_MEMORY); as_relation_set_value (mem_relation, "2500"); @@ -917,10 +926,21 @@ test_yaml_write_requires_recommends (void) as_relation_set_version (id_relation, "1.2"); as_relation_set_compare (id_relation, AS_RELATION_COMPARE_EQ); + as_relation_set_item_kind (dl_relation1, AS_RELATION_ITEM_KIND_DISPLAY_LENGTH); + as_relation_set_value (dl_relation1, "xlarge"); + as_relation_set_display_side_kind (dl_relation1, AS_DISPLAY_SIDE_KIND_LONGEST); + as_relation_set_compare (dl_relation1, AS_RELATION_COMPARE_LE); + + as_relation_set_item_kind (dl_relation2, AS_RELATION_ITEM_KIND_DISPLAY_LENGTH); + as_relation_set_value (dl_relation2, "4200"); + as_relation_set_compare (dl_relation2, AS_RELATION_COMPARE_GE); + as_component_add_relation (cpt, mem_relation); as_component_add_relation (cpt, moda_relation); as_component_add_relation (cpt, kernel_relation); as_component_add_relation (cpt, id_relation); + as_component_add_relation (cpt, dl_relation1); + as_component_add_relation (cpt, dl_relation2); /* test collection serialization */ res = as_yaml_test_serialize (cpt); @@ -946,8 +966,8 @@ test_yaml_read_requires_recommends (void) recommends = as_component_get_recommends (cpt); requires = as_component_get_requires (cpt); - g_assert_cmpint (recommends->len, ==, 2); - g_assert_cmpint (requires->len, ==, 2); + g_assert_cmpint (recommends->len, ==, 3); + g_assert_cmpint (requires->len, ==, 3); /* memory relation */ relation = AS_RELATION (g_ptr_array_index (recommends, 0)); @@ -961,6 +981,13 @@ test_yaml_read_requires_recommends (void) g_assert_cmpint (as_relation_get_item_kind (relation), ==, AS_RELATION_ITEM_KIND_MODALIAS); g_assert_cmpstr (as_relation_get_value (relation), ==, "usb:v1130p0202d*"); + /* display_length relation (REC) */ + relation = AS_RELATION (g_ptr_array_index (recommends, 2)); + g_assert_cmpint (as_relation_get_kind (relation), ==, AS_RELATION_KIND_RECOMMENDS); + g_assert_cmpint (as_relation_get_item_kind (relation), ==, AS_RELATION_ITEM_KIND_DISPLAY_LENGTH); + g_assert_cmpint (as_relation_get_value_display_length_kind (relation), ==, AS_DISPLAY_LENGTH_KIND_XLARGE); + g_assert_cmpint (as_relation_get_compare (relation), ==, AS_RELATION_COMPARE_LE); + /* kernel relation */ relation = AS_RELATION (g_ptr_array_index (requires, 0)); g_assert_cmpint (as_relation_get_kind (relation), ==, AS_RELATION_KIND_REQUIRES); @@ -976,6 +1003,13 @@ test_yaml_read_requires_recommends (void) g_assert_cmpstr (as_relation_get_value (relation), ==, "org.example.TestDependency"); g_assert_cmpstr (as_relation_get_version (relation), ==, "1.2"); g_assert_cmpint (as_relation_get_compare (relation), ==, AS_RELATION_COMPARE_EQ); + + /* display_length relation (REQ) */ + relation = AS_RELATION (g_ptr_array_index (requires, 2)); + g_assert_cmpint (as_relation_get_kind (relation), ==, AS_RELATION_KIND_REQUIRES); + g_assert_cmpint (as_relation_get_item_kind (relation), ==, AS_RELATION_ITEM_KIND_DISPLAY_LENGTH); + g_assert_cmpint (as_relation_get_value_px (relation), ==, 4200); + g_assert_cmpint (as_relation_get_compare (relation), ==, AS_RELATION_COMPARE_GE); }