Dan Nissenbaum
Dan Nissenbaum

Reputation: 13908

Cannot derive from `QSortFilterProxyModel`

I am trying to use a custom QSortFilterProxyModel.

Here is my header:

#include <QSortFilterProxyModel>

class QSortFilterProxyModel_NumbersLast : public QSortFilterProxyModel
{

    Q_OBJECT

    public:

        QSortFilterProxyModel_NumbersLast(QObject * parent = nullptr);

        bool lessThan(const QModelIndex &left, const QModelIndex &right) const;

};

Here is the constructor from the source file:

QSortFilterProxyModel_NumbersLast::QSortFilterProxyModel_NumbersLast(QObject * parent)
    : QSortFilterProxyModel(parent)
{
}

(Also, I have properly - I think - called Q_DECLARE_METATYPE(QSortFilterProxyModel_NumbersLast) and qRegisterMetaType<QSortFilterProxyModel_NumbersLast>("QSortFilterProxyModel_NumbersLast"); .)

Unfortunately, I receive the following error from the compiler:

error C2248: 'QSortFilterProxyModel::QSortFilterProxyModel' : cannot access private member declared in class 'QSortFilterProxyModel'

... I do notice that the constructor for the base class, QSortFilterProxyModel::QSortFilterProxyModel, is declared public:

// (From *qsortfilterproxymodel.h*, in the Qt core)
public:
    explicit QSortFilterProxyModel(QObject *parent = 0);

My question: Why am I receiving the error 'QSortFilterProxyModel::QSortFilterProxyModel' : cannot access private member? What can I do to fix this?


Note:

From other questions, such as this, this, and this, I see that I might by copying somewhere - which is not allowed for QObjects.

However, the only use of my QSortFilterProxyModel_NumbersLast is the following:

QStandardItemModel * model = new QStandardItemModel(ui->listView_dmu_members);
QSortFilterProxyModel_NumbersLast *proxyModel = new QSortFilterProxyModel_NumbersLast(ui->listView_dmu_members);
proxyModel->setSourceModel(model);
ui->listView_dmu_members->setModel(model);

... which, I'd think, doesn't trigger a copy.


Note 2:

Per @KubaOber's comments:

I have removed the Q_DECLARE_METATYPE(QSortFilterProxyModel_NumbersLast) and qRegisterMetaType<QSortFilterProxyModel_NumbersLast>("QSortFilterProxyModel_NumbersLast"); registration. The error I now receive is:

Type is not registered, please use the Q_DECLARE_METATYPE macro to make it known to Qt's meta-object system

I do not believe I am copying the QSortFilterProxyModel_NumbersLast instance. Therefore, I do not understand why this error would be triggered.

(Note that initially, I had not registered the QSortFilterProxyModel_NumbersLast class. It was only due to the above error that I registered the class. I am clear, however, in retrospect, that a QObject-derived class cannot be registered, because it cannot be copied.)

Upvotes: 1

Views: 604

Answers (1)

Q_DECLARE_METATYPE requires access to the copy constructor, and that one is deleted (C++11) or inaccessible (C++98) in all QObject-deriving classes. That's the constructor that the compiler complains about. The fix is not to declare the proxy filter model metatype.

The below works for me under both Qt 4.5.8 and 5.2.1, across major desktop platforms.

#include <QApplication>
#include <QSortFilterProxyModel>
#include <QListView>
#include <QStandardItemModel>

class QSortFilterProxyModel_NumbersLast : public QSortFilterProxyModel
{
   Q_OBJECT
public:
   QSortFilterProxyModel_NumbersLast(QObject * parent = nullptr) :
      QSortFilterProxyModel(parent) {}
   bool lessThan(const QModelIndex &, const QModelIndex &) const {
      return false;
   }
};

int main(int argc, char *argv[])
{
   QApplication app(argc, argv);
   QStandardItemModel * model = new QStandardItemModel(&app);
   QSortFilterProxyModel_NumbersLast *proxyModel = new QSortFilterProxyModel_NumbersLast(&app);
   proxyModel->setSourceModel(model);
   QListView view;
   view.setModel(model);
   view.show();
   model->appendRow(new QStandardItem("Foo"));
   model->appendRow(new QStandardItem("Bar"));
   model->appendRow(new QStandardItem("Baz"));
   return app.exec();
}

#include "main.moc"

In Qt 5, the error message you see comes from the qMetaTypeId method. It is a static assert, so presumably you're seeing a compile time error. This method is called from qRegisterMetaType and from a few other places, mostly to do with templated connection methods in QObject, and with QVariant.

Upvotes: 1

Related Questions