Programming/Qt

[Qt] Drag&Drop으로 QTreeWidget 제어하기

_SYPark 2024. 6. 14. 15:29
728x90

Qt에서는 기본적으로 Drag&Drop Action을 지원합니다. 아래의 코드를 사용하면 QTreeWidget에 기본적으로 구현된 내부 Drag & Drop Action이 실행됩니다.

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    ui->originTree->setSelectionMode(QAbstractItemView::SingleSelection);
    ui->originTree->setDragEnabled(true);
    ui->originTree->viewport()->setAcceptDrops(true);
    ui->originTree->setDropIndicatorShown(true);
}

 

기존에 제공하는 로직이 아닌 다른 동을 하기 위해서는 dropEvent를 overriding 처리를 통해 직접 구현할 수 있습니다.

void dragDropTree::dropEvent(QDropEvent *event)
{
    QByteArray encoded = event->mimeData()->data("application/x-qabstractitemmodeldatalist");
    // 드래그 해온 아이템들에 대한 정보
    QDataStream stream(&encoded, QIODevice::ReadOnly);

    while (!stream.atEnd())
    {
        int row, col;
        QMap<int,  QVariant> roleDataMap;
        QTreeWidgetItem* pCloneItem = new QTreeWidgetItem;

        stream >> row >> col >> roleDataMap;
        for ( auto [role, value] : roleDataMap.asKeyValueRange() ) {
            pCloneItem->setData(col, role, value);
        }

        QModelIndex index = indexAt(event->position().toPoint());
        // 복사할 위치
        auto pItem = itemAt(event->position().toPoint());

        auto dropIndicator = dropIndicatorPosition();       // 아이템이 삽입되는 위치

        switch ( dropIndicator ) {
        case OnItem:            // 아이템으로
            pItem->addChild(pCloneItem);
            break;
        case AboveItem:         // 아이템 상단으로
            if ( !pItem->parent()) {
                insertTopLevelItem(index.row(), pCloneItem);
            } else {
                auto parent = pItem->parent();
                parent->insertChild(index.row(), pCloneItem);
            }
            break;
        case BelowItem:         // 아이템 하단으로
            if ( !pItem->parent()) {
                insertTopLevelItem(index.row()+1, pCloneItem);
            } else {
                auto parent = pItem->parent();
                parent->insertChild(index.row()+1, pCloneItem);
            }
            break;
        case OnViewport:        // 그냥 트리 위젯 공간 안
            insertTopLevelItem(topLevelItemCount(), pCloneItem);
            break;
        }

    } // https://stackoverflow.com/questions/1723989/how-to-decode-application-x-qabstractitemmodeldatalist-in-qt-for-drag-and-drop
}
class dragDropTree : public QTreeWidget {
    Q_OBJECT

protected:
    void dropEvent(QDropEvent *event);
};

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;

    dragDropTree* pOrigin;
};

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    pOrigin = new dragDropTree;
    pOrigin->setObjectName("Origin");

    pOrigin->setSelectionMode(QAbstractItemView::SingleSelection);
    pOrigin->setDragEnabled(true);
    pOrigin->viewport()->setAcceptDrops(true);
    pOrigin->setDropIndicatorShown(true);

    auto item = new QTreeWidgetItem(pOrigin);
    item->setText(0, "text");

    item = new QTreeWidgetItem(pOrigin);
    item->setText(0, "text2");

    ui->horizontalLayout->addWidget(pOrigin);
}

MainWindow::~MainWindow()
{
    delete ui;
}
728x90