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. Dragging out to non-Qt desktop
Qt 6.11 is out! See what's new in the release blog

Dragging out to non-Qt desktop

Scheduled Pinned Locked Moved Unsolved General and Desktop
12 Posts 4 Posters 4.4k 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 Offline
    S Offline
    ShinSat
    wrote on last edited by ShinSat
    #1

    Hello,
    I’m working on dragging and dropping capability in my desktop app, which consists of multiple QWidget.
    D&D works OK if it’s internal movement where the drop receiver is another QWidget.
    My question is how can I achieve the same functionality between the desktop app and non Qt app such as Window desktop where no qt app exists.
    How and where can I handle the dropEvent outside of Qt?

    Many thanks in advance for your help.
    Sat

    raven-worxR 1 Reply Last reply
    0
    • S ShinSat

      Hello,
      I’m working on dragging and dropping capability in my desktop app, which consists of multiple QWidget.
      D&D works OK if it’s internal movement where the drop receiver is another QWidget.
      My question is how can I achieve the same functionality between the desktop app and non Qt app such as Window desktop where no qt app exists.
      How and where can I handle the dropEvent outside of Qt?

      Many thanks in advance for your help.
      Sat

      raven-worxR Offline
      raven-worxR Offline
      raven-worx
      Moderators
      wrote on last edited by
      #2

      @ShinSat
      your question is very unclear.

      How and where can I handle the dropEvent outside of Qt?

      You shouldn't and you wont handle the drop outside your application. Similar to a copy and aste via clipboard you simply provide data to the operating system and let it do the multi-window drag-handling. The final target application which receives the drop handles the data on it's own.
      The only result you get is when your QDrag::exec() returnes and check the returned drop result.

      --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
      If you have a question please use the forum so others can benefit from the solution in the future

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

        Hi
        To drop to desktop, you must follow windows rules for the mimedata
        else it wont accept.

        This sample drags file from Qt to desktop / explorer
        It uses a native windows header. (#include <Shlobj.h>)

        #include "mainwindow.h"
        #include <QApplication>
        #include <QtGui>
        #include <Shlobj.h>
        
        class Widget : public QWidget {
          void mousePressEvent(QMouseEvent* e) {
            QPoint hotSpot = e->pos();
            QList<QUrl> strList;
            FILEGROUPDESCRIPTOR fgd;
            FILEDESCRIPTOR fd[ 1 ];
        
            strList.append( QUrl( "http://www.qt.io/" ) );
            fgd.cItems = 1;
        
            fgd.fgd[ 0 ].dwFlags = FD_PROGRESSUI;
            wcscpy( fgd.fgd[ 0 ].cFileName, L"qtrules.url" );
            QMimeData* mimeData = new QMimeData;
            mimeData->setText("www.gaspar.net");
            mimeData->setUrls( strList );
            mimeData->setData("text/plain", QByteArray( "http://www.gaspar.net" ) );
            mimeData->setData("text/html", QByteArray( "<!--StartFragment--><a href=\"http://www.gaspar.net\">The Gaspar Website</a><!--EndFragment-->" ) );
            mimeData->setData("FileName", QByteArray( "Gaspar Website.url" ) );
            mimeData->setData("FileGroupDescriptorW", QByteArray::fromRawData( ( const char* )&fgd, sizeof ( FILEGROUPDESCRIPTOR ) ) );
            mimeData->setData("FileContents", QByteArray( "[InternetShortcut]\r\nURL=http://www.gaspar.net" ) );
        
            QPixmap pixmap(":/images/imagelists/16x16/webpage.png");
            render(&pixmap);
        
            QDrag* drag = new QDrag(this);
            drag->setMimeData(mimeData);
            drag->setPixmap(pixmap);
            drag->setHotSpot(hotSpot);
        
            Qt::DropAction dropAction = drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction);
        
            if (dropAction == Qt::MoveAction) {
              update();
            }
          }
        };
        
        int main(int argc, char* argv[]) {
          QApplication app(argc, argv);
          Widget window;
          window.show();
          return app.exec();
        }
        

        Credits goes to http://www.gaspar.net/oteqmimewindows.html

        alt text

        JonBJ raven-worxR 2 Replies Last reply
        4
        • mrjjM mrjj

          Hi
          To drop to desktop, you must follow windows rules for the mimedata
          else it wont accept.

          This sample drags file from Qt to desktop / explorer
          It uses a native windows header. (#include <Shlobj.h>)

          #include "mainwindow.h"
          #include <QApplication>
          #include <QtGui>
          #include <Shlobj.h>
          
          class Widget : public QWidget {
            void mousePressEvent(QMouseEvent* e) {
              QPoint hotSpot = e->pos();
              QList<QUrl> strList;
              FILEGROUPDESCRIPTOR fgd;
              FILEDESCRIPTOR fd[ 1 ];
          
              strList.append( QUrl( "http://www.qt.io/" ) );
              fgd.cItems = 1;
          
              fgd.fgd[ 0 ].dwFlags = FD_PROGRESSUI;
              wcscpy( fgd.fgd[ 0 ].cFileName, L"qtrules.url" );
              QMimeData* mimeData = new QMimeData;
              mimeData->setText("www.gaspar.net");
              mimeData->setUrls( strList );
              mimeData->setData("text/plain", QByteArray( "http://www.gaspar.net" ) );
              mimeData->setData("text/html", QByteArray( "<!--StartFragment--><a href=\"http://www.gaspar.net\">The Gaspar Website</a><!--EndFragment-->" ) );
              mimeData->setData("FileName", QByteArray( "Gaspar Website.url" ) );
              mimeData->setData("FileGroupDescriptorW", QByteArray::fromRawData( ( const char* )&fgd, sizeof ( FILEGROUPDESCRIPTOR ) ) );
              mimeData->setData("FileContents", QByteArray( "[InternetShortcut]\r\nURL=http://www.gaspar.net" ) );
          
              QPixmap pixmap(":/images/imagelists/16x16/webpage.png");
              render(&pixmap);
          
              QDrag* drag = new QDrag(this);
              drag->setMimeData(mimeData);
              drag->setPixmap(pixmap);
              drag->setHotSpot(hotSpot);
          
              Qt::DropAction dropAction = drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction);
          
              if (dropAction == Qt::MoveAction) {
                update();
              }
            }
          };
          
          int main(int argc, char* argv[]) {
            QApplication app(argc, argv);
            Widget window;
            window.show();
            return app.exec();
          }
          

          Credits goes to http://www.gaspar.net/oteqmimewindows.html

          alt text

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by
          #4

          @mrjj
          There should be a "Code Snippets" forum here, and this kind of post could be put there with a decent title.

          mrjjM 1 Reply Last reply
          0
          • JonBJ JonB

            @mrjj
            There should be a "Code Snippets" forum here, and this kind of post could be put there with a decent title.

            mrjjM Offline
            mrjjM Offline
            mrjj
            Lifetime Qt Champion
            wrote on last edited by
            #5

            @JNBarchan
            Yes, that would be great. I think we might be able to use the wiki for it since it already has samples.

            1 Reply Last reply
            0
            • mrjjM mrjj

              Hi
              To drop to desktop, you must follow windows rules for the mimedata
              else it wont accept.

              This sample drags file from Qt to desktop / explorer
              It uses a native windows header. (#include <Shlobj.h>)

              #include "mainwindow.h"
              #include <QApplication>
              #include <QtGui>
              #include <Shlobj.h>
              
              class Widget : public QWidget {
                void mousePressEvent(QMouseEvent* e) {
                  QPoint hotSpot = e->pos();
                  QList<QUrl> strList;
                  FILEGROUPDESCRIPTOR fgd;
                  FILEDESCRIPTOR fd[ 1 ];
              
                  strList.append( QUrl( "http://www.qt.io/" ) );
                  fgd.cItems = 1;
              
                  fgd.fgd[ 0 ].dwFlags = FD_PROGRESSUI;
                  wcscpy( fgd.fgd[ 0 ].cFileName, L"qtrules.url" );
                  QMimeData* mimeData = new QMimeData;
                  mimeData->setText("www.gaspar.net");
                  mimeData->setUrls( strList );
                  mimeData->setData("text/plain", QByteArray( "http://www.gaspar.net" ) );
                  mimeData->setData("text/html", QByteArray( "<!--StartFragment--><a href=\"http://www.gaspar.net\">The Gaspar Website</a><!--EndFragment-->" ) );
                  mimeData->setData("FileName", QByteArray( "Gaspar Website.url" ) );
                  mimeData->setData("FileGroupDescriptorW", QByteArray::fromRawData( ( const char* )&fgd, sizeof ( FILEGROUPDESCRIPTOR ) ) );
                  mimeData->setData("FileContents", QByteArray( "[InternetShortcut]\r\nURL=http://www.gaspar.net" ) );
              
                  QPixmap pixmap(":/images/imagelists/16x16/webpage.png");
                  render(&pixmap);
              
                  QDrag* drag = new QDrag(this);
                  drag->setMimeData(mimeData);
                  drag->setPixmap(pixmap);
                  drag->setHotSpot(hotSpot);
              
                  Qt::DropAction dropAction = drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction);
              
                  if (dropAction == Qt::MoveAction) {
                    update();
                  }
                }
              };
              
              int main(int argc, char* argv[]) {
                QApplication app(argc, argv);
                Widget window;
                window.show();
                return app.exec();
              }
              

              Credits goes to http://www.gaspar.net/oteqmimewindows.html

              alt text

              raven-worxR Offline
              raven-worxR Offline
              raven-worx
              Moderators
              wrote on last edited by
              #6

              @mrjj
              Just a note: File drags to desktop can also be achieved using Qt classes only:

              1. start a drag containing all the needed mime-types
              2. create an empty QTemporaryFile with the target file-name and set it's file path to the mime-data (file-urls type)
              3. fill the temporary file once it is requested in the QMimeData::retrieveData() method (see the delayed encoding example)
              4. the OS copies the (temp-)file to the drop-position

              --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
              If you have a question please use the forum so others can benefit from the solution in the future

              mrjjM 1 Reply Last reply
              1
              • raven-worxR raven-worx

                @mrjj
                Just a note: File drags to desktop can also be achieved using Qt classes only:

                1. start a drag containing all the needed mime-types
                2. create an empty QTemporaryFile with the target file-name and set it's file path to the mime-data (file-urls type)
                3. fill the temporary file once it is requested in the QMimeData::retrieveData() method (see the delayed encoding example)
                4. the OS copies the (temp-)file to the drop-position
                mrjjM Offline
                mrjjM Offline
                mrjj
                Lifetime Qt Champion
                wrote on last edited by
                #7

                @raven-worx

                Did you try delayed encoding sample ?

                The sample will not work for me on win 7 or win 10.
                Tried 2 pc. Desktop/explorer wont accept.

                So i wonder if issue with my pcs or just dont work like that in newer Windows.

                raven-worxR 1 Reply Last reply
                0
                • mrjjM mrjj

                  @raven-worx

                  Did you try delayed encoding sample ?

                  The sample will not work for me on win 7 or win 10.
                  Tried 2 pc. Desktop/explorer wont accept.

                  So i wonder if issue with my pcs or just dont work like that in newer Windows.

                  raven-worxR Offline
                  raven-worxR Offline
                  raven-worx
                  Moderators
                  wrote on last edited by
                  #8

                  @mrjj
                  yes, but it's a while ago. I will give it a try.

                  --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
                  If you have a question please use the forum so others can benefit from the solution in the future

                  mrjjM 1 Reply Last reply
                  0
                  • raven-worxR raven-worx

                    @mrjj
                    yes, but it's a while ago. I will give it a try.

                    mrjjM Offline
                    mrjjM Offline
                    mrjj
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    @raven-worx

                    Super. Maybe i just do it wrong.
                    I drag the export Button out from window. It show red stop sign.

                    raven-worxR 1 Reply Last reply
                    0
                    • mrjjM mrjj

                      @raven-worx

                      Super. Maybe i just do it wrong.
                      I drag the export Button out from window. It show red stop sign.

                      raven-worxR Offline
                      raven-worxR Offline
                      raven-worx
                      Moderators
                      wrote on last edited by raven-worx
                      #10

                      @mrjj
                      the following (unoptimized code) works (Qt 5.9, Windows 7):

                      MimeData::MimeData()
                          : QMimeData()
                      {
                          QString filePath = QStandardPaths::writableLocation(QStandardPaths::TempLocation) % QDir::separator() % "Gaspar Website.url";
                          m_File = new QFile( filePath, this );
                      }
                      
                      MimeData::~MimeData()
                      {
                          if( m_File && m_File->isOpen() )
                              m_File->close();
                      }
                      
                      QStringList MimeData::formats() const
                      {
                          return QMimeData::formats() << QLatin1String("text/uri-list");
                      }
                      
                      QVariant MimeData::retrieveData(const QString &mimeType, QVariant::Type type) const
                      {
                          if( mimeType == QStringLiteral("text/uri-list") )
                          {
                              // since this method may be called multiple during a single drag it's not necessary to also write to the file multiple times -> needs optimization
                              if( m_File->open(QFile::WriteOnly) )
                              {
                                  m_File->write( QByteArray("[InternetShortcut]\r\nURL=http://www.gaspar.net") );
                                  m_File->close();
                              }
                      
                              return QVariant::fromValue<QUrl>( QUrl::fromLocalFile(QFileInfo(*m_File).absoluteFilePath()) );
                          }
                          else
                              return QMimeData::retrieveData(mimeType, type);
                      }
                      

                      Although it seems there are some caveats:

                      1. it stopped working when i set the path of the temp file into a subfolder in the temp-dir ... o.O
                      2. the retrieveData() always requests the data with the type QVariant::QVariantList. But still it only works when i return a QUrl (not a QList) packed into the variant data.

                      Very strange.

                      --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
                      If you have a question please use the forum so others can benefit from the solution in the future

                      mrjjM 1 Reply Last reply
                      1
                      • raven-worxR raven-worx

                        @mrjj
                        the following (unoptimized code) works (Qt 5.9, Windows 7):

                        MimeData::MimeData()
                            : QMimeData()
                        {
                            QString filePath = QStandardPaths::writableLocation(QStandardPaths::TempLocation) % QDir::separator() % "Gaspar Website.url";
                            m_File = new QFile( filePath, this );
                        }
                        
                        MimeData::~MimeData()
                        {
                            if( m_File && m_File->isOpen() )
                                m_File->close();
                        }
                        
                        QStringList MimeData::formats() const
                        {
                            return QMimeData::formats() << QLatin1String("text/uri-list");
                        }
                        
                        QVariant MimeData::retrieveData(const QString &mimeType, QVariant::Type type) const
                        {
                            if( mimeType == QStringLiteral("text/uri-list") )
                            {
                                // since this method may be called multiple during a single drag it's not necessary to also write to the file multiple times -> needs optimization
                                if( m_File->open(QFile::WriteOnly) )
                                {
                                    m_File->write( QByteArray("[InternetShortcut]\r\nURL=http://www.gaspar.net") );
                                    m_File->close();
                                }
                        
                                return QVariant::fromValue<QUrl>( QUrl::fromLocalFile(QFileInfo(*m_File).absoluteFilePath()) );
                            }
                            else
                                return QMimeData::retrieveData(mimeType, type);
                        }
                        

                        Although it seems there are some caveats:

                        1. it stopped working when i set the path of the temp file into a subfolder in the temp-dir ... o.O
                        2. the retrieveData() always requests the data with the type QVariant::QVariantList. But still it only works when i return a QUrl (not a QList) packed into the variant data.

                        Very strange.

                        mrjjM Offline
                        mrjjM Offline
                        mrjj
                        Lifetime Qt Champion
                        wrote on last edited by mrjj
                        #11

                        @raven-worx

                        Good work.
                        Ehh so it likes only root of tmp dir ?? odd
                        2: that is a bit odd but i guess it was only ment for 1 file then.

                        Would it be possible to get the test code ?
                        Want to see if win 10 likes it also :)

                        This is nicer than the platform bound i found :) \o/

                        raven-worxR 1 Reply Last reply
                        0
                        • mrjjM mrjj

                          @raven-worx

                          Good work.
                          Ehh so it likes only root of tmp dir ?? odd
                          2: that is a bit odd but i guess it was only ment for 1 file then.

                          Would it be possible to get the test code ?
                          Want to see if win 10 likes it also :)

                          This is nicer than the platform bound i found :) \o/

                          raven-worxR Offline
                          raven-worxR Offline
                          raven-worx
                          Moderators
                          wrote on last edited by raven-worx
                          #12

                          @mrjj said in Dragging out to non-Qt desktop:

                          Would it be possible to get the test code ?

                          thats actually all the code (despite the obvious header file).

                          All i did additionally for testing was this:

                          void MainWindow::mousePressEvent(QMouseEvent *event)
                          {
                              event->accept();
                          
                              MimeData* mimeData = new MimeData;
                          
                              QDrag drag( this );
                                  drag.setMimeData(mimeData);
                              drag.exec(Qt::CopyAction);
                          }
                          

                          the mime type is text/uri-list, so a list does make sense. It also makes sense to copy multiple files at once to a folder in the filesystem explorer.
                          I have no idea why it's not working. Would need to debug into Qt source code to make sure.

                          --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
                          If you have a question please use the forum so others can benefit from the solution in the future

                          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