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();
|
||
}
|
||
}
|