Is it possible to pass a pointer to a QObject using QMimeData during drag-and-drop operation? QMimeData only has this function for storing data:
void QMimeData::setData(constQString &mimeType, const QByteArray &data)
but I can't find a way to safely encode a pointer into a QByteArray.
To clarify my goal: I need to pass a pointer to a QObject from a model to the target widget during the drag-and-drop operation.
Edit:
As far as I undrestand Mime data is all about passing application independent data from one place to another: urls, colors, html code. In my case I need to pass a pointer to a resource object eithin the application. How to you usually deal with this kind of drag-drops?
Thanks
Anton
You can subclass QMimeData and pass whatever you want.
To be on the safe & elegant side, I would come up with unique identifiers (e.g. strings, or numbers) for my objects and pass them as mime objects. Resolving a string back into the corresponding object using QHashmap is fast enough for your purpose.
The dirtiest (not recommended!) way would be that the identifier is the pointer address as int.
If you pass mime data with user interaction, you never know where it goes. If the user drops your pointer onto another application's window, it should fullfill the user's expectations best.
An application that gets a mangled up mime object and crashes for it is worst.
An application that gets a descriptive string and enables the user to understand what he was dropping is probably best.
I know that you can also, using the mime type, somewhat direct where the payload may be dropped and where not. the quintessence however is that you should stay within the mime concept. And that includes not passing a raw pointer.
As Kash said and the Qt docs suggest, subclass QMimeData.
Then, add the following:
text/plain data describing or representing the dragged object, so if you drop this data to notepad.exe, it results in something relevant
custom data type with an identifier or token that enables you to know that some dropped mime data is actually your subclass
add your own data in the subclass
You will still need to test the qobject_cast (or dynamic_cast), because some other program might have proxied your mime data object.
Related
Using reflection, we can get the type name, storage size and the function of the given type(such as uint64, user-defined struct and so on). Even, we can modify some fields of the given type.
How does golang implement reflections? I guess the following ways:
Every type in golang, including user-defined type, itself has the information about type name, fields name and the function name. Golang reflection just reads these information or call the function.
Through some mechanism, Golang can get the type name, storage size and so on. And the type itself doesn’t have these information.
I have read the golang reflection code roughly. I guessed that golang used the second way.
Who can describe the concrete implement of reflection? Or recommend me some documents? Reading all code is difficult for me.
This is just an overview and it might be not 100% accurate but hopefully you will find it helpful.
At build time Go linker will embed information about all types used by the application into the executable (https://github.com/golang/go/blob/master/src/runtime/symtab.go#L39)
Each interface value contains a pointer to the data type descriptor (https://github.com/golang/go/blob/master/src/runtime/type.go#L14)
During conversion from a type that is known at compile time to an interface value Go compiler will point type descriptor of this interface value to the concrete type descriptor (it is known at compile time!).
E.g. when you call reflect.TypeOf(uint(87)):
an interface value is created by the compiler that references uint type descriptor
this interface value is passed to reflect.TypeOf function as argument
reflect.TypeOf function uses type descriptor that has been stored by the linker in the executable to get the align (and other) information about uint type.
The description of interfaces is well described here: The Laws of Reflection.
A variable of interface type stores a pair: the concrete value
assigned to the variable, and that value's type descriptor.
Basically, type are known statically from your code. More flexible interface types keep the original underlying type for getting back to the original data type.
In my app I'm doing internal drag and drops with a QTreeView. Using the tutorial I can happily drag and drop a single leaf by encoding it into a string list using the mime type "application/vnd.text.list".
I then wanted to drag and drop a tree node that had some children and thought the best route to doing this would be to encode the pointer to the node and iterate through all the children in the dropMimeData method.
I declared a mime type in the mimeTypes() method:
QStringList toResultModel::mimeTypes() const {
QStringList types;
types << "text/plain";
types << "application/vnd.mypointerlist.list";
return types;
}
And tried to pass the same string list across, but the application crashes in the dropMimeData() method.
It seems the mime type "application/vnd.text.list" has some hidden meaning which I am unable to find.
I have found this source code: http://fossies.org/linux/tora/src/toresultmodel.cpp where the author sets up a custom coding type "application/vnd.tomodel.list" and also uses "application/vnd.int.list".
What are the rules in using encoding types?
Where are the built-in types strings defined?
Which type should I use for passing a pointer to a tree node?
Four years later...
From the information you give, if your method crashes, it's not related to Drag and Drop in particular, there is some error you need to find in the code. that said, let me clarify D&D in Qt, and answer your question about MIME types. While you have indeed solved the problem you had four years ago, this may be useful for other users today.
You may define your own type for the purpose of your application or reuse an existing one. How to choose?
Can you use an existing MIME type, like text/plain?
Think about your application being the target of a D&D operation initiated from another application. Can you accept an existing MIME type and retrieve your data from it?
Think about another application being the target of a D&D operation initiated from within your application. Could this application handle an existing MIME type?
If this answer is no to any of the questions, then you might have to use your own specific MIME type.
The format name itself is not important
The constraint is that it must be unique, so that you can't receive incorrectly formatted MIME data from another application, and other applications can identify the MIME type as one they cannot handle, and ignore it.
The exact MIME type name doesn't matter as you'll provide the encoder and the decoder into your data model (e.g. see this introduction to view/model for Qt), as well as other information about the MIME type(s) used.
In QAbstractItemModel::mimeTypes, list only the MIME types you are able to deal with. If you don't plan to accept or send MIME data from/to other applications, there is no need to allow more than your specific MIME type.
When your application is the source of a D&D operation, encode (serialize) the MIME data in QAbstractItemModel::mimeData(indexes). The result of the serialization must be a byte array, even when there are multiple indexes to be dragged. The internal format is yours. Include any information required to decode (de-serialize) MIME data. Note that you must provide encoded data in each of the MIME type you've listed in QAbstractItemModel::mimeTypes (see previous point).
When your D&D data are dragged over your application UI, QAbstractItemModel::canDropMimeData(self, mime_data, action, row, column, parent) is called to determine if this location is valid for a drop. You may determine here whether the drop should be allowed at this location. In particular, you may test the content of the MIME data provided, and use mime_data.hasFormat(mime_type) to check if the format you expect is found in the data about to be drooped. Returning false will prevent a drop at this location and a "not allowed here" indication will be provided to the user (this won't cancel the D&D operation itself, the user can continue to move the mouse elsewhere).
When the data is actually dropped, QAbstractItemModel::dropMimeData(mime_data, action, row, column, parent) is called. Get the MIME data format(s) used using QMimeData::hasFormat(mime_type). If you don't find the MIME type you expect, ignore the drop operation as you cannot decode the data provided (the D&D was initiated from another application). This shouldn't happen as prior to drop data, the application has called QAbstractItemModel::canDropMimeData as seen in the previous point. If everything is ok decode the MIME data, and update your model with the data received.
On the other hand, your tree leaf data may fit as path+name encoded in text/plain MIME data, so maybe you can just use this type too. However as other applications can generate text/plain data that don't contain a tree leaf description, you need, in this case, to have a mean to identify irrelevant data and ignore them. It's obvious such approach will need more code for verification of the validity of the drop action than when using a specific MIME type. However this allows to interact with other applications, and is indeed relevant to drag from well know applications like Excel (e.g. cell content) or Firefox (e.g. rich text or image), else we couldn't re-use information from these applications using D&D.
Do you need to use vnd prefix?
vnd in the MIME type means "vendor specific". This prefix is used to distinguish vendors created MIME types from those created by IANA authority. From RFC 6838:
Vendor-tree registrations will be distinguished by the leading facet
"vnd.". That may be followed, at the discretion of the registrant, by
either a media subtype name from a well-known producer (e.g.,
"vnd.mudpie") or by an IANA-approved designation of the producer's
name that is followed by a media type or product designation (e.g.,
vnd.bigcompany.funnypictures).
So in your Drag&Drop tutorial the application/vnd.text.list is a specific one supposedly created by some vendor for their own purpose. Same for application/vnd.mypointerlist.list
In contrast, text/plain is a standard MIME type defined by IANA in RFC 2046. This defines a human readable text:
Plain text does not provide for or allow formatting commands, font
attribute specifications, processing instructions, interpretation
directives, or content markup. Plain text is seen simply as a
linear sequence of characters, possibly interrupted by line breaks
or page breaks. Plain text may allow the stacking of several
characters in the same position in the text. Plain text in scripts
like Arabic and Hebrew may also include facilitites that allow the
arbitrary mixing of text segments with opposite writing directions.
For your type, you may want to use vnd followed by a subtype which is specific to your application, for consistency considerations. But as seen, the actual name is not important, as long as you know which one you use and you are not interacting with other applications in the D&D chain.
Can anyone tell me what is the main advantage of using tuple? In what scenarios do I need to use these?
I assume that you're talking about the Tuple<> type and not anonymous tuple classes.
Like an anonymous type, Tuple<> allows you to avoid declaring a new class just to group a few objects. Unlike anonymous types, tuple types have known names and thus can be used as method return and parameter values, etc.
Personally, I try to avoid heavy use of Tuple<> because it can make for difficult to understand code, expecially when used with primitive types (e. g. if you see a Tuple it's not obvious what each field represents).
One place I have found tuples to be very useful is as dictionary keys. Because Tuples implement Equals() and GetHashCode() (not ==, though!), they are perfect for things like private dictionaries that cache information based on a compound key.
It's used mostly to avoid declaring a class / struct with a few properties only for the sake of passing a group of objects around, where only one object can be passed.
Lets say I have a list of urls to go through and if i get an error (4xx or 5xx) I want to build a list and then either later display it to the user or just look at it in my debugger.
I'd catch the web exception and have a Tuple<string, int> (url, http error code) instead of creating a struct for one or two functions to use. Heck it might even be a foreach loop with a breakpoint on if the list has more then 0 items. Thats when it is useful.
Skimming through the nodejs docs I see options objects being passed to configure features in the http library. However I don't see a quick way to access the original options that were used in a http.request(options, callback) call to construct a http.ClientRequest object, after the fact. Are original options available through the request object and not deemed private, or should I instead hold my own reference to the original options in case I want to use them later?
I assume the options are composited inside the http.ClientRequest object, but that could be wrong.
I could probably try going either way with this (dig into composited info, or pass around an external reference to it), but am new enough to nodejs that I want some sage advice first, to find out what I should do if the option object's available, and by using best practice.
You should always keep your own reference. Most of the time you have no way of telling what's going to happen to that object after you pass it to a constructor. Almost everybody leaves it alone, but some libraries/modules may have side-effects on it. For example, you may see source code doing:
options.foo = options.foo || 'bar';
...modifying your object. So you may even have to clone your object before passing it to a constructor if you want to keep a reference to it.
As for ClientRequest in particular, it doesn't hold a public reference to the options object, but it has properties that match some of the options like req.path or req.port.
I'm making a QList of a custom class called ControlIcon. I create the ControlIcons, and load them up with member variables, and then add them to the list. Here's the append code:
this->cueList.append(firstOne);
Here's the declaration of the QList:
QList< ControlIcon *> cueList;
If I break right after the append, I can see that the ControlIcon that was just added is full of members, and appears fine. I look in the list, and the ControlIcon that's been appended (and it does append a ControlIcon) has no members at all. I've made a QList of custom objects before, so I'm very confused. Could someone help?
Your custom class must be assignable, that means it must provide a default constructor, a copy constructor and a assignment operator. If they don't, weird things like this can happen.
cueList contains pointers to ControlIcon objects, but it is not responsible for creating or keeping those ControlIcon objects. How did you get the pointer firstOne? If it points to something on the stack, that object would be invalid when you try to use it later. If it was created with new, it will stay valid until you clean it up using delete.
I changed the data type of the list to be SerialController (the child of ControlIcon), which is what I was trying to add to it, and it works fine. This is really annoying, because there's other types of controllers, but I guess it will have to work for now.