-1

On a subclassed QListWidget I have several items. Every QListWidget item (e.g. "ROS Init", "Images" etc) that is shown below is associated with a specific icon.

The problem I have is that I am trying to drag and drop the specific icon corresponding to that QListWidget item, but nothing happens.

Below the function responsible for the dragging:

void ListView::startDrag(Qt::DropActions supportedActions)
{
    QMap<int, QString> icons;
    icons.insert(IT_RosInit, "ROS Init");
    icons.insert(IT_Images, "Images");
    icons.insert(IT_Path, "Path");
    icons.insert(IT_RosShutDown, "ROS Shutdown");

    if (supportedActions & Qt::CopyAction)
    {
        const QList<QListWidgetItem *> &m_items(selectedItems());
        if (m_items.isEmpty())
            return;

        QPixmap pixmapLaser("/home/images/laserscan.png");
        QPixmap pixmapPCloud2("/home/images/pcloud2.png");
        // etc ...

        QStringList iconImages;

        for(int i = 0; i < icons.count(); ++i)
        {
            for (const QString &tableType : iconImages) {
                if (tableType == "ROS Init")
                {
                    auto *data = mimeData(m_items);
                    auto *drag = new QDrag(this);
                    drag->setPixmap(pixmapLaser);
                    drag->setMimeData(data);
                    drag->setHotSpot(pixmapLaser.rect().center());
                    drag->exec(Qt::CopyAction);
                 }
                else if(tableType == "Images")
                {
                    auto *data2 = mimeData(m_items);
                    auto *drag2 = new QDrag(this);
                    drag2->setPixmap(pixmapPCloud2);
                    drag2->setMimeData(data2);
                    drag2->setHotSpot(pixmapPCloud2.rect().center());
                    drag2->exec(Qt::CopyAction);
                }
            }
        }
    }
    else
    {
        QListWidget::startDrag(supportedActions);
    }
}

After subclassing the QListWidget I just reimplemented the usual drag and drop function. All other function are working properly but the startDrag and in fact as I try to drag the proper QPixmap, I actually see nothing being dragged.

I consulted this source, useful, and also this other source which was useful but it didn't reimplement the startDrag but instead dropEvent which for me is not a problem because that is working well.

I also consulted this source and this other source but that also didn't help fixing the problem.

Thanks for shedding light on this matter for solving the problem

scopchanov
  • 7,966
  • 10
  • 40
  • 68
Emanuele
  • 2,194
  • 6
  • 32
  • 71
  • Please, show how you populate the list widget. – scopchanov Oct 29 '20 at 02:06
  • Did my answer work for you? – scopchanov Oct 30 '20 at 01:19
  • Hello @scopchanov and sorry for answering late but wanted to make sure I tried and modified all the parts before answering. Ok it almost works, the only problem that I am having is that it does not drop the tables as you see [here](https://i.imgur.com/2Yq6jKa.png). Dragging works, but dropping does not and am trying to figure out what the problem might be. I have been working on [this example code you gave me](https://github.com/scopchanov/SO_QProxy) – Emanuele Oct 30 '20 at 15:41
  • Hi! Your application looks more and more beautiful. That's great! As for the drop, to make it work change all occurrences of `application/x-qabstractitemmodeldatalist` in _GraphicsView.cpp_ to `text/plain`. Do it now, thank me later. ;) – scopchanov Oct 30 '20 at 15:55
  • :) That is right! – Emanuele Oct 30 '20 at 16:11

1 Answers1

0

Solution

I would approach this problem in the following way:

  1. Set the ItemIsDragEnabled flag of QListWidgetItem to enable the item for dragging:

     item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled);
    
  2. Set the desired data for each item:

     item->setData(Qt::UserRole, type);
    

where type is one of the enumerated values IT_RosInit, IT_Images, etc.

  1. Enable the drag functionality of the ListWidget:

     setDragEnabled(true);
     setDragDropMode(QAbstractItemView::DragOnly);
    
  2. Use the item settings to setup the QDrag object, created in startDrag.

Example

Here is an example I have prepared for you to demonstrate how the proposed solution could be implemented:

MainWindow.cpp

MainWindow::MainWindow(QWidget *parent) :
    QWidget(parent)
{
    auto *l = new QVBoxLayout(this);
    auto *list = new ListView(this);

    list->addItem(createItem(":/pix/images/laserscan.png", tr("RosInit"), IT_RosInit));
    list->addItem(createItem(":/pix/images/icons/pcloud2.png", tr("Images"), IT_Images));
    list->addItem(createItem(":/pix/images/icons/some_icon.png", tr("Path"), IT_Path));
    list->addItem(createItem(":/pix/images/icons/another_icon.png", tr("RosShutDown"), IT_RosShutDown));

    l->addWidget(list);

    resize(300, 400);
    setWindowTitle("IconDrag");
}

QListWidgetItem *MainWindow::createItem(const QString &pm, const QString &text, int type)
{
    auto *item = new QListWidgetItem(QIcon(QPixmap(pm)), text);

    item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled);
    item->setData(Qt::UserRole, type);

    return item;
}

ListView.cpp

ListView::ListView(QWidget *parent) :
    QListWidget(parent)
{
    setDragEnabled(true);
    setDragDropMode(QAbstractItemView::DragOnly);
    setSelectionBehavior(QAbstractItemView::SelectRows);
    setSelectionMode(QAbstractItemView::SingleSelection);
}

void ListView::startDrag(Qt::DropActions supportedActions)
{
    if (supportedActions & Qt::CopyAction) {
        const QList<QListWidgetItem *> &items(selectedItems());

        if (items.isEmpty())
            return;

        const QPixmap &pm(items.first()->icon().pixmap(64));
        auto *item = items.first();
        auto *mimeData = new QMimeData();
        auto *drag = new QDrag(this);

        mimeData->setData("text/plain", item->data(Qt::UserRole).toByteArray());

        drag->setPixmap(pm);
        drag->setMimeData(mimeData);
        drag->setHotSpot(pm.rect().center());
        drag->exec(Qt::CopyAction);
    }
}
scopchanov
  • 7,966
  • 10
  • 40
  • 68
  • The `createItem` helper function is a great idea and the code is much more maintainable than just using a straight `QPixmap` with all the related path. I am now working on the `backend.cpp` on the function `void Backend::setupList(ListView *listView)` to see if that might be the problem of not properly dropping the tables on the graphicsview. – Emanuele Oct 30 '20 at 15:54
  • Ok it works I can drag correct icon from the listwidget. The small issue I see is that I keep dropping (despite the correctness of the icon) the same table (ROS Init) on the graphicsview. If I drag another index (and icon) I still drop one table. Do you see something I don't see? Thanks so much for your time in answering so far :) Very much appreciated!! – Emanuele Oct 30 '20 at 16:38
  • I think the `dropEvent` in the `graphicsview.cpp` might be the cause. I am researching the cause. – Emanuele Oct 30 '20 at 17:15