[Solved]Drag and drop images between QListWidget and QGraphicsView



  • Hi all,

    I have imported images into my qlistwidget using QDialog. I would like to drag and drop those images into a QGraphicsView to display the image content. It would be great if anyone could provide me a example of implementation as i couldnt find anything suitable, i have already checked the Qt example programs. The major problem i am facing is

    1. To get the File path of the images, as i am importing the datas using QFileDialog into QListWidget.

    2. Then i couldnt find a method to implement static or variant_cast to cast URLs into Pixmap to set it into created scene for the QGraphicsView.

    It would be great if someone could guide me regarding this.

    Thanks and regards,
    Venkatesh Padmanabhan


  • Lifetime Qt Champion

    Hi,

    With a quick search in "QUrl documentation":http://qt-project.org/doc/qt-4.8/qurl.html you find toLocalFile that you can use to create a QPixmap



  • Hi,

    Thanks for your response. I tried to implement it as per your guidance but the images are not displayed. I am not sure where i am going wrong

    @

    void gview::dropEvent(QDropEvent *event)
    {
    const QMimeData *mimeData=event->mimeData();
    if(mimeData->hasImage()){
    QPixmap pixmap = QPixmap::fromImage(qvariant_cast<QImage>(mimeData->imageData()));
    scene()->addPixmap(pixmap);
    fitInView(scene()->sceneRect(),Qt::IgnoreAspectRatio);
    update();
    event->acceptProposedAction();
    }
    else if (mimeData->hasUrls())
    {
    QUrl url;
    QString str = url.toLocalFile();
    QPixmap pix(str);
    scene()->addPixmap(pix);
    update();
    event->acceptProposedAction();
    }
    }

    @


  • Lifetime Qt Champion

    You don't initialize your url variable



  • Then, how can i use the url without initialising?...


  • Lifetime Qt Champion

    Please, read "QMimeData's documentation":http://qt-project.org/doc/qt-4.8/qmimedata.html#details It's shown there.



  • else if (event->mimeData()->hasUrls())
    Hi,

    I read the documentation and tried this. But no result. I have tried to add the urls in the mimeData into a QString to get the path into it and passed the QString to pixmap to add it to the scene. But nothing happens...

    @

    {
    QList<QUrl> urlList = mimeData->urls();
    QString text;
    for (int i = 0; i < urlList.size() && i < 32; ++i) {
    QString url = urlList.at(i).path();
    text += url + QString("\n");
    }
    QPixmap pix(text);
    scene()->addPixmap(pix);
    update();
    event->acceptProposedAction();
    //}
    }
    }

    @

    Where am i going wrong ???...


  • Lifetime Qt Champion

    You are appending each url to text with an additional carriage return so text will not contain a valid path.



  • Hi, now i am able to drag and drop urls into the qgraphicsview

    code is

    @

              // }
      QList<QUrl> urls = event->mimeData()->urls();
          if (urls.isEmpty())
              return;
          QString fileName = urls.first().toLocalFile&#40;&#41;;
    
               QPixmap pix(fileName);
               scene()->addPixmap(pix);
               update();
               event->acceptProposedAction();
    

    @

    :)


  • Lifetime Qt Champion

    So problem solved ?

    Don't forget to update the thread's title then :)



  • Hi,

    But my real application has to accept drags from the QListWidget. I have implemented it and promoted the QlistWidget to the class but QgraphicsView doesnt accept the drag.

    My Code:

    @

    listWidget::listWidget(QWidget *parent)
    : QListWidget(parent)
    {
    setDragEnabled(true);
    setViewMode(QListView::IconMode);
    setDragDropMode(QAbstractItemView::DragDrop);
    setSelectionMode(QAbstractItemView::SingleSelection);

    }

    void listWidget::dragLeaveEvent(QDragLeaveEvent event)
    {
    event->accept();
    }
    void listWidget::mouseMoveEvent(QMouseEvent event)
    {
    // if (!(event->buttons() & Qt::LeftButton)) return;
    //if (currentItem() == NULL) return;
    QDrag
    drag = new QDrag( this );
    QMimeData
    mimeData = new QMimeData;
    QList<QUrl>list;
    list.append(QUrl(currentItem()->text()));
    mimeData->setUrls(list);
    drag->setMimeData(mimeData);
    drag->start(Qt::CopyAction | Qt::MoveAction);
    event->setAccepted(true);
    }

    void listWidget::performDrag()
    {
    QListWidgetItem *item = currentItem();
    if (item) {
    QMimeData *mimeData = new QMimeData;
    QList<QUrl>list;
    mimeData->setUrls(list);
    QDrag *drag = new QDrag(this);
    drag->setMimeData(mimeData);
    emit itemDrag();
    if (drag->exec(Qt::MoveAction | Qt::CopyAction))
    // delete item;
    }
    }

    void listWidget::dragEnterEvent(QDragEnterEvent *event)
    {

         event->acceptProposedAction();
    

    }

    void listWidget::dragMoveEvent(QDragMoveEvent *event)
    {
    event->acceptProposedAction();
    }

    @

    Whats the problem with it?. As the QGraphicsView is already modelled to accept the URL. I think i should only have to implement the QListWidget to accept Drag right? and add mimeData to the drag. I am confused where i am going wrong...


  • Lifetime Qt Champion

    Are you sure your view accepts drops properly ?



  • Hi,

    Yes my view accepts drops of url from outside the application but it doesnt accept from the listWidget... I dont know why.


  • Lifetime Qt Champion

    Then you should subclass QGraphicsView and implement dropEvent to test that (don't forget to call the base implementation otherwise it'll break the current functionality)



  • Hi,

    I get the following error during the drag and drop from my QListWidget. I couldnt understand what it means

    @

    2013-08-29 12:28:18.743 Mainwindow[990:707] __CFPasteboardIssueSandboxExtensionForPath: error for [/IMG_2458.JPG]

    @



  • Hi,

    As i have already created
    @
    void dragEnterEvent(QDragEnterEvent *event);
    void dragMoveEvent(QDragMoveEvent *event);
    void dropEvent(QDropEvent *event);
    @

    for accepting drops from outside the application into QGraphicsView, it works fine. But it doesn't work when i drop from QListWidget in the same application. Should i again recreate these for accepting drops from QListWidget?


  • Lifetime Qt Champion

    Does the url in your dragged item contain a complete path ?



  • Hi,
    The problem is i am not sure how to get the path of the qlistwidget item. I am trying to find it but i couldn't. It would be great if you could guide me how to get the path of the current item.

    This is how i have implemented
    @

    #include "listWidget.h"
    #include "ui_widget.h"
    #include "widget.h"
    #include <QtGui>

    listWidget::listWidget(QWidget *parent)
    : QListWidget(parent)
    {
    setDragEnabled(true);
    setViewMode(QListView::IconMode);
    //setDragDropMode(QAbstractItemView::DragDrop);
    setSelectionMode(QAbstractItemView::SingleSelection);
    }
    void listWidget::mousePressEvent(QMouseEvent *event)
    {
    if (event->button() == Qt::LeftButton)
    startPos = event->pos();
    QListWidget::mousePressEvent(event);

    }
    

    void listWidget::mouseMoveEvent(QMouseEvent *event)
    {
    if (event->buttons() & Qt::LeftButton) {
    int distance = (event->pos() - startPos).manhattanLength();
    if (distance >= QApplication::startDragDistance())
    startDrag();
    }
    QListWidget::mouseMoveEvent(event);
    }
    void listWidget::startDrag()
    {
    QListWidgetItem *item =currentItem();
    item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled);

    if (item) {
        QFileInfo info(item->text());
      QString str= info.absoluteFilePath();
         QByteArray itemData;
         QDataStream dataStream(&itemData, QIODevice::WriteOnly);
         QPixmap pixmap = qVariantValue<QPixmap>(item->data(Qt::UserRole));
         QPoint location = item->data(Qt::UserRole+1).toPoint();
         dataStream <<pixmap<<location;
         QMimeData *mimeData = new QMimeData;
         mimeData->setData(str,itemData);
         QDrag *drag = new QDrag(this);
         drag->setMimeData(mimeData);
         drag->setPixmap(pixmap);
            //if (drag->start(Qt::MoveAction) == Qt::MoveAction)
               // delete item;
    

    }

    }

    @


  • Lifetime Qt Champion

    AFAICS you don't set any url in your mime data



  • Hi,

    @
    QString str

    @
    contains the full path i just tested it by adding the string to the mime data and dropped it into desktop to check. I could get a text file containing full path. But i dont know why the above code doesnt work... Should i also implement something at the QGraphicsView to accept the drop? Though i have already implemented for receiving drops if there is an image, and url. It works perfectly for drops from outside the application. Awaiting your further guidance...


  • Lifetime Qt Champion

    You're using setData in a wrong manner. The string parameter should contain the mime type of the data you are passing as the second parameter.



  • Hi,

    Is this the only way i could implement it?.. I am bit confused. The mimeType which i am using here is path of the data, so should it be QUrl??... It would be great to have your guidance how to set the mimeType for my application. I am trying to find it. But couldnt get a concrete idea about the implementation. Thanks for your valuable time and help.


  • Lifetime Qt Champion

    Do you use the content of itemData in your drop function ?



  • hi,

    No i didnt modify my drop function. I just wrote it only to accept Url and Images.... Should i modify my dropfunction in qgraphicsView implementation?... How should that be done?...


  • Lifetime Qt Champion

    Then clean your mime data code and try something like this
    @
    QFileInfo info(item->text());
    QString absoluteFilePath= info.absoluteFilePath();
    QMimeData *mimeData = new QMimeData;
    QList<QUrl> urlList;
    urlList << QUrl::fromLocalPath(absoluteFilePath);
    mimeData->setUrls(urlList);
    QDrag *drag = new QDrag(this);
    drag->setMimeData(mimeData);
    @

    DON'T just copy/paste be sure to analyze what it does (disclaimer: I didn't build nor run it, it's from memory)



  • Hi,

    Thank you so much for a guidance, i understood now how the things works. Thanks for the knowledge sharing :)

    But i have a strange error while executing

    @

    2013-08-30 17:20:47.708 Mainwindow[1760:707] __CFPasteboardIssueSandboxExtensionForPath: error for [/Users/venkateshpadmanabhan/Desktop/build-Mainwindow-Desktop-Debug/Mainwindow.app/Contents/MacOS/IMG_2452.JPG]

    @

    I don't even get a clue what does it mean, i tried to google it but in vain...


  • Lifetime Qt Champion

    What version of Qt and OS X are you running ?



  • Hi,

    Thanks for your reply. I found the error. It was in populating the datas onto my QListWidget. My code is

    @

    void Widget::on_pushButton_clicked()
    {
    // QStringList fileName = QFileDialog::getOpenFileName(this,
    // tr("Open File"), QDir::currentPath());
    //ui->listwidget->addItems(fileName);

     QString fileName;
     QStringList fileNames;
     QFileDialog dialog(this);
      dialog.setFileMode(QFileDialog::ExistingFiles);
      if (dialog.exec&#40;&#41;)
         fileNames = dialog.selectedFiles();
      foreach (fileName, fileNames)
     {
          QListWidgetItem *item = new QListWidgetItem(ui->listwidget);
          ui->listwidget->setViewMode(QListWidget::IconMode);
         QFileInfo fi(fileName);
         QString name = fi.absoluteFilePath();
         item->setText(name);
         QIcon icon;
         icon.addPixmap(fileName);
         item->setIcon(icon);
         item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled);
         ui->listwidget->setIconSize(QSize(100,100));
         ui->listwidget->update();
          }
    

    // ui->listwidget->update();

    }

    @
    If i use @fi.fileName@ the drag and drop is not working as we are using only the text of the QListWidgetItem to get the full path. The problem is now when is use @fi.absolutefilePath@ The drag and drop works pretty fine. But in my QListWidget, whole path of the image is displayed as text, which doesnt look pretty. Love to have some suggestion how to tackle the problem.


  • Lifetime Qt Champion

    You can use the QListWidgetItem's data/setData functions storing the path using Qt::UserRole and set the text as you did before.



  • Hi,

    I tried during populating the datas into QListWidget

    @
    setData(Qt::UserRole, name);
    //item->setText(name);
    @

    To hide the file name, showing only the thumbnails but the drag and drop doesnt work. I tried

    @
    data(Qt::UserRole);
    @

    This too doesn't work. How should i use it to hide the data from the user in QListWidget. Awaiting your response.


  • Lifetime Qt Champion

    Use setText(name) so you have your name in your item.
    Use setData to store the path.

    data will return a QVariant. Look at the doc of QVariant to see how to retrieve the string from it.



  • Hi,
    I used while populating into QlistWidget

    @
    QVariant v(fileName);
    item->setData(Qt::UserRole,v);
    @

    and while retrieving data

    @
    QVariant v=data(Qt::UserRole);
    QString s=v.toString();
    @

    This works perfect thank you so much :)



  • Hi,
    Please do suggest your guidance for my new post "here" :http://qt-project.org/forums/viewthread/32022/ . And i know it is a dumb question.I would like to how to add the title as [solved]. I tried to find the way to do it but couldn't edit the title. I could edit only my post


  • Lifetime Qt Champion

    You can do that by editing the first post



  • Hi,
    Thanks I have done that, awaiting your guidance for the new post :) it's been great privilege to have your wonderful support throughout my learning curve...


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.