Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Unsolved How to add progress bar to specific treeview row,column?

    General and Desktop
    2
    6
    2043
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • S
      SRaD last edited by

      Using Qt5. I'm trying to add a progress bar to the second column of a QTreeView, but only to a specific row, not the entire second column. Below is what I have, but nothing shows other than what I put in the first columns.

      //progress.h
      class ProgressDelegate : public QStyledItemDelegate
      {           
          Q_OBJECT
      
          public: 
              ProgressDelegate(QObject *parent = 0); 
              
              void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const override;
      };           
      
      //progress.cpp
      ProgressDelegate::ProgressDelegate(QObject *parent) :
      QStyledItemDelegate(parent) { }
      
      void ProgressDelegate::paint(QPainter *painter,
      const QStyleOptionViewItem &option,
      const QModelIndex &index ) const // override
      {
          if (index.column() == 2)
          {
              QStyleOptionProgressBar progressBarOption;
              progressBarOption.state = QStyle::State_Enabled;
              progressBarOption.direction = QApplication::layoutDirection();
              progressBarOption.rect = option.rect;
              progressBarOption.fontMetrics = QApplication::fontMetrics();
              progressBarOption.minimum = 0;
              progressBarOption.maximum = 100;
              progressBarOption.textAlignment = Qt::AlignCenter;
              progressBarOption.textVisible = true;
      
              QApplication::style()->drawControl(QStyle::CE_ProgressBar,
              &progressBarOption, painter);
          }
          else
              QStyledItemDelegate::paint(painter, option, index);
      
          return;
      }         
      
      // main-window.cpp
      
      testModel = new QStandardItemModel(2, 2);
      testModel->setHorizontalHeaderLabels(headers);
          
      treeView = new QTreeView;
      delegate = new ProgressDelegate(this);
      treeView->setModel(testModel);
      
      QString a = QString::fromStdString("stringA");
      QStandardItem *ai = new QStandardItem(a);
      
      QString b = QString::fromStdString("stringB");
      QStandardItem *bi = new QStandardItem(b);
      
      ai->appendRow(bi);
      
      testModel.setItem(1, 0, ai);
      

      I can see that I don't have a call to somehow put the progress bar in the column, but I'm not sure how that works.

      1 Reply Last reply Reply Quote 0
      • KillerSmath
        KillerSmath last edited by KillerSmath

        @SRaD Hi there.
        Firstly, the counter of rows and columns begins in 0, so if you are trying to set a personal paint in the Second Column, you should to use index.column() == 1

        Don't forget that in Father and Children model, the count of row and column is reseted when you set an item as the child of another item.

        Image from QT - Model/View Tutorial

        Row and column system

        QModexIndex has 3 important Attributes:

        • row
        • column
        • parent

        For default, if you call parent() function of an item that haven't father, it will return a standard QModexIndex

        Below is an example of how you can set a progress bar in the item of first row, second column and in top father level.

        void ProgressDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const // override
        {
            if (index.row() == 0 && index.column() == 1 && index.parent() == QModelIndex()) // first row, second column, at top father level
            {
                QStyleOptionProgressBar progressBarOption;
                progressBarOption.state = QStyle::State_Enabled;
                progressBarOption.direction = QApplication::layoutDirection();
                progressBarOption.rect = option.rect;
                progressBarOption.fontMetrics = QApplication::fontMetrics();
                progressBarOption.minimum = 0;
                progressBarOption.maximum = 100;
                progressBarOption.textAlignment = Qt::AlignCenter;
                progressBarOption.textVisible = true;
        
                QApplication::style()->drawControl(QStyle::CE_ProgressBar,
                &progressBarOption, painter);
            }
            else
                QStyledItemDelegate::paint(painter, option, index);
        }
        

        Read More:
        http://doc.qt.io/qt-5/qmodelindex.html
        http://doc.qt.io/qt-5/model-view-programming.html

        @Computer Science Student - Brazil
        Web Developer and Researcher
        “Sometimes it’s the people no one imagines anything of who do the things that no one can imagine.” - Alan Turing

        1 Reply Last reply Reply Quote 5
        • S
          SRaD last edited by

          Still not seeing progress bars. Here is my tree, and my understanding of row/col id's.

          Root Item (this is column 0)
              +- row = 0 (this is column 1)
          	+ row = 0 (column 2, progress bar here)
          	+ row = 1 (column 2, progress bar here)
          	+ row = 2 (column 2, progress bar here)
          +- row = 1 (this is column 1)
          	+ row = 0 (column 2, progress bar here)
          	+ row = 1 (column 2, progress bar here)
          	+ row = 2 (column 2, progress bar here)
          

          Since I only want to have progress bars to the 3 items in the second column, here is how I set my paint method ...

          void ProgressDelegate::paint(QPainter *painter, 
          const QStyleOptionViewItem &option,
          const QModelIndex &index ) const // override
          {
              if (index.column() == 2 && index.parent() != QModelIndex())
              {
              // ...
          

          However, I still see nothing showing up in the second column of my treeview.

          1 Reply Last reply Reply Quote 0
          • KillerSmath
            KillerSmath last edited by

            @SRaD

            Is the element (row 0, column 2) a child of element ( row 0, column 1) ?
            I am not understanding why your column index is incrementing...

            When an element is appended as child of another, their counters starts in (0,0) again.

            @Computer Science Student - Brazil
            Web Developer and Researcher
            “Sometimes it’s the people no one imagines anything of who do the things that no one can imagine.” - Alan Turing

            1 Reply Last reply Reply Quote 0
            • S
              SRaD last edited by SRaD

              "Is the element (row 0, column 2) a child of element ( row 0, column 1) ?"
              Yes, row 0, column 2 is a child of row 0, column 1.

              "I am not understanding why your column index is incrementing..."
              Doesn't each new column to the right increment? I have 3 columns.

              "When an element is appended as child of another, their counters starts in (0,0) again."
              And I think I have that. I don't see where I'm going wrong.

              Edit:
              I think I see where I might be going wrong. I thought each new append is a new column, but I see in my treevew, this hierarchy shows up in column 1 (or 0) of the treeview and I'm trying to put a progress bar in column 2 (or 1) of the treeview. I think I'm thinking each new child is a column.

              So therefore, I've changed index.column() == 1 thinking this is the 2nd column of my treeview, not the hierarchy above. But still not seeing a progress bar.

              void ProgressDelegate::paint(QPainter *painter, 
                  const QStyleOptionViewItem &option,
                  const QModelIndex &index ) const // override
              {
                  if (index.column() == 1 && index.parent() != QModelIndex())
                  {
                  // ...
              
              1 Reply Last reply Reply Quote 0
              • KillerSmath
                KillerSmath last edited by KillerSmath

                @SRaD

                Look, think in a tree model setted up as below example:

                • Item A (0,0,0)
                  • Item 1 (0,0,1)
                    • Item P1 (0,0,2)
                    • Item P2 (1,0,2)
                    • Item P3 (2,0,2)
                  • Item 2 (1,0,1)
                    • Item P1 (0,0,2)
                    • Item P2 (1,0,2)
                    • Item P3 (2,0,2)
                  • Item 3 (2,0,1)
                    • Item P1 (0,0,2)
                    • Item P2 (1,0,2)
                    • Item P3 (2,0,2)

                Note: Each child has a Z Level depending of their parent but the value of (X,Y) is reseted for each append.

                To set the Progressbar if the element is grandchild, you could to calculate the Z Level using the Parent of this element.

                Example:

                void ProgressDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, 
                                             const QModelIndex &index ) const // override
                {
                    int z = 0;
                
                    for(QModelIndex parentIndex = index.parent(); parentIndex.isValid(); z++){
                        parentIndex = parentIndex.parent();
                    }
                
                    if (index.column() == 0 && z==2)
                    {
                        QStyleOptionProgressBar progressBarOption;
                        progressBarOption.state = QStyle::State_Enabled;
                        progressBarOption.direction = QApplication::layoutDirection();
                        progressBarOption.rect = option.rect;
                        progressBarOption.fontMetrics = QApplication::fontMetrics();
                        progressBarOption.minimum = 0;
                        progressBarOption.maximum = 100;
                        bool isNumber;
                        int number = index.data(Qt::DisplayRole).toInt(&isNumber);
                        if(isNumber){
                            progressBarOption.progress = number;
                        }
                        progressBarOption.textAlignment = Qt::AlignCenter;
                        progressBarOption.textVisible = true;
                
                        QApplication::style()->drawControl(QStyle::CE_ProgressBar,
                                                           &progressBarOption, painter);
                    }
                    else
                        QStyledItemDelegate::paint(painter, option, index);
                }
                
                
                    QStandardItemModel *model = new QStandardItemModel(0,1,this);
                    model->setHorizontalHeaderItem(0, new QStandardItem("Main Column"));
                
                    ProgressDelegate *delegate = new ProgressDelegate(this);
                    ui->treeView->setItemDelegate(delegate);
                    ui->treeView->setModel(model);
                
                    QStandardItem *ia;
                    QStandardItem *i1,*i2,*i3;
                    QStandardItem *p1,*p2,*p3;
                
                    // (Row , Column , Z Level)
                
                    ia = new QStandardItem("Item A"); // (0,0,0)
                
                        i1 = new QStandardItem("Item 1"); // (0,0,1)
                
                            p1 = new QStandardItem("15"); // (0,0,2)
                            p2 = new QStandardItem("30"); // (1,0,2)
                            p3 = new QStandardItem("12"); // (2,0,2)
                
                            i1->appendRow(p1);
                            i1->appendRow(p2);
                            i1->appendRow(p3);
                
                        ia->appendRow(i1);
                
                        i2 = new QStandardItem("Item 2"); // (1,0,1)
                
                            p1 = new QStandardItem("35"); // (0,0,2)
                            p2 = new QStandardItem("77"); // (1,0,2)
                            p3 = new QStandardItem("12"); // (2,0,2)
                
                            i2->appendRow(p1);
                            i2->appendRow(p2);
                            i2->appendRow(p3);
                
                        ia->appendRow(i2);
                
                        i3 = new QStandardItem("Item 3"); // (2,0,1)
                
                            p1 = new QStandardItem("7"); // (0,0,2)
                            p2 = new QStandardItem("22"); // (1,0,2)
                            p3 = new QStandardItem("85");// (2,0,2)
                
                            i3->appendRow(p1);
                            i3->appendRow(p2);
                            i3->appendRow(p3);
                
                        ia->appendRow(i3);
                
                    model->appendRow(ia); // (0,0,0)
                

                Result

                result_image

                But this solution has a processing overhead to calculate the Z Level using the For Loop each time that paint event is called, so, seriously, the best solution is calculate the Z Level when the Data is appended on Model.

                Pseudo-code - when insert the data or changing the root:

                if has parent then
                  Data[Z_Role] := parent_z_level + 1
                else
                  Data[Z_Role] := 0
                

                You could easily get the Z Level on Delegate with this functionality

                // Z_Role = Qt::UserRole+1
                int zLevel = index.data(Qt::UserRole+1).toInt()
                

                @Computer Science Student - Brazil
                Web Developer and Researcher
                “Sometimes it’s the people no one imagines anything of who do the things that no one can imagine.” - Alan Turing

                1 Reply Last reply Reply Quote 4
                • First post
                  Last post