[SOLVED] Generating a UI on the fly
-
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:
@
PK FK to Group FK to Test
1 1 1
2 1 2
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] -
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 [[Doc: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.
-
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.
-
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).
-
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!
-
Well, are my last paragraphs correct or not?
-
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/textfinderThey all use the QUILoader for their user interface in some way or another. Seeing some real world examples should make your live easier.
-
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!
-
[quote author="Volker" date="1308593355"]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.[/quote]
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!
-
[quote author="Joey Dumont" date="1308593123"]
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?
[/quote]
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.
[quote author="Joey Dumont" date="1308593123"]
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.
[/quote]
Yes -
[quote author="loladiro" date="1308593555"]
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.
[/quote]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.
[quote author="loladiro" date="1308593555"]
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 [/quote]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.
-
[quote author="Joey Dumont" date="1308593994"]
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. [/quote]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)?
-
[quote author="loladiro" date="1308594853"]
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)?[/quote]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.
-
Maybe, but since this is for a summer project, I don't think I have time to learn how NoSQL works and redo the work I've already done.
But thanks anyway for the heads-up on that ;)
-
[quote author="Joey Dumont" date="1308596394"]Maybe, but since this is for a summer project, I don't think I have time to learn how NoSQL works and redo the work I've already done.
But thanks anyway for the heads-up on that ;)[/quote]
Summer projects can be the most important ones out of all of them (you learn the most and you have the most fun, because you are motivated :) ). Also, can you post a screenshot or something when you're done with it? Just out of curiosity.
-
Of course. I can post a screenshot as soon as I have something interesting.