QML map binding v2 - qt

I'm complete noob in Qt, so my question may sound too stupid, but I really need help. I know C++ a little and that's it.
So, my task is to write a C++ program which reads INI-alike (format is not very important) file
height=20
width=15
To make it clear, I have no idea what properties will be defined in this file, names or types are unknown to me at compile time.
After that program loads QML file (I can do this) and injects loaded file data (have no idea how to do this) as JavaScript object, for instance named "Settings", so that QML property bindings will use it like
Rectangle {
width: Settings.width
height: Settings.height
}
So the question is: How can I inject read data as JavaScript object into QML so that QML property binding will use it?

One way to do it would be to write a QObject wrapper around QSettings and expose an instance of it to QML, another would be to use the Settings QML Type. I am sure there are others.

Related

How to get the typename of a QObject instance parsing QML?

I have got a QQuickView which has loaded a qml file like the following.
Rectangle { width: 100; height: 100 }
Then I am retrieving the root object via QObject *root = view->rootObject().
Now I want to get the class name from this object.
The following code results into "QQuickRectangle"
root->metaObject()->className()
But what I want is "Rectangle" just like the typename in the qml file.
Any idea?
Edit: I want to build a treeview with the object hirarchie of a qml file like QtCreator.
There is a pattern there, for qml types implemented in C++ the name would be QQuickSomething, for qml types implemented in qml the name would be Something_QMLTYPE_X_MAYBEMORESTUFF(objAddress).
So you can do some basic string editing depending on the result you get to isolate the actual type name:
QString name = QString(root->metaObject()->className());
if (name.contains("QQuick")) name.remove("QQuick");
else if (name.contains("QMLTYPE")) name.remove(QRegExp("_QMLTYPE_[0-9]*.*"));
// else it might be just a QObject or your on custom type you should handle
Edit: I want to build a treeview with the object hirarchie of a qml
file like QtCreator.
Unless you are willing to dig into and use private APIs, it would likely be easier and also more useful to have your own custom model to drive both a view and the actual object tree. Also, QML is quite easy to parse, I'd personally buckle down and write a parses faster than it would take me to get into the existing one, especially if all that is needed is an object tree outline, but YMMV.
There is "better" information kept on this (QQmlType & QQmlMetaType), but it is not accessible through any public API that I can think of.
Can you explain what you would like to do with it? Maybe there's an alternative.
QtQuick doesn't provide some special metadata for QML items. It looks that QtQuick uses item types internally only while parsing the source.
The known workaround is objectName:
Rectangle {
objectName: "Rectangle"
}
and so:
QString className = item->objectName();

Application GUI state saving in Qt

What is an optimal and an appropriate way to save the state of a Qt GUI so I get the same state I had back when I closed the application ?
By state I mean : current indexes (for combo box ...), color palette, widgets positions... right before closing the application
You can use the QSettings class.
Simple use of QSettings class (code inspired from Qt's documentation):
In the main-window of your application code member functions that saves and restore the settings:
void MainWindow::writeSettings()
{
QSettings settings("reaffer Soft", "reafferApp");
settings.beginGroup("MainWindow");
settings.setValue("size", size());
settings.setValue("pos", pos());
settings.endGroup();
}
void MainWindow::readSettings()
{
QSettings settings("reaffer Soft", "reafferApp");
settings.beginGroup("MainWindow");
resize(settings.value("size", QSize(400, 400)).toSize());
move(settings.value("pos", QPoint(200, 200)).toPoint());
settings.endGroup();
}
Call those 2 functions from the MainWindow constructor and from the closeEvent override, like this:
MainWindow::MainWindow()
{
// code from constructor
//...
readSettings();
}
void MainWindow::closeEvent(QCloseEvent *event)
{
//optional check if the user really want to quit
// and/or if the user want to save settings
writeSettings();
event->accept();
}
The direct answer requires specific elaborated design for your code and not really a short Qt question or even the question specific to Qt. That is about C++ which is not the VM-based language that assists with serializing the state of program code to data. Having all objects serializable we can then attempt to apply certain C++/Qt classes/techniques.
This task is much easier to accomplish with languages like Java, though. And with C++/Qt you have to routinely make serialize-able / serialize / restore everything that is running in your code and still no guarantee that works as long as the context is not fully captured. This task is not easy for sure and makes sense only in specific application.
The most you can get directly from Qt is to save/restore QMainWindow and other independent widgets geometry (position/size):
saveGeometry
restoreGeometry
... and that solution is still somewhat incomplete or you may/not use QSettings for the storage.
I use QSettings for this. With routines similar to Zlatomir's.
For each window I have in the project I use a different section in QSettings and have readSettings() and writeSettings() in the source for each window.
Anything on the form that I want to persist I have to explicitly save and recall. In the case of a QComboBox it would be something like:
QSettings settings("Organisation", "MySoftware");
settings.beginGroup("WindowNumberTwo");
settings.setValue("ComboIndex", combobox->currentIndex());
// save more values here
// ...
settings.endGroup();
I don't know of a built in way to persist your window states - it has to be don't value by value.

QML map binding

I'm complete noob in Qt, so my question may sound too stupid, but I really need help. I know C++ a little and that's it.
So, my task is to write a C++ program which reads INI-alike file (I can do this, but not sure of most correct/Qt way)
height=20
width=15
or
height=int:20
width=int:15
if properties should be strongly typed. File format is not very important. To make it clear, I have no idea what properties will be defined in this file, names or types are unknown to me at compile time.
after that program loads QML file (I can do this) and injects loaded file data (have no idea how to do this) as JavaScript object, for instance named "Settings", so that QML property bindings will use it like
Rectangle {
width: Settings.width
}
So the questions are:
What is most correct/qt-style way to read INI-alike file?
How can I inject read data as JavaScript object into QML so that QML property binding will use it?
First: The most Qt-style way is using QSettings class:
QSettings *settings = new QSettings("G:/options1.ini",QSettings::IniFormat);
qDebug()<< "height" <<settings->value("height").toInt();
qDebug()<< "width" <<settings->value("width").toInt();
My file:
height=20
width=15
Output:
height 20
width 15
See description of this class. It is really helpful thing.
http://qt-project.org/doc/qt-4.8/qsettings.html

How to init tableWidget?

I've just started with Qt. I saw some articles, but don't understand one thing.
Here it is.
At this link filesTable comes from nowhere. I don't understand where it was inited?
Another example.
void MainWindow::on_pushButton_clicked()
{
ui->tableWidget->setColumnCount('');
ui->tableWidget->setRowCount('');
}
What is
tableWidget
? I mean, how I can create it?
Sorry for such question. I have to.
filesTable could be a member variable declared in the header file. If you're new to C++, you should probably start by learning C++ first, and then start using Qt.
tableWidget is a variable that points to a QTableWidget type object, which was created in the Qt Designer. It was declared somewhere in the ui header file, for example ui_mainwindow.h. This is a file that is usually auto generated by Qt Creator.

QML and QtGStreamer within plugin

I'm trying to prepare QML plugin to play video on embedded device in a way that other developers can use it without much hassle. However the way it is currently proposed requires almost always writing some C++ wrapper around your QML application. I'm refering to this example:
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/qt-gstreamer/html/examples_2qmlplayer_2main_8cpp-example.html
I would like to be able to have plugin and simply write:
import AwesomeVideoPlugin 1.0
Rect
{
AwesomeVideo
{
width: 320
height: 240
url: "./myvideo.avi"
// ... some minor stuff like mouse click handling, controls, etc.
}
}
Currently QtGStreamer requires to provide videoSurface property to VideoItem. The only way to do this is to create and set context for additional property in rootContext(). And to create GraphicsVideoSurface I need QGraphicsView (QDeclarativeView fills this role).
Is it possible to:
Get QDeclarativeView from within QDeclarativeItem (to which I have only access from QML plugin) in a way that it can be later used to feed GraphicsVideoSurface? My guess is no - however I've found path QFraphicsItem::scene() ==> QGraphScene ==> QGraphScene::views() ==> QList of QGraphicsView - it looks like VERY bad programming but maybe somebody got it to work (I'm getting segfault)
Is there other way to provide video sink for QtGStreamer from within QDeclarativeItem ?
Greetz
Yatsa
I had the same question, but haven't come up with an elegant solution.
However, one thought would be to make the videosurface available via an accessor function from a sub-classed QApplication object.
This would, of course, mean that your plug-in depends on the application subclass having a getVideoSurface method, but it does remove the ugliness from the QML code.
class MyApp : public QApplication
{
....
QGst::Ui::GraphicsVideoSurface *getVideoSurface() { return m_videosurface; }
}
...
int MyApp::init()
{
m_viewer = new QDeclarativeView();
m_viewer->setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
m_videosurface = new QGst::Ui::GraphicsVideoSurface(m_viewer);
}
MyVideoPlugin::MyVideoPlugin(QDeclarativeItem *parent) : QDeclarativeItem(parent)
{
QGst::Ui::GraphicsVideoSurface *surface = ((MyApp*)qApp)->getVideoSurface();
}
...
Now the MyVideoPlugin element may be used without referencing an exported videosurface context item.

Resources