Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Fail to drop in a QListWidget

Fail to drop in a QListWidget

Scheduled Pinned Locked Moved Solved General and Desktop
8 Posts 3 Posters 1.6k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    Alain38 0
    wrote on last edited by Alain38 0
    #1

    Hi,
    I have the following widget structure: a root QWidget contains a QFrame. The QFrame contains a QListWidget and a QTreeView. And, I want to drag-and-drop from the QTreeWidget to the QListWidget.

    But, as I do not want to subclass the QTreeView just for this, what I did is to connect the signal QTreeView::pressed to a slot that is on the root QWidget. This slott contains the following code:

    //-------------------------------------------------------------------------------
    void LoadView::slotInitiateDragAndDrop(const QModelIndex& p_index)
    //-------------------------------------------------------------------------------
    {
        // Initiate the drag operation
        QDrag*     drag     = new QDrag(this);
        QMimeData* mimeData = new QMimeData;
        mimeData->setText(static_cast<QFileSystemModel*>(m_ui.m_dirExplorer->model())->filePath(p_index));
        drag->setMimeData(mimeData);
        Qt::DropAction dropAction = drag->exec(Qt::CopyAction);
    }// slotInitiateDragAndDrop(const QModelIndex &p_index)
    

    On the other side, the QListWidget has the following configuration on its constructor:

        // Accept drop operation
        this->setAcceptDrops(true);
        this->setMouseTracking(true);
        this->setDropIndicatorShown(true);
    

    And I have reimplemented the dragEnterEvent, dragMoveEvent and dropEvent functions.

    Dragging operation is initiated (I see the indicator). But drop is not performed. In fact the QListWidget never enters in the reimplemented functions. I have checked that it is configured to accept copy action.

    So what I did wrong?

    Thanks for your help.

    1 Reply Last reply
    0
    • VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by VRonin
      #2

      did you setDragDropMode(QAbstractItemView::DropOnly) on the listview?

      P.S.

      as I do not want to subclass the QTreeView just for this

      Hacking away a problem for "laziness" is bad. If you work in a team, this kind of things is what gets you a ton of 💩 dumped on. Particularly in this case where the subclassing solution is so much easier than your hack

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      1 Reply Last reply
      1
      • A Offline
        A Offline
        Alain38 0
        wrote on last edited by
        #3

        @VRonin said in Fail to drop in a QListWidget:

        setDragDropMode(QAbstractItemView::DropOnly)

        Yes. But it does nothing. I also tried to apply the setAcceptDrops on the QLIstWidget::viewport(), as seen in a Wiki concerning the QLIstWidget. But it does nothing.

        The drag-and-drop process works well to drop in another application (I tried to drop in Notepad++) but not between these two stupid widgets. I also tried to create the drag object from the QTreeView. but this changes nothing.

        1 Reply Last reply
        0
        • A Offline
          A Offline
          Alain38 0
          wrote on last edited by
          #4

          To add: it seems to not be related to the fact the destination be a QListWidget. I have trie replacing it by a QLineEdit and it is still the same shit.

          1 Reply Last reply
          0
          • mrjjM Offline
            mrjjM Offline
            mrjj
            Lifetime Qt Champion
            wrote on last edited by mrjj
            #5

            Hi
            I tested your slotInitiateDragAndDrop way and it does work for me.
            for the custom listwidget i have

            void mylistwidget::dragEnterEvent(QDragEnterEvent* event) {
              event->acceptProposedAction();
            }
            
            void mylistwidget::dragMoveEvent(QDragMoveEvent* event) {
              event->acceptProposedAction();
            }
            
            void mylistwidget::dropEvent(QDropEvent* event) {
              qDebug() << event->mimeData()->formats();
              QByteArray itemData = event->mimeData()->data("text/plain");
              QDataStream dataStream(&itemData, QIODevice::ReadOnly);
              addItem( itemData );
              event->acceptProposedAction();
            }
            
            

            and
            alt text

            1 Reply Last reply
            2
            • A Offline
              A Offline
              Alain38 0
              wrote on last edited by
              #6

              Hi,
              So, this morning I did the following test:
              1- I have simplified the problem by managing a drag-and-drop internally to my widget. This is the code of the widget:

              #include "FavoriteListView.h"
              
              #include <QtGui/QDragEnterEvent>
              #include <QtGui/QDragMoveEvent>
              #include <QtGui/QDropEvent>
              
              #include <QtCore/QSettings>
              #include <QtCore/QStandardPaths>
              
              #include "VerboseTreeView.h"
              
              //----------------------------------------------------------------------------------------------------------------
              FavoriteListView::FavoriteListView(QWidget* p_parent /* = nullptr */)
                  : QListWidget(p_parent)
              //----------------------------------------------------------------------------------------------------------------
              {
                  m_favoriteFile = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "favorites.ini";
              
                  QSettings favoriteFile(m_favoriteFile, QSettings::IniFormat);
              
                  // Populate the list with default values
                  QListWidgetItem* newItem;
                  newItem = new QListWidgetItem(tr("Desktop"), this);
                  newItem->setData(Qt::UserRole, QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
                  this->addItem(newItem);
              
                  newItem = new QListWidgetItem(tr("Documents"), this);
                  newItem->setData(Qt::UserRole, QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
                  this->addItem(newItem);
              
                  newItem = new QListWidgetItem(tr("User"), this);
                  newItem->setData(Qt::UserRole, QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
                  this->addItem(newItem);
              
                  for (auto currentKey : favoriteFile.allKeys())
                  {
                      // Add additional items
                      QString currentData = favoriteFile.value(currentKey).toString();
                      newItem = new QListWidgetItem(currentKey, this);     // Last name of the directory
                      newItem->setData(Qt::UserRole, currentData);         // Full path
                  }
              
                  // Accept drop operation
                  this->setMouseTracking(true);
                  this->setAcceptDrops(true);
              }// FavoriteListView(QWidget* p_parent)
              
              //----------------------------------------------------------------------------------------------------------------
              FavoriteListView::~FavoriteListView()
              //----------------------------------------------------------------------------------------------------------------
              {
                  QSettings favoriteFile(m_favoriteFile, QSettings::IniFormat);
              
                  // remove previous favorites
                  favoriteFile.clear();
              
                  for (int i = 3; i < this->count(); ++i)
                  {
                      // Save the current item
                      QListWidgetItem* currentItem = this->item(i);
                      QString dataToSave = currentItem->data(Qt::UserRole).toString();
                      favoriteFile.setValue(currentItem->text(), dataToSave);
                  }
              
                  favoriteFile.sync();
              }// ~FavoriteListView()
              
              //---------------------------------------------------------------------------------------
              void FavoriteListView::dragEnterEvent(QDragEnterEvent* p_event)
              //---------------------------------------------------------------------------------------
              {
                  std::cout << "Mime Data: " << p_event->mimeData()->hasFormat("text/plain")
                            << "VerboseTreeView: " << dynamic_cast<VerboseTreeView*>(p_event->source())
                            << "Already present: " << this->isInFavorites(p_event->mimeData()->text()) << std::endl;
                  p_event->acceptProposedAction();
              
                  if ((p_event->mimeData()->hasFormat("text/plain")) &&                       // Content is text
                      (dynamic_cast<VerboseTreeView*>(p_event->source()) != NULL) &&      // Source is a FileExplorerView
                      (!this->isInFavorites(p_event->mimeData()->text())))  // Path is not in the favorites
                  {
                      // Accept the event
                      p_event->acceptProposedAction();
                  }// Accept the event
              }// dragEnterEvent ( QDragEnterEvent * event )
              
              //---------------------------------------------------------------------------------------
              void FavoriteListView::dragMoveEvent(QDragMoveEvent* p_event)
              //---------------------------------------------------------------------------------------
              {
                  std::cout << "Mime Data: " << p_event->mimeData()->hasFormat("text/plain")
                            << "VerboseTreeView: " << dynamic_cast<VerboseTreeView*>(p_event->source())
                            << "Already present: " << this->isInFavorites(p_event->mimeData()->text()) << std::endl;
                  p_event->acceptProposedAction();
              
                  if ((p_event->mimeData()->hasFormat("text/plain")) &&                       // Content is text
                      (dynamic_cast<VerboseTreeView*>(p_event->source()) != NULL) &&      // Source is a FileExplorerView
                      (!this->isInFavorites(p_event->mimeData()->text())))  // Path is not in the favorites
                  {
                      // Accept the event
                      p_event->acceptProposedAction();
                  }// Accept the event
              }// dragMoveEvent ( QDragMoveEvent * event )
              
              //---------------------------------------------------------------------------------------
              void FavoriteListView::dropEvent(QDropEvent* p_event)
              //---------------------------------------------------------------------------------------
              {
                  QString selectedString = p_event->mimeData()->text();
              
                  if (selectedString != "")
                  {
                      QListWidgetItem* curItem = new QListWidgetItem(this);
                      curItem->setText(QFileInfo(selectedString).fileName());
                      curItem->setData(Qt::UserRole, QFileInfo(selectedString).absoluteFilePath());
                      this->addItem(curItem);
                  }// Something selected
              
                  p_event->acceptProposedAction();
              }// dropEvent(QDropEvent *event)
              
              //---------------------------------------------------------------------------------------
              bool FavoriteListView::isInFavorites(const QString& p_path)
              //---------------------------------------------------------------------------------------
              {
                  bool result = false;
                  QString pathWithEnd = p_path + "/"; // to identify that d: and d:/ are the same dir
              
                  for (int i = 0; i < this->count(); ++i)
                  {
                      // Search on each item
                      QListWidgetItem* currentItem = this->item(i);
                      QString fullPath = currentItem->data(Qt::UserRole).toString();
                      result = result || (fullPath == p_path) || (fullPath == pathWithEnd);
                  }
              
                  return result;
              }// isInFavorites(const std::string &p_path)
              
              
              //-------------------------------------------------------------------------------
              void FavoriteListView::mousePressEvent(QMouseEvent* event)
              //-------------------------------------------------------------------------------
              {
                  // Initiate the drag operation
                  QDrag*     drag = new QDrag(this);
                  QMimeData* mimeData = new QMimeData;
                  mimeData->setText("fait chier");
                  drag->setMimeData(mimeData);
                  Qt::DropAction dropAction = drag->exec(Qt::CopyAction);
              }// slotInitiateDragAndDrop(const QModelIndex &p_index)
              
              

              2- If I put this widget in a QDialog (that run in modal mode) everything works well.

              3- But if the widget is a part of my QMainWindow (in my widget hierachy) this does not work. None of the drag event function is called. My widget hierarchy is the following (parenting)

              LoadView (QWidget) ==> QFrame ==> FavoriteListView (QListWidget)

              The LoadView has no parent. And it is in a QStackedWidget. The hierarchy of the stacked widget is:

              QMainWindow ==> QWidget ==> QStackedWidget

              So, there is someone, in this structure, that blocks the drag events.

              1 Reply Last reply
              0
              • A Offline
                A Offline
                Alain38 0
                wrote on last edited by Alain38 0
                #7

                OK,
                I have reproduced the whole hierarchy structure in my QDialog. And in this case everything works well. This helps me to find were the problem is. It is somewhere in the DoDragDrop() function. This one, for an unkonwn reason never call QWindowsOleDropTarget::HandleDrag when the widget is in my QMainWindow.

                Unfortunately, as DoGrapAndDrop is a Windows function I have no access to its code.

                @Addendum: I'm on Windows10 with Qt 5.6.3.

                1 Reply Last reply
                0
                • A Offline
                  A Offline
                  Alain38 0
                  wrote on last edited by
                  #8

                  OK,
                  Finally the problem has been found. In a part of the code there has some calls to COM functions. The routine called CoInitializeSecurity() and CoUninitialized(). By commenting these two functions everything works well now.

                  1 Reply Last reply
                  1

                  • Login

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved