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

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

Scheduled Pinned Locked Moved Solved General and Desktop
7 Posts 2 Posters 411 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