Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

logic to say, if mouseover and checked ...



  • I have a TreeView delegate that detects mouseover events and I also have a custom TreeModel where the items have checkboxes.

    What I'd like to do is have logic that says, if this item is checked, and the mouse is hovering over this same item, then call a function.

    I can detect mouseover's ...

    void MyTreeViewDelegate::paint(QPainter *painter,
    const QStyleOptionViewItem &option, const QModelIndex &index) const 
    {   
        // ...
        if (parent.row() == 0 && index.column() == 1 &&
                (option.state & QStyle::State_MouseOver)) { /* ... */ }
    }
    

    And I can check my checkboxes ...

    QVariant MyTreeModel::data(const QModelIndex &index, int role) const
    {
        // ...
    
        MyTreeItem *item = static_cast<MyTreeItem *>
            (index.internalPointer());
    
        if (role == Qt::CheckStateRole) {
            if (parent.row() == 0 && index.column() == 0)
                return static_cast<int>(item->isChecked() ? Qt::Checked : Qt::Unchecked);
        }
    
        // ...
    }
    

    But I'm not sure how to ties these together.

    Can anyone help out?



  • Just thinking out loud, I'd probably subclass QCheckBox to include a mouse event handler, and add that specialized checkbox class to my treemodel. IIRC, the mount event handler would be active only if the mouse is within the geometry of the checkbox, thus addressing the "mouse-over" requirement.


  • Lifetime Qt Champion

    Hi
    Did you try in delegate to do
    bool isChecked = index.data( Qt::CheckStateRole).toBool();



  • @mrjj - If I understood you correctly, I ended up with this in the delegate.

    void MyTreeViewDelegate::paint(QPainter *painter,
    const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        // ...
        if (parent.row() == 0 && index.column() == 1 &&
                (option.state & QStyle::State_MouseOver)) {
                                                                              
            bool is_checked = index.data(Qt::CheckStateRole).toBool();
        }
        // ...
    }
    

    When I hover the pointer over an item, this gets called, but is_checked always shows false. If I click on the items checkbox, then this still gets called and it will correctly show whether it's true or false, but this doesn't seem to correctly work when just hovering over an item.


  • Lifetime Qt Champion

    @SRaD
    so even is item is is checked (has value in model)
    and you call bool is_checked = index.data(Qt::CheckStateRole).toBool();
    its still false ?

    I wonder that you in data has
    if (parent.row() == 0 && index.column() == 0)
    but in delegate says
    parent.row() == 0 && index.column() == 1
    for Qt::CheckStateRole

    So use the debugger and check if data is called as expected when you do
    bool is_checked = index.data(Qt::CheckStateRole).toBool();



  • @mrjj - Ok, I see what's going on. When I hover over an item, the QModelIndex is for the item I'm hovering over. The problem is, the checkbox is in index.column() = 0 whereas the item I'm hovering over is in index.column() = 1. That's why index.data(Qt::CheckStateRole).toBool() is always false.

    Is there a way to get a QModelIndex for something in the same row, but one column to the left?


  • Lifetime Qt Champion

    Hi,

    QModelIndex::sibling is what you are looking for.


Log in to reply