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 implement setHeaderData in a subclass of QAbstractTableModel?

How to implement setHeaderData in a subclass of QAbstractTableModel?

Scheduled Pinned Locked Moved Solved General and Desktop
qtablemodeltable view
34 Posts 4 Posters 3.5k 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.
  • J jdent

    @jdent I am needing to repeat myself because my question goes unanswered. please help!
    What is wrong with my headerData()? The problem is I cannot see the header of my QTableView! What am I doing wrong?

    JonBJ Online
    JonBJ Online
    JonB
    wrote on last edited by JonB
    #14

    @jdent
    Start by correcting your code, your last 2 return statements are not acceptable for any role.

    	if (orientation == Qt::Horizontal)
    	{
    		if (role == Qt::DisplayRole)
    			return QVariant{ tr("Num %1").arg(section) };
    		return QVariant();
    	}
    	return QVariant();
    

    Then confirm with a breakpoint/debug statement that your headerData() is getting called, and report back.

    I assume you have a QHeaderView in your QTableView to see the headers?

    1 Reply Last reply
    0
    • J Offline
      J Offline
      jdent
      wrote on last edited by
      #15

      ok thanks
      I get Qt::Vertical with role 13, 6, 0, 1
      then I get Qt::Horizontal with roles 13, 6, 0, 1
      I did not have a QHeaderView!! Now I have:

          ui.tableView->setHorizontalHeader(new QHeaderView{ Qt::Horizontal });
      

      and I see a header now!

      1 Reply Last reply
      0
      • J Offline
        J Offline
        jdent
        wrote on last edited by
        #16

        But now I cannot sort by column!!
        and I have

            VectorModel* model = new VectorModel{ std::unique_ptr<AbstractCollection>(new PersistentCollection{ storage(), select(columns(&Claim::id, &Claim::amount))})};
            QSortFilterProxyModel* proxy = new QSortFilterProxyModel{ this };
            proxy->setSourceModel(model);
            ui.tableView->setModel(proxy);
            ui.tableView->setHorizontalHeader(new QHeaderView{ Qt::Horizontal });
            ui.tableView->setSortingEnabled(true);
            ui.tableView->setSelectionMode(QAbstractItemView::SingleSelection);
        
        1 Reply Last reply
        0
        • J Offline
          J Offline
          jdent
          wrote on last edited by
          #17

          Anyway I needed to modify sorting: how do I take control of it? For instance if the column has text then alphanumerical sorting must be done and if it is numeric, then the text in the cell must be converted to numeric and the order set numerically! How is this done?

          JonBJ 1 Reply Last reply
          0
          • J Offline
            J Offline
            jdent
            wrote on last edited by
            #18

            How does one cell's value compare with another? I want to implement intelligent sorting!

            1 Reply Last reply
            0
            • J jdent

              Anyway I needed to modify sorting: how do I take control of it? For instance if the column has text then alphanumerical sorting must be done and if it is numeric, then the text in the cell must be converted to numeric and the order set numerically! How is this done?

              JonBJ Online
              JonBJ Online
              JonB
              wrote on last edited by JonB
              #19

              @jdent
              You should use a QSortFilterProxyModel for displaying your model sorted.

              treeView = new QTreeView;
              model = new YourModel;
              proxyModel = new QSortFilterProxyModel(this);
              proxyModel->setSourceModel(model);
              treeview->setModel(proxyModel);
              

              Then you do sorting (and optionally filtering too) in the proxy model code.

              1 Reply Last reply
              0
              • J Offline
                J Offline
                jdent
                wrote on last edited by
                #20

                I have this but when I click the header nothing happens!

                JonBJ 1 Reply Last reply
                0
                • J jdent

                  I have this but when I click the header nothing happens!

                  JonBJ Online
                  JonBJ Online
                  JonB
                  wrote on last edited by
                  #21

                  @jdent
                  If you go to the doc page I referenced and read through you will find it describes exactly what you need to do and how it relates to QSortFilterProxyModel or sorting your model.

                  The idea is to read through the documentation, search for examples and ask questions here when you have researched and have a problem.

                  1 Reply Last reply
                  0
                  • J Offline
                    J Offline
                    jdent
                    wrote on last edited by jdent
                    #22

                    Ok, I implemented a subclass of QSortFilterProxyModel in the following :

                    class SortFilterProxyModel : public QSortFilterProxyModel
                    {
                    	Q_OBJECT
                    public:
                    	SortFilterProxyModel(QObject* parent = nullptr) : QSortFilterProxyModel(parent) {}
                    
                    	bool lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const override
                    	{
                    		QVariant left_data = sourceModel()->data(source_left);
                    		QVariant right_data = sourceModel()->data(source_right);
                    
                    		switch (left_data.userType())
                    		{
                    		case QMetaType::QDateTime:
                    			return left_data.toDateTime() < right_data.toDateTime();
                    		case QMetaType::Int:
                    			return left_data.toInt() < right_data.toInt();
                    		case QMetaType::QString:
                    			return left_data.toString() < right_data.toString();
                    		default:
                    			return QSortFilterProxyModel::lessThan(source_left, source_right);
                    		}
                    	}
                    };
                    

                    HOWEVER, I click on the header view and nothing happens!! Why?
                    This is with the subclass and without it!! I would expect resorting to occur in the reverse order when clicking the header but nothing changes!

                    1 Reply Last reply
                    0
                    • J Offline
                      J Offline
                      jdent
                      wrote on last edited by jdent
                      #23

                      Sorting is working fine.... its the header view that does not respond to the mouse! What can be going on with the header?

                      JonBJ 1 Reply Last reply
                      0
                      • J jdent

                        Sorting is working fine.... its the header view that does not respond to the mouse! What can be going on with the header?

                        JonBJ Online
                        JonBJ Online
                        JonB
                        wrote on last edited by JonB
                        #24

                        @jdent
                        Did you look at the docs page? Did you follow the Sorting section code?

                        Although it does no harm, with what is in your lessThan() at present I don't think you needed to override it. QSortFilterProxyModel::lessThan() already handles the types you have coded for. But if you were to change the behaviour that's where you would do it.

                        1 Reply Last reply
                        0
                        • J Offline
                          J Offline
                          jdent
                          wrote on last edited by jdent
                          #25

                          Again, sorting is ok - and you are right not needed to subclass it... The problem I am having is that the QHeaderView does not respond to clicking the mouse!! So, I cannot change the column used to sort at runtime!!

                          Yet I have:

                              ui.tableView->setHorizontalHeader(new QHeaderView{ Qt::Horizontal });
                              ui.tableView->setSortingEnabled(true);
                          

                          And yes I read the Sorting section code!

                          JonBJ 1 Reply Last reply
                          0
                          • J jdent

                            Again, sorting is ok - and you are right not needed to subclass it... The problem I am having is that the QHeaderView does not respond to clicking the mouse!! So, I cannot change the column used to sort at runtime!!

                            Yet I have:

                                ui.tableView->setHorizontalHeader(new QHeaderView{ Qt::Horizontal });
                                ui.tableView->setSortingEnabled(true);
                            

                            And yes I read the Sorting section code!

                            JonBJ Online
                            JonBJ Online
                            JonB
                            wrote on last edited by
                            #26

                            @jdent
                            Then the docs say it should be calling sort() in your QSortFilterProxyModel. See if it does, and whether your lessThan() gets called. Is the column's sort indicator responding to your clicks even if sorting is not happening?

                            1 Reply Last reply
                            0
                            • J Offline
                              J Offline
                              jdent
                              wrote on last edited by jdent
                              #27

                              At runtime, sort() and lessThan() get called at the beginning (when below code executes) but not when I click the header... also the column's sort indicator is not responding to my clicks and sorting is not happening when I click the header only after the following code executes

                              When this code executes, sort() is called once and lessThan() is called many times (proportional to number of rows):

                              ui.tableView->setSortingEnabled(true);
                              

                              but not anymore afterwards !

                              Christian EhrlicherC JonBJ 2 Replies Last reply
                              0
                              • J jdent

                                At runtime, sort() and lessThan() get called at the beginning (when below code executes) but not when I click the header... also the column's sort indicator is not responding to my clicks and sorting is not happening when I click the header only after the following code executes

                                When this code executes, sort() is called once and lessThan() is called many times (proportional to number of rows):

                                ui.tableView->setSortingEnabled(true);
                                

                                but not anymore afterwards !

                                Christian EhrlicherC Offline
                                Christian EhrlicherC Offline
                                Christian Ehrlicher
                                Lifetime Qt Champion
                                wrote on last edited by
                                #28

                                @jdent said in How to implement setHeaderData in a subclass of QAbstractTableModel?:

                                but not anymore afterwards !

                                Why should it - once it's sorted why would it need to sort it again?

                                Please provide a minimal, compilable example of your problem.

                                Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                                Visit the Qt Academy at https://academy.qt.io/catalog

                                1 Reply Last reply
                                0
                                • J jdent

                                  At runtime, sort() and lessThan() get called at the beginning (when below code executes) but not when I click the header... also the column's sort indicator is not responding to my clicks and sorting is not happening when I click the header only after the following code executes

                                  When this code executes, sort() is called once and lessThan() is called many times (proportional to number of rows):

                                  ui.tableView->setSortingEnabled(true);
                                  

                                  but not anymore afterwards !

                                  JonBJ Online
                                  JonBJ Online
                                  JonB
                                  wrote on last edited by JonB
                                  #29

                                  @jdent said in How to implement setHeaderData in a subclass of QAbstractTableModel?:

                                  but not anymore afterwards !

                                  Not "anymore afterwards" when you do what?

                                  The behaviour I would expect is:

                                  • The first time you click on a column it should do a sort on that column. You should then see the "sort indicator" on that column's header being shown pointing up or down, to indicate it is sorted on that column in a certain direction.

                                  • If you click on that column again it should reverse sort, and the indicator should reverse its direction. I am not sure whether it actually issues a sort() in this case, since it already has it sorted it could just reverse the order or all the rows showing in the view. Or it may re-sort() in the opposite direction.

                                  • If you click on a different column it should sort() on that new column, and move the sort indicator to show on the new column.

                                  1 Reply Last reply
                                  0
                                  • J Offline
                                    J Offline
                                    jdent
                                    wrote on last edited by
                                    #30

                                    This does not happen:

                                    "The first time you click on a column it should do a sort on that column. You should then see the "sort indicator" on that column's header being shown pointing up or down, to indicate it is sorted on that column in a certain direction.

                                    If you click on that column again it should reverse sort, and the indicator should reverse its direction. I am not sure whether it actually issues a sort() in this case, since it already has it sorted it could just reverse the order or all the rows showing in the view. Or it may re-sort() in the opposite direction.

                                    If you click on a different column it should sort() on that new column, and move the sort indicator to show on the new column."

                                    the header view does not respond to mouse clicks at all!
                                    Could it be that the model is read only?

                                    This is the model:

                                    class VectorModel  : public QAbstractTableModel
                                    {
                                    	Q_OBJECT
                                    
                                    	std::unique_ptr<AbstractCollection> collection;
                                    	std::vector<QVariant> headers;
                                    public:
                                    	VectorModel(std::unique_ptr<AbstractCollection> coll, QObject *parent = nullptr)
                                    		: collection(std::move(coll)), QAbstractTableModel(parent)
                                    	{
                                    		collection->load();
                                    		headers.resize(collection->coll_count());
                                    	}
                                    	~VectorModel() = default;
                                    
                                    	void refresh()
                                    	{
                                    		collection->load();
                                    	}
                                    
                                    	int rowCount(const QModelIndex& parent) const override
                                    	{
                                    		//if(parent.isValid())
                                    		//	return 0;
                                    		return collection->row_count();
                                    	}
                                    
                                    	int columnCount(const QModelIndex& parent) const override
                                    	{
                                    		return collection->coll_count();
                                    	}
                                    
                                    	QVariant data(const QModelIndex& index, int role) const override
                                    	{
                                    		using std::get;
                                    
                                    		if(role != Qt::DisplayRole && role != Qt::EditRole)
                                    		{
                                    			return QVariant();
                                    		}
                                    
                                    		return collection->data(index);
                                    	}
                                    	bool setHeaderData(int section, Qt::Orientation orientation, const QVariant& value, int role) override
                                    	{
                                    		if (orientation == Qt::Horizontal && role == Qt::EditRole)
                                    		{
                                    			headers[section] = value;
                                    			headerDataChanged(orientation, section, section);
                                    			return true;
                                    		}
                                    		return false;
                                    	}
                                    
                                    	QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override
                                    	{
                                    		if (orientation == Qt::Horizontal)
                                    		{
                                    			if (role == Qt::DisplayRole)
                                    				return headers[section];
                                    			return QVariant{};
                                    		}
                                    		return QVariant{};
                                    	}
                                    };
                                    

                                    And this is the preparation code:

                                        VectorModel* model = new VectorModel{ std::unique_ptr<AbstractCollection>(new PersistentCollection{ storage(), select(columns(&Claim::id, &Claim::amount, &Claim::start_date))})};
                                        QSortFilterProxyModel* proxy = new QSortFilterProxyModel{ this };
                                        proxy->setSourceModel(model);
                                        ui.tableView->setHorizontalHeader(new QHeaderView{ Qt::Horizontal });
                                        ui.tableView->setSortingEnabled(true);
                                        ui.tableView->setModel(proxy);
                                        bool ok = proxy->setHeaderData(0, Qt::Horizontal, QObject::tr("ID"));
                                        ok = proxy->setHeaderData(1, Qt::Horizontal, QObject::tr("Amount"));
                                        ok = proxy->setHeaderData(2, Qt::Horizontal, QObject::tr("Start Date"));
                                    

                                    Is that enough code to help me figure out what is hapenning?

                                    1 Reply Last reply
                                    0
                                    • Christian EhrlicherC Offline
                                      Christian EhrlicherC Offline
                                      Christian Ehrlicher
                                      Lifetime Qt Champion
                                      wrote on last edited by
                                      #31

                                      This is not minimal nor compilable - can't test your code until you simplify it.
                                      Also why do you set a new QHeaderView??

                                      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                                      Visit the Qt Academy at https://academy.qt.io/catalog

                                      1 Reply Last reply
                                      1
                                      • J Offline
                                        J Offline
                                        jdent
                                        wrote on last edited by
                                        #32

                                        "Also why do you set a new QHeaderView??" because I wasn't seeing a QHeaderView

                                        1 Reply Last reply
                                        0
                                        • Christian EhrlicherC Offline
                                          Christian EhrlicherC Offline
                                          Christian Ehrlicher
                                          Lifetime Qt Champion
                                          wrote on last edited by Christian Ehrlicher
                                          #33

                                          because I wasn't seeing a QHeaderView

                                          Then you removed it in the design mode as I already told you but we can't tell...

                                          This works fine for me, fix your code until it works or it's compilable for us - don't know what's so hard to create a minimal, compilable example...:

                                          int main(int argc, char* argv[]) {
                                              QApplication app(argc, argv);
                                              auto model = new QStandardItemModel;
                                              for (int i = 0; i < 10; ++i)
                                                  model->appendRow(new QStandardItem(QString::number(i)));
                                              QTableView tv;
                                              tv.setModel(model);
                                              tv.setSortingEnabled(true);
                                              tv.show();
                                              return app.exec();
                                          }
                                          

                                          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                                          Visit the Qt Academy at https://academy.qt.io/catalog

                                          1 Reply Last reply
                                          1

                                          • Login

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