Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt
  • 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.5k 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.
  • 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
                      • Unsolved