QIdentityProxyModel display empty rows - c++

I've implemented QIdentityProxyModel like this:
class ProxyModel : public QIdentityProxyModel
{
Q_OBJECT
public:
ProxyModel(QObject *parent)
{
entriesPerPage = 3;
page = 1;
}
inline int getEntriesPerPage() const
{ return entriesPerPage; }
inline void setEntriesPerPage(int value)
{ entriesPerPage = value; }
inline qint64 getPage() const
{ return page; }
inline void setPage(const qint64 &value)
{ page = value; }
inline int rowCount(const QModelIndex &parent = QModelIndex()) const override{
Q_UNUSED(parent)
if(!sourceModel())
return 0;
return entriesPerPage * page <= sourceModel()->rowCount()
? entriesPerPage
: sourceModel()->rowCount() - entriesPerPage * (page - 1);
}
inline int columnCount(const QModelIndex &parent = QModelIndex()) const override{
Q_UNUSED(parent);
return 6;
}
QModelIndex ProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
{
if(!sourceModel() && !proxyIndex.isValid())
return QModelIndex();
return sourceIndex.isValid()
? createIndex(sourceIndex.row() % entriesPerPage, sourceIndex.column(), sourceIndex.internalPointer())
: QModelIndex();
}
QModelIndex ProxyModel::mapToSource(const QModelIndex &proxyIndex) const
{
if(!sourceModel() && !proxyIndex.isValid())
return QModelIndex();
QModelIndex remapped = createIndex(proxyIndex.row() ,
proxyIndex.column(),
proxyIndex.internalPointer());
return QIdentityProxyModel::mapToSource(remapped);
}
private:
int entriesPerPage;
qint64 page;
};
When I insert a row in the sourceModel() with index more then entriesPerPage, view displays empty rows, so that row number is more then entriesPerPage, although rowCount() return number equal to entriesPerPage.
How can I get rid of empty rows?

First. It is a bad practice to override rowCount/mapFromSource for QIdentityProxyModel. I propose you to use QAbstractProxyModel to have more clear code.
Main. Your problem is in getEntriesPerPage/setPage methods. You need to call beginResetModel/endResetModel after updating such data.
inline void setPage(const qint64 &value)
{
beginResetModel();
page = value;
endResetModel();
}
Offtopic: it is pretty cool, that you have to code with Qt in BSUIR. Who is your teacher?

Related

QAbstractTableModel editing without clearing previous data in cell

I have created a model based off of QAbstractTableModel that allows the user to edit data in that model. The model is displayed in a QTableView in a QMainWindow. So far in my model I am able to make the cells editable, and save whatever the user types in after editing is finished.
The issue is that when the user begins editing, it 'clears' the previous contents of that cell. So if for example I only wanted to change the spelling of a string in a cell, I have to re-type the entire value. I would like when editing that the editor would start with the data that is already in the model, rather than empty.
How can I do that?
Example of the issue:
Before I begin editing a cell:
As soon as I begin editing, the cell is empty. I would like it to star with the previous value already in the model:
Here is a minimal example of my model. My actual model is much larger and uses a struct instead of just a 2D array of QVariants to store the data.
Header:
const int COLS= 2;
const int ROWS= 6;
class EditableTableModel : public QAbstractTableModel
{
Q_OBJECT
private:
QVariant tableData[ROWS][COLS];
public:
EditableTableModel(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
signals:
void editCompleted(QString);
};
Implementation:
EditableTableModel::EditableTableModel(QObject *parent)
: QAbstractTableModel(parent)
{
}
int EditableTableModel::rowCount(const QModelIndex & /*parent*/) const
{
return ROWS;
}
int EditableTableModel::columnCount(const QModelIndex & /*parent*/) const
{
return COLS;
}
QVariant EditableTableModel::data(const QModelIndex &index, int role) const
{
int row = index.row();
int col = index.column();
switch (role) {
case Qt::DisplayRole:
return tableData[row][col];
}
return QVariant();
}
bool EditableTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (role == Qt::EditRole) {
if (!checkIndex(index))
return false;
tableData[index.row()][index.column()] = value;
return true;
}
return false;
}
QVariant EditableTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
switch (section) {
case 0:
return QString("First Name");
case 1:
return QString("Last Name");
}
}
return QVariant();
}
Qt::ItemFlags EditableTableModel::flags(const QModelIndex &index) const
{
return Qt::ItemIsEditable | QAbstractTableModel::flags(index);
}
Data should be returned for Qt::EditRole in the data() method. The following should work:
QVariant EditableTableModel::data(const QModelIndex &index, int role) const
{
int row = index.row();
int col = index.column();
switch (role) {
case Qt::DisplayRole:
case Qt::EditRole: // <-- add this line
return tableData[row][col];
}
return QVariant();
}
Note that the above switch-case uses something known as fallthrough, so that the switch-case will match for both Qt::DisplayRole and Qt::EditRole.

Delete rows from QTreeView with custom model

I'm new to Qt. I'm trying to create custom model for tree view with support of rows deletion. I've implemented it according to examples http://doc.qt.io/qt-5/qtwidgets-itemviews-simpletreemodel-example.html and http://doc.qt.io/qt-5/qtwidgets-itemviews-editabletreemodel-example.html. Also, I've made context menu with option to remove row after pressing with right mouse button on the row.
Now, I have hardly reproducible error (there is no exact pattern, but it is easy to obtain). When I start to delete rows from model randomly, sometimes my program crashes, sometimes I receive following messages to output:
QAbstractItemModel::endRemoveRows: Invalid index ( 1 , 0 ) in model QAbstractItemModel(0x55555580db10)
When program crashes, I almost always in fuction
QModelIndex TreeModel::parent(const QModelIndex &child) const
which is inherited from
QModelIndex QAbstractItemModel::parent(const QModelIndex &child) const
Stack of function calls shows that this function is called from
void QAbstractItemModel::beginRemoveRows(const QModelIndex &parent, int first, int last)
which I call in overrided
bool TreeModel::removeRows(int row, int count, const QModelIndex &parent)
When I compared adresses of child.indernalPointer() (where I store pointer to internal tree Nodes, representing my model) with already deleted Nodes, It became clear, that by some reason beginRemoveRows() using already invalid indices.
There is question with very similar error: QModelIndex becomes invalid when removing rows, howerer I can't understand why and where I use invalid indices.
So, I place the minimal example with this behavior (I've put a lot of effort to minimize it to this size and make the code clear, sorry for it is nevertheless long).
tree.pro
QT += core gui widgets
TARGET = tree
TEMPLATE = app
SOURCES += main.cpp widget.cpp treemodel.cpp
HEADERS += widget.h treemodel.h
treemodel.h
#ifndef TREEMODEL_H
#define TREEMODEL_H
#include <QAbstractItemModel>
class TreeModel : public QAbstractItemModel
{
public:
TreeModel();
~TreeModel();
QModelIndex index(int row, int column, const QModelIndex &parent) const override;
QModelIndex parent(const QModelIndex &child) const override;
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
bool removeRows(int row, int count, const QModelIndex &parent) override;
private:
class Impl;
Impl* impl = nullptr;
};
#endif // TREEMODEL_H
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
private slots:
void projectTreeMenuRequested(const QPoint& point);
void eraseItem();
private:
class Impl;
Impl* impl;
};
#endif // WIDGET_H
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
treemodel.cpp
#include "treemodel.h"
#include <cassert>
#include <string>
#include <list>
#include <memory>
namespace {
struct Node {
Node(const std::string& name)
: text(name)
{
}
~Node() {
}
Node& append(const std::string& name) {
child.emplace_back(name);
Node& n = child.back();
n.parent = this;
return n;
}
size_t getChildNum() const {
return child.size();
}
bool hasParent() const {
return parent != nullptr;
}
Node& getParent() {
assert(hasParent());
return *parent;
}
size_t getIndexInParent() const {
if (parent) {
size_t index = 0;
Childs::iterator it = parent->child.begin();
while (it != parent->child.end()) {
if (&*it == this) {
return index;
}
++it;
++index;
}
}
return 0;
}
Node& getChild(size_t i) {
assert(i < child.size());
Childs::iterator it = child.begin();
std::advance(it, i);
return *it;
}
void setText(std::string name) {
this->text = std::move(name);
}
std::string getText() const {
return text;
}
void remove() {
assert(hasParent());
Node& p = getParent();
for (Childs::iterator it = p.child.begin(); it != p.child.end(); ++it) {
if (&*it == this) {
p.child.erase(it);
return;
}
}
assert(0); // Child for remove not found
}
bool removeChilds(size_t start, size_t end) {
if (start < end && end <= child.size()) {
Childs::iterator it1 = child.begin();
assert(it1 != child.end());
std::advance(it1, start);
assert(it1 != child.end());
Childs::iterator it2 = it1;
std::advance(it2, end - start);
child.erase(it1, it2);
return true;
} else {
return false;
}
}
static const int Columns = 1;
private:
using Childs = std::list<Node>;
std::string text;
Node* parent = nullptr;
Childs child;
};
} // namespace
struct TreeModel::Impl {
Impl()
: root("Root")
{
fill(root);
}
void fill(Node& from, std::string str = "", int depth = 0) {
if (depth == 10) return;
for (int j = 0; j != 5; ++j) {
std::string name = str + std::to_string(j);
fill(from.append(name), name, depth+1);
}
}
Node root;
};
TreeModel::TreeModel()
: impl(new Impl)
{
}
TreeModel::~TreeModel()
{
delete impl;
}
QModelIndex
TreeModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent)) {
return QModelIndex();
} else {
Node* node = nullptr;
if (!parent.isValid()) {
node = &impl->root;
} else {
node = static_cast<Node*>(parent.internalPointer());
}
return createIndex(row, column, &node->getChild(row));
}
}
QModelIndex TreeModel::parent(const QModelIndex &child) const
{
if (!child.isValid()) {
return QModelIndex();
}
Node* node = static_cast<Node*>(child.internalPointer());
if (!node->hasParent()) {
return QModelIndex();
}
return createIndex(node->getIndexInParent(),
child.column(),
&node->getParent());
}
int TreeModel::rowCount(const QModelIndex &parent) const
{
Node* p = nullptr;
if (parent.isValid()) {
p = static_cast<Node*>(parent.internalPointer());
} else {
p = &impl->root;
}
return p->getChildNum();
}
int TreeModel::columnCount(const QModelIndex &) const
{
return Node::Columns;
}
QVariant TreeModel::data(const QModelIndex &index, int role) const
{
if (index.isValid()) {
Node* node = static_cast<Node*>(index.internalPointer());
switch (role) {
case Qt::DisplayRole:
case Qt::EditRole:
return QString::fromUtf8(node->getText().data(),
node->getText().size());
break;
}
}
return QVariant();
}
bool TreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (role != Qt::EditRole)
return false;
Node* node = nullptr;
if (index.isValid()) {
node = static_cast<Node*>(index.internalPointer());
} else {
node = &impl->root;
}
node->setText(value.toString().toStdString());
emit dataChanged(index, index);
return true;
}
Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return 0;
return Qt::ItemIsEditable | QAbstractItemModel::flags(index);
}
bool TreeModel::removeRows(int row, int count, const QModelIndex &parent)
{
Node* node = nullptr;
QModelIndex correctParent;
if (parent.isValid()) {
node = static_cast<Node*>(parent.internalPointer());
correctParent = parent;
} else {
node = &impl->root;
correctParent = QModelIndex();
}
beginRemoveRows(correctParent, row, row + count - 1); // [row, row + count - 1]
bool success = node->removeChilds(row, row + count); // [row, row + count)
endRemoveRows();
return success;
}
widget.cpp
#include "widget.h"
#include <QVBoxLayout>
#include <QTreeView>
#include <QPoint>
#include <QMenu>
#include "treemodel.h"
struct Widget::Impl {
QVBoxLayout* layout;
QTreeView* treeView;
TreeModel* treeModel;
};
Widget::Widget(QWidget *parent)
: QWidget(parent)
, impl(new Impl)
{
impl->layout = new QVBoxLayout(this);
impl->treeView = new QTreeView;
impl->treeModel = new TreeModel;
impl->layout->addWidget(impl->treeView);
impl->treeView->setModel(impl->treeModel);
impl->treeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
impl->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
connect(impl->treeView, SIGNAL(customContextMenuRequested(const QPoint&)),
this, SLOT(projectTreeMenuRequested(const QPoint&)));
}
Widget::~Widget()
{
delete impl->treeModel;
delete impl;
}
void Widget::projectTreeMenuRequested(const QPoint &point)
{
QPoint globalPos = impl->treeView->mapToGlobal(point);
QMenu myMenu;
myMenu.addAction("Erase", this, SLOT(eraseItem()));
myMenu.exec(globalPos);
}
void Widget::eraseItem()
{
for (QModelIndex index : impl->treeView->selectionModel()->selectedIndexes()) {
impl->treeModel->removeRow(index.row(), index.parent());
}
}
EDIT
I think about two ways to solve the problem. The first is direct approach when somebody point me to the incorrect use of Qt API. The second approach is if somebody write independent implementation of this functionality (tree with infinity nesting and ability to remove) and I will try to figure out what I am doing wrong compared to another implementation.
EDIT 2
After thorough analysis of QStandardItemModel I come to conclusion, that it is important to store in internalPointer of indices parent of actual Node, but in my example I use internalPointer to store Node itself. So it seems correct for Qt internal implementation to call parent() on indices of already deleted elements, assuming that the information in indernalPointer is not related to element and remains correct. (Please, correct me if I am wrong.)
Confirmed, that after rewriting implementation to store pointers to parent node in internal nodes, this bug was eliminated. Correction of other bugs is provided in accepted answer.
You are using for(index: selectedIndexes()) in Widget::eraseItem(), but after removing something, indexes changes, so your index in for becomes invalid. Also, it is a bad practice, to change container while you iterating through it.
In removeChilds() try changing the conditional from end <= child.size() to end < child.size()

qml listview does not update information after datachanged() signal

I have a model written based on this example. This model is connected to a listview to display dynamic data. I have made sure the model's datachanged() signal is emitted whenever the source data is being changed. The list view does not update on the datachanged() signal. Here is my code:
DataModel.h:
class DataList {
public:
DataList(const QString &name, const QString &value, const QString &category);
QString name() const;
QString value() const;
QString category() const;
private:
QString m_name;
QString m_value;
QString m_category;
};
class DataModel : public QAbstractListModel {
Q_OBJECT
public:
enum AVRoles {
NameRole = Qt::UserRole + 1,
ValueRole,
CategoryRole
};
DataModel(QAbstractItemModel *parent = 0);
virtual ~DataModel() {}
void addData(const DataList &datalist);
int rowCount(const QModelIndex & parent = QModelIndex()) const;
QVariant data(const QModelIndex & index, int role=Qt::DisplayRole) const;
protected:
QHash<int, QByteArray> roleNames() const;
private:
QList<DataList> m_datalist;
public slots:
void onInitialPolygonAreaChanged(qreal);
};
DataModel.cpp:
DataList::DataList(const QString &name, const QString &value, const QString &category) {
m_name = name;
m_value = value;
m_category = category;
}
QString DataList::name() const {
return m_name;
}
QString DataList::value() const {
return m_value;
}
QString DataList::category() const {
return m_category;
}
DataModel::DataModel(QAbstractItemModel *parent) :
QAbstractListModel(parent) {
}
void DataModel::addData(const DataList &datalist){
beginInsertRows(QModelIndex(), rowCount(), rowCount());
m_datalist << datalist;
endInsertRows();
}
int DataModel::rowCount(const QModelIndex &parent) const{
Q_UNUSED(parent);
return m_datalist.count();
}
QVariant DataModel::data(const QModelIndex &index, int role) const {
if (index.row() < 0 || index.row() >= m_datalist.count())
return QVariant();
const DataList &datalist = m_datalist[index.row()];
if(role ==NameRole )
return datalist.name();
else if(role == ValueRole)
return datalist.value();
else if(role == CategoryRole)
return datalist.category();
return QVariant();
}
QHash<int, QByteArray> DataModel::roleNames() const {
QHash<int, QByteArray> roles;
roles[NameRole] = "name";
roles[ValueRole] = "value";
roles[CategoryRole] = "category";
return roles;
}
void DataModel::onInitialPolygonAreaChanged(qreal ) {
//0 is the index of iPA
qDebug() << "IPA from model" ;
QVector<int> roleVector;
roleVector.append(ValueRole);
roleVector.append(NameRole);
roleVector.append(CategoryRole);
roleVector.append(Qt::DisplayRole);
emit dataChanged(index(0),index(0),roleVector);
}
Mainwindow.cpp:
model.addData(DataList(QString("Initial Polygon Area"),QString::number(av1.initialPolygonArea()) + " sq.km",QString("Area")));
View->rootContext()->setContextProperty("AVModel",&model);
connect(&av1,SIGNAL(initialPolygonAreaChanged(qreal)),&model,SLOT(onInitialPolygonAreaChanged(qreal)));
view.qml:
ListView {
id: view
anchors.top: parent.top
anchors.bottom: parent.bottom
width: parent.width
model: AVModel
delegate: Text { text: name + " " + value; font.pixelSize: 18 ; color: "white"}
}

Qt: undefined reference on constructor of customer class

I'm using a custom class, GpibDevicesModel, inheriting from QAbstractTableModel, and the compiler says that there is an undefined reference on the constructor. But I don't understand why.
Here is the code:
MainWindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
//...
private:
GpibDevicesModel *m_gpibDevicesModel;
};
MainWindow.cpp
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
//...
//undefined reference is located here
m_gpibDevicesModel = new GpibDevicesModel;
//...
}
GpibDevicesModel.h
#ifndef GPIBDEVICESMODEL_H
#define GPIBDEVICESMODEL_H
#include <QAbstractTableModel>
class MeasureDevice;
class GpibDevicesModel : public QAbstractTableModel
{
Q_OBJECT
public:
enum Columns{
NameCol = 0,
AddressCol,
IdCol,
TypeCol,
ConnectedCol,
EndCol //Should always be at end
};
//constructor and destructor
explicit GpibDevicesModel(QObject *parent = 0);
~GpibDevicesModel();
protected:
//Reimplemented from QAbstractTableModel
QVariant data(const QModelIndex &index, int role) const;
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
//Data list getter and setter
QList<MeasureDevice *> measureDevices() const;
void setMeasureDevices(const QList<MeasureDevice *> &measureDevices);
private:
QList<MeasureDevice *> m_measureDevices;
};
#endif // GPIBDEVICESMODEL_H
GpibDevicesModel.cpp
#include "gpibdevicesmodel.h"
#include "measuredevice.h"
#include <QIcon>
GpibDevicesModel::GpibDevicesModel(QObject *parent)
: QAbstractTableModel(parent)
{}
GpibDevicesModel::~GpibDevicesModel()
{}
QVariant GpibDevicesModel::data(const QModelIndex &index, int role) const
{
if(!index.isValid() || index.row() >= m_measureDevices.size())
return QVariant();
switch(role){
//This is roles for ComboBox
case Qt::DisplayRole:
switch(index.column()){
case NameCol: return m_measureDevices.at(index.row())->displayName();
case AddressCol:return m_measureDevices.at(index.row())->gpibName();
case IdCol: return m_measureDevices.at(index.row())->property("internal_id").toString();
case TypeCol: return m_measureDevices.at(index.row())->typeString();
}
break;
case Qt::DecorationRole:
switch(index.column()){
case ConnectedRole: {
MeasureDevice *md = m_measureDevices.at(index.row());
if(md->isConnected()) return QIcon(":/Icons/green_led.png");
else return QIcon(":/Icons/red_led.png");
}
}
break;
}
return QVariant();
}
int GpibDevicesModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return m_measureDevices.size();
}
int GpibDevicesModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return EndCol;
}
QVariant GpibDevicesModel::headerData(int section, Qt::Orientation orientation, int role) const
{
static QStringList headers = QStringList() << tr("Name") << tr("Address") << tr("Id")
<< tr("Type") << tr("Connected") ;
if(role == Qt::DisplayRole && orientation == Qt::Vertical)
return QVariant(); //return section; //uncomment here to displayed row number
if(section >= headers.size())
return QVariant();
switch(role){
case Qt::DisplayRole: return headers.at(section);
}
return QVariant();
}
QList<MeasureDevice *> GpibDevicesModel::measureDevices() const
{
return m_measureDevices;
}
void GpibDevicesModel::setMeasureDevices(const QList<MeasureDevice *> &measureDevices)
{
beginResetModel();
m_measureDevices = measureDevices;
endResetModel();
}
And here is the error message from the compiler
mainwindow.cpp:1430: undefined reference to GpibDevicesModel::GpibDevicesModel(QObject*)'
I think that will be a stupid thing, as always... But I cannot figure out this error. I'm using another custom model in the same way and I don't have any problem.
As I guessed, it was stupid...
I resolved the problem by removing manually the build folder and the Makefiles (makefile, makefile.debug and makefile.release), then I run again qmake -> build and it was ok. So this was not a problem from code, maybe the makefiles was in read-only for an unknown reason.
Thanks for your help and your time Frogatto and Frank Osterfeld.

QTreeView QSortFilterProxyModel trigger filter

Here is my program:
#include <QStandardItemModel>
#include <QSortFilterProxyModel>
#include <QTreeView>
class MySortFilterProxyModel : public QSortFilterProxyModel
{
public:
MySortFilterProxyModel();
void updateFilter(int filterType);
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
bool lessThan(const QModelIndex &left,const QModelIndex &right) const;
private:
int _filterType;
};
MySortFilterProxyModel::MySortFilterProxyModel()
: _filterType(0)
{
}
bool MySortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
QStandardItemModel* source = static_cast<QStandardItemModel*>(sourceModel());
QModelIndex modelIndex = source->index(sourceRow, 0, sourceParent);
QStandardItem* item = source->itemFromIndex(modelIndex);
QVariant v = item->data(Qt::UserRole);
int itemType = v.toInt();
if(itemType == _filterType)
return true;
return false;
}
bool MySortFilterProxyModel::lessThan(const QModelIndex &left,const QModelIndex &right) const
{
QVariant leftData = sourceModel()->data(left);
QVariant rightData = sourceModel()->data(right);
if(leftData.type() == QVariant::String && rightData.type() == QVariant::String)
{
QString leftString = leftData.toString();
QString rightString = rightData.toString();
return QString::localeAwareCompare(leftString, rightString) < 0;
}
return false;
}
void MySortFilterProxyModel::updateFilter(int filterType)
{
_filterType = filterType;
// how can i trigger filteracceptRows here ??
}
int main(int argc, char** argv)
{
QApplication qtApp(argc, argv);
MySortFilterProxyModel mySortFilterProxyModel;
QStandardItemModel standardModel;
QTreeView treeView;
mySortFilterProxyModel.setSourceModel(&standardModel);
treeView.setModel(&standardModel);
treeView.setSortingEnabled(true);
treeView.show();
return qtApp.exec();
}
Everytime i AppendRow to standardModel sort and filter works.
How can i trigger filtering without appending or removing something to standardModel?
I want to filter rows on QTreeView through right click but i couldn't find a way to triggger filterAcceptRows on my void MySortFilterProxyModel::updateFilter(int filterType) function.
Having multiple instances of MySortFilterProxyModel class for every possible filterType value and switching them according to filterType may work but is there a better solution?
calling invalidate() on updateFilter worked for me.
void MySortFilterProxyModel::updateFilter(int filterType)
{
_filterType = filterType;
invalidate();
}