How to identify which UI object is selected in QT? - c++

In this case, I have 2 QTableViews in my form and I am making a copy function to copy and paste in Excel, but to make the function I need to declare a model from the table I am copying:
QAbstractItemModel *abmodel = ui->tableview1->model();
QItemSelectionModel *model = ui->tableview1->selectionModel();
QModelIndexList list = model->selectedIndexes();
so I am making an "if" to for the declaration depending on which QTableView I have selected:
if(ui->tableview1(selected)){
QAbstractItemModel *abmodel = ui->tableview1->model();
QItemSelectionModel * model = ui->tableview1->selectionModel();
QModelIndexList list = model->selectedIndexes();
}
if(ui->tableview2(selected)){
QAbstractItemModel *abmodel = ui->tableview2->model();
QItemSelectionModel *model = ui->tableview2->selectionModel();
QModelIndexList list = model->selectedIndexes();
}
Is there a way to make that happen?

Related

How to get selected items from a QListView which uses custom QAbstractListModel in C++

I have created a custom list model following this guide Creating a cusotm model for a QListView. I am able to show a list of custom objects (such as the Employee as in the example) but I don't know how to retrieve back the selected ones (can I retrieve back the "linked" objects directly?).
Maybe do I have to do something with this command:
myLV->selectionModel()->selectedIndexes();
But I don't really know how to retrieve back the original custom objects.
[EDIT]
So far I have solved retrieving back the object adding a custom method inside my custom list model:
Employee* MyEmployeeListModel::getAtSelectedIndex(const QModelIndex& index){
return employees_.at(index.row());
}
And then calling this on the main window:
QModelIndexList selectedRows;
QItemSelectionModel * selmodel = ui->employeesLV->selectionModel();
selectedRows = selmodel->selectedRows();
MyEmployeeListModel* currModel = dynamic_cast <MyEmployeeListModel*>(ui->employeesLV->model());
for (const QModelIndex & index : selectedRows){
Employee* item=currModel->getAtSelectedIndex(index);
if (item) {
// do something with the item
}
}
Now what I am willing to know is if this is the real best practice or not.
I'm using the following code with a QTreeView (ui->treeMessages), but this should work with a QListView as well:
QModelIndexList selectedRows;
QItemSelectionModel * selmodel = ui->treeMessages->selectionModel();
selectedRows = selmodel->selectedRows();
for (const QModelIndex & index : selectedRows)
{
const QModelIndex sourceIndex = m_sortFilterModel->mapToSource(index);
ItemData * item = sourceIndex.internalPointer();
if (item) {
// do something
}
}

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.

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) ;
}
} ;

Retrieving a QStandardItem through QStandardItemModel by searching or key

Is there any way to assign a unique key to an entry in a QStandardItemModel so that we can check for the presence of that key. If it is present we get the relevant QstandardItem ?
Update:
Here is what I am trying to do. I have 3 column in my table so so i have 3 QStandardItem.
This is the code I am using:
QStandardItem* item0 = new QStandardItem("Column1");
QStandardItem* item1 = new QStandardItem("Column2");
QStandardItem* item2 = new QStandardItem("Column3");
Now my model is called model and I am attaching these to my model as such
moddel->setItem(0,0,item0);
moddel->setItem(0,1,item1);
moddel->setItem(0,2,item2);
I need to assign a row some unique key so that I could check the model for that key and the model would return the row number. Any suggestions.
You could use the setData function of QStandardItem in order to set a custom key for a user defined role, eg
#define MyRole Qt::UserRole + 2
myItem->setData(Qvariant(key), MyRole)
You can get the data of any index in your model by using the data call.
QVariant d = mymodel->data(anindex, MyRole)
Writing a function that checks if a key exists should be straight forward.
The answer by pnezis addresses the storing of a key but not the accessing of a QStandardItem from the model. I addressed the storing of data with a QStandardItem by sub classing QStandardItem as I needed to store a lot of complex data.
To obtain the QStandardItem from the model you need to create a QModelIndex instance with the row/column and then call itemFromIndex(index)
on the model.
My example is taken from a selection callback.
QModelIndex& selectedItem = itemsSelected.front();
QStandardItemModel* model = reinterpret_cast<QStandardItemModel*>(tableView->model());
if (nullptr == model)
return;
QStandardItem *item = model->itemFromIndex(selectedItem);
if (nullptr == item)
return ;

Can’t make child in Qtreeview using QStandardItemModel

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 );