Daguerreo / NodeEditor

Qt Node Editor. Dataflow programming framework
BSD 3-Clause "New" or "Revised" License
18 stars 5 forks source link

Removing ports lets edges hanging #10

Closed mechatheo closed 3 years ago

mechatheo commented 3 years ago

Hello,

first of all, thank you very much for adding the dynamic port feature to the library. I recently started using QtNodes and very soon realized that dynamic ports are crucial to my application. Before starting to fiddle with the library my self, i just thought give it a shot, maybe there is a branch for that and voila!

A problem i came across is the following: When i remove my dynamic output ports, which have an active connection, the connector is not removed automatically. Sure users could work around it, but in my opinion that should happen automatically.

Here are some screenshots from my application illustrating the issue. Here is a graph, an embedded widget controls which parameters are queried. The delete button resets the Parameter Reader and removes all ports.

image

When i do so the connectors are left hanging as shown in the following screenshot:

image

Trying to remove the hanging connectors manually results in a crash with the following stack trace:

1   std::_Hashtable<QUuid, std::pair<QUuid const, QtNodes::Connection *>, std::allocator<std::pair<QUuid const, QtNodes::Connection *>>, std::__detail::_Select1st, std::equal_to<QUuid>, std::hash<QUuid>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>>::_M_find_before_node hashtable.h        1542 0x7ffff7c3c3db 
2   std::_Hashtable<QUuid, std::pair<QUuid const, QtNodes::Connection *>, std::allocator<std::pair<QUuid const, QtNodes::Connection *>>, std::__detail::_Select1st, std::equal_to<QUuid>, std::hash<QUuid>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>>::_M_erase            hashtable.h        1906 0x7ffff7c3c2c5 
3   std::_Hashtable<QUuid, std::pair<QUuid const, QtNodes::Connection *>, std::allocator<std::pair<QUuid const, QtNodes::Connection *>>, std::__detail::_Select1st, std::equal_to<QUuid>, std::hash<QUuid>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true>>::erase               hashtable.h        772  0x7ffff7c3c25d 
4   std::unordered_map<QUuid, QtNodes::Connection *>::erase                                                                                                                                                                                                                                                                                                                                        unordered_map.h    815  0x7ffff7c3aadd 
5   QtNodes::NodeState::eraseConnection                                                                                                                                                                                                                                                                                                                                                            NodeState.cpp      75   0x7ffff7c43b3e 
6   QtNodes::Connection::removeFromNodes                                                                                                                                                                                                                                                                                                                                                           Connection.cpp     271  0x7ffff7c0ac06 
7   QtNodes::FlowScene::deleteConnection                                                                                                                                                                                                                                                                                                                                                           FlowScene.cpp      189  0x7ffff7c15931 
8   QtNodes::FlowView::deleteSelectedNodes                                                                                                                                                                                                                                                                                                                                                         FlowView.cpp       310  0x7ffff7c2dee2 
9   QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (QtNodes::FlowView:: *)()>::call(void (QtNodes::FlowView:: *)(), QtNodes::FlowView *, void * *)                                                                                                                                                                                                                 qobjectdefs_impl.h 152  0x7ffff7c310d4 
10  QtPrivate::FunctionPointer<void (QtNodes::FlowView:: *)()>::call<QtPrivate::List<>, void>(void (QtNodes::FlowView:: *)(), QtNodes::FlowView *, void * *)                                                                                                                                                                                                                                       qobjectdefs_impl.h 185  0x7ffff7c31048 
11  QtPrivate::QSlotObject<void (QtNodes::FlowView:: *)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase *, QObject *, void * *, bool *)                                                                                                                                                                                                                                          qobjectdefs_impl.h 414  0x7ffff7c30f75 
12  QMetaObject::activate(QObject *, int, int, void * *)                                                                                                                                                                                                                                                                                                                                                                   0x7ffff6c5a458 
13  QAction::triggered(bool)                                                                                                                                                                                                                                                                                                                                                                                               0x7ffff76403e6 
14  QAction::activate(QAction::ActionEvent)                                                                                                                                                                                                                                                                                                                                                                                0x7ffff7642aa2 
15  QAction::event(QEvent *)                                                                                                                                                                                                                                                                                                                                                                                               0x7ffff764336f 
16  QApplicationPrivate::notify_helper(QObject *, QEvent *)                                                                                                                                                                                                                                                                                                                                                                0x7ffff7646a66 
17  QApplication::notify(QObject *, QEvent *)                                                                                                                                                                                                                                                                                                                                                                              0x7ffff76500f0 
18  QCoreApplication::notifyInternal2(QObject *, QEvent *)                                                                                                                                                                                                                                                                                                                                                                 0x7ffff6c2e93a 
19  QShortcutMap::dispatchEvent(QKeyEvent *)                                                                                                                                                                                                                                                                                                                                                                               0x7ffff70420ae 
20  QShortcutMap::tryShortcut(QKeyEvent *)                                                                                                                                                                                                                                                                                                                                                                                 0x7ffff7042193 
... <More>                                                                                                                                                                                                                                                                                                                                                                                                                                

What are the thoughts on this? Am i misusing the feature? Should i manually remove the connections when ports are removed?

mechatheo commented 3 years ago

Okay i think the problem was on my side after all, i was removing the ports in batch mode and did send the signals only after everything was done. However in the meantime the internal port structure has been resized already. Now removing one after another and sending the signal right afterwards works.

Daguerreo commented 3 years ago

Dynamic port management requires extra care in managing the timing of signaling, otherwise it can be treaky. Glad you solved your issue. If you have a little example for dynamic output you would add it could be quite useful :)