Displaying forms using Tree in Qt - forms

I'm building a Qt plugin with multiple forms. I have a main form which has a tree widget placed on the left of the form.
I want to add items to this tree, such that clicking on these items would load the corresponding form on the same form. But I want the tree widget to be active so that I can select any other form also.
I was able to display a form on the main form using the following code:
Form1 *myform;
myform=new Form1(this);
myform->show();
where Form1 is the class of the form i intend to display. However this, covers up the tree widget also. And I have to do a string comparison of the item in tree being clicked to display the appropriate form.
Can someone please help me with this as I'm very new to Qt programming.
Thanks

ixM has a good suggestion. The first step should definitely be to use layouts in your main window - separating the tree from the rest of the window - where you are going to put your form. I would suggest using a splitter, because then the user can resize the two halves. You can set the splitter as the main widget of your CentralWidget in your main window.
QSplitter splitter = new QSplitter(CentralWidget);
splitter->setOrientation(Qt::Horizontal);
splitter->setHandleWidth(3);
splitter->setChildrenCollapsible(false);
MyTree= new QTreeWidget(splitter);
splitter->addWidget(MyTree);
Then add your tree widget to the splitter, which will be on the left side.
The next step is to add a placeholder widget on the right side of your splitter. We are also going to add a layout inside that widget. This layout is very important we are going to use it later.
QWidget WidgetRightSide = new QWidget(splitter);
QVBoxLayout setupLayout= new QVBoxLayout(WidgetRightSide);
setupLayout->setSpacing(0);
setupLayout->setContentsMargins(0, 0, 0, 0);
Now, at this point, this is where my answer really differs from the previous answer. You could use a QStackedWidget. That is certainly an option. The problem with that is that you have to create and load all your forms at the beginning. That uses way more memory, and will take longer to start up. That's not so bad if you have 2-5 forms, but when we are talking about 20, 30 or more forms that's really ugly.
So what I would suggest instead, is that when the user selects something in the tree, we will remove the old form, and add the newly selected form at that point.
When the selected item in the tree changes this is now what we have to do.
First, remove all the stuff from the previously selection form.
QLayoutItem *_Item;
while ((_Item = setupLayout->takeAt(0)))
delete _Item;
Next, figure out what form to show next, and create it.
QWidget *ActiveSetupForm = NULL;
if ( I need to load form 1)
{
ActiveSetupForm = new YourNewForm( WidgetRightSide);
}
else ...
And lastly, add your new form to our layout.
if(ActiveSetupForm)
{
setupLayout->addWidget(pActiveSetupForm);
}
Just as a side note. Layouts are tricky to do by hand. I would strongly suggest that you look into using the QtDesigner when you are creating your forms. It makes life soooo much easier. If you would like to know more about it check out this link.

I don't exactly understand what you are trying to achieve but the bit of code you are showing suggests that you do not use the layouts provided by Qt.
If your goal is to be able to dynamically load a form depending on the item that was clicked in the tree, you could achieve that by having a layout (let's say QHBoxLayout) where you would insert your tree and a QStackedWidget in which you could "store" each form (by using addWidget()) and choose which one you want to display by calling setCurrentIndex().

Related

VerticalLayout dynamically hiding visibility

I was wondering whats the best way around dynamically hiding some menu items. At the moment I have 6 items just in a matrix layout row. I want to have 3 items aligned left and 3 items alligned right. If one of the items is set to not visible I want it to move accross. I've done something similiar in a horizontal layout and setting the visibility to hidden. I was wondering if this would work with a vertical layout? Having trouble trying to figure out exactly how I would do it as I'm quite new to UI5 xml css and javscript. Any help would be great.
Also I'm having one other issue unrelated to this, I cant seem to bind my json model to my xml fragment, if I use the same code on my normal xml view it prints out the model data. But on my fragment it just prints it like {person>/fullName} any ideas ?
Belongs to your second question.
Maybe your binding was quoted on copy and paste? Check the native XML Code.
If no data are shown (not "{person>/fullName}"), add dependent to connect the models of your view
var oFragment = sap.ui.xmlfragment(sFragment, "fragmentName", this);
oView.addDependent(oFragment);

GXT add doesn't seem to work after LayoutContainer.removeAll()

GXT 2.25.
I have a screen with a layout container with a TableLayout with two columns. The left column has a tree grid. The right column is a layout container with table layout, one column.
When I click on various items on the tree grid, I want to display editable fields in the layout container on the right that match to the item clicked on.
When I first start the form and am loading the data from the server, I add text to the layout container and it seems to be fine.
After the text is loaded, I call secondLayout.removeAll() to remove all items. Then I click on an item in the tree. The selection method calls secondLayout.removeAll() and then adds a new text item "Loaded..." for testing.
private LayoutContainer secondaryLayout;
And then...
secondaryLayout.removeAll();
secondaryLayout.add(new Text("Loaded..."));
Ideas?
After making structural changes to a container, be sure to invoke (in GXT 2) the layout method to re-run the layout routines. The alternative is to configure the LayoutContainer to re-run layouts on each modification (using setLayoutOnChange), but that would in this case be at least two re-layouts - one for removeAll, and another for each new object added. Could be needlessly expensive, so better to run once and for all when you are finished making changes.
(Worth pointing out perhaps that GXT 2.2.5 is just over two years old, 2.2.6, 2.3.0 have gone out since then, and it is being superseded by GXT 3. In GXT 3, the method here would be forceLayout.)

how to hide and unhide authoerable tabs depending upon value selected from a drop down in CQ5

i am trying to create a footer component in CQ5, where i have 4 columns & all are autherable.
But we have to make no of columns autherable too i.e based on a value selected form a dropdown we have to open those many tabs for authoring those many columns only.
i have created a dropdown and have a maximum range of 6 columns. i know that i have to configure a listener for this purpose but don't know how . Requirement is like if i select 3 from the drop down then 3 tabs should come to author 3 columns
pls help me , i am middle of something very important.i need the solution very early too as i have to finish the job as soon as possible
I might be late for this by now but in case you still need it:
You need to add a listener node before closing your drop-down element:
<listeners
jcr:primaryType="nt:unstructured"
loadcontent="function(box){ //here you also need to handle the hide/unhide when the panel loads for the first time. Use this.getValue() to retrive the intial value }"
selectionchanged="function(box, value) {
for(var c=1;c<=value;c++){
this.findParentByType('tabpanel').unhideTabStripItem("tab"+c); // You need to handle the opposite with hideTabStripItem("tab"+c);
}
}"/>
Then on both "loadcontent" and "selectionchange" (these are events on your drop-down) grab the current selected value and use it to hide/unhide the tabs. In this case the tabs would be named "tab1", "tab2", etc, make sure you get the names right.
The ExtJS in the events is finding the "tabpanel" container for the whole dialog, and then hiding/unhiding based on name. You could also set to enable/disable using the methods ".enable()" and ".setDisabled(true)". Just make sure you get the reference to the tab first if you want to do this (something like ".getComponent(tabName).enable()").
I didn't test this specific code, I couldn't find my actual example from my code base but this should take you in the right direction.

GWT Widget not properly set in the DOM

I would like to print a GWT widget which extends Composite. This widget is composed of a grid whose cells are built with a ListDataProvider. When the user clic on a button print, the widget to print is built. Once this is done, I launch the print:
Element element = widgetToPrint.getElement();
String content = element.getInnerHTML();
print(content);
public static native boolean print(String content)
/*-{
var mywindow = window.open('', 'Printing', '');
mywindow.document.write('<html><head><title>Test</title>');
mywindow.document.write('<link rel="stylesheet" href="/public/stylesheets/ToPrintWidget.css" type="text/css" media="all"/></head><body>');
mywindow.document.write(content);
mywindow.document.write('</body></html>');
mywindow.print();
return true;
}-*/;
So, here is my problem:
The window which is opened by this method contains the core of the widget (built by the UI Binder), but some children are missing...
If I look inside the ListDataProvider and its related FlowPanel, the data are consistent, i.e. I've got several item in my list and in the flowPanel.
Consequently, it should be visible on the printing window...
I thought that maybe the problem was related to the method used to print the widget, so I also tried to add this widget into a dialogbox just before launching the print, to see if the widget was properly built... and it was.
So my widget displays well on a dialogbox, but if I try to give its innerHTML to the print method, by using getElement(), some widgets are missing... I've the feeling that the widgets which should have been built when the ListDataProvider changes are not properly set in the DOM... Somehow it works when I add the widget to a regular component, but it doesn't work when I have to give directly its innerHTML...
Do you have any idea ?
Thanks in advance.
Widgets are not just the sum of their elements, and DOM elements are not just the string that they are serialized to. Widgets are the element, and all events sunk to the dom to listen for any changes or interactions by the user. Elements then have callback functions or handlers they invoke when the user interacts with them.
By serializing the element (i.e. invoking getInnerHTML()), you are only reading out the structure of the dom, not the callbacks, and additionally not the styles set by CSS. This probably shouldn't be expected to work correctly, and as your experience is demonstrating, it doesn't.
As this is just a print window you are trying to create, event handling is probably not a concern. You just want the ability to see, but not interact with, the content that would be in that set of widgets. Styles are probably the main problem here then (though your question doesn't specify 'some children are missing' doesn't tell us what is missing, or give us any more clues as to why...) - you are adding one stylesheet in your JSNI code, but CellTable (which I assume you are using since you reference ListDataProvider) needs additional CssResource instances to appear correctly. I'm not sure how you can hijack those to draw in a new window.
Are you only using this to print content, not to let the user directly interact with the data? If so, consider another approach - use a SafeHtmlBuilder to create a giant, properly escaped string of content to draw in the new window.
String content = element.toString();
This will include all hierarchy elements in the node.
Just a reminder, all the GWT handlers will not work, and you have to sink all the events using DOM.
You might want to grab the outer HTML rather than the inner one.
GWT unfortunately has no getOuterHTML, but it's relatively easy to emulate.
If your widget is the only child within an element, then simply get the inner HTML of the parent element (w.getElement().getParentElement().getInnerHTML())
Otherwise, clone your widget's node add it to a newly created parent element, from which you'll be able to get the inner HTML:
DivElement temp = Document.get().createDivElement();
temp.appendChild(w.getElement().cloneNode(true));
return temp.getInnerHTML();
First thank you for your answers, it helped me to work out this problem.
I've almost solve the problem:
First, I do not use ListDataProvider anymore, because it wasn't clear for me when and how the view was refreshed. Instead I add my widgets by hand, which makes sense since, they are not going to move anyway.
Then, I define the style of my widgets using a common CSS stylesheet. However, in order to do it, I can't rely on CssResource, which was the way I was used to do it with GWT. I think that this comes from the JS method which gets lost by this kind of styles... Instead, I have to specify everything in a static CSS stylesheet, and to give it to the JS.
It works perfectly well, ie, I have my widgets, with thei styles, and I can print it.
But...
The color of some widgets depends on the color of the object that they represent. Consequently, I cannot write a generic CSS stylesheet... And as I said, I can't add a style using CssResource... Do you have any ideas on the way to handle that ?
To make sure I'm clear on the way I'm adding styles, here is an example:
Label l = new Label("Here is a cell in my grid to be printed");
l.addStyleName("PrintLineCell-kind_1");
With, in a public CSS stylesheet:
.PrintLineCell-kind_1{
background-color: red;
}
I hope there is a better way than to write 300 styles to cover 300 different colors...

GWT Tree Item:How to add image to tree item?

I am using gwt 2.3 version.I am using gwt tree in my application.
Here is my code:
public void onModuleLoad() {
// Create a tree with a few items in it.
TreeItem root = new TreeItem("root");
root.addItem("item0");
root.addItem("item1");
root.addItem("item2");
// Add a CheckBox to the tree
TreeItem item = new TreeItem(new CheckBox("item3"));
root.addItem(item);
Tree t = new Tree();
t.addItem(root);
// Add it to the root panel.
RootPanel.get().add(t);
}
There is a item with check box.I want add image to this tree item.But I am not able to do this as I already added one widget check box.Is there any other way add image to tree item with check box??
TreeItem has a TreeItem(Widget w) constructor.
You can put anything you want in there. So write a small widget that has an image and text next to each other in a div and the Tree will render it correctly.
You are already using it in your example code. So just write one more widget that combines the CheckBox with an image in a FlowPanel or HorizontalPanel. Whatever you want.
This is something that made me whack my head for a while also. Basically I found 2 options:
Use SmartGWT, it has nice customizable tree widgets that let you change the pictures of the nodes:
http://www.smartclient.com/smartgwt/showcase/#tree_databinding_local
Use GWT's tree-image:
http://google-web-toolkit.googlecode.com/svn/javadoc/1.5/com/google/gwt/user/client/ui/TreeImages.html
If you ask me, SmartGWT is somewhat demanding and rigid, and you might not like the fact that it doesn't let you go to the low leves like GWT does but it does have a nice set of customizable tree widgets. TreeImage on the other hand lets you still work with pure GWT (which I think is better overall), but it doesn't let you customize the tree as much as Smart GWT does