NSTableView detect row scrolled off - nstableview

I have a view-based NSTableView and each row has to generate some images which takes time. These are done on a background NSoperationQueue and started when a request for an image is made (through a binding).
When a row is scrolled off screen, if the NSOperation is still pending, I'd like to be able to cancel it, but I need to detect when a row is no longer visible. Should I be looking for the delloc on my CustomTableRowView, CustomTableCellView, or something else?
I guess I need the opposite of tableView:willDisplayCell:forTableColumn:row:
Some sort of tableView:willHideCell:forTableColumn:row:
Apple's TableView Playground has a comment:
// We would have to keep track of the block with an NSBlockOperation, if we wanted to later support cancelling operations that have scrolled offscreen and are no longer needed. That will be left as an exercise to the user.
I can cancel the operation, but I am not sure how to detect when a row is scrolled off.

I believe this is solved with
tableView:didRemoveRowView:forRow:
though I am not sure if it is called immediately after the row scrolls off or a short while later.

Related

How to get notified when changes in the document actually happens?

The following question is about RichTexFX. For standard JavaFX components, I've never had this issue before.
In my application, I am adding text content to the end of a GenericStyledArea (actually a subclass of it, but that should have no impact on the behaviour I am observing). Every time new content has been added to the end of the document, I scroll to the bottom so the new content is always in view. I use the following code to scroll to bottom (actually written in Kotlin, but I have translated it to Java below):
showParagraphAtTop(document.getParagraphs().size() - 1)
This almost always works. However, in some cases the screen will not show the newly added element. I have come to the conclusion that by the time showParagraphAtTop is called, some internal state in richtextfx has not been updated. This is because I added a button that I can click on to call the code above, and if I click it after the scroll failed, it scrolls to the bottom as expected.
I have tried various ways to work around this, but the only solution that works reliably is to do the following:
FxTimer.runLater(Duration.ofMillis(10), () -> showParagraphAtTop(getDocument().getParagraphs().size() - 1));
In other words, I force a short delay before actually scrolling the screen.
Even though the above works, it's incredibly unsatisfactory, and there should be some way to do this the right way. However, I have been unable to figure it out.
I saw another question (Autoscroll JavaFX TextFlow) which suggested the use of layout() prior to scrolling. This does not remove the problem, although it does appear to make it less common.

QTableWidget Scrolling With Selected Item

So i am using a QTableWidget as a logger of sorts for a user, with new rows being inserted at the top, and bottom ones falling off eventually as i read in updates every second or so.
I am currently running these 3 commands to keep the user from being able to do anything with the widget.
summaryTable->setSelectionMode(QAbstractItemView::NoSelection);
summaryTable->setFocusPolicy(Qt::NoFocus);
summaryTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
This works, the user cant select a box(doesnt get highlighted more on that later), cant edit a box, all is good.
Except even if a user clicks on a cell, even though its not highlighted visibly there is still something allowing it to be selected such that when that cell gets "pushed" down below the current scroll area from inserts at the top the table begins scrolling down to follow this cell all the way to the bottom.
Obviously this is confusing, if a user clicks a cell within a few seconds its going to keep scrolling them down the table over and over again and it becomes a fight for them to scroll back up and click on a header or something to prevent future scrolling.
How do i prevent this? I thought by preventing selection and turning off what i did it would stop this, but there is still some type of selection happening within QT even if its not visible as its tracking the selected cell.
Oops, didnt realize there is a SetAutoScroll method, setting this to false fixed the issue.
This Method May Work QTableWidget::scrollToItem() or
QTableWidget::scrollTo() is will Work :)
You can manually scroll the item by putting row index as -
self.ui.tableWidget.verticalScrollBar().setValue(index)
OR
You can auto scroll the item by current index:
row = self.ui.tableWidget.currentIndex().row()
self.ui.tableWidget.verticalScrollBar().setValue(row)

How to make two side by side Qt Windows sticky and act like a single window?

I am trying to implement a scenario where two Qt windows will be placed side by side and they will be kind of sticky to each other. By dragging one of them, the other also gets dragged. Even when doing an alt-tab they should behave like a single window.
Any help or pointer will be extremely helpful.
-Soumya
What you describe sounds like it's a good fit for a "docking" scenario. You're probably most familiar with docking from toolbars; where you can either float a toolbar on its own or stick it to any edge of an app's window. But Qt has a more generalized mechanism:
http://doc.qt.io/qt-5/qtwidgets-mainwindows-dockwidgets-example.html
http://doc.qt.io/qt-5/qdockwidget.html
It won't be a case where multiple top level windows are moved around in sync with their own title bars and such. The top-level windows will be merged into a single containing window when they need to get "sticky". But IMO this is more elegant for almost any situation, and provides the properties you seem to be seeking.
Install a event filter on the tracked window with QObject::installEventFilter() and filter on QEvent::Move
You can then change the position of tracking window whenever your filter is called with that event type.
I found a way to keep two windows anchored: when the user moves a window, the other follows, keeping its relative position to the moved one.
It is a bit of a hack, because it assumes that the event QEvent::NonClientAreaMouseButtonPress is sent when the user left clicks on the title bar, holding it pressed while he moves the window, and releasing it at the end, so that QEvent::NonClientAreaMouseButtonRelease is sent.
The idea is to use the QWidget::moveEvent event handler of each window to update the geometry of the other, using QWidget::setGeometry.
But the documentation states that:
Calling setGeometry() inside resizeEvent() or moveEvent() can lead to infinite recursion.
So I needed to prevent the moveEvent handler of the windows which was not moved directly by the user, to update the geometry of the other.
I achieved this with result via QObject::installEventFilter, intercepting the summentioned events.
When the user clicks on the title bar of WindowOne to start a move operation, WindowOne::eventFilter catches its QEvent::NonClientAreaMouseButtonPress and sets the public attribute WindowTwo::skipevent_two to true.
While the user is moving WindowOne, WindowTwo::moveEvent is called upon the setGeometry operation, performed on WindowTwo from WindowOne::moveEvent.
WindowTwo::moveEvent checks WindowTwo::skipevent_two, and if it is true, returns without performing a setGeometry operation on WindowOne which would cause infinite recursion.
As soon as the user releases the left mouse button, ending the window move operation, WindowOne::eventFilter catches QEvent::NonClientAreaMouseButtonRelease and sets back the public attribute WindowTwo::skipevent_two to false.
The same actions are performed if the user clicks the titlebar of WindowTwo, this time causing WindowOne::skipevent_one attribute to be set to true and preventing WindowOne::moveEvent to perform any setGeometry operation on WindowTwo.
I believe this solution is far from being clean and usable. Some problems:
I am not sure when and why QEvent::NonClientAreaMouseButtonRelease and QEvent::NonClientAreaMouseButtonRelease are dispatched, apart from the case considered above.
When/if one window is resized without user interaction or without the proper mouse clicks from the user, probably everything will go the infinite recursion way.
There is no guarantee that those mouse events will be dispatched the same way in the future.
Free space for more...
Proof of concept:
https://github.com/Shub77/DockedWindows

How can I create a draganddrop wrapper inside a table row, that can represent the whole row

When I use treetable in Vaadin, it is working fine drag and drop the whole row when click the left and right blank ereas. but that is not user friendly, I wanna create a draggable layout inside the row, let's say the 1st component of the each row, that when clicking it, the whole row is selected and can be draged and dropped to reorder.
The thing is I can create a vertical layout with wrapper doing that, but drag mode is only for its component or the wrapper itself, and when doing the drag action, it doesn't actually showing the whole row is moving, which may confuse the clients. What can I do to make it looking like I am dragging the whole row, similar with the one you drag the blank area of each row? Thanks.
I'm afraid there currently is no way for adding a wrapper that would extend the entire row instead of just one cell. To do this you'd need to extend the client-side implementation of Table (VScrollTable) and this is not something I would recommend as it is quite complex.
I do think that what you describe should be possible in core Vaadin (without using drag & drop wrappers), so could you please file a ticket at dev.vaadin.com? And please attach a small application showing the problem to make it easier for us to see the problem and fix it.
Anyways, in order for you to get it working today I'd suggest that you change your UI design a bit and for example borrow drag handles from iOS. By this I mean that you could add an icon that suggests "draggable" as a background-image in the first cell (or in the row header cell of each row) that encourages the user to grab the row there, where it is "empty" and dragging works. This way the user might not be too confused if dragging only works reliably in some parts of the rows.

Qt drag and drop animation

I have two QTreeViews side by side and I want to implement dragging one item from one table into the other table. What I would like to do however is that when the item to be dropped reaches the destination table, that the two rows sort of "make space for it" and separate to really show the user exactly where the item would be dropped. Could someone point me in the right direction as to how to do this as I have no idea really where to start.
Thanks,
Stephen
http://doc.trolltech.com/latest/dnd.html should lead you to pretty much anything you want to do re drag and drop.
As for your specific goal, you need to implement QWidget::dragMoveEvent(QDragMoveEvent* event), which will get called every time the mouse moves within the destination tree while dragging an item. Then get the position of the cursor with QDragMoveEvent::pos(). After that, while in dragMoveEvent, use QTreeView::indexAt(pos()) to get the item under the mouse. Now, I don't know how to get the items to separate in a smooth animated way, which would be ideal. But what you can do is (temporarily) add a blank item to the list, which will have the almost identical effect. Then implement QWidget::dropEvent() to handle the drop event, and when this happens delete the blank item and insert the dragged item in the location where it was.

Resources