Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to add progress bar to specific treeview row,column?

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

Scheduled Pinned Locked Moved Unsolved General and Desktop
6 Posts 2 Posters 3.0k Views
  • 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 Offline
    S Offline
    SRaD
    wrote on last edited by
    #1

    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
    0
    • KillerSmathK Offline
      KillerSmathK Offline
      KillerSmath
      wrote on last edited by KillerSmath
      #2

      @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
      5
      • S Offline
        S Offline
        SRaD
        wrote on last edited by
        #3

        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
        0
        • KillerSmathK Offline
          KillerSmathK Offline
          KillerSmath
          wrote on last edited by
          #4

          @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
          0
          • S Offline
            S Offline
            SRaD
            wrote on last edited by SRaD
            #5

            "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
            0
            • KillerSmathK Offline
              KillerSmathK Offline
              KillerSmath
              wrote on last edited by KillerSmath
              #6

              @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
              4

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved