Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Drag and Drop different item text in two QListWidgets



  • I have two QListWidgets , one named “Commands” on the left side and other named “XML Script” on the right side , I am able to drag and drop items from one List to another, How ever, when I drag one item, I don’t want drop that same item text, I want some changed text to be dropped.

    Example: In this example when I dragged “SetScroll Command” from “commands” QListWidget and I am trying to drop this in “XML Script” QListWidget , I need some different text to be dropped like If I drag ‘Pause Command’ from “Commands”, the dropped item in “XML Script ”should have item with text like “This is a Pause Command”

    ?? How can I achieve this, I am intending to keep a Map data structure which will have key as “Pause Command” and Value as “This is a Pause Command”. Whenever key text is dragged , value text shall be dropped,

    Any help appreciated.
    6f71daaf-0908-436a-9a91-1d0adef05f43-image.png



  • You can add user data to QListWidgetItem

    QListWidgetItem *item = new QListWidgetItem("Pause Command");
    item->setData(Qt::UserRole, QString("This is a Pause Command"));
    

    And in the mimeData function which you has reimplemented, use

    item->data(Qt::UserRole).toString()
    

    instead of item->text()
    *Note: If you want to drop different text to different text editers, then this won't work.

    You can even define more user roles to store different datas

    #define MIME_TEXT_ROLE Qt::UserRole + 1
    #define MIME_HTML_ROLE Qt::UserRole + 2
    


  • Can you please code the mimeData Function ??



  • @Mr-Workalot
    It's just the reimplemented QListWidget::mimeData function, I think you already implemented it in your previous post.

    protected:
        QMimeData* mimeData(const QList<QListWidgetItem*> items) const
        {
            QMimeData* mime= QListWidget::mimeData(items);
            QString text;
            for (QListWidgetItem* item : items)
                text.append(item->data(Qt::UserRole).toString()).append('\n');
            mime->setText(text);
            return mime;
        }
    


  • @Bonnie i tried the above mimeData function , when i drag from one QListWIdget to another QListWidget, it only transfers "Pause Command" and not its data i.e"This is a Pause Command",

    However, when i drag from QListWidget to QTextEdit , after dragging it shows "This is a Pause Command".



  • No need to reimplement QListWidget::mimeData. See https://forum.qt.io/post/444126



  • @VRonin Thanks for this, i got slight hope that my problem is solvable , but still kind of helpless here, in my case i want to drag item from one QListWidget-1 to QListWidget-2 but after dragging the text of that item in List widget -2 should change.

    How can i acheive this ? , can you please provide code for Drop EVent ?


  • Lifetime Qt Champion

    Hi,

    You have the code in the link @VRonin provided.



  • @SGaist Okay, But in my case this function does not gets executed, so, before

    void MainWindow::dropEvent(QDropEvent* event) 
    

    gets invoked , do i need to enter any other function ??


  • Lifetime Qt Champion

    Why are you implementing that method for your MainWindow ?



  • @Mr-Workalot
    Oh, sorry, I was misunderstanding your need, thinking you need to drop the text to a text edit.
    If you reimplement dropEvent, I think you should create a new class for listwidget-2 and reimplement there.



  • @SGaist Yeah, that's what, it kind of felt wrong to me, the place from where i am dragging is a modified QListWIdget,

    std::map<QString, QString> commands;
    bool first_time = true;
    
    class ListWidget : public QListWidget {
    private:
    
       //  map<QString, QString>::iterator it;
    public:
       using QListWidget::QListWidget; 
    protected: 
       QMimeData* mimeData(const QList<QListWidgetItem*> items) const
       {
           
           QMimeData* md = QListWidget::mimeData(items);
           QStringList texts;
           for (QListWidgetItem* item : selectedItems())
           {
             auto it = commands.find(item->text());
              texts << it->second;
           }
           if (first_time == true)
           {
               QString end = "</Script>";
               md->setText("<?xml version=\"1.0\" encoding=\"utf - 8\"?> \n <Script> \n"  + texts.join(QStringLiteral("\n")));
               first_time = false;
               return md;
           }
           else
           {
               md->setText(texts.join(QStringLiteral("\n")));
               return md;
           }
       }
    };
    

    and where i am dropping is a normal QListWidget,

    should , i create a DropEvent for where i am dropping, right ??

    and how do i create that , im very new to QT ?



  • @Bonnie said in Drag and Drop different item text in two QListWidgets:

    If you reimplement dropEvent, I think you should create a new class for listwidget-2 and reimplement there.

    oh okay, thanks for clarifying. and how can i reimpliment drop event for listwidget-2 ??
    what are the steps ??
    , i know im asking too much but if you help me once, im gonna learn this for life.



  • @Mr-Workalot
    Hmm..I tried to find an easiest way to handle this...
    The QDataStream decode/encode thing may need to subclass the model, too.
    So I think you just let it drop in the normal way, and then change it.

    protected:
        bool dropMimeData(int index, const QMimeData *data, Qt::DropAction action)
        {
            if(QListWidget::dropMimeData(index, data, action)) {
                if(QListWidgetItem *dropped = item(index)) {
                    dropped->setData(Qt::DisplayRole, dropped->data(Qt::UserRole));
                }
                return true;
            }
            return false;
        }
    

    This is only working when you'll only accept drops from a item which you need to change its text to its Qt::UserRole.
    If you want to accept drops from other items, you may need to add some conditional statements.


Log in to reply