Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. How QDataStream and QByteArray work together with QMimeData?
Forum Updated to NodeBB v4.3 + New Features

How QDataStream and QByteArray work together with QMimeData?

Scheduled Pinned Locked Moved Unsolved Qt for Python
8 Posts 3 Posters 573 Views 2 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.
  • superagaS Offline
    superagaS Offline
    superaga
    wrote on last edited by
    #1

    Hi expert!

    I checked about this topic and I didn't find a clear thread that was covering my questions, then I decided to post this.
    I'd like to ask you some general questions regarding the use of these 3 classes.

    All starts from an issue I have related to the drag and drop, however I don't want to dwell on this for now, I rather want to understand the general "mechanism" exists behind the scene to "transfer" data within Qt.

    At the beginning I thought that QDataStream was acting like a "pipe" to transfer data, but since it needs QByteArray to "store" data, I didn't find an equivalence for that. If I talk about a QDataStream what metaphor can i use?

    While QByteArray is just a buffer which clearly represents the data container isn't it?

    Then there is also the QMimeData which is defined as: Multipurpose Internet Mail Extensions. This description applied to the Qt programming environment sounds to me a bit misleading...

    So to wrap-up, this is what I understood so far:

    To transmit "something" using a mechanism like drag and drop I have to:

    • Create a QDataStream object (based on the QByteArray "container").
    • Load my data (for this example just consider plain text) into the QDataStream.
    • Create a QMimeData object.
    • "Encode" the QDataStream into the QMimeData specifying which type of "media" I'm transmitting (text/plain).

    Is this correct or not?

    To receive the data, i.e. in the dropEvent, I should clearly "unwrap" my data following the opposite process isn't it?

    Kind regards,
    AGA

    1 Reply Last reply
    0
    • Christian EhrlicherC Offline
      Christian EhrlicherC Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #2

      QDataStream is a stream - it streams data to/from a buffer. But since QDataStream uses an internal format to store the data it's not really usable with QMimeData when someone outside your app should retrieve it.
      QMimeData has a lot of functions to send / receive data without the need of a QByteArray and QDataStream.

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      1 Reply Last reply
      1
      • superagaS Offline
        superagaS Offline
        superaga
        wrote on last edited by
        #3

        Hi @Christian-Ehrlicher,

        many thanks for your answer, this already shed some light on my problem.

        I saw some examples (like this) were a "combination" of QDataStream, QByteArray and QMimeData, were used, but now that you wrote me: QMimeData has a lot of functions to send / receive data without the need of a QByteArray and QDataStream, I can clearly see (from other examples) that the "drag and drop" can be achieved using only the QDataStream.

        Why then some examples used them?

        So, focusing only on the QMimeData class, I've been able to make the drag and drop code work, but probably I need some advice to polish it a bit.

        Since I wrote it in Python, do I need to move this post in the Python section or can I leave it here?
        I started the post here in the General and Desktop section because I think that it is more related to a workflow question, so anyone could benefit.

        --------------------------------------------------------------------------------------------------------------------------

        Here what I did:

        • I have a dialog with 2 QListWidget where I want to copy the left items into the right items using the drag and drop action.

        1766f9fc-a75f-4393-a267-b31bee4d76a4-image.png

        Although I've been able to make the code work I need some advice to understand better what "should stay", what is superfluous and what I miss.

        • Since I had to add 2 QListWidget I decided to re-implement the QListWidget class in a generic way that I could use for both the Host and the Target (see more in the code below).
          • In the class I re-implemented "only" these drag and drop methods: QDragEnterEvent, QDragMoveEvent and QDropEvent.
          • I used the startDrag method to "load" the selected item into the mime data.

        In the "main" code I created the 2 QListWidget as:
        Host:

           ...
           # create a list - host
           self.listHostTestFiles = ListView()
           self.listHostTestFiles.setDragEnabled(True)
           self.listHostTestFiles.setDropIndicatorShown(True)
           ...
        
        • To the left QListWidget I added these "options": drag enable and drop indicator because is the one where the drag starts.

        Target:

           ...
           # create a list - target
           self.listTargetTestFiles = ListView()
           self.listTargetTestFiles.setAcceptDrops(True)
           ...
        
        • To the right QlistView I added only the accept drop "option" since it just need to receive the drop.

        The code for the entire re-implemented class is instead:

        class ListView(QListWidget):
            def __init__(self, parent=None) -> None:
                super().__init__(parent)
        
            # this method is called when the mouse starts to enter over the widget
            def dragEnterEvent(self, event) -> None:
                if event.mimeData().hasFormat("text/plain"):
                    event.accept()
                else:
                    event.ignore()
        
            # this method is called when the drag and drop action is in progress
            def dragMoveEvent(self, event) -> None:
                if event.mimeData().hasFormat("text/plain"):
                    #event.setDropAction(Qt.DropAction.CopyAction)
                    event.accept()
                else:
                    event.ignore()
        
            # if the dragEnterEvent is accepted, then the dropEvent is called
            def dropEvent(self, event) -> None:
                if event.mimeData().hasFormat("text/plain"):
                    item = event.mimeData().text()
                    self.addItem(item)
                    event.setDropAction(Qt.DropAction.CopyAction)
                    event.accept()
                else:
                    event.ignore()
        
            def startDrag(self, dropActions) -> None:
                item = self.currentItem()
                mimeData = QMimeData()
                mimeData.setText(item.text())
                drag = QDrag(self)
                drag.setMimeData(mimeData)
                drag.exec(Qt.DropAction.CopyAction)
        

        Here my questions:

        • Is it a good practice, or it would be better to re-implement a custom class for each of the 2 QlistWidget?
        • When do I need to use the QDragLeaveEvent? I didn't really figure out when I should.
          • To be fair, I didn't understand even why do I need both the dragEnterEvent and the dragMoveEvent.
            I tried commenting out first one and then the other but the "demo" didn't work.
          • Why do I need to use both "together"? Of course I already had a look to the doc, but unfortunately it is still not clear to me.
          • Is there an order in which the methods are triggered?
        • For each method I always checked for the mimeData format, is it necessary? Or can I use it just for the first method called?
        • What about the setDropAction? Can I use it only one time (i.e. in the startDrag, or do I need to use it also in the last dropEvent?

        To close all these questions: on the official drag and drop page I saw that a very different example is made using the mouseXEvent.

        At this point I'm confused about the right approach to use for the drag and drop.

        • Which approach should I prefer?
        • Is there a reason why there are these 2 different "way": dragEvents or mouseEvents?

        Many thanks!
        AGA

        1 Reply Last reply
        0
        • Christian EhrlicherC Offline
          Christian EhrlicherC Offline
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @superaga said in How QDataStream and QByteArray work together with QMimeData?:

          can be achieved using only the QDataStream.
          Why then some examples used them?

          Did not read the rest but I never said it's not possible:

          usable with QMimeData when someone outside your app should retrieve it.

          Your example does internal drag'n'drop so all is fine.

          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
          Visit the Qt Academy at https://academy.qt.io/catalog

          1 Reply Last reply
          0
          • superagaS Offline
            superagaS Offline
            superaga
            wrote on last edited by
            #5

            Hi @Christian-Ehrlicher,

            many thanks for your help.

            It is clear that the first is related to the fact that something starts when the mouse is pressed, so it can happen in any part of the GUI, while the second happens just when you are on the widget.
            Now, it is clear to me that even the first approach, when acts as drag and drop action, will falls within the second case, so there are no differences.

            Could you please just explain me a bit those questions (sorry to be repetitive)? 😅

            • Why do I need both the dragEnterEvent and the dragMoveEvent?
              • I tried commenting out first one and then the other but the "demo" didn't work.
                Why do I need to use both "together"? Of course I already had a look to the doc, but unfortunately it is still not clear to me.
            • Is there an order in which the methods are triggered?
            • For each method I always checked for the mimeData format, is it necessary? Or can I use it just for the first method called?
            • What about the setDropAction? Can I use it only one time (i.e. in the startDrag, or do I need to use it also in the last dropEvent)?

            Many thanks!
            AGA

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              Hi,

              Determine on enter whether further processing shall be done.
              And for the move, your entire widget might not be a target for dropping or might change the outcome based on some condition.

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

              superagaS 1 Reply Last reply
              0
              • SGaistS SGaist

                Hi,

                Determine on enter whether further processing shall be done.
                And for the move, your entire widget might not be a target for dropping or might change the outcome based on some condition.

                superagaS Offline
                superagaS Offline
                superaga
                wrote on last edited by superaga
                #7

                Hi @SGaist,

                many thanks for your explanation.
                Now I'm seeing more using than just a drag and drop case...

                So just to answer to my questions and close this thread:

                Why do I need both the dragEnterEvent and the dragMoveEvent?

                Really depends by what you need. For a simple drag and drop just use only the dropEvent. -> That (inexplicably) didn't work. I still need to re-implement also the dragEnterEvent and the dragMoveEvent. 🤷‍♂️

                Is there an order in which the methods are triggered?

                Yes, it follows the mouse movements, so it should be from the external to the internal: dragEnterEvent, dragMoveEvent, dropEvent and finally dragLeaveEvent.

                For each method I always checked for the mimeData format, is it necessary? Or can I use it just for the first method called?

                I think that this could be related just to the first method used to "validate" the "action type" for that event.

                Pay attention that the same event might accept and perform different actions based on the different file format dragged on.

                What about the setDropAction? Can I use it only one time (i.e. in the startDrag, or do I need to use it also in the last dropEvent)?

                It is still not clear to me, although I might assume that it depends by the kind of action that event needs to execute.

                Kind reagards,
                AGA

                SGaistS 1 Reply Last reply
                0
                • superagaS superaga

                  Hi @SGaist,

                  many thanks for your explanation.
                  Now I'm seeing more using than just a drag and drop case...

                  So just to answer to my questions and close this thread:

                  Why do I need both the dragEnterEvent and the dragMoveEvent?

                  Really depends by what you need. For a simple drag and drop just use only the dropEvent. -> That (inexplicably) didn't work. I still need to re-implement also the dragEnterEvent and the dragMoveEvent. 🤷‍♂️

                  Is there an order in which the methods are triggered?

                  Yes, it follows the mouse movements, so it should be from the external to the internal: dragEnterEvent, dragMoveEvent, dropEvent and finally dragLeaveEvent.

                  For each method I always checked for the mimeData format, is it necessary? Or can I use it just for the first method called?

                  I think that this could be related just to the first method used to "validate" the "action type" for that event.

                  Pay attention that the same event might accept and perform different actions based on the different file format dragged on.

                  What about the setDropAction? Can I use it only one time (i.e. in the startDrag, or do I need to use it also in the last dropEvent)?

                  It is still not clear to me, although I might assume that it depends by the kind of action that event needs to execute.

                  Kind reagards,
                  AGA

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

                  The dragEnterEvent is the first step that will determine whether D&D handling shall start. The dragMoveEvent is the continuous handling of the drag and dropEvent is the end of it.

                  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