未知的方法返回类型,即使已声明

时间:2018-06-28 18:26:37

标签: c++ qt qml

Qt5.11 / QML。我正在尝试创建两级QAbstractListModel以在QML中进行查看。认为是文件夹(第一级)和文件(第二级)模型。

这是我的代码:

model.h

class File
{
public:
    File(const QString name) { _name = name; }

    QString name() const { return _name; }
    void setName(const QString &name) { _name = name; }

    QPixmap thumbnail() const { return _thumbnail; }
    void setThumbnail(QPixmap thumbnail) { _thumbnail = thumbnail; }

private:
    QString _name;
    QPixmap _thumbnail;
};

class FilesModel : public QAbstractListModel
{
    Q_OBJECT

public:
    enum FileRoles
    {
        NameRole = Qt::UserRole + 1,
        ThumbnailRole
    };

    FilesModel(QObject *parent = nullptr);
    void addFile(const File &file);
    int rowCount(const QModelIndex &parent = QModelIndex()) const;
    QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const;

protected:
    QHash<int, QByteArray> roleNames() const;

private:
    QString _name;
    QList<File> _listFiles;

};

class Folder
{
public:
    Folder(const QString name);

    QString name() const { return _name; }
    void setName(const QString &name) { _name = name; }

    FilesModel *model() { return _model; }

private:
   QString _name;
   FilesModel *_model;
};

class FolderModel : public QAbstractListModel
{
    Q_OBJECT

public:
    enum FolderRoles
    {
        NameRole = Qt::UserRole + 1,
        ModelRole
    };

    FolderModel(QObject *parent = nullptr);
    void addFolder(const Folder &folder);
    void clear();
    int rowCount(const QModelIndex &parent = QModelIndex()) const;
    QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const;
    Folder *findFolder(QString name);

    FilesModel *filesModel(QString name);

protected:
    QHash<int, QByteArray> roleNames() const;
    bool removeRows(int row, int count, const QModelIndex &parent);

private:
    QString _name;
    QList<Folder> _list;

};

Q_DECLARE_METATYPE(FilesModel*)

model.cpp

FilesModel::FilesModel(QObject *parent) : QAbstractListModel(parent) { }

void FilesModel::addFile(const File &file)
{
    beginInsertRows(QModelIndex(), rowCount(), rowCount());
    _listFiles << file;
    endInsertRows();
}

int FilesModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return _listFiles.count();
}

QVariant FilesModel::data(const QModelIndex &index, int role) const
{
    if (index.row() < 0 || index.row() >= _listFiles.count()) return QVariant();

    const File &item = _listFiles[index.row()];
    switch (role) {
    case NameRole: return item.name(); break;
    case ThumbnailRole: return item.thumbnail(); break;
    default: return QVariant();
    }
}

QHash<int, QByteArray> FilesModel::roleNames() const
{
    QHash<int, QByteArray> roles;
    roles[NameRole] = "name";
    roles[ThumbnailRole] = "thumbnail";
    return roles;
}

FolderModel::FolderModel(QObject *parent) : QAbstractListModel(parent) { }

void FolderModel::addFolder(const Folder &folder)
{
    beginInsertRows(QModelIndex(), rowCount(), rowCount());
    _list << folder;
    endInsertRows();
}

bool FolderModel::removeRows(int row, int count, const QModelIndex &parent)
{
    if (count == 0) return false;
    beginRemoveRows(parent, row, row + count - 1);
    for (int i = 0; i < count; i++) _list.removeAt(row);
    endRemoveRows();
    emit dataChanged(this->index(row, 0), this->index(row, 0));
    return true;
}

void FolderModel::clear()
{
    removeRows(0, rowCount(), QModelIndex());
}

int FolderModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return _list.count();
}

QVariant FolderModel::data(const QModelIndex &index, int role) const
{
    if (index.row() < 0 || index.row() >= _list.count()) return QVariant();

    const Folder &item = _list[index.row()];
    switch (role) {
    case NameRole: return item.name(); break;
    default: return QVariant();
    }
}

Folder *FolderModel::findFolder(QString name)
{
    for (int i = 0; i < _list.size(); i++)
    {
        if (_list[i].name() == name) return &_list[i];
    }
    return NULL;
}

FilesModel *FolderModel::filesModel(QString name)
{
    Folder *folder = findFolder(name);
    if (folder)
    {
        FilesModel *model = folder->model();
        QQmlEngine::setObjectOwnership(model, QQmlEngine::CppOwnership);
        return model;
    }
    return NULL;
}

QHash<int, QByteArray> FolderModel::roleNames() const
{
    QHash<int, QByteArray> roles;
    roles[NameRole] = "name";
    roles[ModelRole] = "model";
    return roles;
}

Folder::Folder(const QString name) : _name(name)
{
    _model = new FilesModel();
}

main.cpp

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);
    MyApp myapp;

    QQmlApplicationEngine qmlEngine;
    qmlEngine.rootContext()->setContextProperty("MyModel", myapp.model());
    qmlEngine.rootContext()->setContextProperty("MyApp", &myapp);
    qmlEngine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (qmlEngine.rootObjects().isEmpty()) return -1;

    return app.exec();
}

在MyApp.cpp中,我填充了一些项目:

FolderModel _model;
_model.addFolder(Folder("Folder1"));
_model.addFolder(Folder("Folder2"));

// ...

Folder *objFolder = _model.findFolder(folder);
objFolder->model()->addFile(File("File 1"));
objFolder->model()->addFile(File("File 2"));

QML代码主要基于Photo Viewer演示。 main.qml

ApplicationWindow {
    id: mainWindow
    visible: true

    DelegateModel { id: albumVisualModel; model: MyModel; delegate: AlbumDelegate {} }

    GridView {
        id: albumView        
        width: parent.width
        height: parent.height
        cellWidth: 210
        cellHeight: 220
        model: albumVisualModel.parts.album
        visible: albumsShade.opacity !== 1.0
    }

    Rectangle {
        id: albumsShade; color: mainWindow.color
        width: parent.width; height: parent.height; opacity: 0.0
    }

    ListView {
        anchors.fill: parent
        model: albumVisualModel.parts.browser
        interactive: false
    }    
}

AlbumDelegate.qml(第一部分)

Component {
    id: albumDelegate

    Package {

        Item {
            Package.name: 'browser'
            GridView {
                id: photosGridView; model: visualModel.parts.grid; width: mainWindow.width; height: mainWindow.height - 21
                x: 0; y: 21; cellWidth: 160; cellHeight: 153; interactive: false
                onCurrentIndexChanged: photosListView.positionViewAtIndex(currentIndex, ListView.Contain)
            }
        }

        Item {
            Package.name: 'fullscreen'
            ListView {
                id: photosListView; model: visualModel.parts.list; orientation: Qt.Horizontal
                width: mainWindow.width; height: mainWindow.height; interactive: false
                onCurrentIndexChanged: photosGridView.positionViewAtIndex(currentIndex, GridView.Contain)
                highlightRangeMode: ListView.StrictlyEnforceRange; snapMode: ListView.SnapOneItem
            }
        }

        Item {
            Package.name: 'album'
            id: albumWrapper; width: 210; height: 220

            DelegateModel {
                property string tag
                id: visualModel; delegate: PhotoDelegate { }
                model: MyApp.filesModel(tag)
            }

它可以正确显示第一级模型(文件夹),但是当我尝试显示其中一个文件时出现以下错误,它会失败:

qrc:/AlbumDelegate.qml:36: Error: Unknown method return type: FilesModel*

但是我已经使用Q_DECLARE_METATYPE声明了该类型。 我需要添加其他内容吗?

据我所知,我不需要qRegisterMetaType(),因为我不在信号或插槽中使用它。

0 个答案:

没有答案