Drag und Drop zwischen und innerhalb QListWidget

Alles rund um die Programmierung mit Qt
Antworten
samir_bmw
Beiträge: 41
Registriert: 11. Juli 2008 16:51

Drag und Drop zwischen und innerhalb QListWidget

Beitrag von samir_bmw »

Hallo Zusammen,
seit 2 Tagen versuche ich das Problem zu lösen, leider ohne bzw. Teilerfolg. Zu Hilfe habe ich das Beispiel habe aus dem Buch "C++ GUI Programmierung mit Qt4" auf Seite 261 für Drag und Drop genommen.

Ich habe CDListWidgetItem implementiert, weil ich den id brauche. Er ist Referenz auf anderen Daten.
Die Klasse CDListWidget erbt von QListWidget und ich habe einige Methoden überschrieben.

Jetzt Ich kann CDListWidgetItem von einem zum anderem CDListWidget bewegen. Ich kann es nicht in eine bestimte Position hinzufügen. Das item lässt sich nicht zwischen anderen items hinzufügen, immer am Ende.

Code: Alles auswählen

class CDListWidget : public QListWidget
{
    Q_OBJECT
public:
    explicit CDListWidget(const QString& name, QWidget *parent = 0);
protected:
    //bool event(QEvent *e);
    void mousePressEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void dragEnterEvent(QDragEnterEvent *event);
    void dragMoveEvent(QDragMoveEvent *event);
    //void dragLeaveEvent(QDragLeaveEvent *e);
    void dropEvent(QDropEvent *event);
private:
    void startDrag();
    QPoint _startPos;
    QString _name;
};
class CDListWidgetItem : public QListWidgetItem {
public:
    CDListWidgetItem(const QString &text, quint32 id, QListWidget *parent = 0);
    void setId(quint32 id);
    quint32 id() const;
private:
    quint32 _id;
};

Code: Alles auswählen

CDListWidget::CDListWidget(const QString& name, QWidget *parent)
    : QListWidget(parent),
      _name(name)
{
    setDragEnabled(true);
    setDragDropMode(QAbstractItemView::InternalMove);
    viewport()->setAcceptDrops(true);
    setDropIndicatorShown(true);
}

void CDListWidget::startDrag() {
    qDebug() << "Drag() ...";
    CDListWidgetItem* item = dynamic_cast<CDListWidgetItem*>(currentItem());
    qDebug() << "size: " << item->sizeHint();
    if (item) {
        qDebug() << "startDrag() ...";
        QString str = item->text();
        str += "::";
        str += QString::number(item->id());
        qDebug() << str;

        QMimeData *mimeData = new QMimeData;
        mimeData->setText(str);

        QDrag *drag = new QDrag(this);
        drag->setMimeData(mimeData);

        if (drag->exec(Qt::MoveAction) == Qt::MoveAction) {
            delete item;
            qDebug() << "startDrag item deleted ...";
        }
    }
}

//bool CDListWidget::event(QEvent *e) {
//    //qDebug() << static_cast<int>(e->type());
//    return QListWidget::event(e);
//}

void CDListWidget::mousePressEvent(QMouseEvent *event) {
    qDebug() << "mousePressEvent()";
    if (event->button() == Qt::LeftButton)
        _startPos = event->pos();
    QListWidget::mousePressEvent(event);
}

void CDListWidget::mouseMoveEvent(QMouseEvent *event) {
    qDebug() << "mouseMoveEvent()" << event->pos();
    if (event->buttons() & Qt::LeftButton) {
        int distance = (event->pos() - _startPos).manhattanLength();
        if (distance >= QApplication::startDragDistance())
            startDrag();
    }
    QListWidget::mouseMoveEvent(event);
}

void CDListWidget::dragEnterEvent(QDragEnterEvent *event) {
    qDebug() << _name << "dragEnterEvent()";
    _dragLeave = false;
    CDListWidget* src = qobject_cast<CDListWidget*>(event->source());
    if (src) {
        event->setDropAction(Qt::MoveAction);
        event->accept();
    }
}

void CDListWidget::dragMoveEvent(QDragMoveEvent *event) {
    //qDebug() << _name << "dragMoveEvent()" << event->answerRect();
    CDListWidget *src = qobject_cast<CDListWidget *>(event->source());
    if (src) {
        event->setDropAction(Qt::MoveAction);
        event->accept();
    }
}

void CDListWidget::dropEvent(QDropEvent *event) {
    qDebug() << _name << "dropEvent()" << event->pos();
    CDListWidget* src = qobject_cast<CDListWidget* >(event->source());
    if (src) {
        QStringList qstrList= event->mimeData()->text().split("::");
        if (!qstrList.isEmpty()) {
            QString str = qstrList[0];
            quint32 id  = qstrList[1].toUInt();

            new CDListWidgetItem(str, id, this);
            event->setDropAction(Qt::MoveAction);
            event->accept();
        }
    }
}

CDListWidgetItem::CDListWidgetItem(const QString &text,
                               quint32 id,
                               QListWidget *parent)
    : QListWidgetItem(text, parent),
      _id(id)
{
}

void CDListWidgetItem::setId(quint32 id) {
    _id = id;
}

quint32 CDListWidgetItem::id() const {
    return _id;
}
Ich denke, in CDListWidget::dropEvent(QDropEvent *event) muss ich herausfinden über welchen item ich gerade bin. Leider weiß ich es nicht.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Drag und Drop zwischen und innerhalb QListWidget

Beitrag von Christian81 »

In QMimeData musst Du alles einpacken was Du auf der Gegenseite benötigst um den Inhalt wieder herzustellen.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
samir_bmw
Beiträge: 41
Registriert: 11. Juli 2008 16:51

Re: Drag und Drop zwischen und innerhalb QListWidget

Beitrag von samir_bmw »

Danke für die Antwort. Das habe ich schon hinbekommen. Bei Drop kann ich nicht das Item in gewünschte Position tun. Zum Beispiel, wenn ich 5 Items habe, zwischen 3 und 4 hinzufügen.
Wenn ich QListWidget benutze, ohne eigene Klasse zu erstellen, das funktioniert. Ich überschreibe die dropEvent Methode und dadurch geht alles verloren von QListWidget.
Antworten