Update a QGraphicsItem whilst a drag is occuring - qt

I'm creating a QGraphicsView-derived widget which, amongst other things, needs to create connections between items in it - a little like a control flow graph. But I am having trouble implementing a method to 'draw' the connections
I've tried two approaches:
Creating a QGraphicsLineItem-derived object when the source object's mouseMoveEvent(..) is fired, and updating it with each subsequent move. The line is drawn and updated successfully, but ultimately this does not work because it seems that moving the mouse 'locks' the event loop into only handling mouse move events, so the other object's hoverEnterEvent(..)/hoverMoveEvent(..)/etc. methods are not called (these are required to finalise the connection).
Creating a QDrag instance in the mouseMoveEvent(..) to create the connection between two objects allows the two objects to form a connection once dropped, but ultimately this does not work because the QDrag::exec() call provides no means for other objects to be notified of the mouse moving - so the drawn connection cannot be updated.
I really need a mix of the two: in a perfect world the QDrag::exec() call would allow other some sort of notification of a mouse move, so I could update the object that represents the connection. Does anybody have a suggestion?
Similar to this question.

I have an open source widget that does this, it is for PyQt, but it may help for what you are looking for.
You can find it in the projexui framework at http://dev.projexsoftware.com/projects/projexui
The code you are looking for is specifically the XNodeWidget class found in projexui/widgets/xnodewidget
Ultimately, I am using the mouse press event to start a connection via the scene and am ignoring the event (based on some sort of trigger - control press or hotspot zone etc.)
Hope that helps!
(an example of what it looks like is the table view on the Orbiter app - http://www.projexsoftware.com/software/orbiter)

Related

Propagate event to entire object

I just recently started exploring Qt (version 5 at the moment) and I came across an issue to which I could not find any solution:
I would like to send a custom event to the main window such that the event is then propagated to the entire object tree (given by QObject::dumpObjectTree()). Then, certain parts of the object tree can choose to react to the event.
Is there a method to do so in Qt?
What you're looking for (a kind of broadcast event) does not exist in Qt. Events are targeted to specific objects.
Signals are closer to what you want. You can generate a signal without specifying who it's for. Then any other object is able to connect a slot to that signal if it's interested in it.

UITableViewCells and NSURLConnection

I have a custom UITableViewCell, and when the user clicks a button i make a request to a server and update the cell. I do this with a NSUrlConnection and it all works fine (this is all done inside the cell class) and once it returns it fires a delegate method and the tableivew controller handles this. However when i create the cell in the tableview, i use the dequeue method and reuse my cells. So if a cell has fired a asynchronous nsurlconnection, and the cell gets reused whilst this is still going on, will this in turn erase the current connection? I just want to make sure that if the cell is reused, the actual memory that was assigned to the cell is still there so the connection can fulfil its duty??
You can customize the behavior of a UITableViewCell by subclassing it and overriding the -perpareForReuse method. In this case, I would recommend destroying the connection when the cell is dequeued. If the connection should still keep going, you’ll need to remove the reference to it (set it to nil) and handle its delegate methods elsewhere.
It's never a good idea to keep a reference of a connection or any data that you want to display in a cell, no matter how much of effort you put into it afterward to work around to arising problems. Your approach will never work reliable.
In your case, if the user quickly scrolls the table view up and down, your app will start and possibly cancel dozens of connections and yet never finishes to load something. That will be an awful user experience, and may crash the app.
Better you design your app with MVC in mind: the cell is just a means to display your model data, nothing else. It's the View in this architectural design.
For that purpose the Table View Delegate needs to retrieve the Model's properties which shall to be displayed for a certain row and setup the cell. The model encapsulates the network connection. The Controller will take the role to manage and update change notification and process user inputs.
A couple of Apple samples provide much more details about this topic, and there is a nice introduction about MVC, please go figure! ;)
http://developer.apple.com/library/ios/#documentation/general/conceptual/devpedia-cocoacore/MVC.html
The "Your Second iOS App: Storyboards" also has a step by step explanation to create "Data Controller Classes". Quite useful!
Now, when using NSURLConnection which updates your model, it might become a bit more complex. You are dealing with "lazy initializing models". That is, they may provide some "placeholder" data when the controller accesses the property instead of the "real" data when is not yet available. The model however, starts a network request to load it. When it is eventually loaded, the model must somehow notify the Table View Controller. The tricky part here is to not mess with synchronization issues between model and table view. The model's properties must be updated on the main thread, and while this happens, it must be guaranteed that the table view will not access the model's properties. There are a few samples which demonstrate a few techniques to accomplish this.

How to enforce calling a cancel or other methods once the user leave the dialog

I have a case represented by user starting a dialog to create a "certain node" and that dialog has two choices only inside it one for create which implies an update of properties that entered by the user and other for cancel/close.
The complete scenario is represented here :
Listener for starting dialog (action Listener) that will create a anode without any properties for prepare it to the create process. Why Listener because i use the same dialog to serve multiple
type of nodes and i need the listener to supply a node of a certain type without properties that the user will use it later.
Create will update properties of a node, that created in the listener.
Cancel/Close will removed the temporal referenced node that created previously in the listener.
Now, i'm ensure that once the user leave the dialog from the close button the temporal node is removed but what about leaving the dialog by clicking on another actions in the page such as logout, company home or others.
Your replies are highly appreciated.
Thanks
There are many different ways that your 2nd stage could not get run. Certainly the user could browse away to a different link, but equally they could close their browser, or time out, or even the server could be shut down.
What you'll want to do instead is to have a background job run. This job should search for these temporary nodes, and if they were created too long ago (eg more than an hour) then delete them.
To make this easy, you'll want to ensure that your temporary nodes have a specific type or aspect on them, so you can locate them easily with a lucene query.

Preventing timers from running when something is already busy (using Qt)

In my mathematical application I am using timers to regularly perform certain actions. These actions can also be configured by my users. Now I don't want these actions to be executed if there is already another action busy.
E.g. if the user just started a complex calculation by selecting a menu entry, I don't want to execute the actions behind my timers.
Problem is that the user can execute an action via a lot of different ways (via the menu, by clicking somewhere, via popup menu, via drag-and-drop, ...). What I effectively want is to prevent the timers from going off if the application is currently not in the main event loop.
I will give a more concrete example to make it clearer:
At startup I create the timers
If a timer goes off, I execute some actions which, in practice, could access almost every bit in may application's data structure.
Now suppose the user starts a mathematical algorithm (via the menu, by clicking or by dragging elements on the screen, it doesn't matter how he started it).
The algorithm will perform lots of calculations (in the main thread). Since they are executed in the main thread, the timer events will not go off.
Now the algorithm shows a message box (could be a warning or a question).
While the message box is open, events are processed again, including my timer events, which could possibly perform incorrect calculations because there is already another algorithm running.
Reworking my application so that I move logic to a separate worker thread, or adding checks to all of my actions isn't possible at this moment. So please don't suggest to completely rework my application.
What I tried so far is the following:
Using postEvent to send an event, hoping that this event would only be executed in the main event loop. Unfortunately, also the message box's event loop seems to process posted events.
Using the QEvent::WindowBlocked and QEvent::WindowUnblocked events to see when a modal dialog was opened. In my timer-event-logic I can check whether we are between QEvent::WindowBlocked-QEvent::WindowUnblocked calls or not. Unfortunately, these events only work for modal dialogs created by Qt itself, not for other dialogs (e.g. the Windows MessageBox, or the system's printer configuration dialog). Also, this trick would not help if there would be other event loops created by sub routines.
What I actually need to solve my problem is a simple function, that:
If the application is handling an event in the main event loop returns true
If the application is handling an event in another [sub] event loop, it returns false
An alternative could be to return a level that indicates the 'depth' of the handled event.
Anyone suggestions?
You could hook into the event loop of your main thread/application using QAbstractEventDispatcher. Conditionaly filter out QTimer-events based on your application state.

howto avoid massive notification in DataBinding

I guess it's quite a common problem in databinding scenarios.
What do you usually do, if you are running a batch update and want to avoid that a propertychanged-dependend calculations/actions/whatever are executed for every single update?
The first thing which usually comes to my mind, is to either introduces a new boolean or unhook/hook the eventhandler, ...
What I don't like about this approaches is:
they introduce new complexity (has to be maintained, ...)
they are error prone, because you have to make sure that a suppressed notifications are sent afterwards
I'm wondering if somebody addressed this problem already in a more convenient way that is more easy to handle?
tia
Martin
Edit: not to missunderstand me. I know about the things .NET provides like RaiseListChangedEvents from BindingList, ... They are all addressing the problem in more/less the same way as I described, but I'm searching for a different way which doesn't have to listed drawbacks.
Maybe I'm on the wrong track, but I though I give it a try here...
There isn't a single one-size-fits-all solution, unfortunately. I've applied or seen the following solutions:
There are two singals. One signal is emitted when the change comes from a user action, the other always fires. This allows to distinguish between changes in the UI and updates by code.
A boolean to protect code
The property event framework stops propagating events automatically when a value didn't really change.
A freeze/thaw method on the signal or the signal manager (i.e. the whole framework)
A way to merge signals into a single one. You can do N updates and they get collected into M signals where M <= N. If you change the same property 100 times, you still only get 1 signal.
Queuing of signals (instead of synchronous execution). The queuing code can then merge signals, too. I've used this with great success in an application that doesn't have a "Save" button. All changes are saved to the database as you make them. When you change a text, the changes are merged over a certain time (namely until the previous DB update returns) and then, they are committed as a single change.
An API to set several values at once; only a single signal is emitted.
The signal framework can send signals at different levels of granularity. Say you have a person with a name. When you change the name, you get two signals: One for the name change and one "instance field changed". So if you only care "has something changed", then you can hook into the instance instead of all the fields.
What platform? The post makes me think .NET.
What is the underlying objects? For example, BindingList<T> as a source allows you to disable notifications by setting RaiseListChangedEvents to false while doing the update.
Other than that (or similar); yes, disconnect the binding during big updates
The easiest route to take is to use the BindingSource component for your data binding. Instead of binding your controls to a particular object (or IList), use that object as the DataSource for the BindingSource, then bind the controls to the BindingSource.
The BindingSource class has SuspendBinding() and ResumeBinding() functions.

Resources