Skip to content

Added Expand/Collapse API to GroupLayer#4009

Closed
PalaBeaveR wants to merge 3 commits intomapeditor:masterfrom
PalaBeaveR:3997_expand_collapse_layers_api
Closed

Added Expand/Collapse API to GroupLayer#4009
PalaBeaveR wants to merge 3 commits intomapeditor:masterfrom
PalaBeaveR:3997_expand_collapse_layers_api

Conversation

@PalaBeaveR
Copy link
Copy Markdown

Related issue: #3997

Added a new scripting field in GroupLayer called expanded that controls the layer's expand state.

From what I'd been able to gather, in order to expand/collapse layers I would need access to LayerView(QTreeView) which controls layer expansion with setExpanded. It wasn't possible since those properties were privated so I added getters to access LayerDock, LayerView, QAbstractProxyModel.

Right now the expanded state is stored in GroupLayer and is not synced, however since Qt already stores that state itself, the scripting interface can be made to use that instead.

I also don't know if the same API is appropriate for ObjectGroup(as requested by #3997), but i have that code made in the same way as GroupLayer if it is needed.

I'm not sure if the new definitions in changelayer.h/undocommands.h are needed since i was just copying code from other places in the repo so it would be nice to have that clarified.

Group layers can now be expanded/collapsed from scripts
@bjorn
Copy link
Copy Markdown
Member

bjorn commented Jul 14, 2024

I think it would be better to allow the scripting API to interact directly with the UI. There is no need for this to go through an undo command. I also don't think we need to store that state on the GroupLayer object itself.

There already is QSet<int> expandedGroupLayers on the MapDocument, which actually exists only because it is saved in the session. But if the scripting API just talks to the view, updating that container should happen automatically.

Maybe it could just be some additional functions like tiled.mapEditor.layersView.setExpanded(layer, true), along with isExpanded.

@PalaBeaveR
Copy link
Copy Markdown
Author

PalaBeaveR commented Jul 14, 2024

Alright I've removed the state from GroupLayer and added setExpanded/isExpanded to tiled.mapEditor.layersView.
ObjectGroup and tiled.mapEditor.objectsView got the same treatment.

One thing I noticed is that for now changing group layer expanded state does not reflect in ObjectsView. This is what the code does right now, but we need to figure out how to go about it, because i assume it would be better to not sync them between trees, but need some input on that.

Also I got segfaults when passing the wrong layer to the setExpanded method and want to know whether this should be handled or not.

@bjorn bjorn self-assigned this Nov 18, 2024
Copy link
Copy Markdown
Member

@bjorn bjorn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PalaBeaveR Sorry it seems this one got buried for way too long. Are you still interested in finishing it? It looks like you're almost there and I've leaving some notes now.

Somebody was asking about taking this over at #3997, so alternatively you can also let them know they can proceed.

One thing I noticed is that for now changing group layer expanded state does not reflect in ObjectsView. This is what the code does right now, but we need to figure out how to go about it, because i assume it would be better to not sync them between trees, but need some input on that.

This is fine. Since we're interacting directly with the views, it works the same way as if the user has clicked around in the UI, and expansion of group layers or object groups is not synchronized between views.

Also I got segfaults when passing the wrong layer to the setExpanded method and want to know whether this should be handled or not.

That should definitely be prevented, even misuse of the scripting API should not crash Tiled if it can be prevented. At the very least you need to check the incoming pointers to see if they're not nullptr to avoid a crash, and if you can still crash it then we should have a look at how we can prevent that.

QList<Layer*>::iterator end() { return mLayers.end(); }
QList<Layer*>::const_iterator begin() const { return mLayers.begin(); }
QList<Layer*>::const_iterator end() const { return mLayers.end(); }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please avoid changing this file at all. I realize these are remnants of earlier changes.

auto documentManager = DocumentManager::instance();
auto mapEditor = static_cast<MapEditor*>(documentManager->editor(Document::MapDocumentType));
mapEditor->layerDock()->setExpanded(groupLayer(), expanded);
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert your changes to editablegrouplayer.cpp/h and editableobjectgroup.cpp.h entirely. Since we decided to go with a view-based API we don't need these functions here at all.

void setMapDocument(MapDocument *mapDocument);

Q_INVOKABLE bool isExpanded(EditableGroupLayer *layer) const { return isExpanded(layer->groupLayer()); };
Q_INVOKABLE void setExpanded(EditableGroupLayer *layer, bool expanded) { setExpanded(layer->groupLayer(), expanded); };
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These functions need to check at the very least that layer is not a nullptr. If so, raise a script error (see other script functions for how to do this) and return. I think their implementation should be moved into the cpp file.

void setMapDocument(MapDocument *mapDoc);

Q_INVOKABLE bool isExpanded(EditableObjectGroup *layer) const { return isExpanded(layer->objectGroup()); };
Q_INVOKABLE void setExpanded(EditableObjectGroup *layer, bool expanded) { setExpanded(layer->objectGroup(), expanded); };
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here regarding nullptr checks.

@bjorn
Copy link
Copy Markdown
Member

bjorn commented Mar 19, 2026

I'll close this one now that @Oval17 has taken over at #4379. Thanks for getting this started, @PalaBeaveR!

@bjorn bjorn closed this Mar 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants