Qt application with public QML code that user can edit
-
Hello,
I want to allow users to change visual aspect of my application editing '.qml' files.
I know this is possible but have no idea how. Can someone put me on the right track please ?
I found this :
QML files in the file system
Files are stored without compression and encryption
Faster to build but slower to deploy Stored without compression so they take more storage space Easy to do UI changes on the fly on target (just edit QML and restart) < this is what i need i think
so how to store files without compression and encryption?
QML files in the resource file
Resources are compiled to the binary file making the executable file size bigger
Slower to build but faster to deploy. Takes less storage space because resources are compressed by default. Because the executable size is bigger the program takes more memory when running. You can't do changes to UI without re-compiling
Thx in advance
LA -
@SGaist hello,
As i said i'm trying to create a qtQuick app, with .qml files avalabls for the user (user can edit qml files)@SGaist said in Qt application with public QML code that user can edit:
One possible way is to copy the file you want to allow editing from the resource to a suitable writable location (see QStandardPaths).
Then you have to tell your application to load that file if it exists otherwise the one from the resource.So I'm trying to subclass QQuickPaintedItem,
class QMProgressBar : public QQuickPaintedItem{ // I want to read a .qml file ('user file' if it exists, otherwise the one from the resource) create the item corresponding that qml code, show it on the screen };
then i will register my class : qmlRegisterType<QMProgressBar>("QMProgressBar", 1, 0, "Bar");
To be able to create QMProgressBar{} in QML.
So, for the moment in my class I'm able to load the right file, cast it to QQuickItem*, read properties :
QQmlComponent component(&qengine, QUrl::fromUserInput(homeLocation)); userItem = qobject_cast<QQuickItem*>(component.create()); qDebug() << userItem->property("maxValue");
Last thing i have to do, is to show that item.
Thx
@LeLev said in Qt application with public QML code that user can edit:
Last thing i have to do, is to show that item.
Ok, last thing to do was to set the visual parent of my qquickitem ! now is is working.
userItem->setParentItem(this);
@SGaist thank you very much for help!
LA -
Hi,
One possible way is to copy the file you want to allow editing from the resource to a suitable writable location (see QStandardPaths).
Then you have to tell your application to load that file if it exists otherwise the one from the resource.
-
Hi,
One possible way is to copy the file you want to allow editing from the resource to a suitable writable location (see QStandardPaths).
Then you have to tell your application to load that file if it exists otherwise the one from the resource.
-
Note that this also allows you to do a "reset" if the edits ends breaking something (and you can be sure it will at some point)
-
Note that this also allows you to do a "reset" if the edits ends breaking something (and you can be sure it will at some point)
@SGaist thx again.
I sublclassed QQuickPaintedItem;
constructor:
#include "qmprogressbar.h" QMProgressBar::QMProgressBar() { QString homeLocation = QStandardPaths::locate(QStandardPaths::DocumentsLocation, QString(), QStandardPaths::LocateDirectory); homeLocation.append("QMProgressBar.qml"); QQmlEngine qengine; QFile file(homeLocation); if( file.exists()){ qDebug()<< "User file found..."<< homeLocation ; QQmlComponent component(&qengine,QUrl::fromUserInput(homeLocation)); userItem = qobject_cast<QQuickItem*>(component.create()); qDebug()<< userItem->property("maxValue"); } else{ homeLocation = ":/QMProgressBar.qml"; QFile homefile(homeLocation); if(homefile.exists()){ qDebug()<< "QRC file found..."<< homeLocation; QQmlComponent component(&qengine,QUrl::fromUserInput(homeLocation)); userItem = qobject_cast<QQuickItem*>(component.create()); qDebug()<< userItem->property("maxValue"); } } userItem->deleteLater(); }
if file exists in writable homeLocation it will be used else
qrc file is used. This is ok.Now could you please tell me how can i display this item on the screen ?
I saw this exemple http://doc.qt.io/qt-5/qtquick-scenegraph-customgeometry-example.html
but i can not understand what exactly i have to do ..Do i have to implement paint(QPainter *painter) method ?
-
I did this :
void QMProgressBar::paint(QPainter *painter){ //test painter->drawPie(boundingRect().adjusted(1, 1, -1, -1), 90 * 16, 290 * 16); // this works }
There is a method drawPixmap( x,y,w,h,QPixmap &pm )
so I'm trying to convert my QMProgressBar.qml to a pixmap :
void QMProgressBar::paint(QPainter *painter){ QPixmap itemPxMap; itemPxMap.load("qrc:///QMProgressBar.qml"); painter->drawPixmap(50,50,100,100,itemPxMap); // this will not work : application starts and shows white screen }
Is it possible to convert a .qml file to QPixmap ? Please tell me what i'm doing wrong here.
-
What exactly are you trying to achieve ? I thought you wanted to load a QML file and run it live in your application which seems to not be what you are doing.
-
@SGaist hello,
As i said i'm trying to create a qtQuick app, with .qml files avalabls for the user (user can edit qml files)@SGaist said in Qt application with public QML code that user can edit:
One possible way is to copy the file you want to allow editing from the resource to a suitable writable location (see QStandardPaths).
Then you have to tell your application to load that file if it exists otherwise the one from the resource.So I'm trying to subclass QQuickPaintedItem,
class QMProgressBar : public QQuickPaintedItem{ // I want to read a .qml file ('user file' if it exists, otherwise the one from the resource) create the item corresponding that qml code, show it on the screen };
then i will register my class : qmlRegisterType<QMProgressBar>("QMProgressBar", 1, 0, "Bar");
To be able to create QMProgressBar{} in QML.
So, for the moment in my class I'm able to load the right file, cast it to QQuickItem*, read properties :
QQmlComponent component(&qengine, QUrl::fromUserInput(homeLocation)); userItem = qobject_cast<QQuickItem*>(component.create()); qDebug() << userItem->property("maxValue");
Last thing i have to do, is to show that item.
Thx
-
Like this exemple : http://doc.qt.io/qt-5/qtqml-tutorials-extending-qml-example.html
except :
void PieChart::paint(QPainter *painter) { QPen pen(m_color, 2); painter->setPen(pen); painter->setRenderHints(QPainter::Antialiasing, true); // painter->drawPie(boundingRect().adjusted(1, 1, -1, -1), 90 * 16, 290 * 16); //instead of 'drawPie()', i want to drow 'userItem' }
-
@SGaist hello,
As i said i'm trying to create a qtQuick app, with .qml files avalabls for the user (user can edit qml files)@SGaist said in Qt application with public QML code that user can edit:
One possible way is to copy the file you want to allow editing from the resource to a suitable writable location (see QStandardPaths).
Then you have to tell your application to load that file if it exists otherwise the one from the resource.So I'm trying to subclass QQuickPaintedItem,
class QMProgressBar : public QQuickPaintedItem{ // I want to read a .qml file ('user file' if it exists, otherwise the one from the resource) create the item corresponding that qml code, show it on the screen };
then i will register my class : qmlRegisterType<QMProgressBar>("QMProgressBar", 1, 0, "Bar");
To be able to create QMProgressBar{} in QML.
So, for the moment in my class I'm able to load the right file, cast it to QQuickItem*, read properties :
QQmlComponent component(&qengine, QUrl::fromUserInput(homeLocation)); userItem = qobject_cast<QQuickItem*>(component.create()); qDebug() << userItem->property("maxValue");
Last thing i have to do, is to show that item.
Thx
@LeLev said in Qt application with public QML code that user can edit:
Last thing i have to do, is to show that item.
Ok, last thing to do was to set the visual parent of my qquickitem ! now is is working.
userItem->setParentItem(this);
@SGaist thank you very much for help!
LA