Why can't QString built from a QJsonDocument be set in a Q_PROPERTY?
-
I'm trying to save a json string into a Q_PROPERTY (so that it saves into the .ui XML) in a custom designer widget. The problem is that every time I run .toJson it updates the variable but it does not store it in the .ui/xml...
Example
This will update the xml document...Q_PROPERTY(bool someBool MEMBER m_my_bool);
This will update the xml document but ONLY if the value is not derived from the json Assignment Example...
Q_PROPERTY(QString someString MEMBER m_someString);
Assignment Example (I trigger this through a custom task menu call when the user double clicks the custom widget in the designer)
QJsonArray jarray; for(int i = 0; i < 10; i++) { QJsonObject jobj; jobj[QString::number(i)] = "Value " + QString::number(i); jarray.append(jobj); } QJsonDocument document; document.setArray(jarray); m_someString = document.toJson();
-
@KidTrent
I don't know anything about QML so cannot answer why "it does not store it in the .ui/xml.".However, the issue cannot be due to "QString built from a QJsonDocument".
document.toJson()
just returns aQString
like any other.In your case the document/string is always the same (if that makes any difference), you have an array of objects with
"0": "Value 0"
etc. The string comes out something like:[ { "0": "Value 0" }, { "1": "Value 1" }, ... ]
If you assign that as literal string to your
m_someString
you should find you are in the same situation? -
Hi,
You have not defined a NOTIFY signal with your property, therefore, nobody can know it has changed.
-
@JonB said in Why can't QString built from a QJsonDocument be set in a Q_PROPERTY?:
@KidTrent
I don't know anything about QML so cannot answer why "it does not store it in the .ui/xml.".However, the issue cannot be due to "QString built from a QJsonDocument".
document.toJson()
just returns aQString
like any other.In your case the document/string is always the same (if that makes any difference), you have an array of objects with
"0": "Value 0"
etc. The string comes out something like:[ { "0": "Value 0" }, { "1": "Value 1" }, ... ]
If you assign that as literal string to your
m_someString
you should find you are in the same situation?I am not using QML, this is strictly in QT creator. I agree that this should not happen as it should be just a string, but it does... If I input it manually it works and if I modify the property manually it works. However, it appears differently... (It actually shows displays the value in the designer as a formatted string (new lines are registered as new lines)... Then if I edit it manually, the formatting appears to vanish and all fits in one line.
@SGaist said in Why can't QString built from a QJsonDocument be set in a Q_PROPERTY?:
Hi,
You have not defined a NOTIFY signal with your property, therefore, nobody can know it has changed.
Hmmm, my understanding is that since it's a MEMBER type it does not necessarily need to notify anything of the change as the actual member variable is being updated. The boolean does not have a NOTIFY either, but it still updates the UI when it's enabled/disabled.....
-
I still don't understand the real problem here. Can you please provide some code to show what's going wrong in your opinion?
I am not using QML, this is strictly in QT creator.
What do you mean with this? In the next line you speak of designer, then again some manual editing.
A json document does not need to have line breaks or indentation at all. -
@Christian-Ehrlicher said in Why can't QString built from a QJsonDocument be set in a Q_PROPERTY?:
I still don't understand the real problem here. Can you please provide some code to show what's going wrong in your opinion?
I am not using QML, this is strictly in QT creator.
What do you mean with this? In the next line you speak of designer, then again some manual editing.
A json document does not need to have line breaks or indentation at all.I've managed to figure out why the .ui file does not update it does not have to do with JSON.... It's because the property is updated through the code instead of in the properties window... Given the following code in a custom widget, the properties window does update (if I click off the widget that is updated and then click back on to it). However, it does not update the .ui file unless I manually edit the property in the properties panel by hand (not by code). How can I fix this?
// The following is code out of my custom EditableTableWidget class Q_PROPERTY(QString serializedColumnTemplates MEMBER m_serialized_column_templates WRITE setSerializedColumns); void setSerializedColumns(const QString& serialized_columns) { m_serialized_column_templates = serialized_columns; }
// This code updates the variable and the properties panel value does reflect that when it reads the variable again (by clicking off and then back on to the custom widget... but the changes are not saved to the .ui file. They only ever save to the .ui file when I edit the property manually in the properties panel. my_editable_table_widget->setProperty("serializedColumnTemplates", "Whatever value I give it...");
-
@KidTrent said in Why can't QString built from a QJsonDocument be set in a Q_PROPERTY?:
Given the following code in a custom widget, the properties window does update (if I click off the widget that is updated and then click back on to it)
What do you mean with 'updated' here? I mean - what should be updated here by simply clicking on the custom widget?
-
The custom property that is set on the widget updates a property on the panel (the panel only updates if I click off and then click back on the custom widget... refreshing the property READ command). This is not the main problem though, the main problem is that making changes to these properties via the code does not add/update the properties in the .ui file as it does when we manually update a property by hand.
For example.... this should be added when the code sets the property, but it's not... It is only ever added when we manually edit the property in the properties panel. So to be clear, using setProperty this is not added to the .ui file... but if we edit manually it is.
<property name="serializedColumnTemplates"> <string>TheSerializedJsonString</string> </property>
-
@KidTrent said in Why can't QString built from a QJsonDocument be set in a Q_PROPERTY?:
void setSerializedColumns(const QString& serialized_columns)
{
m_serialized_column_templates = serialized_columns;
}Since you define your own setter, it's your responsibility to emit the notify signal.
-
Even if I don't define my own setter, it still does not work. Does the properties panel automatically listen for the NOTIFY emitter?
Ugh nevermind I just read the documentation...
"Note that a NOTIFY signal must be specified to allow QML property bindings."I'll try adding one and edit this post...
Edit
I'm still experiencing the same issue. I've added the following changes...Q_PROPERTY(QString serializedColumnTemplates MEMBER m_serialized_column_templates WRITE setSerializedColumnTemplates NOTIFY serializedColumnTemplatesChanged); void setSerializedColumns(const QString& serialized_columns) { m_serialized_column_templates = serialized_columns; emit serializedColumnTemplatesChanged(m_serialized_column_templates ); }
Note that I did also define the signal in the .h.
signals: void serializedColumnTemplatesChanged( const QString& newSerializedColumnTemplates);
-
I would say - please provide a minimal, compilable example so we can reproduce it locally. A simplye QWidget derived custom class with your property would be enough.
-
@Christian-Ehrlicher said in Why can't QString built from a QJsonDocument be set in a Q_PROPERTY?:
I would say - please provide a minimal, compilable example so we can reproduce it locally. A simplye QWidget derived custom class with your property would be enough.
Unfortunately, I don't have enough "privilege's" to upload it... So I uploaded it to the follow URL for 48 hours...
https://volafile.org/r/1g0dkrekr
This has both the custom widget, the task bar extension that sets the property (broken part), and the custom widget tester. The custom widget tester has instructions on the MainWindow.ui file on how to reproduce the problem (note that you must first of course install the BrokenCustomWidgetPlugin.dll into your Qt).
Also here is a video of the problem...
https://puu.sh/GHE1p/927038e95a.gif -
Thx, will take a look on it asap.
-
Ok, really nice work - I did not know until now that this is even possible :)
But I also found the problem. The first hint was that the form was not marked as modified when your attribute changes. This means the designer must be informed somehow but your plugin does not (yet). So looking at the example and go toTicTacToeDialog::saveState()
we see thatQDesignerFormWindowInterface
is used but not in your code. So the solution was easy:void BrokenCustomWidgetColumnSelector::on_SetBtn_clicked() { if (QDesignerFormWindowInterface *formWindow = QDesignerFormWindowInterface::findFormWindow(m_table_widget)) { formWindow->cursor()->setProperty("serializedColumnTemplates", ui->JSONInput->toPlainText()); } accept(); }
-
@Christian-Ehrlicher Awesome, thanks! I assumed the designer was updated in the backend magically for Q_PROPERTY values haha. I'll try it out when I get home later today.
Yah it was difficult to find documentation, because I was searching for guides using the wrong word... but then I started typing "Qt Custom Widget Property Extension" and that turned up the correct results :).