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?
Forum Updated to NodeBB v4.3 + New Features

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