How to etree findall() on many levels - python-3.x

I try to manipulate an diagrams.net (formerly draw.io) not compressed XML exported drawing.
Cables can be hooked up to elements and I want to get a cables-list.
I do a search for all cables by testing if the element has source and target attributes. Then I compare the id's of both with the full list of elements to find the connected label in value.
That works great until someone tries to add an "addon-tag". After that (even if it's deleted), the element gets wrapped in a <object> that has the id attribute but the source and target attribute stay in a child node called like this:
before:
<mxCell id="ferXMembXyNwfAPwV5vA-22" value="" style="..endless list" edge="1" parent="1" source="ferXMembXyNwfAPwV5vA-8" target="ferXMembXyNwfAPwV5vA-18">
<mxGeometry relative="1" as="geometry">
<mxPoint x="540" y="520" as="sourcePoint" />
<mxPoint x="700" y="520" as="targetPoint" />
</mxGeometry>
</mxCell>
after:
<object label="" id="ferXMembXyNwfAPwV5vA-53">
<mxCell style="..endless long list" edge="1" parent="1" source="ferXMembXyNwfAPwV5vA-42" target="ferXMembXyNwfAPwV5vA-51">
<mxGeometry relative="1" as="geometry">
<mxPoint x="660" y="340" as="sourcePoint" />
<mxPoint x="770" y="360" as="targetPoint" />
</mxGeometry>
</mxCell>
</object>
this findall works for normal mxCell formated to find id, source and target elements:
list_of_mxCell_elements = root.findall(root_node,".//*[#source][#target]")
and this for objects elements id's:
list_of_objects_elements = root.findall(root_node,".//*[#source][#target]/..")
But how can I access the mxCell element from the list_of_objects_elements, so I can get hold of source and target id's?

I found a solution by my own.
After findall 'elements' i iterate over the list of elements and just do another findall on each cable element i got.
It looks somewhat like this:
list_of_objects_elements = root.findall(root_node,'.//*[#source][#target]/..')
for cable in list_of_objects_elements:
for mxCell in cable.findall('./*[#source][#target]'):
Note the slighly different findall path:
This makes an search for source & target in <mxCells> while passing back the next higher element <object> from root.
.//*[#source][#target]/..
./*[#source][#target]
While the lower searches for source & target in only one element deeper than <object>
To me those paths are still a Mindblow.

Related

How to use sort="auto" on A object?

I have a listheader element with sort="auto" set, but when I click the column, the list doesn't sort. The arrows appear and reverse direction, but the list order doesn't change.
The Components appended to the list are org.zkoss.zul.A objects, which appears to be the reason sorting does not work.
Is there a workaround to get sorting to work for a Listbox whose list items are A objects?
my zul:
<listbox id="myList" checkmark="true" multiple="true">
<listhead>
<listheader id='select' label="" width="30px" align="left"/>
<listheader label="myLabel" width="75px" sort="auto"/>
</listhead>
</listbox>
groovy:
Listitem li = new Listitem(value: "myId")
li.appendChild(new Listcell())
Listcell listcell = new Listcell()
Long theId = "12345"
A link = new A(label: theId.toString(), style: "color:blue;")
listcell.appendChild(invoiceLink)
li.appendChild(listcell)
I'am using MVVM approach and this is how I sort my listbox
<listbox>
<listhead>
<listheader label="Hopper" width="60px" sort="auto(hopperCode)" />
<listheader label="Stop Time" width="80px" sort="auto(startTime)" />
</listhead>
<template name="model">
<listitem>
<listcell label="#load(each.hopperCode)" />
<listcell label="#load(each.startTime)" />
</listitem>
</template>
</listbox>
According to this paragraph in the documentation, sort auto sorts by the label of the listcell. You are not using Listcell.setLabel(), but append an A component to it. Since the listcells' labels are all the same (i.e. ""), sorting doesn't do anything.
Try setting custom comparators. For this purpose I advise using a model instead of creating the listitems yourself.

SAPUI5 - Seach field on a table with column list items

EDIT: Silly me, was pointing at the wrong property. Should have been pointing it at ArticleDescription instead of value.
I require a search field on a table with custom list items. The table brings through the data fine, but a requirement now is to add a search field for easy searching due to sometimes the table can get large.
Following the SAPUI5 explored page, I cannot seem to get this to work.
Ideally I would like it to use the liveChange property so this is done on the fly. I've got it to the point where that's doing it's job but I'm not ring back the search data.
Any help would be appreciated.
Table image
main.view.xml
<!-- Search box -->
<SearchField liveChange="onSearch" width="100%" class="sapUiMediumMarginBottom"/>
<!-- Table -->
<Table id="stock_table" itemPress="onOrderClicked" items="{stock>/Items}" keyboardMode="Edit" showFullScreenButton="true">
<infoToolbar>
<Toolbar>
<ToolbarSpacer/>
<Label text="{ path:'stock>/CurrentDate', formatter:'.tableHeader'}"/>
<ToolbarSpacer/>
</Toolbar>
</infoToolbar>
<columns>
<Column minScreenWidth="Tablet" demandPopin="true">
<Text text="{i18n>Article}"/>
</Column>
<Column minScreenWidth="Tablet" width="10em" demandPopin="true">
<Text text="{i18n>UnitOfMeasure}"/>
</Column>
<Column minScreenWidth="Tablet" width="8em" demandPopin="true">
<Text text="{i18n>Quantity}"/>
</Column>
</columns>
<items>
<ColumnListItem class="sapUiSizeCompact">
<customData>
<core:CustomData key="mydata" value="{stock>_errorStateClass}"
writeToDom="true"/>
</customData>
<HBox>
<core:Icon src="sap-icon://message-information"
tooltip="{i18n>ArticleNumber}: {stock>ArticleNumber}"
class="sapUiSmallMarginEnd greggslightblue"/>
<Text text="{stock>ArticleDescription}"/>
</HBox>
<Text text="{stock>UnitOfMeasureDescription}"/>
<HBox>
<Input id="quantity_input" valueLiveUpdate="true" value="{stock>_Quantity}"
liveChange="onQuantityAmountChanged"
class="CanHaveInteraction green_enter" width="5rem"/>
<core:Icon src="sap-icon://message-error"
tooltip="{stock>_ErrorMessage}"
class="sapUiSmallMarginEnd greggsred input-warning-icon"
visible="{stock>_ErrorStatus}" press="onErrorIconPressed"/>
<core:Icon src="sap-icon://message-warning"
tooltip="{stock>_ErrorMessage}"
class="sapUiSmallMarginEnd greggsred input-warning-icon"
visible="{stock>_WarningStatus}"/>
</HBox>
</ColumnListItem>
</items>
</Table>
main.controller.js
onSearch : function (oEvt) {
// add filter for search
var aFilters = [];
var sQuery = oEvt.getSource().getValue();
if (sQuery && sQuery.length > 0) {
var filter = new Filter("Name", sap.ui.model.FilterOperator.Contains, sQuery);
aFilters.push(filter);
}
// update list binding
var list = this.getView().byId("stock_table");
var binding = list.getBinding("items");
binding.filter(aFilters, "Application");
}
are you sure the following line contains a valid search query:
var sQuery = oEvt.getSource().getValue();
As documented in the API https://openui5.hana.ondemand.com/#docs/api/symbols/sap.m.SearchField.html#event:liveChange you have to use the event source parameter 'newValue':
var sQuery = oEvt.getParameter("newValue");
Update
Please show your data structure as you try to filter on path 'Name'. But within the table column binding I cannot see any attribute called 'Name'. Rather you can try to filter on attribute 'ArticleDescription':
var filter = new Filter("ArticleDescription", sap.ui.model.FilterOperator.Contains, sQuery);

Ext:BooleanColumn,when editing ,it shows true or false value

I have a grid and there is ext:BooleanColumn inside it,and I put a combobox for editing boolen colum.everything works fine ,except of this one .when I click boolen colum to edit,it shows false or true inside it,
I added a image what I trying to say.
how I can avoid this .thank you
and here is the my code :
<ext:BooleanColumn ID="BooleanColumn1" runat="server" DataIndex="BorcOdendimi" TrueText="odendi" Text="ödenme durumu"
FalseText="odenmedi" >
<Editor>
<ext:ComboBox runat="server" Text="odendi durumu" Editable="false">
<Items>
<ext:ListItem Text="Odendi" Value="1" />
<ext:ListItem Text="Odenmedi" Value="0" />
</Items>
</ext:ComboBox>
</Editor>
</ext:BooleanColumn>
To get it working the Values of the ComboBox's Items should match the values of a BooleanColumn. Currently, true/false (BooleanColumn's values) doesn't match 1/0 (ComboBox Items' values).
You can replace the existing ComboBox's Items with:
<ext:ListItem Text="Odendi" Value="true" Mode="Raw" />
<ext:ListItem Text="Odenmedi" Value="false" Mode="Raw" />
Answered in the Ext.NET forums thread.

Sharepoint Custom Field Render Pattern: Render to multiple fields

Initial Question
Can I render the data from one field into multiple columns?
Background
I have created a custom field that contains a drop down list and two text boxes. The idea is that users can select a supplier from the drop down list that is connected to a list of suppliers. Which will get the contact name and number of the supplier and populate the corresponding textboxes.
I have done it this way as it is important to be able to override the contact number and the address but the client wants to see the defaults.
Heres what it looks like:
On saving the new entry the value of the field is saved as follows:
;#1;#Supplier 1;#Contact Name;#01234 567890;#
I chose to save the data in this was so I can treat it like a multi-column field when I render it.
I am using the below code to split the data and override the display pattern for the list view:
<RenderPattern Name="DisplayPattern">
<Switch>
<Expr>
<Column />
</Expr>
<Case Value="" />
<Default>
<!--<Column SubColumnNumber="0" HTMLEncode="TRUE" />
<HTML><![CDATA[<br/>]]></HTML>-->
<Column SubColumnNumber="1" HTMLEncode="TRUE" />
<HTML><![CDATA[ - ]]></HTML>
<Column SubColumnNumber="2" HTMLEncode="TRUE" />
<HTML><![CDATA[ - ]]></HTML>
<Column SubColumnNumber="3" HTMLEncode="TRUE" />
<HTML><![CDATA[]]>]></HTML>
</Default>
</Switch>
</RenderPattern>
This allows me to present the data to the end user as follows:
Question
I would like to be able to display this split data in seperate columns. I notice that the build in title field SharePoint uses has four types of columns you can add to a view for a single field. I am trying to reproduce this kind of functionality so each section of the data can be added or removed from views. Is this possible?
It turns out you have access the list item which meant I was able to simply just add to additional fields within the list item by overriding the UpdateFieldValueInItem method.
Public Overrides Sub UpdateFieldValueInItem()
Me.ItemFieldValue = ddlSupplier.SelectedItem.Value
If Me.Item.Fields.ContainsField(Me.Field.InternalName & "-" & "Telephone") Then
Me.Item(Me.Field.InternalName & "-" & "Telephone") = txtTelephone.Text
End If
End Sub
A much more effective way of doing this.

WPF - Border with a OpacityMask/VisualBrush: Memory Leaks

A brief explanation about my app:
the application in which I'm working on is such a greeting cards designer. Imagine something in which there is a background image, and an indefinite number of "layers" (in particular, pictures) that stay over the background and can be moved, resized, moved front and back, etc...
It is also possibile to apply particular shapes to these layers, like a star, an ellipse, .. and after the card is made, it's possibile to save is to jpeg file.
The problem
Everything works correctly, but I detected that when a shape is applied to a layer, a memory leak is generated.
Here is the code of the UserControl of each layer:
<UserControl>
.....
<Grid x:Name="_myGrid" >
<Border x:Name="im_the_problem" BorderThickness="0" OpacityMask="{Binding Path=MyMask.Data, Converter={StaticResource MaskConverter}}">
<!-- My Image... -->
</Border>
</Grid>
</UserControl>
where MaskConverter code is the following:
public class MaskConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
String maskData = value as String;
if (maskData == null)
return null;
if (maskData == "")
return null;
VisualBrush vb = new VisualBrush();
vb.Visual = XamlReader.Parse(maskData) as Visual;
return vb;
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
}
The Parameter "MyMask.Data" is a XAML Path (that is the shape that I'm applying) that I dinamically load from a textfile that contains different shapes.
So, the principle is that if I have the border named *im_the_problem*, the memory is NOT released. If I comment *im_the_problem* (so I'll just have rectangular layers/pictures without shapes) everything work like a charm, without memory leaks.
The problem should be in the OpacityMask + VisualBrush.
Am I doing something wrong?
Or is there a known problem? Is there a way to do the same (apply a shape to a picture..) in a different manner?
Thanks.
You might be able to try binding the MyMask.Data to an actual Path.Data, and setting the Path.Fill to an ImageBrush created from the image?
You need to freeze your VisualBrush ;)
I had this problem in a DataGrid's column template where I was using a <Canvas><Path /></Canvas> (as a static-resource) into a VisualBrush (also a static-resource) and using that as the OpacityMask for a Rectangle. Whenever the DataGrid was reloaded the Rectangle wouldn't release VisualBrush references to the OpacityMask, I used a memory-profiler tool to reveal that all the VisualBrush objects were using the bulk of memory.
I don't understand why or how this happened - but I'm glad I'm not alone (even if I had the same problem some 6.5 years later...).
My XAML was something like this:
<DataGrid.Resources>
<Canvas x:Key="icon" ...>
<Path ... />
</Canvas>
<VisualBrush x:Key="iconBrush" Stretch="Uniform" Visual="{StaticResource icon}" />
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Rectangle
Fill="{Binding Foreground, ElementName=myDataGrid}"
Width="14"
Height="14"
Margin="4"
Visibility="{Binding IconVisibility}"
OpacityMask="{StaticResource iconBrush}"
/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
...
</DataGrid.Columns>
I read that setting IsFrozen = true (done using this technique: https://www.codeproject.com/Tips/72221/Freeze-brushes-directly-in-the-XAML-to-improve-you ) would help memory issues with Brushes, however this seemingly had no effect at all. Weird.
I thought I'd experiment and I reasoned that if the issue was leaking the VisualBrush then I wondered if having it as a StaticResource was messing with object-references, so I changed it to an "owned" object, like so:
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Rectangle
Fill="{Binding Foreground, ElementName=myDataGrid}"
Width="14"
Height="14"
Margin="4"
Visibility="{Binding IconVisibility}"
>
<VisualBrush Stretch="Uniform" Visual="{StaticResource iconBrush}" />
</Rectangle>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
This fixed the issue! And I still don't know why - I wonder if it's a bug in WPF?
On a related note, I came to realise that using a VisualBrush was overkill as I'm rendering just a simple Path - VisualBrush is expensive because it renders an entire WPF view - I also learned from other documentation that Path itself isn't necessary for rendering simple shapes because itself is a complete UIElement and FrameworkElement - which are "heavier" types.
I changed my code to store the path in a PathGeometry value inside a GeometryDrawing static-resource which is loaded into a DrawingBrush:
<GeometryDrawing x:Key="iconDrawing" Brush="Black" Geometry="..." />
<Rectangle
Fill="{Binding Foreground, ElementName=myDataGrid}"
Width="14"
Height="14"
Margin="4"
Visibility="{Binding IconVisibility}"
OpacityMask="{StaticResource iconBrush}"
>
<DrawingBrush Stretch="Uniform" Drawing="{StaticResource iconDrawing}" />
</Rectangle>
Doing this also made a dent in memory usage, and hopefully, performance.
In your project I see you're not using the path information as a resource, but the same technique applies: load your path into a PathGeometry (or rather, StreamGeometry object, which is even faster and is meant for immutable geometry) and set that as the Drawing for a DrawingBrush.

Resources