c++qtqtreeviewqprogressbarqstyleditemdelegate

Tree view with a progress bar delegate shows an extra line at the bottom


Whenever I add a progress bar delegate to my tree view, an extra line is shown in the UI under the QTreeView.

enter image description here

#include <QtCore/QBitArray>
#include <QtWidgets/QStyleOptionProgressBar>
#include <QtGui/QColor>
#include <QtGui/QIcon>

class CustomStyleOptionProgressBar : public QStyleOptionProgressBar
{
public:
    CustomStyleOptionProgressBar() = default;

    QColor color {Qt::blue};
    QIcon icon {QIcon()};
    bool hasSegments {false};
    QBitArray segments;
};

void ProgressBarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QStyleOptionViewItem myOption = option;

    if (index.column() == 1) {
        const int progress = index.data(Qt::UserRole + 1).toInt();
        CustomStyleOptionProgressBar progressBarOption;
        progressBarOption.state = myOption.state;
        progressBarOption.direction = QApplication::layoutDirection();
        progressBarOption.rect = myOption.rect;
        progressBarOption.fontMetrics = QApplication::fontMetrics();
        progressBarOption.minimum = 0;
        progressBarOption.maximum = 100;
        progressBarOption.textAlignment = Qt::AlignCenter;
        progressBarOption.textVisible = false;
        progressBarOption.palette = myOption.palette;
        progressBarOption.progress = progress;
        progressBarOption.color = QColor(143, 224, 252);
        // progressBarOption.icon = stateIcon(state);

        QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter);
    } else {
        QStyledItemDelegate::paint(painter, myOption, index);
    }
}

QStandardItemModel *model = new QStandardItemModel;

    // Create Items
    QStandardItem *item_0 = new QStandardItem("Item 0");
    QStandardItem *item_0_0 = new QStandardItem("Item 0_0");
    QStandardItem *item_1 = new QStandardItem("Item 1");
    
    QStandardItem *item_2 = new QStandardItem();
    item_2->setData(50,Qt::DisplayRole);
    QStandardItem *item_3 = new QStandardItem("Item 3");

    ProgressBarDelegate *customDelegate = new ProgressBarDelegate(this);
    ui->treeView->setItemDelegateForColumn(1, customDelegate);
    // Root Item
    QStandardItem * rootItem = model->invisibleRootItem();

    // Define the tree structure
    rootItem->appendRow(item_0);
    rootItem->appendRow(item_1);

    item_0->appendRow(QList<QStandardItem*>{item_0_0,item_2});
    item_2->setData(12, Qt::UserRole + 1);

    model->setItem(1,1,item_3);

    ui->treeView->setAutoFillBackground(false);
    ui->treeView->setModel(model);

Also, the progress value is not shown in the progress bar.


Solution

  • You are overwriting existing flags in progressBarOption.state by doing this:

    progressBarOption.state = myOption.state;
    

    You should instead add myOption.state flags to it like this:

    progressBarOption.state = progressBarOption.state | myOption.state;
    

    I'll also include this explanation from this answer:

    When storing the flags you combine their values using the bitwise OR operator.

    Result:

    Progress Bar in an item of a tree view

    For more: