awaisharoon
awaisharoon

Reputation: 503

Disable QAction if the QTreeView item has no children

I have QTreeView populated from database.

I have contextmenu configured as:

ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);

I have the method to look for a right click to open contextMenu on the item.

void MainWindow::on_treeView_customContextMenuRequested(const QPoint &pos)
{
QModelIndex idx = ui->treeView->indexAt(pos);
if (!idx.isValid())
        {return;}
else{
   QPoint globalPos = ui->treeView->mapToGlobal(pos);
   QAction* selectedItem = contextMenu->exec(globalPos);
    if (selectedItem){
        qDebug () << selectedItem;
    }
}

h.file

QMenu *contextMenu;

How do I check if the selected item from QTreeView is not a parent of any item & it has a parent.

Should I include QTreeView and QStandardItem code here to see or that's irrelevant?

Upvotes: 0

Views: 781

Answers (1)

Scheff&#39;s Cat
Scheff&#39;s Cat

Reputation: 20171

The Qt doc. has a dedicated chapter for this topic:

Model/View Programming

which I recommend to get an overview.

Concerning the actual question of OP:

How do I check if the selected item from QTreeView is not a parent of any item & it has a parent.

The QTreeView inherits QAbstractItemView::model() which provides a pointer to the QAbstractItemModel which in turn provides the underlying model data for the rendered tree view items.

Any provided QModelIndex in a view should refer to this model.

The QAbstractItemModel provides a variety of methods to retrieve data concerning visualization and relations of model items. The QTreeView uses this but it should be used as well for any added function.

So, selected item is not parent of any item is turned around into "selected item has no children" for which QAbstractItemModel::hasChildren() is good for:

bool QAbstractItemModel::hasChildren(const QModelIndex &parent = QModelIndex()) const

Returns true if parent has any children; otherwise returns false.

Use rowCount() on the parent to find out the number of children.

Note that it is undefined behavior to report that a particular index hasChildren with this method if the same index has the flag Qt::ItemNeverHasChildren set.

Note: This function can be invoked via the meta-object system and from QML. See Q_INVOKABLE.

See also parent() and index().

and it has a parent can be retrieved using QAbstractItemModel::parent():

QModelIndex QAbstractItemModel::parent(const QModelIndex &index) const

Returns the parent of the model item with the given index. If the item has no parent, an invalid QModelIndex is returned.

A common convention used in models that expose tree data structures is that only items in the first column have children. For that case, when reimplementing this function in a subclass the column of the returned QModelIndex would be 0.

When reimplementing this function in a subclass, be careful to avoid calling QModelIndex member functions, such as QModelIndex::parent(), since indexes belonging to your model will simply call your implementation, leading to infinite recursion.

Note: This function can be invoked via the meta-object system and from QML. See Q_INVOKABLE.

See also createIndex().

Putting this together, OPs function should look like this:

void MainWindow::on_treeView_customContextMenuRequested(const QPoint &pos)
{
    QModelIndex idx = ui->treeView->indexAt(pos);
    if (!idx.isValid()
      || !ui->treeView->model()->hasChildren(idx)
      && !ui->treeView->model()->parent(idx).isValid()) {
      return;
      // bail out -> no context menu for leaf nodes or toplevel nodes
    } else {
       QPoint globalPos = ui->treeView->mapToGlobal(pos);
       QAction* selectedItem = contextMenu->exec(globalPos);
        if (selectedItem) {
            qDebug () << selectedItem;
        }
    }
}

I'm not quite sure whether this matches exactly OPs required behavior. It might be necessary to fix the condition but this should be not that hard.

Upvotes: 1

Related Questions