How can I create a reference to existing model objects? - eclipse-emf

I'm new to MDSD/EMF but am making great progress thanks to Eclipse's support.
I created a toy model as answered yesterday as awynne suggested, and I'm very close. I'm only using EMF and its generated tree editor.
Here's a summary of my EMF meta-model:
- EClass: Widget
- name
- EClass: WidgetReference
- aWidgetReference : Widget [0..1] Containment = false
- EClass: WidgetContainer
- myWidgets : Widget [0..*] Containment = true
- EClass: ReferenceContainer
- myReferences : WidgetReference [0..*] Containment = true
- EClass: TopLevelClass
- myWidgetContainer : [1] WidgetContainer Containment = true
- myReferenceContainer : [1] ReferenceContainer Containment = true
What's happening now is that in the generated tree editor for the model, I create everything starting from the TopLevelClass. I can successfully create multiple widgets in the WidgetContainer, and I can create a single WidgetReference in the ReferenceContainer and associate it with a specific Widget.
In case anyone runs into this, there is a bug in the generated EMF editor code:
When I try to add more than one WidgetReference to the ReferenceContainer, the tree editor only shows the first WidgetReference under the ReferenceContainer. If I click on the WidgetReferences item in the tree, it does show multiple WidgetReferences in the properties view. It just won't let me see them in the tree, and therefore won't let me select them to change their reference to associate it to an actual widget.
The workaround to this is to create as many references as you need, save and close the model, and then re-open it. Upon re-opening it, all of the references will be shown.
Thanks for any help/guidance.
Jeff

I think the answer to your question is related to the idea of "containment." Any parent object which has a containment reference (containment=true in the EMF metamodel) to a child object manages the lifecycle of that child. So when the child is created, the parent's reference to that object is made automatically. If the reference is not of type containment (containment=false), then you can point the reference to any existing model object of the correct type. I think you need to set your reference as containment=false.
I have not used Acceleo so let's use the EMF tree editor as an example (the concept also applies to the GMF editior): In the tree editor, if the parent object has a containment reference to a child, the user is able to create the child by right-clicking the parent and choosing "new-->child-->ChildObject." If the reference to the child is NOT of type containment , the user will be able to choose instances of that object that already exist in the model by clicking the appropriate child property in the properties window of the parent object.
Does that help? If this description is confusing, it may help to create a toy model with some non-containment references and generate the EMF editor for it.

I'm not sure the concept of referencing between models in EMF is what you describe. However, in a model you do can reference elements in other models. In the Generic EMF editor with you create model instances, you can click the right button and then select "Load Resource...". That new resource can be any other model that is related to your model (your metamodel references the other model's metamodel).
You can to that as well at the meta-model level. In the graphical Ecore editor, you can drag and drop classes from other metamodels. They will keep in synch.
I'm not sure, however, if this is what you're asking.

Related

Layered architecture by Zenject's DiContainers with flat GameObjectContext hierarchy

Previous question: link
In my application I have three layers:
Data (Entities and Data Access Objects)
Model (Managers)
Presentation (Views)
How can I setup Game Object Context that Model layer will include all Data layer dependencies and Presentation layer will include all Model&Data layers dependencies?
Is there any way to set parent component for Game Object Context?
You can add a GameObjectContext by right clicking in the Scene Hierarchy and selecting Zenject -> GameObjectContext. You can add one for data, model, and presentation. Then you just have to set the transform parents up the same way you want the container parents to be. From your description I think you probably want it like this:
Then you can add each installer by attaching a MonoInstaller to each context. You an also do all this dynamically using a FromSubContainerResolve inside a SceneContext installer as well, if you prefer.

Do I need to redesign my application?

I may be bordering on a discussion type question here so I apologise if the question is not specific enough.
I would like to know if I my current application design is inherently weak/flawed. My background is C so I am not using clever c++ patterns to their fullest extent, of this I am sure.
My application is similar to a 3D modelling package, without geometry creation (e.g setting up animations using existing models). The user imports a geometry and can set various parameters on pre existing geometry, and there are time dependent values that relate to the whole system. The output is a text file to be processed by another application.
I am using a QTreeview to render a QStandardItemModel. I simply store pointers to my core classes in the model's items. These have specific UI for each class type, and are all descended from a common base class. They all have a QWidget which is their "mainwidget"
When the user clicks on part of the treeview, the stored class is retrieved and its mainwidget is displayed on a pane on the UI. So - treeview on the left, pane to the right with the current item's contents, and a 3D view showing the geometry.
Most of my data is stored in the classes UI elements themselves; I don't have a central database which stores anything, and when it's time to save the project, I traverse the tree and let every item write itself to a QSettings file. This feels quite naive but it does work, and the reverse happens on project load. The project class generates new classes based on the type information in the settings file and they then read the contents out of the file themselves.
Similarly when writing the output file, each item knows how to write itself and does so. Where other classes can influence the output of others (for example, start and end times), higher level classes process the children and will set start and end times based on the order and duration of each child.
Should I be storing more data in the QStandardItemModel itself, or defining my own model perhaps? Does it sound like I have set myself up for future problems?
At the moment I have modified this system a couple of times to provide customised applications, but I am about to try and make it more generic. I welcome suggestions for improving my design. Go easy, please!
You should try to avoid creating god objects. Split your tasks and duties into smaller chunks. It makes it much easier to maintain and also much easier to extend if you need to.
Your specific use-case would benefit a lot from a more complete use of the Model-View-Controller pattern.
What doesn't make sense in your design is that your data objects hold a UI element. Since only one item can be shown in the right pane, this seems like a waste of resources. It makes more sense to have a single object that then gets passed a data object to display.
What I suggest for your program is the following:
Splitting your data into classes that only have functions for reporting and modifying values. There should be no knowledge of how to display data or store to a file.
Create separate class that handles the reading and writing from a file. If your model is very simple, you could just use single functions to do this using the method shown in the documentation for QDataStream or QTextStream.
Use your QTreeView and QStandardItemModel as Adaptor class between your data objects and the left pannel.
Create a controller class that gets informed by the QTreeView if data needs to be displayed in the right panel. The controller will then retrieve the data item and pass it to the right panel in order to be displayed.
The right panel should act like another View class with the sole responsibility of graphically displaying the data passed in from the controller class.
One advantage of doing it this way is that, if there are different categories of data that get displayed differently in the right panel, the controller could examine the selected data item, determine what the category is, create a view widget to put in the right panel, and then pass it the data to display.
This pattern is open-ended as far as extendability is concerned because you do not need to change your data classes if you need a new display, you merely need to create a new right-panel widget, and then teach your controller class how to determine when the new view should be used.
Another advantage of this pattern is that you only ever need to have a single widget created to display data in your right panel. If you change your selected item, you can just pass it to the view class that already exists and get it to refresh its display with the newly selected data. You only need to distroy the right-panel view widget if a different category of data object is selected and its data needs to be drawn in a different way. The controller class can determine whether a right-panel view widget can be re-used or whether it needs to be swapped out for a different widget.

QListWidget sharing the same model

If I understood the concept of the Qt models correct, then I can have multiple views, sharing the same model, so that when data is updated in the model, all views using it, will also update their view accordingly right?
Now I have multiple widgets in my application, which should have individual selections, but they should operate on the same underlying data. So when a row is added in one of the panels, the others should be able to display this new row as well.
Since the QListWidget provides all the features that I need, there would be no point in writing my own model and use it with a QListView. But I realized that QListWidget doesn't allow me to change the model, because the setModel()method is made private.
So is there some way that I can achieve this, without the need of writing a full model on my own? I'm rather new to Qt so maybe there is a ready made general purpose model, that I can use? But so far I haven't found one.
You are trying to use QListWidget to set your own model which is not possible.
You are better off using the MVC pattern the QT imposes. You can refer here on how to use the MVC pattern. This way would be more manageable and correct. Also you can make of the QStandardItemModel or the more general QAbstractListModel or QStringListModel model for lists. You can refer here for more details
But to answer your question yes they is a hack you can use.
Create a QListWidget and treat that widget as your model.
For other views create a QListView and set the model that is returned by the QListWidget
.
For e.g. refer
QAbstractItemModel* model = listWidget->model();
listView->setModel(model);
listView_2->setModel(model);
Then you can use the listWidget as your model. Any operation (add/delete) performed on the listWidget will also affect the listView and listView_2.
I am still of the opinion that instead of the hack creating your own model would be better and more correct.

Add meta-data to a Qt property

I'm developing an application which displays items on a QGraphicsScene. These
items have properties, which I would like to display in a tree-view, if the
item is selected. If possible, I would like to stick with the property system
implemented by QObject. However, this does not fit all my needs because I need
to store some meta-data along the properties, e.g.
a category used for grouping (e.g. "System properties" and "User properties")
a tooltip text which is shown when the mouse hovers over the property in
the tree-view.
Inspired by Qt Property Browser and by Qt's object framework, I have thought to
implement the following system:
All items in the scene are derived from PropertyItem (which itself inherits
QGraphicsItem or QGraphicsObject). It contains
the logic to get and set the value of a property.
Every class derived from PropertyItem has a static MetaPropertyItem.
A MetaPropertyItem holds instances of the class MetaProperty in order
to store meta-data about the properties of such as the category, the
tooltip string and the type of the property.
Whenever an item is selected in the scene, instances of the Property class
are created for every MetaProperty from the associated MetaPropertyItem.
These properties are then shown in the tree-view and deleted when the item
is deselected.
The more I think about this design, the more I get the feeling that I'm doing
something wrong. It seems that I'm just duplicating what is already part of Qt:
PropertyItem <--> QObject
MetaPropertyItem <--> QMetaObject
MetaProperty <--> QMetaProperty
Property <--> needs to be implemented
I also found this bug ticket, which proposes to add meta-data to a Qt property.
Unfortunately, it did not get any attention so far.
Looking for alternatives, I also stumbled upon QMetaPropertyBuilder which
will (probably?) be part of Qt 5. Unfortunately, documentation about this class is sparse
and what I understood from reading the sources it would not solve my problem.
Thus, my question: Is there actually a better way to achieve what I'm
looking for without re-implementing another Qt framework?

What level of seperation should my UI elements and model objects have?

I'm building a desktop app in QT (although that may be irrelevant) and I'm having a hard time working through the class structure and layout. The data model is fairly simple with a root container with a number of containers of items. Consider the following representation:
Root
+ Parent
+ Child
The UI is fairly simple and follows that data model with a main window with a scrollable area (root), widgets that contain layouts (parents) of custom widgets (children) with some labels and buttons.
My trouble is with handling events that need to go up the chain and then back down like moving a child from one parent to another, moving elements, or updating child meta-data that impacts several to many other widgets.
I'm currently splitting UI widgets and model objects but having each widget and corresponding model object pointing to and from each other feels cumbersome and I think it is leading to too much maintenance.
I'd suggest following a standard MVC pattern and ensure there are no dependencies from the model to the view; in your case this would mean that while there is a widget for every model item, the model items do not reference their corresponding widgets.
While the MVC pattern has many flavours, one way to accomplish this would be to have a view class that monitors the model for any changes and updates the view accordingly (this can be accomplished by connecting a slot in the view class to a signal emitted from the model class). Any changes the user initiates through the view can then be:
1) handled directly by the model
through a simple signal/slot
connection
2) handled
by a controller class which can
direct the model to update accordingly
Either of these would then cause the model to emit an update signal which would cause your view to update. The benefit of this is the ability to change your view (or add additional views) without having to update your model.
I'd recommend reading Qt's Model/View Programming Guide to better understand how MVC works in Qt and to see if there's an existing class or interface (e.g. QAbstractItemModel) that you could use instead of baking your own.
Consider using factory pattern and command pattern. There are plenty of samples. I am just giving a hint here.
http://en.wikipedia.org/wiki/Factory_method_pattern
http://en.wikipedia.org/wiki/Command_pattern
Forgot mention about qt book: cartan-cas-dot-suffolk-dot-edu/oopdocbook/html/