June 20, 2011

Joey Dumont Joey Dumont
Lab Rat
116 posts

[SOLVED] Generating a UI on the fly

Page  
1

Hello Qt devs!

I’m working on a GUI to a DB. I want to create a form that enables the user to enter data in the DB. The data that has to be entered are results from multiple tests. In my DB, I have a table that details what tests pertain to what group. In fact, it kinda looks like that:

  1. PK     FK to Group     FK to Test
  2. 1       1                      1
  3. 2       1                      2
  4. 3       1                      3

You get the idea. Now, suppose I want to enter data for group 1. I want my interface to generate, on-the-fly, a GUI that allows user to easily enter data.

Would it be possible to do that by subclassing QWidget for each test and add that widget to a QstackedWidget?

It seems to me that this is the most elegant solution, as it is very flexible.

Any ideas?

Thanks!

[EDIT: table formatting, Volker]
[EDIT 2: table formatting is currently broken, wrapping in @-tags meanwhile, Volker]

 Signature 

Joey Dumont

19 replies

June 20, 2011

loladiro loladiro
Lab Rat
596 posts

I might not have completly understood your use case, but why don’t you just use standard layouts and widgets (you could still create your own widgets if the data is too complex to fit standard widgets) and instantiate them as necessary?

June 20, 2011

Volker Volker
Ant Farmer
5428 posts

That idea sounds good.

Although this would make the tests hardwired to your application. If you want to be more flexible you should have a look at QUiLoader. This way you could design the forms using Qt Designer or the designer component of Qt Creator, store that in a database too and load it dynamically. You the can add more tests very easily without having to recompile your application.

June 20, 2011

Joey Dumont Joey Dumont
Lab Rat
116 posts

Well, for instance, if I do quality assurance on a certain device and acquire data from the field. There are pre-determined grouping of tests that have to be done.

When the user selects a certain grouping, I want to generate a single QDialog that will contain everything that needs to be entered. Since I want to separate this data entry on a per test basis, it seemed more flexible to subclass QWidget for each test and generate a QStackedWidget containing an instance of each subclass per page.

That way, if the table above changes in the DB, the UI does not need to be changed, as everything is driven by data in the DB.

It the use case clearer now?

Tell me if there’s anything you need to know.

 Signature 

Joey Dumont

June 20, 2011

loladiro loladiro
Lab Rat
596 posts

Yes, thanks, I think that sounds like a good solution, but as Volker mentioned you should look at UiLoader. That way you are more flexible and advanced users might even be able to create their own uis and tests etc. (assuming of course the app is not just for your personal use).

June 20, 2011

Joey Dumont Joey Dumont
Lab Rat
116 posts

Thanks for your suggestions!

Just to make sure I understand this correctly, if I use QUILoader, I don’t need to subclass QWidget for each of my test. Instead, I create a .ui file (with its implementation in .h and .cpp files) for each test, and store the .ui in the DB.

When it’s time for data entry, I let QUILoader know that UI forms to include in my QStackedWidget (or QTabWidget, or whatever) and it will go fetch them in the DB.

Now, when data entry is done, is there a way to commit the data to the DB with a single button?

Well, don’t answer that last question, I’ll have a deeper look into QUILoader before.

Thanks a lot!

 Signature 

Joey Dumont

June 20, 2011

loladiro loladiro
Lab Rat
596 posts

Ok, feel free to ask if you have any further questions.

June 20, 2011

Joey Dumont Joey Dumont
Lab Rat
116 posts

Well, are my last paragraphs correct or not?

 Signature 

Joey Dumont

June 20, 2011

Volker Volker
Ant Farmer
5428 posts

If you use QUILoader, you do not have .h and .cpp files (you could have, but it makes no sense in your context, as you would have your compile time dependency again).

The QUILoader should work completely dynamically. Just name the widgets according to some scheme which would ideally be base on the field names of your tests or the like. Design it that way, that you can construct the name of a widget and access that in the ui.

Then, having a pointer to that object you can inspect it using Qt’s nice object system. E.g. check with method inherits() if an object is of a certain type (eg. a line edit), you then can safely cast to QLineEdit and get the text.

You might want to look at those examples in the Qt sources:

examples/designer/calculatorbuilder
examples/designer/worldtimeclockbuilder
examples/script/calculator
examples/script/qstetrix
examples/uitools/textfinder

They all use the QUILoader for their user interface in some way or another. Seeing some real world examples should make your live easier.

June 20, 2011

Joey Dumont Joey Dumont
Lab Rat
116 posts

In the calculator example, the implementation is a script that is alongside the UI in a resources file.

So how do I not need .h and .cpp implementation files that are stored in the DB. Otherwise, I have a nice UI that does nothing, no?

Plus, most of my tests have different sets of results, so I would need to have a .UI file for each of them, or at least most of them.

Sorry for the noob questions, and thanks a bunch for your answers!

 Signature 

Joey Dumont

June 20, 2011

Volker Volker
Ant Farmer
5428 posts

That would be in the scope of some example code. Hopefully I’ll have some time this week to put it together, but that may take some days. Please stay tuned.

June 20, 2011

Joey Dumont Joey Dumont
Lab Rat
116 posts
Volker wrote:
That would be in the scope of some example code. Hopefully I’ll have some time this week to put it together, but that may take some days. Please stay tuned.

Please, don’t waste too much of your time on me. I’ll just read and try things by myself. I’m really grateful that you answer my questions, and I feel bad that you take so much of your time for me!

 Signature 

Joey Dumont

June 20, 2011

loladiro loladiro
Lab Rat
596 posts

Joey Dumont wrote:

So how do I not need .h and .cpp implementation files that are stored in the DB. Otherwise, I have a nice UI that does nothing, no?

Very true. One thing you can do is iterate over all editable fields in the .ui file and save the value in the appropriate field in the database. You could encode the field in some property, e.g. the objectName. I actually had a very similar problem of dynamically providing UI’s for certain user created content. At first I wanted to solve it with UiLoader, but it proved to be too limiting in the end. I ended up using a plugin for every that encapsulated the interface and provided a nice API (I also wrote a tool to convert .ui into a skeleton for these plugins – it worked really well, but it was still painful). I’m looking into switching to some kind of qml based ui, to be truly cross-platform.

In conclusion, if you need complex interaction with your UI (i.e. everything you can’t do with signal/slots), you’ll have to find another solution.

Joey Dumont wrote:

Plus, most of my tests have different sets of results, so I would need to have a .UI file for each of them, or at least most of them.

Yes

June 20, 2011

Joey Dumont Joey Dumont
Lab Rat
116 posts
loladiro wrote:
In conclusion, if you need complex interaction with your UI (i.e. everything you can’t do with signal/slots), you’ll have to find another solution.

I need to be able to take the data that was entered into the editable fields and commit it to the DB. I also need to fetch some data from the DB and display it in the UI.

loladiro wrote:
At first I wanted to solve it with UiLoader, but it proved to be too limiting in the end. I ended up using a plugin for every that encapsulated the interface and provided a nice API

That loosely sounds similar to my initial idea of subclassing QWidget for each test, which I guess I will have to resort to, given the low degree of redundancy of data entry format for my tests. What I mean by that is that some tests have tables as results, others a single line of text, others a single value, others have expected values and blah blah blah. They are very heterogeneous.

 Signature 

Joey Dumont

June 20, 2011

loladiro loladiro
Lab Rat
596 posts
Joey Dumont wrote:
That loosely sounds similar to my initial idea of subclassing QWidget for each test, which I guess I will have to resort to, given the low degree of redundancy of data entry format for my tests. What I mean by that is that some tests have tables as results, others a single line of text, others a single value, others have expected values and blah blah blah. They are very heterogeneous.

I know the problematic. BTW, If I may ask, if you have so many different test with test data, do you just have a different SQL table for every test or do you somehow serialize the data and place it all in one table (I would do the first, but I’ve seen plenty of implementation that do the latter to keep the DB structure simple)?

June 20, 2011

Joey Dumont Joey Dumont
Lab Rat
116 posts
loladiro wrote:
I know the problematic. BTW, If I may ask, if you have so many different test with test data, do you just have a different SQL table for every test or do you somehow serialize the data and place it all in one table (I would do the first, but I’ve seen plenty of implementation that do the latter to keep the DB structure simple)?

I do the former, but not to keep the DB structure simple, but they to be able to add tests at will. It is cumbersome to add tables every time, and I have over 300 tests, which you make the DB unwieldy.

Adding lines, on the other hand, is very easy, hence the single table structure.

 Signature 

Joey Dumont

Page  
1

  ‹‹ Detect & get web page change on the fly?      [SOLVED] Generating a UI on the fly, Pt.2 ››

You must log in to post a reply. Not a member yet? Register here!