Storing pointers using QListWidgetItem::setData - qt

I have a QListWidget of calendars. Each QListWidgetItem is logically associated with an instance of Calendar, which is a class that belongs to the Model side of the application.
Can I store this association in the form of a pointer using QListWidgetItem::setData? When I attempt to do this, I get the following error:
error: 'QVariant::QVariant(void*)' is private

There is another constructor for void*: QVariant::QVariant(int typeOrUserType, const void * copy) where you should pass an unique integer to represent the pointer type.
But as stated by the documentation, you could declare your pointer type with Q_DECLARE_METATYPE(Calendar*) and use QVariant::fromValue<Calendar*>(...) and QVariant::value<Calendar*>() to store and retrieve the value.
Or instead, because you are using a QListWidget instead of a regular model, you can just subclass QListWidgetItem, and add a Calendar* member variable with the required accessors, to avoid the overhead of using QVariant.

I would suggest looking at this solution as well, which I think is quite elegant:
(there are minor syntax errors, but you will spot them quickly or the compiler will issue an error)
https://web.archive.org/web/20171025163314/http://blog.bigpixel.ro/2010/04/storing-pointer-in-qvariant/

Related

What's the point of unique_ptr?

Isn't a unique_ptr essentially the same as a direct instance of the object? I mean, there are a few differences with dynamic inheritance, and performance, but is that all unique_ptr does?
Consider this code to see what I mean. Isn't this:
#include <iostream>
#include <memory>
using namespace std;
void print(int a) {
cout << a << "\n";
}
int main()
{
unique_ptr<int> a(new int);
print(*a);
return 0;
}
Almost exactly the same as this:
#include <iostream>
#include <memory>
using namespace std;
void print(int a) {
cout << a << "\n";
}
int main()
{
int a;
print(a);
return 0;
}
Or am I misunderstanding what unique_ptr should be used for?
In addition to cases mentioned by Chris Pitman, one more case you will want to use std::unique_ptr is if you instantiate sufficiently large objects, then it makes sense to do it in the heap, rather than on a stack. The stack size is not unlimited and sooner or later you might run into stack overflow. That is where std::unique_ptr would be useful.
The purpose of std::unique_ptr is to provide automatic and exception-safe deallocation of dynamically allocated memory (unlike a raw pointer that must be explicitly deleted in order to be freed and that is easy to inadvertently not get freed in the case of interleaved exceptions).
Your question, though, is more about the value of pointers in general than about std::unique_ptr specifically. For simple builtin types like int, there generally is very little reason to use a pointer rather than simply passing or storing the object by value. However, there are three cases where pointers are necessary or useful:
Representing a separate "not set" or "invalid" value.
Allowing modification.
Allowing for different polymorphic runtime types.
Invalid or not set
A pointer supports an additional nullptr value indicating that the pointer has not been set. For example, if you want to support all values of a given type (e.g. the entire range of integers) but also represent the notion that the user never input a value in the interface, that would be a case for using a std::unique_ptr<int>, because you could get whether the pointer is null or not as a way of indicating whether it was set (without having to throw away a valid value of integer just to use that specific value as an invalid, "sentinel" value denoting that it wasn't set).
Allowing modification
This can also be accomplished with references rather than pointers, but pointers are one way of doing this. If you use a regular value, then you are dealing with a copy of the original, and any modifications only affect that copy. If you use a pointer or a reference, you can make your modifications seen to the owner of the original instance. With a unique pointer, you can additionally be assured that no one else has a copy, so it is safe to modify without locking.
Polymorphic types
This can likewise be done with references, not just with pointers, but there are cases where due to semantics of ownership or allocation, you would want to use a pointer to do this... When it comes to user-defined types, it is possible to create a hierarchical "inheritance" relationship. If you want your code to operate on all variations of a given type, then you would need to use a pointer or reference to the base type. A common reason to use std::unique_ptr<> for something like this would be if the object is constructed through a factory where the class you are defining maintains ownership of the constructed object. For example:
class Airline {
public:
Airline(const AirplaneFactory& factory);
// ...
private:
// ...
void AddAirplaneToInventory();
// Can create many different type of airplanes, such as
// a Boeing747 or an Airbus320
const AirplaneFactory& airplane_factory_;
std::vector<std::unique_ptr<Airplane>> airplanes_;
};
// ...
void Airline::AddAirplaneToInventory() {
airplanes_.push_back(airplane_factory_.Create());
}
As you mentioned, virtual classes are one use case. Beyond that, here are two others:
Optional instances of objects. My class may delay instantiating an instance of the object. To do so, I need to use memory allocation but still want the benefits of RAII.
Integrating with C libraries or other libraries that love returning naked pointers. For example, OpenSSL returns pointers from many (poorly documented) methods, some of which you need to cleanup. Having a non-copyable pointer container is perfect for this case, since I can protect it as soon as it is returned.
A unique_ptr functions the same as a normal pointer except that you do not have to remember to free it (in fact it is simply a wrapper around a pointer). After you allocate the memory, you do not have to afterwards call delete on the pointer since the destructor on unique_ptr takes care of this for you.
Two things come to my mind:
You can use it as a generic exception-safe RAII wrapper. Any resource that has a "close" function can be wrapped with unique_ptr easily by using a custom deleter.
There are also times you might have to move a pointer around without knowing its lifetime explicitly. If the only constraint you know is uniqueness, then unique_ptr is an easy solution. You could almost always do manual memory management also in that case, but it is not automatically exception safe and you could forget to delete. Or the position you have to delete in your code could change. The unique_ptr solution could easily be more maintainable.

What's the Nicest Way to do This? (Qt and Enum style arguments)

In Qt, it is common to see something similar to the following:
QSettings obj3(QSettings::SystemScope, "MySoft", "Star Runner");
The important bit is the QSettings::SystemScope, which is an enum.
I want to have a settings provider (pay no attention to the previous example here, it has nothing to do with the following), with a get/set property.
Settings.set(Settings::refreshRate)
The refreshRate has to link to a key (string), and a default value (variant).
Should I make an enum and two dicts for the key and default values, or make a struct and a whole bunch of variables that encapsulate the settings I need? Should I try something else?
Thanks!
Edit!
This is what I did.
// Interface
class Settings {
public:
static QVariant get(Setting setting);
static void set(Setting setting, QVariant value);
const static Setting serverRefreshRate;
const static Setting serverReportTimeout;
};
// Implementation
const Setting Settings::serverRefreshRate = { "server/refreshRate", 10000 };
const Setting Settings::serverReportTimeout = { "server/reportTimeout", 1000 };
Well I guess since you're using enum which most likely will be easily castable to numbers from to 0 to N-1 I guess just storing variants and strings in two vectors or one vector of pairs would work just fine.
There's also another question though -- how to initialize all of that and how you will be adding new settings to it. I can suggest two methods - first one writing a bunch of function calls with arguments: enum, string, variant. Thus way though if programmer adds another value to enum he can forget to call initializing function. The other way is to create function (or maybe two) which will do switch on all enum values (without default case) and will return pair of string and variant. You can turn on the compiler warning about all enum values being processed in switch and thus way control if you forget to implement some of them in that function. And then initialize your structures using loop on all of enum values. These initializing functions should be called somewhere near the beginning of your program (before reading settings initially).
Well, that's my thoughts on it, you are free to try some different ways though.

Error with sequence argument when using QtConcurrent map

I'm trying to use QtConcurrent::map to run this function
//This function is used through QtConcurrent::map to create images from a QString path
void MainWindow::createQImage(QString* path) {
//create an image from the given path
QImage* t = new QImage(*path);
imageList->append(t);
}
on this container/sequence (declared in the mainwindow header and initialized in the mainwindow constructor)
QList<QImage *> *imageList = new QList<QImage *>;
Here's the code I'm trying to run
QFutureWatcher<void> futureWatcher;
futureWatcher.setFuture(QtConcurrent::map(imageList, &MainWindow::createQImage));
and here are the errors I'm getting:
request for member 'begin' in 'sequence', which is of non-class type 'QList<QImage*>*'
request for member 'end' in 'sequence', which is of non-class type 'QList<QImage*>*'
I need the "createQImage" function to be run for every element in "imageList," which can reach into the thousands. I believe the problem to be with the first parameter to the map function. And from what I've read, it may have to do with compatibility. There isn't much sample code online that I was able to relate to. I'm new to Qt and not the most experienced of programmers but I'd appreciate some help and feedback.
Alternatively, is there better way to do this using QtConcurrent?
Thanks in advance!
QtConcurrent::map wants a sequence as its first argument. You passed it a pointer to a sequence.
If you do
futureWatcher.setFuture(QtConcurrent::map(*imageList, &MainWindow::createQImage));
it should be happy.
Note that the compiler was reasonably clear about what the problem was. Take the time to read the errors carefully, they're usually not as cryptic as they perhaps at first seem. In this case it was telling you that the argument you passed was not of a class type. A quick look at the argument type at the end of the error reveals that it is a pointer.
QList, QImage, QString are Copy-On-Write types (see other Qt implicitly shared types), so you shouldn't use pointers to these types because they are basically already smart pointers.
And if you remove all pointers from your code, it should also fix the main problem.

Modifying a QVariantMap with JavaScript

The QtWebKit Bridge documentation states the following -
Compound (JSON) objects JavaScript
compound objects, also known as JSON
objects, are variables that hold a
list of key-value pairs, where all the
keys are strings and the values can
have any type. This translates very
well to QVariantMap, which is nothing
more than a QMap of QString to
QVariant. The seamless conversion
between JSON objects and QVariantMap
allows for a very convenient way of
passing arbitrary structured data
between C++ and the JavaScript
environment. The native QObject has to
make sure that compound values are
converted to QVariantMaps and
QVariantLists, and JavaScript is
guaranteed to receive them in a
meaningful way. Note that types that
are not supported by JSON, such as
JavaScript functions and
getters/setters, are not converted.
Does this mean that, while JavaScript is able to read a QVariantList, it is unable to modify it?
I've tried adding a getter and setter for test purposes -
Q_PROPERTY( QVariantMap Settings READ GetShadowSettings WRITE SetShadowSettings )
The getter function is being called when the JavaScript wants to access any data from the QVariantMap. Unfortunately, when the JavaScript attempts to update the QVariantMap, the getter function is called again (rather than the setter function).
I can modify the data using a simple helper function such as -
Q_INVOKABLE void Update( QString key, QVariant value ) {
settings[key] = value;
}
I was just wondering if there was a way of doing this without the need for a helper function?
I use QVariantMap for PhantomJS and it works just fine. For example, WebPage#viewportSize is just QVariantMap in its implementation. The usual problem is you can't try to update one of its property only, e.g. viewportSize.width = 300. You have to pass back an object, e.g.:
viewportSize = { width: 300, height: 200 }.
If you need to able to do the former, the only (ugly) workaround that might work is to create a helper object, e.g. Size in the above case, which has the proper setter and getter for the individual property and handle the housekeeping of bridging.

Qt: QAbstractItemModel and 'const'

I'm trying to use a QTreeView for the first time with QAbstractItemModel and instantly have a problem. QAbstractItemModel interface declares methods as const, assuming they will not change data. But I want the result of a SQL query displayed, and returning data for a record with specified index requires the use of QSqlQuery::seek() which is non-const. Are there any 'official' guidelines to using a QAbstractItemModel with data that must be changed in order to get the number of items, data per item etc? Or must I hack C++ with const casts?
You can get away without any const casts by holding a pointer to the QSqlQuery; your pointer won't change, only the value to which you point, hence the operation will still be considered "const".

Resources