/** @short Reimplemented to show custom pixmap during drag&drop Qt's model-view classes don't provide any means of interfering with the QDrag's pixmap so we just rip off QAbstractItemView::startDrag and provide our own QPixmap. */ void MsgListView::startDrag(Qt::DropActions supportedActions) { // indexes for column 0, i.e. subject QModelIndexList baseIndexes; Q_FOREACH(const QModelIndex &index, selectedIndexes()) { if (!(model()->flags(index) & Qt::ItemIsDragEnabled)) continue; if (index.column() == Imap::Mailbox::MsgListModel::SUBJECT) baseIndexes << index; } if (!baseIndexes.isEmpty()) { QMimeData *data = model()->mimeData(baseIndexes); if (!data) return; // use screen width and itemDelegate()->sizeHint() to determine size of the pixmap int screenWidth = QApplication::desktop()->screenGeometry(this).width(); int maxWidth = qMax(400, screenWidth / 4); QSize size(maxWidth, 0); // Show a "+ X more items" text after so many entries const int maxItems = 20; QStyleOptionViewItem opt; opt.initFrom(this); opt.rect.setWidth(maxWidth); opt.rect.setHeight(itemDelegate()->sizeHint(opt, baseIndexes.at(0)).height()); size.setHeight(qMin(maxItems + 1, baseIndexes.size()) * opt.rect.height()); // State_Selected provides for nice background of the items opt.state |= QStyle::State_Selected; // paint list of selected items using itemDelegate() to be consistent with style QPixmap pixmap(size); pixmap.fill(Qt::transparent); QPainter p(&pixmap); for (int i = 0; i < baseIndexes.size(); ++i) { opt.rect.moveTop(i * opt.rect.height()); if (i == maxItems) { p.fillRect(opt.rect, palette().color(QPalette::Disabled, QPalette::Highlight)); p.setBrush(palette().color(QPalette::Disabled, QPalette::HighlightedText)); p.drawText(opt.rect, Qt::AlignRight, tr("+ %n additional item(s)", 0, baseIndexes.size() - maxItems)); break; } itemDelegate()->paint(&p, opt, baseIndexes.at(i)); } QDrag *drag = new QDrag(this); drag->setPixmap(pixmap); drag->setMimeData(data); drag->setHotSpot(QPoint(0, 0)); Qt::DropAction dropAction = Qt::IgnoreAction; if (defaultDropAction() != Qt::IgnoreAction && (supportedActions & defaultDropAction())) dropAction = defaultDropAction(); else if (supportedActions & Qt::CopyAction && dragDropMode() != QAbstractItemView::InternalMove) dropAction = Qt::CopyAction; if (drag->exec(supportedActions, dropAction) == Qt::MoveAction) { // QAbstractItemView::startDrag calls d->clearOrRemove() here, so // this is a copy of QAbstractItemModelPrivate::clearOrRemove(); const QItemSelection selection = selectionModel()->selection(); QList<QItemSelectionRange>::const_iterator it = selection.constBegin(); if (!dragDropOverwriteMode()) { for (; it != selection.constEnd(); ++it) { QModelIndex parent = it->parent(); if (it->left() != 0) continue; if (it->right() != (model()->columnCount(parent) - 1)) continue; int count = it->bottom() - it->top() + 1; model()->removeRows(it->top(), count, parent); } } else { // we can't remove the rows so reset the items (i.e. the view is like a table) QModelIndexList list = selection.indexes(); for (int i = 0; i < list.size(); ++i) { QModelIndex index = list.at(i); QMap<int, QVariant> roles = model()->itemData(index); for (QMap<int, QVariant>::Iterator it = roles.begin(); it != roles.end(); ++it) it.value() = QVariant(); model()->setItemData(index, roles); } } } } }
int QAbstractItemView::qt_metacall(QMetaObject::Call _c, int _id, void **_a) { _id = QAbstractScrollArea::qt_metacall(_c, _id, _a); if (_id < 0) return _id; if (_c == QMetaObject::InvokeMetaMethod) { switch (_id) { case 0: pressed((*reinterpret_cast< const QModelIndex(*)>(_a[1]))); break; case 1: clicked((*reinterpret_cast< const QModelIndex(*)>(_a[1]))); break; case 2: doubleClicked((*reinterpret_cast< const QModelIndex(*)>(_a[1]))); break; case 3: activated((*reinterpret_cast< const QModelIndex(*)>(_a[1]))); break; case 4: entered((*reinterpret_cast< const QModelIndex(*)>(_a[1]))); break; case 5: viewportEntered(); break; case 6: reset(); break; case 7: setRootIndex((*reinterpret_cast< const QModelIndex(*)>(_a[1]))); break; case 8: doItemsLayout(); break; case 9: selectAll(); break; case 10: edit((*reinterpret_cast< const QModelIndex(*)>(_a[1]))); break; case 11: clearSelection(); break; case 12: setCurrentIndex((*reinterpret_cast< const QModelIndex(*)>(_a[1]))); break; case 13: scrollToTop(); break; case 14: scrollToBottom(); break; case 15: update((*reinterpret_cast< const QModelIndex(*)>(_a[1]))); break; case 16: dataChanged((*reinterpret_cast< const QModelIndex(*)>(_a[1])),(*reinterpret_cast< const QModelIndex(*)>(_a[2]))); break; case 17: rowsInserted((*reinterpret_cast< const QModelIndex(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2])),(*reinterpret_cast< int(*)>(_a[3]))); break; case 18: rowsAboutToBeRemoved((*reinterpret_cast< const QModelIndex(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2])),(*reinterpret_cast< int(*)>(_a[3]))); break; case 19: selectionChanged((*reinterpret_cast< const QItemSelection(*)>(_a[1])),(*reinterpret_cast< const QItemSelection(*)>(_a[2]))); break; case 20: currentChanged((*reinterpret_cast< const QModelIndex(*)>(_a[1])),(*reinterpret_cast< const QModelIndex(*)>(_a[2]))); break; case 21: updateEditorData(); break; case 22: updateEditorGeometries(); break; case 23: updateGeometries(); break; case 24: verticalScrollbarAction((*reinterpret_cast< int(*)>(_a[1]))); break; case 25: horizontalScrollbarAction((*reinterpret_cast< int(*)>(_a[1]))); break; case 26: verticalScrollbarValueChanged((*reinterpret_cast< int(*)>(_a[1]))); break; case 27: horizontalScrollbarValueChanged((*reinterpret_cast< int(*)>(_a[1]))); break; case 28: closeEditor((*reinterpret_cast< QWidget*(*)>(_a[1])),(*reinterpret_cast< QAbstractItemDelegate::EndEditHint(*)>(_a[2]))); break; case 29: commitData((*reinterpret_cast< QWidget*(*)>(_a[1]))); break; case 30: editorDestroyed((*reinterpret_cast< QObject*(*)>(_a[1]))); break; case 31: d_func()->_q_columnsAboutToBeRemoved((*reinterpret_cast< const QModelIndex(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2])),(*reinterpret_cast< int(*)>(_a[3]))); break; case 32: d_func()->_q_columnsRemoved((*reinterpret_cast< const QModelIndex(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2])),(*reinterpret_cast< int(*)>(_a[3]))); break; case 33: d_func()->_q_rowsRemoved((*reinterpret_cast< const QModelIndex(*)>(_a[1])),(*reinterpret_cast< int(*)>(_a[2])),(*reinterpret_cast< int(*)>(_a[3]))); break; case 34: d_func()->_q_modelDestroyed(); break; case 35: d_func()->_q_layoutChanged(); break; case 36: d_func()->_q_fetchMore(); break; } _id -= 37; } #ifndef QT_NO_PROPERTIES else if (_c == QMetaObject::ReadProperty) { void *_v = _a[0]; switch (_id) { case 0: *reinterpret_cast< bool*>(_v) = hasAutoScroll(); break; case 1: *reinterpret_cast< int*>(_v) = autoScrollMargin(); break; case 2: *reinterpret_cast<int*>(_v) = QFlag(editTriggers()); break; case 3: *reinterpret_cast< bool*>(_v) = tabKeyNavigation(); break; case 4: *reinterpret_cast< bool*>(_v) = showDropIndicator(); break; case 5: *reinterpret_cast< bool*>(_v) = dragEnabled(); break; case 6: *reinterpret_cast< bool*>(_v) = dragDropOverwriteMode(); break; case 7: *reinterpret_cast< DragDropMode*>(_v) = dragDropMode(); break; case 8: *reinterpret_cast< bool*>(_v) = alternatingRowColors(); break; case 9: *reinterpret_cast< SelectionMode*>(_v) = selectionMode(); break; case 10: *reinterpret_cast< SelectionBehavior*>(_v) = selectionBehavior(); break; case 11: *reinterpret_cast< QSize*>(_v) = iconSize(); break; case 12: *reinterpret_cast< Qt::TextElideMode*>(_v) = textElideMode(); break; case 13: *reinterpret_cast< ScrollMode*>(_v) = verticalScrollMode(); break; case 14: *reinterpret_cast< ScrollMode*>(_v) = horizontalScrollMode(); break; } _id -= 15; } else if (_c == QMetaObject::WriteProperty) { void *_v = _a[0]; switch (_id) { case 0: setAutoScroll(*reinterpret_cast< bool*>(_v)); break; case 1: setAutoScrollMargin(*reinterpret_cast< int*>(_v)); break; case 2: setEditTriggers(QFlag(*reinterpret_cast<int*>(_v))); break; case 3: setTabKeyNavigation(*reinterpret_cast< bool*>(_v)); break; case 4: setDropIndicatorShown(*reinterpret_cast< bool*>(_v)); break; case 5: setDragEnabled(*reinterpret_cast< bool*>(_v)); break; case 6: setDragDropOverwriteMode(*reinterpret_cast< bool*>(_v)); break; case 7: setDragDropMode(*reinterpret_cast< DragDropMode*>(_v)); break; case 8: setAlternatingRowColors(*reinterpret_cast< bool*>(_v)); break; case 9: setSelectionMode(*reinterpret_cast< SelectionMode*>(_v)); break; case 10: setSelectionBehavior(*reinterpret_cast< SelectionBehavior*>(_v)); break; case 11: setIconSize(*reinterpret_cast< QSize*>(_v)); break; case 12: setTextElideMode(*reinterpret_cast< Qt::TextElideMode*>(_v)); break; case 13: setVerticalScrollMode(*reinterpret_cast< ScrollMode*>(_v)); break; case 14: setHorizontalScrollMode(*reinterpret_cast< ScrollMode*>(_v)); break; } _id -= 15; } else if (_c == QMetaObject::ResetProperty) { _id -= 15; } else if (_c == QMetaObject::QueryPropertyDesignable) { _id -= 15; } else if (_c == QMetaObject::QueryPropertyScriptable) { _id -= 15; } else if (_c == QMetaObject::QueryPropertyStored) { _id -= 15; } else if (_c == QMetaObject::QueryPropertyEditable) { _id -= 15; } else if (_c == QMetaObject::QueryPropertyUser) { _id -= 15; } #endif // QT_NO_PROPERTIES return _id; }
int QAbstractItemView::qt_metacall(QMetaObject::Call _c, int _id, void **_a) { _id = QAbstractScrollArea::qt_metacall(_c, _id, _a); if (_id < 0) return _id; if (_c == QMetaObject::InvokeMetaMethod) { if (_id < 39) qt_static_metacall(this, _c, _id, _a); _id -= 39; } #ifndef QT_NO_PROPERTIES else if (_c == QMetaObject::ReadProperty) { void *_v = _a[0]; switch (_id) { case 0: *reinterpret_cast< bool*>(_v) = hasAutoScroll(); break; case 1: *reinterpret_cast< int*>(_v) = autoScrollMargin(); break; case 2: *reinterpret_cast<int*>(_v) = QFlag(editTriggers()); break; case 3: *reinterpret_cast< bool*>(_v) = tabKeyNavigation(); break; case 4: *reinterpret_cast< bool*>(_v) = showDropIndicator(); break; case 5: *reinterpret_cast< bool*>(_v) = dragEnabled(); break; case 6: *reinterpret_cast< bool*>(_v) = dragDropOverwriteMode(); break; case 7: *reinterpret_cast< DragDropMode*>(_v) = dragDropMode(); break; case 8: *reinterpret_cast< Qt::DropAction*>(_v) = defaultDropAction(); break; case 9: *reinterpret_cast< bool*>(_v) = alternatingRowColors(); break; case 10: *reinterpret_cast< SelectionMode*>(_v) = selectionMode(); break; case 11: *reinterpret_cast< SelectionBehavior*>(_v) = selectionBehavior(); break; case 12: *reinterpret_cast< QSize*>(_v) = iconSize(); break; case 13: *reinterpret_cast< Qt::TextElideMode*>(_v) = textElideMode(); break; case 14: *reinterpret_cast< ScrollMode*>(_v) = verticalScrollMode(); break; case 15: *reinterpret_cast< ScrollMode*>(_v) = horizontalScrollMode(); break; } _id -= 16; } else if (_c == QMetaObject::WriteProperty) { void *_v = _a[0]; switch (_id) { case 0: setAutoScroll(*reinterpret_cast< bool*>(_v)); break; case 1: setAutoScrollMargin(*reinterpret_cast< int*>(_v)); break; case 2: setEditTriggers(QFlag(*reinterpret_cast<int*>(_v))); break; case 3: setTabKeyNavigation(*reinterpret_cast< bool*>(_v)); break; case 4: setDropIndicatorShown(*reinterpret_cast< bool*>(_v)); break; case 5: setDragEnabled(*reinterpret_cast< bool*>(_v)); break; case 6: setDragDropOverwriteMode(*reinterpret_cast< bool*>(_v)); break; case 7: setDragDropMode(*reinterpret_cast< DragDropMode*>(_v)); break; case 8: setDefaultDropAction(*reinterpret_cast< Qt::DropAction*>(_v)); break; case 9: setAlternatingRowColors(*reinterpret_cast< bool*>(_v)); break; case 10: setSelectionMode(*reinterpret_cast< SelectionMode*>(_v)); break; case 11: setSelectionBehavior(*reinterpret_cast< SelectionBehavior*>(_v)); break; case 12: setIconSize(*reinterpret_cast< QSize*>(_v)); break; case 13: setTextElideMode(*reinterpret_cast< Qt::TextElideMode*>(_v)); break; case 14: setVerticalScrollMode(*reinterpret_cast< ScrollMode*>(_v)); break; case 15: setHorizontalScrollMode(*reinterpret_cast< ScrollMode*>(_v)); break; } _id -= 16; } else if (_c == QMetaObject::ResetProperty) { _id -= 16; } else if (_c == QMetaObject::QueryPropertyDesignable) { _id -= 16; } else if (_c == QMetaObject::QueryPropertyScriptable) { _id -= 16; } else if (_c == QMetaObject::QueryPropertyStored) { _id -= 16; } else if (_c == QMetaObject::QueryPropertyEditable) { _id -= 16; } else if (_c == QMetaObject::QueryPropertyUser) { _id -= 16; } #endif // QT_NO_PROPERTIES return _id; }
void TreeViewWidget::startDrag(Qt::DropActions pSupportedActions) { // This a reimplementation of QAbstractItemView::startDrag, so that we can // provide OpenCOR with a better pixmap for the drag object // Note: indeed, on Windows, the pixmap only shows the dragged item that are // visible in the QTreeView. Also, if there an item covers several // columns, then the pixmap will show several 'cells' some of them // empty if a column is empty, so... instead we want to provide a // generic pixmap which looks 'good' on all platforms... // Retrieve the selected draggable items, if any // Note: the following code is based on // QAbstractItemViewPrivate::selectedDraggableIndexes... QModelIndexList selectedDraggableIndexes = selectedIndexes(); for (int i = selectedDraggableIndexes.count()-1; i >= 0; --i) if ( !(model()->flags(selectedDraggableIndexes[i]) & Qt::ItemIsDragEnabled) || selectedDraggableIndexes[i].column()) // The current selected item is not draggable or is not in the first // column // Note: regarding the test on the column number, it is because we // may have a model data that requires several columns (e.g. // QFileSystemModel) in which case selectedIndexes would // return a number of indexes equal to the number of rows // times the number of columns while we only want a number of // indexes to be equal to the number of rows (since we have a // selection mode of QAbstractItemView::ExtendedSelection) selectedDraggableIndexes.removeAt(i); // Start the dragging action is there is at least one selected draggable // item if (selectedDraggableIndexes.count()) { // There is at least one selected draggable item, so create a QMimeData // object for it QMimeData *mimeData = model()->mimeData(selectedDraggableIndexes); if (!mimeData) return; // Create the pixmap that will be associated with the dragging action QPixmap pixmap((selectedDraggableIndexes.count() == 1)? ":oxygen/mimetypes/application-x-zerosize.png": ":oxygen/places/document-multiple.png"); // Create the drag object QDrag *drag = new QDrag(this); drag->setMimeData(mimeData); drag->setPixmap(pixmap); drag->setHotSpot(QPoint(0.5*pixmap.width(), 0.5*pixmap.height())); // Do the dragging itself Qt::DropAction realDefaultDropAction = Qt::IgnoreAction; if ( (defaultDropAction() != Qt::IgnoreAction) && (pSupportedActions & defaultDropAction())) realDefaultDropAction = defaultDropAction(); else if ( (pSupportedActions & Qt::CopyAction) && (dragDropMode() != QAbstractItemView::InternalMove)) realDefaultDropAction = Qt::CopyAction; if (drag->exec(pSupportedActions, realDefaultDropAction) == Qt::MoveAction) { // We want to move the items // Note: the following code is based on // QAbstractItemViewPrivate::clearOrRemove... const QItemSelection selection = selectionModel()->selection(); if (!dragDropOverwriteMode()) { foreach (const QItemSelectionRange &itemSelectionRange, selection) { QModelIndex parent = itemSelectionRange.parent(); if (itemSelectionRange.left()) continue; if (itemSelectionRange.right() != (model()->columnCount(parent)-1)) continue; model()->removeRows(itemSelectionRange.top(), itemSelectionRange.bottom()-itemSelectionRange.top()+1, parent); } } else {
void MacroTreeView::startDrag(Qt::DropActions supportedActions) { QModelIndexList indexes = selectionModel()->selectedRows(); for(int i = indexes.count() - 1 ; i >= 0; --i) { if (!(indexes.at(i).isValid()) || !(model()->flags(indexes.at(i)) & Qt::ItemIsDragEnabled)) { indexes.removeAt(i); } } if (indexes.count() > 0) { QMimeData *data = model()->mimeData(indexes); if (!data) { return; } QPixmap dragPixmap(":/icons/resources/macro.png"); QModelIndex srcIndex = dynamic_cast<QSortFilterProxyModel*>(model())->mapToSource(indexes[0]); const ModelItemMacro* item = static_cast<const ModelItemMacro*>(srcIndex.internalPointer()); graph::Vertex::Ptr dummyVertex = app::MacroManager::instance().createVertexInstance(item->macro().signature()); if (!dummyVertex.isNull()) { graph::VertexItem::Ptr vertexItem = dummyVertex->sceneItem().staticCast<graph::VertexItem>(); if (!vertexItem.isNull()) { dragPixmap = vertexItem->paintToPixmap(); } app::MacroManager::instance().deleteVertexInstance(dummyVertex); } data->setImageData(dragPixmap.toImage()); QDrag* dragObjectPtr = new QDrag(this); dragObjectPtr->setPixmap(dragPixmap); dragObjectPtr->setMimeData(data); dragObjectPtr->setHotSpot(dragPixmap.rect().center()); Qt::DropAction defDropAction = Qt::IgnoreAction; if (defaultDropAction() != Qt::IgnoreAction && (supportedActions & defaultDropAction())) { defDropAction = defaultDropAction(); } else if (supportedActions & Qt::CopyAction && dragDropMode() != QAbstractItemView::InternalMove) { defDropAction = Qt::CopyAction; } if (dragObjectPtr->exec(supportedActions, defDropAction) == Qt::MoveAction) { // clear or remove dragged items const QItemSelection selection = selectionModel()->selection(); QList<QItemSelectionRange>::const_iterator it = selection.constBegin(); if (!dragDropOverwriteMode()) { for (; it != selection.constEnd(); ++it) { QModelIndex parent = (*it).parent(); if ((*it).left() != 0) continue; if ((*it).right() != (model()->columnCount(parent) - 1)) continue; int count = (*it).bottom() - (*it).top() + 1; model()->removeRows((*it).top(), count, parent); } } else { QModelIndexList list = selection.indexes(); for (int i=0; i < list.size(); ++i) { QModelIndex index = list.at(i); QMap<int, QVariant> roles = model()->itemData(index); for (QMap<int, QVariant>::Iterator it = roles.begin(); it != roles.end(); ++it) { it.value() = QVariant(); } model()->setItemData(index, roles); } } } } }