Can’t make child in Qtreeview using QStandardItemModel - c++

After reading some examples I am still missing here something.
I have Qtreeview for view and QStandardItemModel for the data interface, also using QSortFilterProxyModel subclass but I don't know if its relevant.
This is my logic:
First I create the model with the QWidget as the parent:
QStandardItemModel m_model = new QStandardItemModel(0,4,parent);
then setSourceModel(m_model) for the widget
Set the treeview with QSortFilterProxyModel. something like this:
GroupProxyModel = new GroupSortFilterProxyModel;
GroupProxyModel->setDynamicSortFilter(true);
setSourceModel(createSubjectModel(parent));
ui.treeView_mainwindow->setModel(GroupProxyModel);
ui.treeView_mainwindow->setSortingEnabled(true);
Then later I fill the first row like this:
QList<QStandardItem *> items;
items.insert(0,new QStandardItem("Test 0"));
items.at(0)->setEditable(false);
m_model->insertRow(0,items);
Until now every thing working fine and I see the row with the data. But when I like to
add child to the row like this:
QModelIndex parentQModelIndex = m_model->item(0,0)->index();
m_model->insertRows(0,1,parentQModelIndex);
m_model->insertColumns(0,1,parentQModelIndex);
QModelIndex indexB = m_model->index(0, 0, parentQModelIndex);
m_model->setData(indexB,"Child test",Qt::DisplayRole);
But I don't see the child, why?

That's not how QStandardItemModel works - to add a child, call appendRow(s)/insertRow(s) on the parent QStandardItem:
QStandardItem* child = new QStandardItem( tr("Child test") );
...
QStandardItem* parentItem = m_model->item( 0, 0 );
parentItem->appendRow( child );

Related

qt treewidget widget item QCheckBox alignment

I have a QTreeWidget where I insert different widgets (QDoubleSpinBox,QSpinBox,QCheckBox...)
QTreeWidget *t = ui->treeWidget;
QTreeWidgetItem *item = new QTreeWidgetItem();
int c = 0;
QDoubleSpinBox *dspb = new QDoubleSpinBox();
t->setItemWidget(item, c++, dspb);
QSpinBox *spb = new QSpinBox();
t->setItemWidget(item, c++, spb);
QCheckBox *cb = new QCheckBox();
t->setItemWidget(item, c++, cb);
t->addTopLevelItem(item);
However, the cb widget looks wired since the checkbox is aligned to the left. I would like to see it aligned in the center.
Q: How can I change the checkbox to appear in the middle of the TreeWidget cell?
I need to be able to access the cb item again later. Currently, I use the following code:
QTreeWidgetItem *itm = t->topLevelItem(0);
bool checked = qobject_cast<QCheckBox *>(t->itemWidget(itm,c++))->checkState() == Qt::Checked;
If I need to do some workaround to get the central alignment going, how can I access the cb object then?
Found it:
cb->setStyleSheet("margin-left:50%; margin-right:50%;");
works!

How to select item in QComboBox with QTreeView

I was trying to select item "leaf2" from QComboBox with QTreeView in the below code.
I just want to select items with no child from text by code. (if there is a child, it won't be selectable)
How can I select item or index with no child item?
Can anyone help me with this problem?
Thank you.
void Main::initView()
{
QStandardItemModel *model = new QStandardItemModel;
QStandardItem *root_item = model->invisibleRootItem();
// Build Model Items
QStandardItem *node_item = NULL;
node_item = new QStandardItem("Node");
node_item->setFlags(Qt::ItemIsEnabled);
root_item->appendRow(node_item);
QStandardItem *leaf_item = new QStandardItem("leaf1");
leaf_item ->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
node_item->appendRow(leaf_item );
leaf_item = new QStandardItem("leaf2");
leaf_item ->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
node_item->appendRow(leaf_item );
// Set Model to TreeViewComboBox
ui.cb_treevew->setModel(model);
ui.cb_treeview->setCurrentIndex(0); // "Node" is selected.
ui.cb_treeview->setCurrentIndex(1); // Nothing is selected.
ui.cb_treeview->setCurrentIndex(2); // Nothing is selected.
ui.cb_treeview->setCurrentIndex(3); // Nothing is selected.
}
Here is my code for CTreeViewComboBox.
CTreeViewComboBox::CTreeViewComboBox(QWidget *parent) : QComboBox(parent)
{
QTreeView* treeView = new QTreeView(this);
treeView->setEditTriggers(QTreeView::NoEditTriggers);
treeView->setSelectionBehavior(QTreeView::SelectRows);
treeView->setSelectionMode(QTreeView::SingleSelection);
treeView->setItemsExpandable(true);
treeView->header()->setVisible(false);
treeView->setWordWrap(true);
setView(treeView);
}
PS: I tried to select items as following, but not working. :(
ui.cb_treeview->treeView()->setCurrentIndex(getModelIndexFromText("leaf2"));
If the nodes with children will never have the same text with the nodes without children then the following method is appropriate.
QModelIndexList modelIndexes = model->match(
model->index(0, 0),
Qt::DisplayRole,
"leaf2",
-1,
Qt::MatchRecursive);
QModelIndex index = modelIndexes.first();
ui.cb_treeview.setRootModelIndex(index.parent());
ui.cb_treeview.setCurrentIndex(index.row());
On the other hand, if the nodes with children can have the same text as the nodes without children, you should use the following method.
QModelIndexList modelIndexes = model->match(
model->index(0, 0),
Qt::DisplayRole,
"leaf2",
-1,
Qt::MatchRecursive);
QModelIndexList::iterator tstIt = std::find_if(modelIndexes.begin(),
modelIndexes.end(),
[] (const QModelIndex & index) {
return !index.model()->hasChildren(index);
});
ui.cb_treeview.setRootModelIndex(tstIt->parent());
ui.cb_treeview.setCurrentIndex(tstIt->row());
In both cases I am assuming that nodes without children always have different texts. If nodes without children match the name, choose one of them.

C++ QListView with icons And Signals on items clicked

I have a QListview where I have set a model. The model contains the QList. Now I want to get the contents of QListview on clicking the item. But I don't know how to do this? Through some tutorials I followed I am able to get two items appear in the QListview as follows. But I dont know how to make it work?? Please anyone help. The code which I am working as follows.
listviewmodel =new QListView;
listviewmodel->setModel( createModel() );
listviewmodel->setViewMode(QListView::IconMode);
listviewmodel->setIconSize(QSize(size().width()/8, size().height()/8));
connect(listviewmodel,SIGNAL(clicked(const QModelIndex)),this,SLOT(ItemClicked(QModelIndex)));
QAbstractItemModel *MainWindow::createModel()
{
QStandardItemModel *model = new QStandardItemModel();
QList<QStandardItem *> listItem;
QStandardItem *item2 = new QStandardItem();
item2->setIcon(QIcon(QPixmap::fromImage(qimages2)));
listItem << item2;
QStandardItem *item1 = new QStandardItem();
item1->setIcon(QIcon(QPixmap::fromImage(qimages1)));
listItem << item1;
model->appendColumn(listItem);
return model;
}
void MainWindow::ItemClicked (QModelIndex index )
{
textEdit->setText(index.data().toString());
}
I checked your code in QtCreator and it works as you described. So what is the problem? Are you getting some errors? Maybe did you not put declaration of ItemClicked(QModelIndex) below the public slots:? Are you sure that connect returns true? Try to check it:
bool success = connect(listviewmodel,SIGNAL(clicked(const QModelIndex)),this,SLOT(ItemClicked(QModelIndex)));
Q_ASSERT(success);
EDIT: If you want to display only icons at QListView and get some text informations after clicking on specified item, you can do it in the following way:
item2->setIcon(QIcon(QPixmap::fromImage(qimages2)));
item2->setData("informations about item2", Qt::UserRole);
(...)
void MainWindow::ItemClicked (QModelIndex index )
{
QString data = index.data(Qt::UserRole).value<QString>();
ui->textEdit->setText(data);
}

Qt QTreeWidget alternative to IndexFromItem?

I have derived the class QTreeWidget and creating my own QtPropertyTree. In order to populate the tree with widgets (check boxes, buttons, etc) I am using the following code:
// in QtPropertyTree.cpp
QTreeWidgetItem topItem1 = new QTreeWidgetItem(this);
QTreeWidgetItem subItem = new QTreeWidgetItem(this);
int column1 = 0
int Column2 = 1;
QPushButton myButton = new QPushButton();
this->setIndexWidget(this->indexFromItem(this->subItem,column1), myButton);
QCheckBox myBox = new QCheckBox();
this->setIndexWidget(this->indexFromItem(this->subItem,column2), myBox);
This works fine, but the problem is that i want to avoid using the "indexFromItem" function since it is protected, and there are other classes that are populating the tree and need access to that funcion. Do you know any alternative to using that function?
You can try to use your QTreeWidget's model (QAbstractItemModel) to get the right index by the column and row numbers:
// Row value is 1 because I want to take the index of
// the second top level item in the tree.
const int row = 1;
[..]
QPushButton myButton = new QPushButton();
QModelIndex idx1 = this->model()->index(row, column1);
this->setIndexWidget(idx1, myButton);
QCheckBox myBox = new QCheckBox();
QModelIndex idx2 = this->model()->index(row, column2);
this->setIndexWidget(this->indexFromItem(idx2, myBox);
UPDATE
For sub items, the same approach can be used.
QModelIndex parentIdx = this->model()->index(row, column1);
// Get the index of the first child item of the second top level item.
QModelIndex childIdx = this->model()->index(0, column1, parentIdx);
The obvious solution is to de-protect indexFromItem like this:
class QtPropertyTree {
...
public:
QModelIndex publicIndexFromItem(QTreeWidgetItem * item, int column = 0) const
return indexFromItem (item, column) ;
}
} ;

QStandardItemModel append new items on top of the rest

i like to make my QStandardItemModel that populates items in qtreeview
to append rows on top the allready defined items in the view .
something like the twitter view , new items first.
all i see in the QStandardItemModel is the appendRow/s that appends then to button.
this is what im using now.
SWidget *widget = new SWidget;
QStandardItem *newItem = new QStandardItem;
newItem->setSizeHint( widget->size() );
appendRow( newItem );
view->setIndexWidget( newItem->index(), widget );
void QStandardItemModel::insertRow ( int row, QStandardItem * item ) inserts a row at row containing item. So instead of calling appendRow(newItem); call insertRow(0, newItem);