how to updating a view's proxy model when the source model changes.



  • CustomListModel.h File

    class CustomListModel : public QStandardItemModel
    {
    public:
       CustomListModel(QObject* parent = 0);
       CustomListModel(const int row, const int coloumn, QObject *parent = 0);
       Qt::ItemFlags flags(const QModelIndex& index) const;
       QVariant data(const QModelIndex &index, int role) const;
       bool setData(const QModelIndex &index, const QVariant &value, int role);
    private:
       QSet<QPersistentModelIndex> checkedItems;
    };
    

    CustomListModel.cpp File

    CustomListModel::CustomListModel(QObject *parent) :
    	QStandardItemModel(parent) {
    }
    
    CustomListModel::CustomListModel(const int row,const int coloumn, QObject *parent) :
    	QStandardItemModel(row,coloumn) {
    }
    
    Qt::ItemFlags CustomListModel::flags(const QModelIndex & index) const {
    	Qt::ItemFlags defaultFlags = QStandardItemModel::flags(index);
    	if (index.isValid()) {
    		
    		return defaultFlags | Qt::ItemIsUserCheckable;
    	}
    	return defaultFlags;
    }
    
    
    QVariant CustomListModel::data(const QModelIndex &index,
    	int role) const {
    	if (!index.isValid())
    		return QVariant();
    
    	if (role == Qt::CheckStateRole)
    	{
    		return (checkedItems.contains(index) ? Qt::Checked : Qt::Unchecked);
    	}
    
    	return (QStandardItemModel::data(index, role));
    }
    
    bool CustomListModel::setData(const QModelIndex &index,
    	const QVariant &value, int role) {
    
    	if (!index.isValid())	
    		return false;
    
    	if ((true)&&(role == Qt::CheckStateRole)) {
    		if (value == Qt::Checked) {
    			checkedItems.insert(index);
    		}
    		else {
    			checkedItems.remove(index);
    		}
    		emit dataChanged(index, index);
    	}
    
    	else {
    		QStandardItemModel::setData(index, value, role);
    	}
    	return true;
    }
    
    
    class HardwareProxyModel : public  QSortFilterProxyModel {
    	bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const {
    		QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
    		
    		if (!index.isValid()) {
    			return false;
    		}
    
    		bool supportAc = index.data(Qt::UserRole + 1).toBool();
    
    		bool ret = false;
    
    		if ((!showOnlyAc) || (showOnlyAc && supportAc)) {
    			ret = true;
    		}
    
    		return ret;
    	}
    
    public:
    	void ShowOnlyAcHardware() {
    		 showOnlyAc = true;
    		 invalidateFilter();
    	}
    	void ShowAllHardware() {
    		showOnlyAc = false;
    		invalidateFilter();
    	}
    
    private:
    	bool showOnlyAc = false;
    };
    

    mainUI.cpp file

    auto hwList = new QListView;
    auto hwListProxyModel = new HardwareProxyModel;
    auto dummy = new CustomListModel(0, 0);
    hwListProxyModel->setSourceModel(dummy);
    hwList->setModel(hwListProxyModel);
    
    //add item into model 
    for (auto it = newLines.begin(); it != newLines.end(); ++it) {
          auto count = model->rowCount();
          model->insertRow(count);
          auto index = model->index(count, 0);
          model->setData(index, it->name, Qt::DisplayRole);
          model->setData(index, it->channelAmount, Qt::UserRole); 
          model->setData(index, Qt::Unchecked, Qt::CheckStateRole);
    }
    

    I like to change the value of check box for item. So that, I can change value with help of
    hwListProxyModel->setData(hwList->currentIndex(), Qt::Checked, Qt::CheckStateRole);

    but I would like to update checkbox with help of sourcemodel.
    (source model name = dummy). so that i am trying with help of below line.
    hwListProxyModel->sourceModel()->setData(hwList->currentIndex(), Qt::Checked, Qt::CheckStateRole);

    but it is not updating view.

    Here I found Some Documentation
    similar question. http://www.qtcentre.org/threads/55962-Updating-a-view-s-proxy-model-when-the-source-model-changes

    http://doc.qt.io/archives/qt-4.8/qsortfilterproxymodel.html#dynamicSortFilter-prop

    How can I update the view if i will change the source model Data? I make many change but something I miss. Please any one give me direction. What change should I make?



  • @mrjj any suggestion?


  • Qt Champions 2019

    @Yash001 said in how to updating a view's proxy model when the source model changes.:

    hwList->currentIndex()

    You're using the wrong model index . See mapToSource/mapFromSource: http://doc.qt.io/qt-5/qsortfilterproxymodel.html#mapToSource
    You will also get a warning at runtime about the wrong model index usage.



  • Thank you @Christian-Ehrlicher for your answer. I got check mark after getting guidance from you. Thank you so much.



  • @Christian-Ehrlicher is it any way to determine, whether check box check mark is done by User Mouse Click or with help of coding like sourceModel->setData(hwListProxyModel->mapToSource(hwList->currentIndex()), Qt::Checked, Qt::CheckStateRole);?

    I am trying to add another argument or Function before calling setData Function.

    I wrote this function for differentiate Click

    bool CustomListModel::setDataAndFilterCheckMarkClick(const QModelIndex &index, const QVariant &value, int role, bool ChannelSelected) {
    	if (!index.isValid())
    		return false;
    
    	if ((ChannelSelected) && (role == Qt::CheckStateRole)) {
    		if (value == Qt::Checked) {
    			qDebug() << "click get from view ";
    		}
    		else {
    			qDebug() << "click does not get from view";
    		}
    	}
    	return this->setData(index, value, role);
    }
    

    checkbox is check whenever I wanted to do using coding. I used code line like
    sourceModel->setDataAndFilterCheckMarkClick(hwListProxyModel->mapToSource(hwList->currentIndex()), Qt::Checked, Qt::CheckStateRole,true);

    but if the user Click from the view then it won't selected.

    I saw in Qcheckbox. which is give me position of the mouse pos.
    bool QAbstractButton::hitButton(const QPoint & pos) const, but i don't know. how can we access the checkbox pointer from the model?

    In general I would like to differentiate Check box Check from user and Check box check by Coding. what is good way to do this?



  • Your QStandardItemModel is useless. QStandardItemModel can already manage Qt::CheckStateRole

    In general I would like to differentiate Check box Check from user and Check box check by Coding. what is good way to do this?

    While this is usually a sign of something in your design going wrong, you can subclass the delegate and reimplement editorEvent. You can start by looking at the source: https://code.woboq.org/qt5/qtbase/src/widgets/itemviews/qstyleditemdelegate.cpp.html#_ZN19QStyledItemDelegate11editorEventEP6QEventP18QAbstractItemModelRK20QStyleOptionViewItemRK11QModelIndex



  • @VRonin Thank you for giving me direction. let me trying with QStyledItemDelegate.



  • @VRonin How can i access the checkbox Pointer, So i can identify the pointer of mouse is inside the Checkbox or not?

    If I will get access for class QStyledItemDelegatePrivate. then I can get access for the QCheckbox.
    const QWidget *widget = QStyledItemDelegatePrivate::widget(option);



  • if you look inside QStyledItemDelegatePrivate::widget(option); you'll see it is equivalent to option.widget;



  • @VRonin Thank you. Yesterday, I tried same things. But it was not working than later on I found, I forget to add file name in SOURCE , HEADER. Now it is work as expectation.