Get children from ListBox (gtk4) - rust

When I was using gtk3 I was able to access a ListBox's children this way:
let list_box = ListBox::new();
let label = Label::new(Some("Label 1"));
list_box.append(&label);
for row in list_box.children() {
list_box.remove(&row);
}
In gtk4, it seems like children() doesn't exist anymore: "no method named `children` found for struct `gtk4::ListBox`".
I checked ListBox in the gtk4 docs, but I couldn't find anything related to accessing a ListBox's children.
How to access a ListBox's children in gtk4?

There is observe_children, but like it's name suggests you should not modify the container while using it. Or more specifically you can't keep using it's iterator once you modify the underlying container.
For your usecase you can iterate and remove children using first_child/last_child like this:
while let Some(row) = list_box.last_child() {
list_box.remove(&row);
}

Related

Custom editor in MPS

I have an concept in Jetbrains MPS which I would like to create a custom editor for.
The concept have a number of children.
For each child I would like to display the child's own editor but with a "-" in front of it.
I'm not completely sure I'm trying to solve this in the right way.
But my first attempt is a custom cell looping over the child nodes.
My problem is that I can't figure out how to find the editor cell of the child nodes:
My cell provider:
return new AbstractCellProvider(node) {
#Override
public EditorCell createEditorCell(EditorContext ctx) {
EditorCell_Collection cells = EditorCell_Collection.createVertical(ctx, node);
foreach n in node.elements {
EditorCell_Collection a = EditorCell_Collection.createHorizontal(ctx, node);
EditorCell_Label label = new EditorCell_Constant(ctx, node, "-");
a.addEditorCell(label);
cells.addEditorCell(a);
how to add the child node's editor here?
}
return cells;
}
What are you really trying to achieve? An example might help here...
Without further context (so I may misunderstand your problem), I think you could use an EditorComponent (https://www.jetbrains.com/help/mps/editor.html#editorcomponentsandeditorcomponentcells) for the original editor and then make an editor with a "-" constant followed by the EditorComponent to achieve the desired effect.

Can't modify/remove a field from an ActivityNode using sbt

I created an ActivityNode (an Entry) and I can add custom fields with the
setFields(List<Field> newListField)
fonction.
BUT
I am unable to modify these fields. (In this case I try to modify the value of the field named LIBENTITE)
FieldList list = myEntry.getTextFields();
List<Field> updatedList = new ArrayList<Field>();
//I add each old field in the new list, but I modify the field LIBENTITE
for(Field myField : list){
if(myField.getName().equals("LIBENTITE")){
((TextField)myField).setTextSummary("New value");
}
updatedList.add(myField);
}
myEntry.setFields(updatedList);
activityService.updateActivityNode(myEntry);
This code should replace the old list of fields with the new one, but I can't see any change in the custom field LIBENTITE of myEntry in IBM connections.
So I tried to create a new list of fields, not modifying my field but adding a new one :
for(Field myField:list){
if(!myField.getName().equals("LIBENTITE")){
updatedList.add(myField);
}
}
Field newTextField = new TextField("New Value");
newTextField .setFieldName("LIBENTITE");
updatedList.add(newTextField );
And this code is just adding the new field in myEntry. What I see is that the other custom fields did not change and I have now two custom fields named LIBENTITE, one with the old value and the second with the new value, in myEntry.
So I though that maybe if I clear the old list of Fields, and then I add the new one, it would work.
I tried the two fonctions
myEntry.clearFieldsMap();
and
myEntry.remove("LIBENTITE");
but none of them seems to work, I still can't remove a custom field from myEntry using SBT.
Any suggestions ?
I have two suggestions, as I had (or have) similar problems:
If you want to update an existing text field in an activity node, you have to call node.setField(fld) to update the field in the node object.
Code snippet from my working application, where I'm updating a text field containing a (computed) start time:
ActivityNode node = activityService.getActivityNode(id);
node.setTitle(formatTitle()); // add/update start and end time in title
boolean startFound = false;
// ...
FieldList textfields =node.getTextFields();
Iterator<Field> iterFields = textfields.iterator();
while (iterFields.hasNext()) {
TextField fld = (TextField) iterFields.next();
if (fld.getName().equals(Constants.FIELDNAME_STARTTIME)) {
fld.setTextSummary(this.getStartTimeString()); // NOTE: .setFieldValue does *not* work
node.setField(fld); // write updated field back. This seems to be the only way updating fields works
startFound=true;
}
}
If there is no field with that name, I create a new one (that's the reason I'm using the startFound boolean variable).
I think that the node.setField(fld) should do the trick. If not, there might be a way to sidestep the problem:
You have access to the underlying DOM object which was parsed in. You can use this to tweak the DOM object, which finally will be written back to Connections.
I had to use this as there seems to be another nasty bug in the SBT SDK: If you read in a text field which has no value, and write it back, an error will be thrown. Looks like the DOM object misses some required nodes, so you have to create them yourself to avoid the error.
Some code to demonstrate this:
// ....
} else if (null == fld.getTextSummary()) { // a text field without any contents. Which is BAD!
// there is a bug in the SBT API: if we read a field which has no value
// and try to write the node back (even without touching the field) a NullPointerException
// will be thrown. It seems that there is no value node set for the field. We
// can't set a value with fld.setTextSummary(), the error will still be thrown.
// therefore we have to remove the field, and - optionally - we set a defined "empty" value
// to avoid the problem.
// node.remove(fld.getName()); // remove the field -- this does *not* work! At least not for empty fields
// so we have to do it the hard way: we delete the node of the field in the cached dom structure
String fieldName = fld.getName();
DeferredElementNSImpl fldData = (DeferredElementNSImpl) fld.getDataHandler().getData();
fldData.getParentNode().removeChild(fldData); // remove the field from the cached dom structure, therefore delete it
// and create it again, but with a substitute value
Field newEmptyField = new TextField (Constants.FIELD_TEXTFIELD_EMPTY_VALUE); // create a field with a placeholder value
newEmptyField.setFieldName(fieldName);
node.setField(newEmptyField);
}
Hope that helps.
Just so that post does not stay unanswered I write the answer that was in a comment of the initial question :
"currently, there is no solution to this issue, the TextFields are read-only map. we have the issue recorded on github.com/OpenNTF/SocialSDK/issues/1657"

Can't set Orchard field values unless item already created

I seem to be having a problem with assigning values to fields of a content item with a custom content part and the values not persisting.
I have to create the content item (OrchardServices.ContentManager.Create) first before calling the following code which modifies a field value:
var fields = contentItem.As<MyPart>().Fields;
var imageField = fields.FirstOrDefault(o => o.Name.Equals("Image"));
if (imageField != null)
{
((MediaLibraryPickerField)imageField).Ids = new int[] { imageId };
}
The above code works perfectly when against an item that already exists, but the imageId value is lost if this is done before creating it.
Please note, this is not exclusive to MediaLibraryPickerFields.
I noticed that other people have reported this aswell:
https://orchard.codeplex.com/workitem/18412
Is it simply the case that an item must be created prior to amending it's value field?
This would be a shame, as I'm assigning this fields as part of a large import process and would inhibit performance to create it and then modify the item only to update it again.
As the comments on this issue explain, you do need to call Create. I'm not sure I understand why you think that is an issue however.

Best way to access information inside of another class with TCL?

Basically, I'm trying to create a get method for a tcl class that I have so that I can access data inside that class within a proc that isn't inside a class. For example, it would look like this:
itcl::class foo {
set list []
proc getFilterList {} {
return $list
}
}
proc bar {} {
set list itcl::foo::getFilterList
}
But hilariously the the list contains the phrase "itcl::foo::getFilterList" so I'm obviously doing something wrong. Sorry if this is an obvious one, I just can't seem to figure it out.
In addition to following the selected answer, I also made my variable available at a global scale which works for me seeing as how from creation to manipulation I know exactly when my variable is being modified and when I can access it's values.
Use
proc bar {} {
set list [itcl::foo::getFilterList]
}

ADOMD: Drill down levels without retrieving all members of level

I have code like the following:
Microsoft.AnalysisServices.AdomdClient.Dimension dimension = cubeDef.Dimensions[dimensionName];
string hierarchyName = matches[1].Value.Replace("[", "").Replace("]", "");
Microsoft.AnalysisServices.AdomdClient.Hierarchy hierarchy = dimension.Hierarchies[hierarchyName];
Microsoft.AnalysisServices.AdomdClient.Level adomdLevel = hierarchy.Levels[levelNumber];
MemberCollection levelMembers = adomdLevel.GetMembers();
Which is good to get all the members at a level.
However what I want is to narrow the members to just the ones at have a certain parent.
So that the members are the children from a chosen parent drilled down on.
There are overloads for GetMembers, but I was not able to work out how I could use them to filter in only the parent dimensions children.
Is there a way to do this?
The code I have gets the full level and then filters in code:
foreach (Microsoft.AnalysisServices.AdomdClient.Member memberData in levelMembers)
{
if (memberData.Parent.UniqueName != parentMemberUniqueName)
{ continue; }
// code using child of parent here
}
This is proving slower as I drill down deeper.
Thanks,
Jasonlan

Resources