PDA

View Full Version : why Qt classes seem so inflexibile (example: dropindicator)



Andrew
11th April 2007, 14:39
Hi,

I wanted to change a minor thing in QListWidget
I don't like how drop indicator is working.
In the current default behaviour, if you move the drag item(s) around and if the cursor is on the right position, the drop indicator appears after \ before an item or even on the entire item (if you change and a flag to the item flags)

Now, I searched in the doc and source code to see how can I make the region which determines to display the drop indicator after \ before an item, a little big bigger.

My result now is that it can be done only if I re-write drag move and drop events.

So I have 2 issues:
1. to make the dropindicator 'zone' a little bigger.
2. when dropping an item over another item the default behaviour will append the dragged item at the end of the list.

for #2: i end up in this code which shows clearly this behaviour:

bool QAbstractItemViewPrivate::dropOn(QDropEvent *event, int *dropRow, int *dropCol, QModelIndex *dropIndex)
{
.....

// If we are allowed to do the drop
if (model->supportedDropActions() & event->proposedAction()) {
int row = -1;
int col = -1;
if ((index != root) &&
(model->flags(index) & Qt::ItemIsDropEnabled
|| model->flags(index.parent()) & Qt::ItemIsDropEnabled)) {
dropIndicatorPosition = position(event->pos(), q->visualRect(index));
switch (dropIndicatorPosition) {
case QAbstractItemView::AboveItem:
row = index.row();
col = index.column();
index = index.parent();
break;
case QAbstractItemView::BelowItem:
row = index.row() + 1;
col = index.column();
index = index.parent();
break;
case QAbstractItemView::OnItem:
case QAbstractItemView::OnViewport:
break;
}
} else {
dropIndicatorPosition = QAbstractItemView::OnViewport;
}
*dropIndex = index;
*dropRow = row;
*dropCol = col;
return true;
}
return false;
}

so this means that if the dragged item is on another item the OUT variables dropIndex is -1which makes QListWidget::dropEvent( ) to append at the end.

void QListWidget::dropEvent(QDropEvent *event) {

.....

if (d->dropOn(event, &row, &col, &topIndex)) {

.....

// insert them back in at their new positions
for (int i = 0; i < persIndexes.count(); ++i) {
// Either at a specific point or appended
if (row == -1) {
insertItem(count(), taken.takeFirst()); <---------- ends up here
} else {
int r = dropRow.row() >= 0 ? dropRow.row() : row;
insertItem(qMin(r, count()), taken.takeFirst());
}
}


why QAbstractItemView::OnItem is implemented like this is a mistery to me.

wysota
11th April 2007, 16:06
Could you explain a bit further what are you trying to achieve? What does "after/before an item" mean? Maybe you could present a mockup of what you want to have?

Brandybuck
11th April 2007, 17:40
You aks "why Qt classes seem so inflexibile". The answer is that they are not inflexible, they are very flexible. I know some C++ toolkits that won't even let you subclass a widget! But that does not mean that with Qt it is zero effort to do anything you want. Just that Qt gives you the flexibility to do it.

I'm not fully understanding your question with regards to list widgets, but I do note that your source code snippet shows that QListWidget determines the dropzone based on the visualRect() of the index. This may give you a clue.