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. QHeaderView doesn't change when QTableView's model is reset.

QHeaderView doesn't change when QTableView's model is reset.

Scheduled Pinned Locked Moved Solved General and Desktop
7 Posts 2 Posters 527 Views 2 Watching
  • 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.
  • D Offline
    D Offline
    deleted385
    wrote on last edited by deleted385
    #1

    Here's how the table is defined in the constructor of the widget/view:

    table = new QTableView(this);
    tableHeader = new TableHeader(table);
    tableModel = new QSqlTableModel(table);
    table->setHorizontalHeader(tableHeader);
    table->setModel(tableModel);
    table->setItemDelegate(new TableItemDelegate(table));
    

    on the combobox's selection change, this is called:

    void TableWidget::onComboSelectionChanged(int index)
    {
        db.open();
        tableModel->setTable(comboModel->data(comboModel->index(index, 0)).toString());
        tableModel->select();
        db.close();
    }
    

    and this is how it looks in the ui:

    x1.gif

    so initially, the table, Surah, had 6 columns and 6 QLineEdit were shown in the header. When I selected the table VerbDef, it'd 4 columns BUT TableHeader showed 6 QLineEdit and same thing happened with the table table, VerbForm. The count() hasn't been updated in TableHeader. If I select some table that has more than 6 columns then the app crashes because there's a shortfall of QLineEdit in the QList<QLineEdit*>, and, as aresult, I get index out of range exception.

    Which signal of QTableView/QSqlTableModel should be used to notify QHeaderView about that fact and update the count() and in which slot of QHeaderView?

    Here's how the TableHeader has been defined:

    TableHeader::TableHeader(QTableView * parent) :
        QHeaderView(Qt::Horizontal, parent)
    {
        setDefaultAlignment(Qt::AlignTop | Qt::AlignHCenter);
        connect(this, &TableHeader::sectionResized, this, &TableHeader::updateGeometries);
        connect(parent->horizontalScrollBar(), &QScrollBar::valueChanged, this, &TableHeader::updatePosition);
    }
    TableHeader::~TableHeader() { }
    void TableHeader::showEvent(QShowEvent *e)
    {
        qDeleteAll(lineEdits);
        for (int i = 0; i < count(); i++) {
            auto edit = new QLineEdit(this);
            lineEdits.append(edit);
            connect(edit, &QLineEdit::textChanged, this, &TableHeader::textChanged);
            edit->setGeometry(sectionViewportPosition(i), height() / 2, sectionSize(i), height() / 2);
            edit->show();
        }
        QHeaderView::showEvent(e);
    }
    QSize TableHeader::sizeHint() const
    {
        int width = 0;
        int height = 0;
        for (int i = 0; i < count(); i++){
            width += sectionSize(i);
            auto size = sectionSizeFromContents(i);
            width += size.width();
            height = size.height();
        }
        return QSize(width, height * 2);
    }
    QList<QString> TableHeader::getQueries() { return queries; }
    void TableHeader::updateGeometries()
    {
        if(!lineEdits.size()) return;
        for (int i = 0; i < count(); i++) {
            auto edit = lineEdits.at(i);
            edit->setGeometry(sectionViewportPosition(i), height() / 2, sectionSize(i), height() / 2);
        }
        QHeaderView::updateGeometries();
    }
    void TableHeader::updatePosition()
    {
        int height = QHeaderView::sizeHint().height();
        for (int i = 0; i < count(); i++){
            auto edit = lineEdits.at(i);
            edit->move(sectionPosition(i) - offset(), height);
        }
    }
    void TableHeader::textChanged()
    {
        queries.clear();
        for (int i = 0; i < count(); i++){
            auto edit = lineEdits.at(i);
            queries.append(edit->text());
        }
        emit queryChanged();
    }
    
    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #6

      If diff is negative your loop should run for quite a long time.

      Shouldn't you rather use the absolute value of count ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      D 1 Reply Last reply
      1
      • D Offline
        D Offline
        deleted385
        wrote on last edited by deleted385
        #2

        This, probably, isn't the right way BUT somehow it works:

        TableHeader::TableHeader(QTableView * parent) :
            QHeaderView(Qt::Horizontal, parent)
        {
            setDefaultAlignment(Qt::AlignTop | Qt::AlignHCenter);
            connect(this, &TableHeader::sectionResized, this, &TableHeader::updateGeometries);
            connect(parent->horizontalScrollBar(), &QScrollBar::valueChanged, this, &TableHeader::updatePosition);
            connect(this, &TableHeader::sectionCountChanged, this, &TableHeader::onSectionCountChanged);
        }
        TableHeader::~TableHeader() { }
        QSize TableHeader::sizeHint() const
        {
            if(count() != lineEdits.size()) return QSize(0, 0);
            int width = 0;
            int height = 0;
            for (int i = 0; i < count(); i++){
                width += sectionSize(i);
                auto size = sectionSizeFromContents(i);
                width += size.width();
                height = size.height();
            }
            return QSize(width, height * 2);
        }
        QList<QString> TableHeader::getQueries() { return queries; }
        void TableHeader::updateGeometries()
        {
            if(count() != lineEdits.size()) return;
            for (int i = 0; i < count(); i++) {
                auto edit = lineEdits.at(i);
                edit->setGeometry(sectionViewportPosition(i), height() / 2, sectionSize(i), height() / 2);
            }
        }
        void TableHeader::updatePosition()
        {
            int height = QHeaderView::sizeHint().height();
            for (int i = 0; i < count(); i++){
                auto edit = lineEdits.at(i);
                edit->move(sectionPosition(i) - offset(), height);
            }
        }
        void TableHeader::textChanged()
        {
            queries.clear();
            for (int i = 0; i < count(); i++){
                auto edit = lineEdits.at(i);
                queries.append(edit->text());
            }
            emit queryChanged();
        }
        void TableHeader::onSectionCountChanged(int oldCount, int newCount)
        {
            if(oldCount > 0 && newCount == 0) {
                foreach(auto line, lineEdits) line->disconnect();
                qDeleteAll(lineEdits);
            }
            else if(oldCount == 0 && newCount > 0){
                lineEdits.clear();
                for (int i = 0; i < count(); i++) {
                    auto edit = new QLineEdit(this);
                    lineEdits.append(edit);
                    connect(edit, &QLineEdit::textChanged, this, &TableHeader::textChanged);
                    edit->show();
                }
            }
        }
        

        What's the correct approach of QHeaderView implementation? It'd be nice if we could give it a Layout to render like:

        tableHeader = new TableHeader(table);
        tableHeader ->setLayout(new VBoxLayout(){ with the columnName and QLineEdit}); // doesn't exist.
        table->setHorizontalHeader(tableHeader);
        
        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #3

          Hi,

          Since your number of line edits depends on the number sections I don't see a problem here.

          However there's no need to nuke all and rebuild everything. Just add missing line edits and remove those exceeding.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          D 2 Replies Last reply
          1
          • SGaistS SGaist

            Hi,

            Since your number of line edits depends on the number sections I don't see a problem here.

            However there's no need to nuke all and rebuild everything. Just add missing line edits and remove those exceeding.

            D Offline
            D Offline
            deleted385
            wrote on last edited by
            #4

            @SGaist, good idea, will try that.

            1 Reply Last reply
            0
            • SGaistS SGaist

              Hi,

              Since your number of line edits depends on the number sections I don't see a problem here.

              However there's no need to nuke all and rebuild everything. Just add missing line edits and remove those exceeding.

              D Offline
              D Offline
              deleted385
              wrote on last edited by deleted385
              #5

              @SGaist, here's what I've now to add/remove extras:

              void TableHeader::resetBoxes(int count){
                  queries.clear();
                  if(count == lineEdits.size()) {
                      for (int i = 0; i < lineEdits.size(); i++) {
                          lineEdits[i]->setText("");
                          queries.append("");
                      }
                      return;
                  }
                  int diff = count - lineEdits.size();
                  if(diff > 0){
                      for (int i = 0; i < diff; i++) {
                          auto edit = new QLineEdit(this);
                          edit->installEventFilter(this);
                          lineEdits.append(edit);
                          connect(edit, &QLineEdit::textChanged, this, &TableHeader::textChanged);
                          edit->show();
                      }
                  }
                  else{
                      for (int i = 0; i < diff; i++) {
                          auto line = lineEdits.takeLast();
                          line->disconnect();
                          //line->deleteLater();
                          delete line;
                      }
                  }
                  qDebug() << lineEdits.size();
                  for (int i = 0; i < lineEdits.size(); i++) {
                      lineEdits[i]->setText("");
                      queries.append("");
                  }
              }
              

              It adds extra line edits if necessary BUT doesn't remove from the QList lineEdits or UI when necessary. So it looks like this:

              x2.gif

              initially there was 6 line edits, in subsequent two tables there should've been 4 BUT I got 6. Then I've got 10 and finally when I got back to the first table with 6 columns It'd shown 7 line edits in the UI BUT there was 10 in the QList lineEdits. Here's the output of qDebug() << lineEdits.size();:

              6
              6
              6
              10
              10

              1 Reply Last reply
              0
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on last edited by
                #6

                If diff is negative your loop should run for quite a long time.

                Shouldn't you rather use the absolute value of count ?

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                D 1 Reply Last reply
                1
                • SGaistS SGaist

                  If diff is negative your loop should run for quite a long time.

                  Shouldn't you rather use the absolute value of count ?

                  D Offline
                  D Offline
                  deleted385
                  wrote on last edited by deleted385
                  #7

                  @SGaist, that was the issue. Now, with these in else block:

                  else{
                      diff = abs(diff);
                      for (int i = 0; i < diff; i++) {
                          auto line = lineEdits.takeLast();
                          delete line;
                      }
                  }
                  

                  it shows the right number of line edits in header and the qDebug output is also correct. I haven't measured the time BUT feels like this approach is little bit slower than the previous approach (removing all old and adding new).

                  I also have removed this
                  connect(this, &TableHeader::sectionCountChanged, this, &TableHeader::onSectionCountChanged);

                  and call reset directly in the TableWidget:

                  void TableWidget::queryDatabase(){
                      db.open();
                      tableModel->setTable(tableName);
                      tableHeader->resetBoxes(tableModel->columnCount());
                      tableProxy->setQueries(tableHeader->getQueries());
                      tableModel->select();
                      while (tableModel->canFetchMore()) tableModel->fetchMore();
                      db.close();
                  }
                  
                  1 Reply Last reply
                  0

                  • Login

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