182 lines
6.3 KiB
C++
182 lines
6.3 KiB
C++
|
|
#include "CAutoListView.h"
|
|||
|
|
|
|||
|
|
#include <QDrag>
|
|||
|
|
#include <QPainter>
|
|||
|
|
CAutoListView::CAutoListView(QWidget *parent)
|
|||
|
|
:QListView(parent)
|
|||
|
|
{
|
|||
|
|
// setSelectionMode(QAbstractItemView::ExtendedSelection);
|
|||
|
|
// setDragEnabled(true);
|
|||
|
|
// setAcceptDrops(true);
|
|||
|
|
// setDropIndicatorShown(true);
|
|||
|
|
// setDefaultDropAction(Qt::MoveAction);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CAutoListView::mousePressEvent(QMouseEvent *event)
|
|||
|
|
{
|
|||
|
|
if(event->buttons() & Qt::LeftButton){
|
|||
|
|
startPos = event->pos();
|
|||
|
|
}
|
|||
|
|
QListView::mousePressEvent(event);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CAutoListView::mouseReleaseEvent(QMouseEvent *event)
|
|||
|
|
{
|
|||
|
|
QListView::mouseReleaseEvent(event);
|
|||
|
|
if((event->pos() - startPos).manhattanLength() > 5) return;
|
|||
|
|
|
|||
|
|
QModelIndex index = indexAt(event->pos());
|
|||
|
|
setCurrentIndex(index); //鼠标relesse时才选中
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CAutoListView::mouseMoveEvent(QMouseEvent *event)
|
|||
|
|
{
|
|||
|
|
QListView::mouseMoveEvent(event);
|
|||
|
|
if(event->buttons() & Qt::LeftButton){
|
|||
|
|
if((event->pos() - startPos).manhattanLength() < QApplication::startDragDistance()) return;
|
|||
|
|
|
|||
|
|
QModelIndex theDragIndex = indexAt(startPos);
|
|||
|
|
theDragRow = theDragIndex.row();
|
|||
|
|
|
|||
|
|
setCurrentIndex(theDragIndex); //拖拽即选中
|
|||
|
|
|
|||
|
|
QStandardItemModel *listModel = qobject_cast<QStandardItemModel *>(model());
|
|||
|
|
QStandardItem *theDragItem = static_cast<QStandardItem *>(listModel->item(theDragRow));
|
|||
|
|
|
|||
|
|
//[1]把拖拽数据放在QMimeData容器中
|
|||
|
|
QString text = theDragItem->text();
|
|||
|
|
QByteArray itemData;
|
|||
|
|
QDataStream dataStream(&itemData, QIODevice::WriteOnly);
|
|||
|
|
dataStream << text;
|
|||
|
|
|
|||
|
|
QMimeData *mimeData = new QMimeData;
|
|||
|
|
mimeData->setData(myMimeType(), itemData);
|
|||
|
|
//[1]
|
|||
|
|
|
|||
|
|
// 创建 QDrag 对象并设置拖拽数据和预览图
|
|||
|
|
QPixmap pixmap = QPixmap(100, 50); // 创建一个固定大小的预览图
|
|||
|
|
pixmap.fill(Qt::transparent); // 透明背景
|
|||
|
|
QPainter painter(&pixmap);
|
|||
|
|
painter.setPen(Qt::black);
|
|||
|
|
painter.setFont(QFont("Arial", 10));
|
|||
|
|
painter.drawText(pixmap.rect(), Qt::AlignCenter, text); // 在图像上绘制文本
|
|||
|
|
|
|||
|
|
QDrag *drag = new QDrag(this);
|
|||
|
|
drag->setMimeData(mimeData);
|
|||
|
|
drag->setPixmap(pixmap);
|
|||
|
|
drag->setHotSpot(QPoint(pixmap.width() / 2, pixmap.height() / 2)); // 设置热点位置为图像中心
|
|||
|
|
|
|||
|
|
//删除的行需要根据theInsertRow和theDragRow的大小关系来判断(这个也是我根据实际情况测试发现的)
|
|||
|
|
if(drag->exec(Qt::MoveAction) == Qt::MoveAction){
|
|||
|
|
int theRemoveRow = -1;
|
|||
|
|
if(theInsertRow < theDragRow) theRemoveRow = theDragRow + 1;
|
|||
|
|
else theRemoveRow = theDragRow;
|
|||
|
|
model()->removeRow(theRemoveRow);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CAutoListView::dragEnterEvent(QDragEnterEvent *event)
|
|||
|
|
{
|
|||
|
|
CAutoListView *source = qobject_cast<CAutoListView *>(event->source());
|
|||
|
|
if (source && source == this) {
|
|||
|
|
//IsDraging(标志位)判断是否正在拖拽
|
|||
|
|
IsDraging = true;
|
|||
|
|
event->setDropAction(Qt::MoveAction);
|
|||
|
|
event->accept();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CAutoListView::dragLeaveEvent(QDragLeaveEvent *event)
|
|||
|
|
{
|
|||
|
|
oldHighlightedRow = theHighlightedRow;
|
|||
|
|
theHighlightedRow = -2;
|
|||
|
|
|
|||
|
|
//之前QListWidget用的是update(QRect),这里用的是update(QModelIndex),当然这里也可以使用update(QRect),只是想换一种方法而已
|
|||
|
|
update(model()->index(oldHighlightedRow, 0)); //UpRow
|
|||
|
|
update(model()->index(oldHighlightedRow + 1, 0)); //DownRow
|
|||
|
|
|
|||
|
|
IsDraging = false; //IsDraging(标志位)判断是否正在拖拽
|
|||
|
|
|
|||
|
|
theInsertRow = -1;
|
|||
|
|
event->accept();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CAutoListView::dragMoveEvent(QDragMoveEvent *event)
|
|||
|
|
{
|
|||
|
|
CAutoListView *source = qobject_cast<CAutoListView *>(event->source());
|
|||
|
|
if (source && source == this) {
|
|||
|
|
|
|||
|
|
oldHighlightedRow = theHighlightedRow;
|
|||
|
|
theHighlightedRow = indexAt(event->pos() - QPoint(0, offset())).row();
|
|||
|
|
|
|||
|
|
//offset() = 19 = 40 / 2 - 1,其中40是行高
|
|||
|
|
if(event->pos().y() >= offset()){
|
|||
|
|
|
|||
|
|
if(oldHighlightedRow != theHighlightedRow){
|
|||
|
|
//刷新旧区域使dropIndicator消失
|
|||
|
|
update(model()->index(oldHighlightedRow, 0));
|
|||
|
|
update(model()->index(oldHighlightedRow + 1, 0));
|
|||
|
|
|
|||
|
|
//刷新新区域使dropIndicator显示
|
|||
|
|
update(model()->index(theHighlightedRow, 0));
|
|||
|
|
update(model()->index(theHighlightedRow + 1, 0));
|
|||
|
|
}else{
|
|||
|
|
update(model()->index(theHighlightedRow, 0));
|
|||
|
|
update(model()->index(theHighlightedRow + 1, 0));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
theInsertRow = theHighlightedRow + 1;
|
|||
|
|
}else{
|
|||
|
|
theHighlightedRow = -1;
|
|||
|
|
update(model()->index(0, 0));
|
|||
|
|
update(model()->index(1, 0));
|
|||
|
|
theInsertRow = 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
event->setDropAction(Qt::MoveAction);
|
|||
|
|
event->accept();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CAutoListView::dropEvent(QDropEvent *event)
|
|||
|
|
{
|
|||
|
|
CAutoListView *source = qobject_cast<CAutoListView *>(event->source());
|
|||
|
|
if (source && source == this){
|
|||
|
|
|
|||
|
|
IsDraging = false; //IsDraging(标志位)判断是否正在拖拽
|
|||
|
|
|
|||
|
|
oldHighlightedRow = theHighlightedRow;
|
|||
|
|
theHighlightedRow = -2;
|
|||
|
|
|
|||
|
|
//刷新旧区域使dropIndicator消失
|
|||
|
|
update(model()->index(oldHighlightedRow, 0));
|
|||
|
|
update(model()->index(oldHighlightedRow + 1, 0));
|
|||
|
|
|
|||
|
|
|
|||
|
|
if(theInsertRow == theDragRow || theInsertRow == theDragRow + 1) return;
|
|||
|
|
|
|||
|
|
//这里我像QListWidget那样调用父类dropEvent(event)发现不起作用(原因尚不明),没办法,只能删除旧行,插入新行
|
|||
|
|
//if(theSelectedRow == theDragRow){
|
|||
|
|
//QListView::dropEvent(event);
|
|||
|
|
//return;
|
|||
|
|
//}
|
|||
|
|
|
|||
|
|
QString text;
|
|||
|
|
QIcon icon, icon_hover;
|
|||
|
|
QByteArray itemData = event->mimeData()->data(myMimeType());
|
|||
|
|
QDataStream dataStream(&itemData, QIODevice::ReadOnly);
|
|||
|
|
dataStream >> text;
|
|||
|
|
|
|||
|
|
model()->insertRow(theInsertRow);
|
|||
|
|
|
|||
|
|
QStandardItemModel *listModel = qobject_cast<QStandardItemModel *>(model());
|
|||
|
|
listModel->setItem(theInsertRow, 0, new QStandardItem(text));
|
|||
|
|
|
|||
|
|
setCurrentIndex(model()->index(theInsertRow, 0)); //插入行保持选中状态
|
|||
|
|
|
|||
|
|
event->setDropAction(Qt::MoveAction);
|
|||
|
|
event->accept();
|
|||
|
|
}
|
|||
|
|
}
|