Qt QScriptEngine and default conversions from Qt Script to C++ - c++

I'm trying to convert a QVariantMap to Qt Script object. If I understood correctly it should go something like this:
QScriptEngine* engine = new QScriptEngine();
QVariantMap* test = new QVariantMap();
test.insert("testkey", QString("testvalue"));
QScriptValue testqs = engine->toScriptValue(test);
QString value = testqs.property("testkey").toString();
I'm not sure if that is the right way to event try to ask for the value from the ScriptValue. But the root problem is that the Script object I get, doesn't seem the have any of the properties that were in the map to begin with.
So, what am I missing?

Ok, so I figured out my problem. If I would have read the specs correctly I would have noticed that the toScriptValue() method won't take a pointer. So the fix was:
QScriptValue testqs = engine->toScriptValue(*test);

Related

Passing object to a function in QT causes Segmentation Fault

Thanks in advance for your time. I'm still new to the coding world, so excuse me if I ask something silly or obvious.
I'm coding a small program with QT for manipulating data of a data base. To represent the data I'm using QTableViews. I have a few of them with the same configuration, so I made a function to configure them:
QT 5.12
void MainWindow::configureTableView(QSqlTableModel *model, QTableView *table, QString DBTable)
{
//Pacients table.
model = new QSqlTableModel(this);
model->setTable(DBTable);
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
model->select();
table->setModel(model);
table->setSortingEnabled(true);
table->setCornerButtonEnabled(true);
table->hideColumn(0);
}
I have some QSqlTableModel defined in the mainwindow.h as:
QSqlTableModel *PatientsTable;
...
I call the function with:
configureTableView(PatientsTable, ui->ClientsTabTableView, "Pacientes");
Program starts and shows OK, but as soon as I try to do anything with the view like set a filter
PatientsTable->setFilter(Search)
where Search is a QString configured by other function based on user input, the program crashes and QT tells me it received a signal from the operative system: SIGSEGV (segmentation fault).
Now when is was coding all of this, at some point I had:
void MainWindow::configureTableView(QTableView *table, QString DBTable)
PatientsTable = new QSqlTableModel(this);
PatientsTable->setTable(DBTable);
PatientsTable->setEditStrategy(QSqlTableModel::OnManualSubmit);
PatientsTable->select();
table->setModel(PatientsTable);
table->setSortingEnabled(true);
table->setCornerButtonEnabled(true);
table->hideColumn(0);
which works with no issues at all.
What am I missing? I've been digging for a while now and the code and explanations I found on Internet aren't working.
Thanks again for your time!
The problem is that your function does not modify the PatientsTable variable. Just passing a pointer to a function does not let you modify the pointer itself (only what it's pointing to). Simple solution, pass the pointer by reference.
void MainWindow::configureTableView(QSqlTableModel *&model, QTableView *table, QString DBTable)
The alternative (better in my view) would be to return the pointer from the function
QSqlTableModel *MainWindow::configureTableView(QTableView *table, QString DBTable)
{
QSqlTableModel *model = new QSqlTableModel(this);
...
return model;
}
PatientsTable = configureTableView(ui->ClientsTabTableView, "Pacientes");
It's a very common beginner misunderstanding. Pass pointers to modify what is being pointed to. The pointer itself cannot be modified. In this regard pointers are just like any other kind of variable.

Why can't I open another process in Qt framework with this function?

In the Qt framework we're supposed to be able to open another .exe using QProcess. The following doesn't work when I click a button and the callback is called:
void MainWindow::on_pushButton_clicked()
{
QProcess *process = new QProcess(this);
QString wordPath = "C:/Program Files/Internet Explorer/iexplore.exe";
process->start(wordPath);
}
However if I change process->start(wordPath) to:
process->start(wordPath, QStringList());
Which is an overload of the same function, it works. The second parameter is supposed to be the arguments passed to the new process you want to start. The only way I can make the single-argument version work it seems is if something is in my PATH variable, because both "explorer.exe" and "msconfig" work. What is the story behind this only working with the second QStringList(), which is just an empty list?
In another SO question I saw a user specifically add an empty string, like this:
QString wordPath = "C:\\Program Files\\Microsoft Office\\Office12\\WINWORD.EXE"
process->start(wordPath, QStringList() << "");
I would love to know what the reason is behind this.
Your path "C:/Program Files/Internet Explorer/iexplore.exe" contains spaces, so when you use the first version the program is interpreted as being "C:/Program" with arguments "Files/Internet" and "Explorer/iexplore.exe".
The second version treats all of the first argument as the program and the QStringList as the arguments.
From the Qt documentation:
Arguments containing spaces must be quoted to be correctly supplied to the new process.
Try
QString wordPath = "\"C:/Program Files/Internet Explorer/iexplore.exe\"";

How do I cast QML items to corresponding C++ Item in Qt Quick

My question is best clarified by an example. I have QML with a Text{} item. In C++ I can get to this item and I have no problem using qobject_cast to turn anything into a QQuickItem*. But how do I turn it into the closest corresponding item so that I can call more specific methods directly like setText() the same way I might call setWidth()? I realize I can use the generic setProperty() method but I'm after the compile time checking that casting offers.
I'm after a more general answer for finding the correspondence between QML and their C++ classes, so that I can find out how to do this for Rectangles, MenuBars etc. I can't seem to find this in the docs. For those that prefer code examples:
auto text_object = app_item->findChild<QObject*>("myTextArea");
text_object->setProperty("text","New Text set from Code"); //THIS WORKS BUT...
auto text_qitem = qobject_cast<QQuickItem*>(text_object);
text_qitem->setWidth(128);
auto text_quick_text = qobject_cast<WHATGOESHERE???*>(text_object);
text_quick_text->setText("new Text for qml item"); //I WANT TO DO THIS
Q: but I'm after the compile time checking that casting offers.
qobject_cast does not offer any compilation-time checking. It is all runtime and dynamic, thus this request is not plausible. The context property is fine, or you could also get the class name with QMetaObject. Then, you could build a static LUT, but the effort may not be worth it overall...
All QML properties and methods are exposed to the meta-object system and can be called from C++ using Object::setProperty and QMetaObject::invokeMethod() respectively. invokeMethod parameters and return values passed from QML are always translated into QVariant values in C++:
QString msg("That's it");
auto text_object = app_item->findChild<QObject*>("myTextArea");
if (text_object)
QMetaObject::invokeMethod(text_object, "append", Q_ARG(QString, msg));

QVariant conversion to QPainterPath

I have a problem right now with my mini-game I am making. The problem is as follows: I have created an level editor for my game and thus I had to create my own delegate and model, the problem occurs when I try to edit through a shapeeditor ( which more likely creates a painterpath ). I then return the painterpath through data but when I try to paint it with my delegate, qt tells me the following error:
/usr/include/qt4/QtCore/qmetatype.h:169: error: 'qt_metatype_id' is not a member of 'QMetaTypeId<QPainterPath>'
I am not quite sure why I am having this error. For information regarding the source code of the project, I can give if needed. But I am simply thinking the conversion from qvariant to qpainterpath isn't possible. They must be a way to do it.
Note: I tried to do the following
QVariant var = index.model()->data(index, Qt::DecorationRole);
QPainterPath path = var.value<QPainterPath>(); // The error occurs here, this is line 169
But this didn't work >.< Thanks if you can help me
Possible solution, is there anyway to create a pixmap from the painterpath? I could simply return the pixmap instead of the painterpath.
Looks like you need to use Q_DECLARE_METATYPE macro with QPainterPath
Like
Q_DECLARE_METATYPE (QPainterPath)
Here is documentation for the same.

Why does this work and how? Non-static Qt object

I'm a little confused and would like to clear this up.
//QDir()::rmdir is from Qt Creator auto complete.
//It does not work.
//Says no such static function.I looked it up, turns out to be true.
//Fair enough...though I'm not sure why auto-complete suggested it.
bool success = QDir()::rmdir("Y:/dir1/dir2/dir3"); //Does not work.
//Now I could make a QDir object as such.
//I didn;t test this but I'm sure it would work fine.
//However it seems clumsy.
QDir d("Y:/"); //This seems like a waste.
d.rmdir("Y:/dir1/dir2/dir3");
//Lastly, the source of my confusion. QDir().rmdir
//This works, but WHY?
//There is no empty constructor for QDir in Qt Documentation.
//http://doc.qt.nokia.com/4.7/qdir.html
//Yet this empty constructor version works. Why?
bool success = QDir().rmdir("Y:/dir1/dir2/dir3");
My main concern is why does the last examaple [QDir().rmdir] work?
I've noticed this on a number of Qt classes. Is this an anonymous object and if so
what does this mean with regards to object clean up? Is this form safe to use?
One of the QDir constructors is:
QDir ( const QString & path = QString() )
Your QDir().xxx code is calling this constructor, which then uses default to using a QString() as one argument.
This is safe and normal to do.
QDir creates a temporary object. Pretty the same if you callsth. like:
QString s("123");
int answer = 40 + s.left(2).right(1).toInt();
Second line produces 2 temporary objects.