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. setDragCursor for QTreeView?

setDragCursor for QTreeView?

Scheduled Pinned Locked Moved Unsolved General and Desktop
23 Posts 5 Posters 6.9k Views 3 Watching
  • 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.
  • S StudentScripter

    @KenAppleby-0 @qwasder85 Well thank you 2 so much im really kind of a noobie with qt, but i really want to get this done. :)

    So well @KenAppleby-0 so you say i would have to implement the drag and drop behaviour myself when i override the look of the cursor?
    If so what exactly would i have to do and to handle to make this work, could you please give me a minimum starting point (i know thats much to ask for, as im sure you have plenty to do also)

    KenAppleby 0K Offline
    KenAppleby 0K Offline
    KenAppleby 0
    wrote on last edited by
    #14

    @StudentScripter
    Here's a very rudimentary example. It turns out that you can reuse most of the QAbstractView drag and drop functionality. You just need to set up the QDrag object correctly with the model indexes.
    Caveat emptor.

    #include <QMainWindow>
    #include <QApplication>
    #include <QStandardItemModel>
    #include <QTreeView>
    #include <QHBoxLayout>
    #include <QPainter>
    #include <QMouseEvent>
    #include <QMimeData>
    #include <QDrag>
    
    class MainWindow : public QMainWindow
    {
    public:
        MainWindow(QWidget * parent =nullptr);
    
        QStandardItemModel mModel;
    };
    
    class TreeView : public QTreeView
    {
    public:
        TreeView(QWidget * parent);
    
        void setPixmaps(QPixmap red, QPixmap green, QPixmap blue);
        void mousePressEvent(QMouseEvent * event) override;
        void mouseMoveEvent(QMouseEvent * event) override;
        void dragEnterEvent(QDragEnterEvent * event) override;
        void dragMoveEvent(QDragMoveEvent * event) override;
    
        void dropEvent(QDropEvent * e) override;
    
        QPixmap mRed;
        QPixmap mGreen;
        QPixmap mBlue;
        QPoint mDragPos;
        bool mDragging{ false };
    };
    
    TreeView::TreeView(QWidget * parent)
        : QTreeView{ parent }
    {
        setDragDropMode(InternalMove);
    }
    
    void TreeView::setPixmaps(QPixmap red, QPixmap green, QPixmap blue)
    {
        mRed = red; mGreen = green; mBlue = blue;
    }
    
    void TreeView::mousePressEvent(QMouseEvent * event)
    {
        if (event->button() == Qt::LeftButton)
        {
            QModelIndex index{ indexAt(event->pos()) };
            if (index.isValid())
            {
                mDragPos = event->pos();
                mDragging = true;
            }
        }
        QTreeView::mousePressEvent(event); // implements item selection
    }
    
    void TreeView::mouseMoveEvent(QMouseEvent * e)
    {
        if (mDragging)
        {
            QPoint p = mDragPos - e->pos();
            int d = p.manhattanLength();
            if (d >= QApplication::startDragDistance())
            {
                QModelIndexList selectedItems = selectedIndexes(); // at least one item must be selected
                if (selectedItems.size())
                {
                    QMimeData * mimeData = model()->mimeData(selectedItems);
                    QDrag * drag = new QDrag(this);
                    connect(drag, &QObject::destroyed, this, []()
                    {
                        qDebug() << "drop dead";
                    });
    
                    drag->setPixmap(mBlue);
                    drag->setMimeData(mimeData);
                    drag->setDragCursor(mGreen, Qt::MoveAction);
                    drag->setDragCursor(mRed, Qt::IgnoreAction);
    
                    Qt::DropAction result = drag->exec(Qt::CopyAction|Qt::MoveAction, Qt::IgnoreAction);
                    qDebug() << "drag exec result" << result;
                }
            }
        }
    }
    
    void TreeView::dragEnterEvent(QDragEnterEvent * event)
    {
        qDebug() << "drag enter" << event->proposedAction() << event->possibleActions();
        QTreeView::dragEnterEvent(event);
    }
    
    void TreeView::dragMoveEvent(QDragMoveEvent * event)
    {
        QTreeView::dragMoveEvent(event);
        event->acceptProposedAction();
    }
    
    void TreeView::dropEvent(QDropEvent * e)
    {
        qDebug() << "drop accepted" << e->mimeData()->hasText() << e->mimeData()->text();
        QTreeView::dropEvent(e);
        e->acceptProposedAction();
    }
    
    
    MainWindow::MainWindow(QWidget * parent)
        : QMainWindow{ parent }
    {
        QWidget * centralwidget;
        QHBoxLayout * horizontalLayout;
        TreeView * treeView;
    
        resize(450, 400);
        centralwidget = new QWidget{ this };
        horizontalLayout = new QHBoxLayout{ centralwidget };
        treeView = new TreeView{ centralwidget };
        horizontalLayout->addWidget(treeView);
    
        setCentralWidget(centralwidget);
    
        QImage canvas{ 32, 32, QImage::Format_ARGB32 };
        canvas.fill(Qt::transparent);
        QPainter painter{ &canvas };
        painter.setBrush(Qt::red);
        painter.drawEllipse(0, 0, 32, 32);
        QPixmap red{ QPixmap::fromImage(canvas) };
        painter.setBrush(Qt::green);
        painter.drawEllipse(0, 0, 32, 32);
        QPixmap green{ QPixmap::fromImage(canvas) };
        painter.setBrush(Qt::blue);
        painter.drawEllipse(0, 0, 32, 32);
        QPixmap blue{ QPixmap::fromImage(canvas) };
        treeView->setPixmaps(red, green, blue);
    
        QStandardItem * parentItem = mModel.invisibleRootItem();
        for (int i = 1; i <= 4; ++i)
        {
            QStandardItem * item = new QStandardItem(QString("item %1").arg(i));
            parentItem->appendRow(item);
        }
    
        treeView->setModel(&mModel);
    }
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
        return a.exec();
    }
    
    S 2 Replies Last reply
    1
    • KenAppleby 0K KenAppleby 0

      @StudentScripter
      Here's a very rudimentary example. It turns out that you can reuse most of the QAbstractView drag and drop functionality. You just need to set up the QDrag object correctly with the model indexes.
      Caveat emptor.

      #include <QMainWindow>
      #include <QApplication>
      #include <QStandardItemModel>
      #include <QTreeView>
      #include <QHBoxLayout>
      #include <QPainter>
      #include <QMouseEvent>
      #include <QMimeData>
      #include <QDrag>
      
      class MainWindow : public QMainWindow
      {
      public:
          MainWindow(QWidget * parent =nullptr);
      
          QStandardItemModel mModel;
      };
      
      class TreeView : public QTreeView
      {
      public:
          TreeView(QWidget * parent);
      
          void setPixmaps(QPixmap red, QPixmap green, QPixmap blue);
          void mousePressEvent(QMouseEvent * event) override;
          void mouseMoveEvent(QMouseEvent * event) override;
          void dragEnterEvent(QDragEnterEvent * event) override;
          void dragMoveEvent(QDragMoveEvent * event) override;
      
          void dropEvent(QDropEvent * e) override;
      
          QPixmap mRed;
          QPixmap mGreen;
          QPixmap mBlue;
          QPoint mDragPos;
          bool mDragging{ false };
      };
      
      TreeView::TreeView(QWidget * parent)
          : QTreeView{ parent }
      {
          setDragDropMode(InternalMove);
      }
      
      void TreeView::setPixmaps(QPixmap red, QPixmap green, QPixmap blue)
      {
          mRed = red; mGreen = green; mBlue = blue;
      }
      
      void TreeView::mousePressEvent(QMouseEvent * event)
      {
          if (event->button() == Qt::LeftButton)
          {
              QModelIndex index{ indexAt(event->pos()) };
              if (index.isValid())
              {
                  mDragPos = event->pos();
                  mDragging = true;
              }
          }
          QTreeView::mousePressEvent(event); // implements item selection
      }
      
      void TreeView::mouseMoveEvent(QMouseEvent * e)
      {
          if (mDragging)
          {
              QPoint p = mDragPos - e->pos();
              int d = p.manhattanLength();
              if (d >= QApplication::startDragDistance())
              {
                  QModelIndexList selectedItems = selectedIndexes(); // at least one item must be selected
                  if (selectedItems.size())
                  {
                      QMimeData * mimeData = model()->mimeData(selectedItems);
                      QDrag * drag = new QDrag(this);
                      connect(drag, &QObject::destroyed, this, []()
                      {
                          qDebug() << "drop dead";
                      });
      
                      drag->setPixmap(mBlue);
                      drag->setMimeData(mimeData);
                      drag->setDragCursor(mGreen, Qt::MoveAction);
                      drag->setDragCursor(mRed, Qt::IgnoreAction);
      
                      Qt::DropAction result = drag->exec(Qt::CopyAction|Qt::MoveAction, Qt::IgnoreAction);
                      qDebug() << "drag exec result" << result;
                  }
              }
          }
      }
      
      void TreeView::dragEnterEvent(QDragEnterEvent * event)
      {
          qDebug() << "drag enter" << event->proposedAction() << event->possibleActions();
          QTreeView::dragEnterEvent(event);
      }
      
      void TreeView::dragMoveEvent(QDragMoveEvent * event)
      {
          QTreeView::dragMoveEvent(event);
          event->acceptProposedAction();
      }
      
      void TreeView::dropEvent(QDropEvent * e)
      {
          qDebug() << "drop accepted" << e->mimeData()->hasText() << e->mimeData()->text();
          QTreeView::dropEvent(e);
          e->acceptProposedAction();
      }
      
      
      MainWindow::MainWindow(QWidget * parent)
          : QMainWindow{ parent }
      {
          QWidget * centralwidget;
          QHBoxLayout * horizontalLayout;
          TreeView * treeView;
      
          resize(450, 400);
          centralwidget = new QWidget{ this };
          horizontalLayout = new QHBoxLayout{ centralwidget };
          treeView = new TreeView{ centralwidget };
          horizontalLayout->addWidget(treeView);
      
          setCentralWidget(centralwidget);
      
          QImage canvas{ 32, 32, QImage::Format_ARGB32 };
          canvas.fill(Qt::transparent);
          QPainter painter{ &canvas };
          painter.setBrush(Qt::red);
          painter.drawEllipse(0, 0, 32, 32);
          QPixmap red{ QPixmap::fromImage(canvas) };
          painter.setBrush(Qt::green);
          painter.drawEllipse(0, 0, 32, 32);
          QPixmap green{ QPixmap::fromImage(canvas) };
          painter.setBrush(Qt::blue);
          painter.drawEllipse(0, 0, 32, 32);
          QPixmap blue{ QPixmap::fromImage(canvas) };
          treeView->setPixmaps(red, green, blue);
      
          QStandardItem * parentItem = mModel.invisibleRootItem();
          for (int i = 1; i <= 4; ++i)
          {
              QStandardItem * item = new QStandardItem(QString("item %1").arg(i));
              parentItem->appendRow(item);
          }
      
          treeView->setModel(&mModel);
      }
      
      int main(int argc, char *argv[])
      {
          QApplication a(argc, argv);
          MainWindow w;
          w.show();
          return a.exec();
      }
      
      S Offline
      S Offline
      StudentScripter
      wrote on last edited by
      #15

      @KenAppleby-0

      Can't thank you enough. Seeing your response definitely made me smile. Gonna have a look and test it tomorrow to get an understanding of whats going on. :)

      1 Reply Last reply
      0
      • KenAppleby 0K KenAppleby 0

        @StudentScripter
        Here's a very rudimentary example. It turns out that you can reuse most of the QAbstractView drag and drop functionality. You just need to set up the QDrag object correctly with the model indexes.
        Caveat emptor.

        #include <QMainWindow>
        #include <QApplication>
        #include <QStandardItemModel>
        #include <QTreeView>
        #include <QHBoxLayout>
        #include <QPainter>
        #include <QMouseEvent>
        #include <QMimeData>
        #include <QDrag>
        
        class MainWindow : public QMainWindow
        {
        public:
            MainWindow(QWidget * parent =nullptr);
        
            QStandardItemModel mModel;
        };
        
        class TreeView : public QTreeView
        {
        public:
            TreeView(QWidget * parent);
        
            void setPixmaps(QPixmap red, QPixmap green, QPixmap blue);
            void mousePressEvent(QMouseEvent * event) override;
            void mouseMoveEvent(QMouseEvent * event) override;
            void dragEnterEvent(QDragEnterEvent * event) override;
            void dragMoveEvent(QDragMoveEvent * event) override;
        
            void dropEvent(QDropEvent * e) override;
        
            QPixmap mRed;
            QPixmap mGreen;
            QPixmap mBlue;
            QPoint mDragPos;
            bool mDragging{ false };
        };
        
        TreeView::TreeView(QWidget * parent)
            : QTreeView{ parent }
        {
            setDragDropMode(InternalMove);
        }
        
        void TreeView::setPixmaps(QPixmap red, QPixmap green, QPixmap blue)
        {
            mRed = red; mGreen = green; mBlue = blue;
        }
        
        void TreeView::mousePressEvent(QMouseEvent * event)
        {
            if (event->button() == Qt::LeftButton)
            {
                QModelIndex index{ indexAt(event->pos()) };
                if (index.isValid())
                {
                    mDragPos = event->pos();
                    mDragging = true;
                }
            }
            QTreeView::mousePressEvent(event); // implements item selection
        }
        
        void TreeView::mouseMoveEvent(QMouseEvent * e)
        {
            if (mDragging)
            {
                QPoint p = mDragPos - e->pos();
                int d = p.manhattanLength();
                if (d >= QApplication::startDragDistance())
                {
                    QModelIndexList selectedItems = selectedIndexes(); // at least one item must be selected
                    if (selectedItems.size())
                    {
                        QMimeData * mimeData = model()->mimeData(selectedItems);
                        QDrag * drag = new QDrag(this);
                        connect(drag, &QObject::destroyed, this, []()
                        {
                            qDebug() << "drop dead";
                        });
        
                        drag->setPixmap(mBlue);
                        drag->setMimeData(mimeData);
                        drag->setDragCursor(mGreen, Qt::MoveAction);
                        drag->setDragCursor(mRed, Qt::IgnoreAction);
        
                        Qt::DropAction result = drag->exec(Qt::CopyAction|Qt::MoveAction, Qt::IgnoreAction);
                        qDebug() << "drag exec result" << result;
                    }
                }
            }
        }
        
        void TreeView::dragEnterEvent(QDragEnterEvent * event)
        {
            qDebug() << "drag enter" << event->proposedAction() << event->possibleActions();
            QTreeView::dragEnterEvent(event);
        }
        
        void TreeView::dragMoveEvent(QDragMoveEvent * event)
        {
            QTreeView::dragMoveEvent(event);
            event->acceptProposedAction();
        }
        
        void TreeView::dropEvent(QDropEvent * e)
        {
            qDebug() << "drop accepted" << e->mimeData()->hasText() << e->mimeData()->text();
            QTreeView::dropEvent(e);
            e->acceptProposedAction();
        }
        
        
        MainWindow::MainWindow(QWidget * parent)
            : QMainWindow{ parent }
        {
            QWidget * centralwidget;
            QHBoxLayout * horizontalLayout;
            TreeView * treeView;
        
            resize(450, 400);
            centralwidget = new QWidget{ this };
            horizontalLayout = new QHBoxLayout{ centralwidget };
            treeView = new TreeView{ centralwidget };
            horizontalLayout->addWidget(treeView);
        
            setCentralWidget(centralwidget);
        
            QImage canvas{ 32, 32, QImage::Format_ARGB32 };
            canvas.fill(Qt::transparent);
            QPainter painter{ &canvas };
            painter.setBrush(Qt::red);
            painter.drawEllipse(0, 0, 32, 32);
            QPixmap red{ QPixmap::fromImage(canvas) };
            painter.setBrush(Qt::green);
            painter.drawEllipse(0, 0, 32, 32);
            QPixmap green{ QPixmap::fromImage(canvas) };
            painter.setBrush(Qt::blue);
            painter.drawEllipse(0, 0, 32, 32);
            QPixmap blue{ QPixmap::fromImage(canvas) };
            treeView->setPixmaps(red, green, blue);
        
            QStandardItem * parentItem = mModel.invisibleRootItem();
            for (int i = 1; i <= 4; ++i)
            {
                QStandardItem * item = new QStandardItem(QString("item %1").arg(i));
                parentItem->appendRow(item);
            }
        
            treeView->setModel(&mModel);
        }
        
        int main(int argc, char *argv[])
        {
            QApplication a(argc, argv);
            MainWindow w;
            w.show();
            return a.exec();
        }
        
        S Offline
        S Offline
        StudentScripter
        wrote on last edited by StudentScripter
        #16

        @KenAppleby-0 So thanks Ken, i tested the code you provided and it's really great! :D

        But two small problems:
        1. the items i move do not get removed/deleted from their old position so i end up with a bunch of copies

        2. In the drag i don't see the item beeing dragged/grapped like it's natively in qt treeview (hope you understand what i mean), i only see the cursor that is changed now; BIG THANKS

        So yeah may you could help me with these two again if you got a minute the next few days. Would be really appreciated. :)

        KenAppleby 0K 1 Reply Last reply
        0
        • S StudentScripter

          @KenAppleby-0 So thanks Ken, i tested the code you provided and it's really great! :D

          But two small problems:
          1. the items i move do not get removed/deleted from their old position so i end up with a bunch of copies

          2. In the drag i don't see the item beeing dragged/grapped like it's natively in qt treeview (hope you understand what i mean), i only see the cursor that is changed now; BIG THANKS

          So yeah may you could help me with these two again if you got a minute the next few days. Would be really appreciated. :)

          KenAppleby 0K Offline
          KenAppleby 0K Offline
          KenAppleby 0
          wrote on last edited by
          #17

          @StudentScripter

          @StudentScripter said in setDragCursor for QTreeView?:

          1. the items i move do not get removed/deleted from their old position so i end up with a bunch of copies

          Yes, that is puzzling. I don't know how to help with that specifically at the moment. But see below.

          @StudentScripter said in setDragCursor for QTreeView?:

          1. In the drag i don't see the item beeing dragged/grapped like it's natively in qt treeview (hope you understand what i mean), i only see the cursor that is changed now

          That's done by rendering the selected items to a pixmap and setting the pixmap of the drag object with the result.

          Have you looked at the source code for QAbstractItemView? It's in Src/qtbase/src/widgets/itemviews/

          I realise now that there's only one function you need to override:

          QAbstractItemView::startDrag()
          

          Use the souce code from QAbstractItemView.
          That already does everything you want to do with the exception of the drag cursors. It should be easy to change that in an override. I'm sorry I didn't think of this sooner: I didn't realise that startDrag() is a virtual function.

          [ This does all seem a lot of work to do just because you don't like the system-provided drag cursors! :-) ]

          S 1 Reply Last reply
          1
          • KenAppleby 0K KenAppleby 0

            @StudentScripter

            @StudentScripter said in setDragCursor for QTreeView?:

            1. the items i move do not get removed/deleted from their old position so i end up with a bunch of copies

            Yes, that is puzzling. I don't know how to help with that specifically at the moment. But see below.

            @StudentScripter said in setDragCursor for QTreeView?:

            1. In the drag i don't see the item beeing dragged/grapped like it's natively in qt treeview (hope you understand what i mean), i only see the cursor that is changed now

            That's done by rendering the selected items to a pixmap and setting the pixmap of the drag object with the result.

            Have you looked at the source code for QAbstractItemView? It's in Src/qtbase/src/widgets/itemviews/

            I realise now that there's only one function you need to override:

            QAbstractItemView::startDrag()
            

            Use the souce code from QAbstractItemView.
            That already does everything you want to do with the exception of the drag cursors. It should be easy to change that in an override. I'm sorry I didn't think of this sooner: I didn't realise that startDrag() is a virtual function.

            [ This does all seem a lot of work to do just because you don't like the system-provided drag cursors! :-) ]

            S Offline
            S Offline
            StudentScripter
            wrote on last edited by
            #18

            @KenAppleby-0 Well the thing is i want to override the cursor to make a different one for when the user drags an item onto another (parenting) vs. other cursor for just moving/reordering the item. With the standard cursors it's alwasy the accept proposed action cursor, which also confused myself regularely.

            I currently reverted my code back to the standard implementation, but could you please elaborate more on the start drag and changing the cursor?

            PS: Yes i know much work for a hobby project, but well i tried 2 months now to get my treeview setup how i want it, therefore no problem with trying to get the last things finished. :D

            KenAppleby 0K 1 Reply Last reply
            0
            • S StudentScripter

              @KenAppleby-0 Well the thing is i want to override the cursor to make a different one for when the user drags an item onto another (parenting) vs. other cursor for just moving/reordering the item. With the standard cursors it's alwasy the accept proposed action cursor, which also confused myself regularely.

              I currently reverted my code back to the standard implementation, but could you please elaborate more on the start drag and changing the cursor?

              PS: Yes i know much work for a hobby project, but well i tried 2 months now to get my treeview setup how i want it, therefore no problem with trying to get the last things finished. :D

              KenAppleby 0K Offline
              KenAppleby 0K Offline
              KenAppleby 0
              wrote on last edited by
              #19

              @StudentScripter said in setDragCursor for QTreeView?:

              Well the thing is i want to override the cursor to make a different one for when the user drags an item onto another (parenting) vs. other cursor for just moving/reordering the item

              Ah, I see. I hadn't picked that requirement up.
              If that isn't already provided by QAbstractItemView and QStandardItemModel then that would be done in the dragMoveEvent, I think. You'd need to track the model indexes that the cursor is on or between.
              I can only suggest that you look at the source code for QAbstractItemView, particularly dragMoveEvent() and startDrag().

              S 1 Reply Last reply
              0
              • KenAppleby 0K KenAppleby 0

                @StudentScripter said in setDragCursor for QTreeView?:

                Well the thing is i want to override the cursor to make a different one for when the user drags an item onto another (parenting) vs. other cursor for just moving/reordering the item

                Ah, I see. I hadn't picked that requirement up.
                If that isn't already provided by QAbstractItemView and QStandardItemModel then that would be done in the dragMoveEvent, I think. You'd need to track the model indexes that the cursor is on or between.
                I can only suggest that you look at the source code for QAbstractItemView, particularly dragMoveEvent() and startDrag().

                S Offline
                S Offline
                StudentScripter
                wrote on last edited by
                #20

                @KenAppleby-0 Well i got the some system implemented to check where the cursor is, but still i don't know how to set the cursor cause with the methode as mentioned before i can't get the old items deleted when they are moved to a new position.

                But two small problems:

                1. the items i move do not get removed/deleted from their old position so i end up with a bunch of copies

                2. In the drag i don't see the item beeing dragged/grapped like it's natively in qt treeview (hope you understand what i mean), i only see the cursor that is changed now; BIG THANKS*Here is the system i implemented to check where the mouse is on dragMoveEvent():**

                void ViewLayerList::dragMoveEvent(QDragMoveEvent *event)
                {
                
                    QModelIndex indexAtMouse = indexAt(event->pos());
                
                
                    if (indexAtMouse.isValid())
                    {
                    
                    ViewLayerStandartItemModel* model = dynamic_cast<ViewLayerStandartItemModel*>(this->model);
                
                        if (model)
                        {
                            QStandardItem* itemAtMouse = model->itemFromIndex(indexAtMouse);
                
                            if (itemAtMouse)
                            {
                            
                                QRect itemRect = visualRect(indexAtMouse); // QRect des Items
                                int RectMinHeight = itemRect.y();
                                int RectMaxHeight = itemRect.height() + itemRect.y();
                                QPoint mousePos = event->position().toPoint(); // Mausposition in der Ansicht
                
                                // Übersetzen Sie die Mauskoordinaten in das Koordinatensystem des Items
                                QPoint mousePosInItem = mapFrom(this, itemRect.topLeft()) + mousePos - itemRect.topLeft();
                
                                qDebug() << "ItemIndex:" << itemAtMouse << " ItemRect MinHeight: " << RectMinHeight << " ItemRect MaxHeight: " << RectMaxHeight << "    MousePos: " << mousePosInItem;
                
                                
                                
                                if(mousePosInItem.y() < RectMinHeight + 5)
                                {
                                    qDebug() << "Mouse is ABOVE Item: " << itemAtMouse;
                                
                                }else if(mousePosInItem.y() > RectMaxHeight-5){
                                    qDebug() << "Mouse is BELOW Item: " << itemAtMouse;
                                
                                }
                            }
                        }
                    }
                
                 QTreeView::dragMoveEvent(event);
                 event->acceptProposedAction();
                 
                
                
                  
                }
                
                KenAppleby 0K 1 Reply Last reply
                0
                • S StudentScripter

                  @KenAppleby-0 Well i got the some system implemented to check where the cursor is, but still i don't know how to set the cursor cause with the methode as mentioned before i can't get the old items deleted when they are moved to a new position.

                  But two small problems:

                  1. the items i move do not get removed/deleted from their old position so i end up with a bunch of copies

                  2. In the drag i don't see the item beeing dragged/grapped like it's natively in qt treeview (hope you understand what i mean), i only see the cursor that is changed now; BIG THANKS*Here is the system i implemented to check where the mouse is on dragMoveEvent():**

                  void ViewLayerList::dragMoveEvent(QDragMoveEvent *event)
                  {
                  
                      QModelIndex indexAtMouse = indexAt(event->pos());
                  
                  
                      if (indexAtMouse.isValid())
                      {
                      
                      ViewLayerStandartItemModel* model = dynamic_cast<ViewLayerStandartItemModel*>(this->model);
                  
                          if (model)
                          {
                              QStandardItem* itemAtMouse = model->itemFromIndex(indexAtMouse);
                  
                              if (itemAtMouse)
                              {
                              
                                  QRect itemRect = visualRect(indexAtMouse); // QRect des Items
                                  int RectMinHeight = itemRect.y();
                                  int RectMaxHeight = itemRect.height() + itemRect.y();
                                  QPoint mousePos = event->position().toPoint(); // Mausposition in der Ansicht
                  
                                  // Übersetzen Sie die Mauskoordinaten in das Koordinatensystem des Items
                                  QPoint mousePosInItem = mapFrom(this, itemRect.topLeft()) + mousePos - itemRect.topLeft();
                  
                                  qDebug() << "ItemIndex:" << itemAtMouse << " ItemRect MinHeight: " << RectMinHeight << " ItemRect MaxHeight: " << RectMaxHeight << "    MousePos: " << mousePosInItem;
                  
                                  
                                  
                                  if(mousePosInItem.y() < RectMinHeight + 5)
                                  {
                                      qDebug() << "Mouse is ABOVE Item: " << itemAtMouse;
                                  
                                  }else if(mousePosInItem.y() > RectMaxHeight-5){
                                      qDebug() << "Mouse is BELOW Item: " << itemAtMouse;
                                  
                                  }
                              }
                          }
                      }
                  
                   QTreeView::dragMoveEvent(event);
                   event->acceptProposedAction();
                   
                  
                  
                    
                  }
                  
                  KenAppleby 0K Offline
                  KenAppleby 0K Offline
                  KenAppleby 0
                  wrote on last edited by
                  #21

                  @StudentScripter
                  This code from QAbstractItemView is where the drag->exec() is called, and on return from that, at the end of the drag, the affected indexes are removed in the call to the private function clearOrRemove().

                  if (drag->exec(supportedActions, defaultDropAction) == Qt::MoveAction && !d->dropEventMoved) {
                              if (dragDropMode() != InternalMove || drag->target() == viewport())
                                  d->clearOrRemove();
                  

                  That function uses the current selection from the selection model. It would take me some time to understand how all that works!

                  To set the drag cursor during the move, something like this might work, just as an illustration:

                  void TreeView::dragMoveEvent(QDragMoveEvent * event)
                  {
                      QModelIndex atIndex{ indexAt(event->position().toPoint()) };
                      if ((atIndex.row() & 1) == 0)
                      {
                          mDrag->setDragCursor(mRed, Qt::MoveAction);
                      }
                      else
                      {
                          mDrag->setDragCursor(mGreen, Qt::MoveAction);
                      }
                      QTreeView::dragMoveEvent(event);
                  }
                  

                  This just alternates the drag cursor depending on the row index.

                  The startDrag() function can deal with the inserting and removing of dragged rows before and after the drag. The following does something like that, only it doesn't work correctly! I'm just offering it as a possible hint of a way forward.

                  void TreeView::startDrag(Qt::DropActions supportedActions)
                  {
                      QModelIndexList indexes = selectedIndexes();
                      qDebug() << "start drag" << indexes;
                      if (indexes.size() == 1)
                      {
                          QMimeData * data = model()->mimeData(indexes);
                          if (data)
                          {
                              QRect rect;
                              QPixmap pixmap = renderToPixmap(indexes, &rect);
                              rect.adjust(horizontalOffset(), verticalOffset(), 0, 0);
                  
                              mDrag = new QDrag(this);
                              connect(mDrag, &QObject::destroyed, this, [this]() { mDrag = nullptr; });
                  
                              mDrag->setPixmap(pixmap);
                              mDrag->setMimeData(data);
                              mDrag->setHotSpot(mDragPos - rect.topLeft());
                              Qt::DropAction defaultDropAction = Qt::IgnoreAction;
                              if (dragDropMode() == InternalMove)
                              {
                                  supportedActions &= ~Qt::CopyAction;
                              }
                              if (supportedActions & Qt::CopyAction && dragDropMode() != QAbstractItemView::InternalMove)
                              {
                                  defaultDropAction = Qt::CopyAction;
                              }
                              model()->removeRow(indexes.front().row(), indexes.front().parent()); // <<<< WRONG!
                              if (not (mDrag->exec(supportedActions, defaultDropAction) == Qt::MoveAction))
                              {
                                  model()->insertRow(indexes.front().row(), indexes.front().parent()); // <<<< WRONG!
                              }
                          }
                      }
                  }
                  

                  That function also attempts to set the pixmap to be drawn during the drag. The functions that do that are:

                  QPixmap TreeView::renderToPixmap( const QModelIndexList& indexes, QRect * r ) const
                  {
                      QPixmap result;
                      ItemViewPaintPairs paintPairs = draggablePaintPairs(indexes, r);
                      if (! paintPairs.isEmpty())
                      {
                          QPixmap pixmap(r->size());
                          pixmap.fill(Qt::transparent);
                          QPainter painter(&pixmap);
                          painter.setOpacity(0.9);
                          QStyleOptionViewItem option;
                          option.initFrom(this);
                          option.state |= QStyle::State_Selected;
                          for (int j = 0; j < paintPairs.count(); ++j)
                          {
                              option.rect = paintPairs.at( j ).first.translated( -r->topLeft() );
                              const QModelIndex& current = paintPairs.at( j ).second;
                              itemDelegateForIndex(current)->paint(&painter, option, current);
                          }
                          result = pixmap;
                      }
                      return result;
                  }
                  TreeView::ItemViewPaintPairs TreeView::draggablePaintPairs(const QModelIndexList& indexes, QRect * r) const
                  {
                      QRect& rect = *r;
                      const QRect viewportRect = viewport()->rect();
                      ItemViewPaintPairs ret;
                      for ( int i = 0; i < indexes.count(); ++i )
                      {
                          const QModelIndex& index = indexes.at( i );
                          const QRect current = this->visualRect( index );
                          if ( current.intersects( viewportRect ) )
                          {
                              ret += qMakePair( current, index );
                              rect |= current;
                          }
                      }
                      rect &= viewportRect;
                      return ret;
                  }
                  

                  The code is modified from that in the QAbstractItemView sources.

                  I'm sure you understand that I am just hacking away here, this is nowhere near a proper solution! I just hope it might help in some way. If I'm leading you up the garden path, which I may well be, I apologise.

                  S 1 Reply Last reply
                  0
                  • KenAppleby 0K KenAppleby 0

                    @StudentScripter
                    This code from QAbstractItemView is where the drag->exec() is called, and on return from that, at the end of the drag, the affected indexes are removed in the call to the private function clearOrRemove().

                    if (drag->exec(supportedActions, defaultDropAction) == Qt::MoveAction && !d->dropEventMoved) {
                                if (dragDropMode() != InternalMove || drag->target() == viewport())
                                    d->clearOrRemove();
                    

                    That function uses the current selection from the selection model. It would take me some time to understand how all that works!

                    To set the drag cursor during the move, something like this might work, just as an illustration:

                    void TreeView::dragMoveEvent(QDragMoveEvent * event)
                    {
                        QModelIndex atIndex{ indexAt(event->position().toPoint()) };
                        if ((atIndex.row() & 1) == 0)
                        {
                            mDrag->setDragCursor(mRed, Qt::MoveAction);
                        }
                        else
                        {
                            mDrag->setDragCursor(mGreen, Qt::MoveAction);
                        }
                        QTreeView::dragMoveEvent(event);
                    }
                    

                    This just alternates the drag cursor depending on the row index.

                    The startDrag() function can deal with the inserting and removing of dragged rows before and after the drag. The following does something like that, only it doesn't work correctly! I'm just offering it as a possible hint of a way forward.

                    void TreeView::startDrag(Qt::DropActions supportedActions)
                    {
                        QModelIndexList indexes = selectedIndexes();
                        qDebug() << "start drag" << indexes;
                        if (indexes.size() == 1)
                        {
                            QMimeData * data = model()->mimeData(indexes);
                            if (data)
                            {
                                QRect rect;
                                QPixmap pixmap = renderToPixmap(indexes, &rect);
                                rect.adjust(horizontalOffset(), verticalOffset(), 0, 0);
                    
                                mDrag = new QDrag(this);
                                connect(mDrag, &QObject::destroyed, this, [this]() { mDrag = nullptr; });
                    
                                mDrag->setPixmap(pixmap);
                                mDrag->setMimeData(data);
                                mDrag->setHotSpot(mDragPos - rect.topLeft());
                                Qt::DropAction defaultDropAction = Qt::IgnoreAction;
                                if (dragDropMode() == InternalMove)
                                {
                                    supportedActions &= ~Qt::CopyAction;
                                }
                                if (supportedActions & Qt::CopyAction && dragDropMode() != QAbstractItemView::InternalMove)
                                {
                                    defaultDropAction = Qt::CopyAction;
                                }
                                model()->removeRow(indexes.front().row(), indexes.front().parent()); // <<<< WRONG!
                                if (not (mDrag->exec(supportedActions, defaultDropAction) == Qt::MoveAction))
                                {
                                    model()->insertRow(indexes.front().row(), indexes.front().parent()); // <<<< WRONG!
                                }
                            }
                        }
                    }
                    

                    That function also attempts to set the pixmap to be drawn during the drag. The functions that do that are:

                    QPixmap TreeView::renderToPixmap( const QModelIndexList& indexes, QRect * r ) const
                    {
                        QPixmap result;
                        ItemViewPaintPairs paintPairs = draggablePaintPairs(indexes, r);
                        if (! paintPairs.isEmpty())
                        {
                            QPixmap pixmap(r->size());
                            pixmap.fill(Qt::transparent);
                            QPainter painter(&pixmap);
                            painter.setOpacity(0.9);
                            QStyleOptionViewItem option;
                            option.initFrom(this);
                            option.state |= QStyle::State_Selected;
                            for (int j = 0; j < paintPairs.count(); ++j)
                            {
                                option.rect = paintPairs.at( j ).first.translated( -r->topLeft() );
                                const QModelIndex& current = paintPairs.at( j ).second;
                                itemDelegateForIndex(current)->paint(&painter, option, current);
                            }
                            result = pixmap;
                        }
                        return result;
                    }
                    TreeView::ItemViewPaintPairs TreeView::draggablePaintPairs(const QModelIndexList& indexes, QRect * r) const
                    {
                        QRect& rect = *r;
                        const QRect viewportRect = viewport()->rect();
                        ItemViewPaintPairs ret;
                        for ( int i = 0; i < indexes.count(); ++i )
                        {
                            const QModelIndex& index = indexes.at( i );
                            const QRect current = this->visualRect( index );
                            if ( current.intersects( viewportRect ) )
                            {
                                ret += qMakePair( current, index );
                                rect |= current;
                            }
                        }
                        rect &= viewportRect;
                        return ret;
                    }
                    

                    The code is modified from that in the QAbstractItemView sources.

                    I'm sure you understand that I am just hacking away here, this is nowhere near a proper solution! I just hope it might help in some way. If I'm leading you up the garden path, which I may well be, I apologise.

                    S Offline
                    S Offline
                    StudentScripter
                    wrote on last edited by
                    #22

                    @KenAppleby-0 Oh man well guess the leads to nothing, or atleast nothing the is in the range of what im capable of yet. Thanks anyway.
                    BUT why the hell has it to be that difficult to change a simple cursor??? Is there any way to open a request about that?

                    @SGaist

                    SGaistS 1 Reply Last reply
                    0
                    • S StudentScripter

                      @KenAppleby-0 Oh man well guess the leads to nothing, or atleast nothing the is in the range of what im capable of yet. Thanks anyway.
                      BUT why the hell has it to be that difficult to change a simple cursor??? Is there any way to open a request about that?

                      @SGaist

                      SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on last edited by
                      #23

                      @StudentScripter these are standard cursors that users expect to see when they are doing drag and drop operation with item views.

                      Interested in AI ? www.idiap.ch
                      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                      1 Reply Last reply
                      0

                      • Login

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