Creating subtree with QTreeWidgetItem - qt

Im trying to create a subtree using QTreeWidgetItem.
Here's code
m_pRoot = new QTreeWidgetItem(treeWidget);
m_pRoot->setText(0, "root");
m_pRoot->setData(0, Qt::UserRole, IT_ROOT);
createTreeItem(m_pRoot, m_pText, "subtree_1", IT_TEXT);
m_pRoot->setExpanded(true);
createTreeItem(m_pText, m_pPlainText, "subtree_2", IT_TEXT);
that's method:
void createTreeItem(PTR(QTreeWidgetItem) parent, PTR(QTreeWidgetItem) item, CREF(QString) name, ItemType itemType)
{
item = new QTreeWidgetItem(parent);
item->setText(0, name);
item->setData(0, Qt::UserRole, QVariant(itemType));
}
It's ok when im creating a "subtree_1" with m_pRoot as root item, but it breaks down when i want to create "subtree_2" with m_pText as root item.
P.S PTR() equal *parent.
Cant understand what's the problem. Any suggestions?

If your PTR(QTreeQWidgetItem) macro yields QTreeWidgetItem*, then item is not initialized by createTreeItem function.
The simplest and most logical fix seems to change createTreeItem function to return new item:
QTreeWidgetItem* createTreeItem(PTR(QTreeWidgetItem) parent, PTR(QTreeWidgetItem) item,
CREF(QString) name, ItemType itemType)
{
item = new QTreeWidgetItem(parent);
item->setText(0, name);
item->setData(0, Qt::UserRole, QVariant(itemType));
return item;
}
and use the returned value to initialize m_pText.

Related

QTreeWidget takeChild() - Qt

I have a treeWidget in which I need to remove the QTreeWidgetItem's childelement.
QTreeWidgetItem *listing = new (ui->treeWidget);
AddChild(listing,id);
AddChild(listing,id);`// this is what i need to delete
AddChild(listing,id);
listing->takeChild(1);
I tried func takeChild(int index) but nothing happend
void AddChild(QTreeWidget *s,int id)
{
QTreeWidgetItem *_s = new QTreeWidgetItem(ui->treeWidget);
_s->setText(0,QString::number(id));
s->addChild(_s);
}
There are errors in your code,
QTreeWidgetItem *listing = new (ui->treeWidget);
should be:
QTreeWidgetItem *listing = new QTreeWidgetItem(ui->treeWidget);
and the signature of AddChild() functions is wrong:
void AddChild(QTreeWidget *s,int id)
should be:
AddChild(QTreeWidgetItem *s,int id)
Now the main issue why takeChild() is not working for you, is that you are not adding the items as children to listing , but you are adding them to the treeWidget, thus in your AddChild(), you should set the parent to S which is listing, So your code should be:
QTreeWidgetItem *listing = new QTreeWidgetItem(ui->treeWidget);
listing->setText(0, tr("Listing"));
AddChild(listing,0);
AddChild(listing,1); // this is what i need to delete
AddChild(listing,2);
listing->takeChild(1);
and the function AddChild()
void AddChild(QTreeWidgetItem *s,int id)
{
QTreeWidgetItem *_s = new QTreeWidgetItem(s);
_s->setText(0,QString::number(id));
s->addChild(_s);
}

How to create items programmatically in Sitecore

In the content tree, the structure is as follows
Home
-England
-France
-Germany
There is a sublayout (CommentsForm.ascx), which is used in all the 3 pages. When user browses 'France' and submits a comment, the 'Comment' item should get saved under 'France' and so on..
In this scenario, the Parent item (under which the new item has to be created), is dynamic. So, how to get the parent item in such case. Is this correct?
protected void btnSubmit_Click(object sender, EventArgs e)
{
Sitecore.Data.Database masterDB = Sitecore.Configuration.Factory.GetDatabase("master");
Item parentItem = Sitecore.Context.Item;
string name = "Comment_" + Sitecore.DateUtil.IsoNow;
TemplateItem template = masterDb.GetTemplate("/sitecore/templates/userdefined/Comment");
using (new SecurityDisabler())
{
//how to go about here??
//newItem["Author"] = txtAuthor.text;
//newItem["CommentText"] = txtComments.Text;
//parentItem.Add("name", template);
}
}
You can use UserSwitcher safer in production, but you can also use SecurityDisabler using(newSecurityDisabler()){}
Editing and renaming must happen in an Editing.BeginEdit() transaction
Sitecore.Data.Database masterDB = Sitecore.Configuration.Factory.GetDatabase("master");
Item parentItem = Sitecore.Context.Item;
string name = "Comment_" + Sitecore.DateUtil.IsoNow;
var template = masterDb.GetTemplate("/sitecore/templates/userdefined/Comment");
using (new Sitecore.SecurityModel.SecurityDisabler())
{
try
{
Item newItem = parentItem.Add("Name", template);
if (newItem!=null)
{
newItem.Editing.BeginEdit();
newItem["Author"] = txtAuthor.text;
newItem["CommentText"] = txtComments.Text;
newItem.Editing.EndEdit();
}
}
catch
{
newItem.Editing.CancelEdit();
}
}
Create items programmatically based on template in sitecore using the simple code
// The SecurityDisabler is required which will overrides the current security model, allowing the code
// to access the item without any security.
using (new Sitecore.SecurityModel.SecurityDisabler())
{
// Get the master database
Sitecore.Data.Database master = Sitecore.Data.Database.GetDatabase("master");
// Get the template for which you need to create item
Items.TemplateItem template = master.GetItem("/sitecore/templates/Sample/Sample Item");
// Get the place in the site tree where the new item must be inserted
Item parentItem = master.GetItem("/sitecore/content/home");
// Add the item to the site tree
Item newItem = parentItem.Add("NameOfNewItem", template);
// Set the new item in editing mode
// Fields can only be updated when in editing mode
// (It's like the begin transaction on a database)
newItem.Editing.BeginEdit();
try
{
// Assign values to the fields of the new item
newItem.Fields["Title"].Value = "NewValue1";
newItem.Fields["Text"].Value = "NewValue2";
// End editing will write the new values back to the Sitecore
// database (It's like commit transaction of a database)
newItem.Editing.EndEdit();
}
catch (System.Exception ex)
{
// Log the message on any failure to sitecore log
Sitecore.Diagnostics.Log.Error("Could not update item " + newItem.Paths.FullPath + ": " + ex.Message, this);
// Cancel the edit (not really needed, as Sitecore automatically aborts
// the transaction on exceptions, but it wont hurt your code)
newItem.Editing.CancelEdit();
}
}
using (new Sitecore.SecurityModel.SecurityDisabler())
{
Item newItem = parentItem.Add("Name", TemplateItem.TemplateId);
newItem.Editing.BeginEdit();
newItem.Fields[Constants.IDs.Fields.SicParent.Code].Value = row.SicCode.ToString();
newItem.Fields[Constants.IDs.Fields.SicParent.Description].Value = row.Description;
// this field is a DropList
newItem.Fields[Constants.IDs.Fields.SicParent.Grouping].SetValue(groupItem, true);
newItem.Editing.EndEdit();
}
You can add and item to parentItem and then edit the new item like this:
using (new SecurityDisabler())
{
Item newItem = parentItem.Add("name", template);
newItem.Editing.BeginEdit();
newItem["Author"] = txtAuthor.text;
newItem["CommentText"] = txtComments.Text;
newItem.Editing.EndEdit();
}

JavaFX8: How to create listener for selection of row in Tableview?

I currently have two tableviews in one screen, which results in both TableViews have rows which the user can select.
Now I want only one row to be selected at the same time (doesn't matter which TableView it is selected from). I was thinking about some kind of listener which deselects the other row when a row is selected. This is my initial setup:
Step 1
Search for a way to bind a method to the selection of a row (there is not something like tableview.setOnRowSelected(method))
Step 2
Create the method which acts like a kind of listener: when a row is selected, deselect the other row (I know how to do this part)
Class1 selectedObject1 = (Class1)tableview1.getSelectionModel().getSelectedItem();
Class2 selectedObject2 = (Class2)tableview2.getSelectionModel().getSelectedItem();
if(selectedObject1 != null && selectedObject2 != null) {
tableview1.getSelectionModel().clearSelection();
}
So, step one is the problem. I was thinking of an observable list on which a listener can be created, and then add the selected row to the list. When this happens, the listener can call the method.
Anyone any clue how to make this?
Any help is greatly appreciated.
The selectedItem in the selection model is an observable property, so you should be able to achieve this with:
tableview1.getSelectionModel().selectedItemProperty().addListener((obs, oldSelection, newSelection) -> {
if (newSelection != null) {
tableview2.getSelectionModel().clearSelection();
}
});
tableview2.getSelectionModel().selectedItemProperty().addListener((obs, oldSelection, newSelection) -> {
if (newSelection != null) {
tableview1.getSelectionModel().clearSelection();
}
});
My solution would be creating custom cell factory for table and set it for each table columns.
Callback<TableColumn<..., ...>, TableCell<..., ...>> value = param -> {
TextFieldTableCell cell = new TextFieldTableCell<>();
cell.addEventFilter(MouseEvent.MOUSE_CLICKED, event -> {
//your code
}
);
return cell;
};
packageName.setCellFactory(value);
table1.column1.setCellFactory();
table2.column1.setCellFactory();
...
I use it for deleting the chosen row.
public void ButtonClicked()
{
ObservableList<Names> row , allRows;
allRows = table.getItems();
row = table.getSelectionModel().getSelectedItems();
row.forEach(allRows::remove);
}
This question helped me but during experiment in javafx and jfoenix this also works for me.
deleteSingle.addEventHandler(MouseEvent.MOUSE_CLICKED, (e) -> {
StringProperty selectedItem = table.getSelectionModel().getSelectedItem().getValue().link1;
System.out.println("That is selected item : "+selectedItem);
if (selectedItem.equals(null)) {
System.out.println(" No item selected");
} else {
System.out.println("Index to be deleted:" + selectedItem.getValue());
//Here was my database data retrieving and selectd
// item deleted and then table refresh
table.refresh();
return;
}
});
In case you need not only the row, but the x|y position of the table cell, do this:
table.getFocusModel().focusedCellProperty().addListener(
new ChangeListener<TablePosition>() {
#Override
public void changed(ObservableValue<? extends TablePosition> observable,
TablePosition oldPos, TablePosition pos) {
int row = pos.getRow();
int column = pos.getColumn();
String selectedValue = "";
if (table.getItems().size() > row
&& table.getItems().get(row).size() > column) {
selectedValue = table.getItems().get(row).get(column);
}
label.setText(selectedValue);
}
});
In this example, I am using a "classic" TableView with List<String> as column model. And, of course, that label is just an example from my code.

Level as list in QtreeWidget

I have vector with 6 numbers, which I want insert to list and add this list to QTreeWidget. First number of list is on "root" level and other numbers are sublevel "root".
I don't know how to do it.
Image with describe:
Code:
void modal::zapis() {
ui->listWidget->clear();
ui->treeWidget->clear();
QList<QTreeWidgetItem *> items;
for(int i=0;i<v.size();i++)
{
QString string;
string.setNum(v.at(i));
ui->listWidget->addItem(string);
QTreeWidgetItem *root = new QTreeWidgetItem(ui->treeWidget);
if(i==0)
{
root->setText(0, string);
}
else
{
QTreeWidgetItem *item = new QTreeWidgetItem(root);
item->setText(0, string);
}
}
}
Thank you for any ideas.
You are creating a new root node on every iteration, it just needs creating once per call.

HowTo find Subitem in QAbstractItemModel and QTreeView class?

Question: how to find sub item, in a QTreeView loaded QAbstractItemModel model with model->match() method?
Problem: model->match() can't find sub items, wtf?!
Here is the example:
As you can see from the picture, I'm trying to expand Layouts sub item with this code:
void Dialog::restoreState(void)
{
// get list
QSettings settings("settings.ini", QSettings::IniFormat);
settings.beginGroup("MainWindow");
QStringList List = settings.value("ExpandedItems").toStringList();
settings.endGroup();
foreach (QString item, List)
{
if (item.contains('|'))
item = item.split('|').last();
// search `item` text in model
QModelIndexList Items = model->match(model->index(0, 0), Qt::DisplayRole, QVariant::fromValue(item));
if (!Items.isEmpty())
{
// Information: with this code, expands ONLY first level in QTreeView
view->setExpanded(Items.first(), true);
}
}
}
Where settings.ini file contains:
[MainWindow]
ExpandedItems=Using Containers, Connection Editing Mode, Form Editing Mode, Form Editing Mode|Layouts
PS: root items successfully expands on start!
Here is the solution:
QModelIndexList Items = model->match(
model->index(0, 0),
Qt::DisplayRole,
QVariant::fromValue(item),
2, // look *
Qt::MatchRecursive); // look *
* Without that argument match() function searches only 1 level
My working example on QTreeView.
QModelIndexList Indexes = this->ui->treeView->selectionModel()->selectedIndexes();
if(Indexes.count() > 0)
{
QStandardItemModel *am = (QStandardItemModel*)this->ui->treeView->model();
QStack<QModelIndex> mis;
QModelIndex mi = Indexes.at(0);
while(mi.isValid())
{
mis.push(mi);
mi = mi.parent();
}
QStandardItem *si;
bool FirstTime = true;
while (!mis.isEmpty())
{
mi = mis.pop();
if(FirstTime)
{
FirstTime = false;
si = am->item(mi.row());
}
else
{
si = si->child(mi.row());
}
}
// "si" - is selected item
}
Wanted to add to the answer that #mosg gave
The forth parameter is actually the hits parameters.
It decides ho many matches one wants to return.
For all matches specify -1 as can be seen
here:
QModelIndexList Items = model->match(
model->index(0, 0),
Qt::DisplayRole,
QVariant::fromValue(item),
-1, // any number of hits
Qt::MatchRecursive); // look *

Resources