Solved Disabling horizontal autoscroll of QTreeView when selectionBehavior is SelectRows
-
Hi,
I am experiencing the same "bug" as in this report:
https://bugreports.qt.io/browse/QTBUG-5115If a subclass of QAbstractItemView is configured with autoscroll(true) and the selection mode select the whole row on selection, the autoscrolling should not scroll horizontally. The row are considered as a single entity so scrolling horizontally is a strange behavior.
A proposed workaround is given in the same report basically as:
a) setAutoScroll(false) by default
b) derive from QTreeView, reimplement startDrag and wrap a call to drag->exec like this:
setAutoScroll ( true );
drag->exec ( supportedActions );
setAutoScroll ( false );I have tried to copy the existing code from
QAbstractItemView::startDrag()
and just added the two wrapper lines ending with the\\HACK
comment as below:void TreeView::startDrag(Qt::DropActions supportedActions) { Q_D(QAbstractItemView); QModelIndexList indexes = d->selectedDraggableIndexes(); if (indexes.count() > 0) { QMimeData *data = d->model->mimeData(indexes); if (!data) return; QRect rect; QPixmap pixmap = d->renderToPixmap(indexes, &rect); rect.adjust(horizontalOffset(), verticalOffset(), 0, 0); QDrag *drag = new QDrag(this); drag->setPixmap(pixmap); drag->setMimeData(data); drag->setHotSpot(d->pressedPosition - rect.topLeft()); Qt::DropAction defaultDropAction = Qt::IgnoreAction; if (d->defaultDropAction != Qt::IgnoreAction && (supportedActions & d->defaultDropAction)) defaultDropAction = d->defaultDropAction; else if (supportedActions & Qt::CopyAction && dragDropMode() != QAbstractItemView::InternalMove) defaultDropAction = Qt::CopyAction; setAutoScroll(true); //HACK if (drag->exec(supportedActions, defaultDropAction) == Qt::MoveAction) d->clearOrRemove(); setAutoScroll(false); //HACK // Reset the drop indicator d->dropIndicatorRect = QRect(); d->dropIndicatorPosition = OnItem; } }
However, this does not compile, producing all these errors:
How do I go about implementing the proposed hack in the BUG report?
-
@Diracsbracket
you cannot simply copy and paste method implementations from Qt source code.
Since they are using private classes (Q_D(...)
macro).
The startDrag() method isn't that complicated and can mostly be reimplemented. You need to do so and replace all method calls to the d-pointer with your custom implementations. -
@raven-worx said in Disabling horizontal autoscroll of QTreeView when selectionBehavior is SelectRows:
you cannot simply copy and paste method implementations from Qt source code.
Well, since this is a
virtual
method, I just thought I could use exactly the same code in a derived class, but apparently not. I didn't know about the D pointer, so thanks.And yes, nothing is difficult, if you know how.
-
@raven-worx said in Disabling horizontal autoscroll of QTreeView when selectionBehavior is SelectRows:
You need to do so and replace all method calls to the d-pointer with your custom implementations
If it's that easy, can you show me how to do it? How can I reimplement the call to e.g.
d->selectedDraggableIndexes();
or worse,d->model->mimeData(indexes);
? -
@Diracsbracket said in Disabling horizontal autoscroll of QTreeView when selectionBehavior is SelectRows:
Well, since this is a virtual method, I just thought I could use exactly the same code in a derived class, but apparently not
virtual methods are only only tell that they are derivable. But for their contents the general visibility rules apply. The d-pointer is private and thus only accessible in this class (or it's friend classes).
@Diracsbracket said in Disabling horizontal autoscroll of QTreeView when selectionBehavior is SelectRows:
How can I reimplement the call to e.g. d->selectedDraggableIndexes(); or worse, d->model->mimeData(indexes);?
see the implementation of this method. Basically it's just getting a list of all selected indexes and remove the ones which are not drag enabled (by inspecting their item flags)
The model is already available via the public interface (QAbstractItemView::model()), so no problem there.
-
@raven-worx said in Disabling horizontal autoscroll of QTreeView when selectionBehavior is SelectRows:
The model is already available via the public interface (QAbstractItemView::model())
Yes, that one is easy. The others are less straight forward.
Anyway... This is way too much hassle for what should have been a simple setting to distinguish between vertical autoscroll and horizontal autoscroll.I will just try to intercept the selection change, and override the selected column to 0.
-
@Diracsbracket said in Disabling horizontal autoscroll of QTreeView when selectionBehavior is SelectRows:
I will just try to intercept the selection change, and override the selected column to 0.
you may want to look at QAbstractItemView::selectionCommand() then.
I am not sure if it is also called in for your case, but in general this method is called before the actual selection change happens. Thus you can prevent a "jumping effect" in your GUI. -
@raven-worx Cheers!
-
I found an even lazier method, as I just realized that the autoscroll does not happen if I don't use the
resizeColumnToContents()
method on the columns.In that case, even when clicking on an item with truncated text, the list won't scroll horizontally, unless the viewport width is below some value it seems.
I will just settle with this for now.