/*! \reimp */ QItemSelection QIdentityProxyModel::mapSelectionToSource(const QItemSelection& selection) const { Q_D(const QIdentityProxyModel); QItemSelection sourceSelection; if (!d->model) return sourceSelection; QItemSelection::const_iterator it = selection.constBegin(); const QItemSelection::const_iterator end = selection.constEnd(); for ( ; it != end; ++it) { Q_ASSERT(it->model() == this); const QItemSelectionRange range(mapToSource(it->topLeft()), mapToSource(it->bottomRight())); sourceSelection.append(range); } return sourceSelection; }
/** @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); } } } } }
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); } } } } }