简体   繁体   English

qml未知方法返回类型:ArchiveFile *,即使调用了qmlRegisterUncreatableType

[英]qml Unknown method return type: ArchiveFile*, even though qmlRegisterUncreatableType was called

Brief description of what I'm trying to do 我正在尝试做的简要描述

I'm trying to make an application for opening some very structurally similar, related files. 我正在尝试创建一个应用程序来打开一些结构相似的相关文件。 Í have a base class, named GenericFile , and a subclass, named ArchiveFile . Í有一个名为GenericFile的基类和一个名为ArchiveFile的子类。 There also exists subclasses of ArchiveFile , which contain implementation logic for the specific archive file format, but those are not relevant for QML and therefore not exposed to QML. 还存在ArchiveFile子类,它包含特定存档文件格式的实现逻辑,但这些子类与QML无关,因此不会暴露给QML。

I've yet another class named FileManager , which exposes certain methods to QML to create instances of GenericFile and to downcast them to classes like ArchiveFile , based on GenericFile.getFileCategory . 我还有另一个名为FileManager类,它将某些方法暴露给QML以创建GenericFile实例,并将它们ArchiveFileArchiveFile等基于GenericFile.getFileCategory

The problem 问题

I've registered both GenericFile and ArchiveFile using qmlRegisterUncreatableType , like this: 我已经注册都GenericFileArchiveFile使用qmlRegisterUncreatableType ,就像这样:

int main(int argc, char** argv) {
    QApplication app(argc, argv);
    QQmlApplicationEngine engine;
    qmlRegisterUncreatableType<GenericFile>("me.henkkalkwater", 1, 0, "GenericFile", "Get your copy of GenericFile using FileManager!");
    qmlRegisterUncreatableType<ArchiveFile>("me.henkkalkwater", 1, 0, "ArchiveFile", "Get your copy of ArchiveFile using FileManager!");
    qmlRegisterSingletonType<FileManager>("me.henkkalkwater", 1, 0, "FileManager", [](QQmlEngine* engine, QJSEngine* jsEngine) -> QObject* {
        Q_UNUSED(engine)
        Q_UNUSED(jsEngine)
        return new FileManager();
    });
    const QUrl url(QStringLiteral("qrc:/qml/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);
}

Calling GenericFile* FileManager.getFile(int index) works fine in QML. 调用GenericFile* FileManager.getFile(int index)在QML中工作正常。 But calling ArchiveFile* FileManager.getArchive(int index) doesn't work, with the message "Error: Unknown method return type: ArchiveFile*". 但是调用ArchiveFile* FileManager.getArchive(int index)不起作用,消息“Error:Unknown method return type:ArchiveFile *”。

Has the problem to do with the fact that ArchiveFile inherits from GenericFile or did I make a silly mistake somewhere else? 已经做的事实问题ArchiveFile从继承GenericFile还是我做出愚蠢的错误别的地方? Or is the design of my classes seriously flawed? 或者我的课程设计严重缺陷? Am I taking some Java conventions to C++ which should be done in another way? 我是否将一些Java约定用于C ++,这应该以另一种方式完成?

My code 我的代码

genericfile.h: genericfile.h:

class GenericFile;
typedef GenericFile* (*CreateFileFunction) (QIODevice* file, QString fileName, QObject* parent);

class GenericFile : public QObject {
    Q_OBJECT
public:
    enum FileCategory {
        UNKNOWN,
        COMPRESSED,
        ARCHIVE,
        LAYOUT
    };
    Q_ENUM(FileCategory)

    GenericFile(QIODevice* source, QString name, QObject* parent = nullptr);
    virtual ~NinFile();

    Q_PROPERTY(QString fileName READ getFileName)
    Q_PROPERTY(FileCategory fileCategory READ getFileCategory)

    /**
     * @brief Register a file usign a certain string of magic bytes.
     * @param magic
     * @param fn
     */
    static void RegisterFile(QLatin1String magic, CreateFileFunction fn);

    /**
     * @brief Return one of the subclasses of the file.
     * @param file The file to determine.
     * @return The class able to parse this file format.
     *
     * Scans the magic bytes and returns a subclass of GenericFile that represents the file.
     * The subclass will take ownership of the QFile and destroy it whenever it is destroyed
     * itself.
     */
    static GenericFile* fromFile(QFile* file, QObject* parent = nullptr);
    static GenericFile* fromIODevice(QIODevice* file, QString filename, QObject* parent = nullptr);

    /**
     * @brief Initialize the default file associations.
     */
    static void init();

    /**
     * @return The filename of this file
     */
    QString getFileName() const {
        return fileName;
    }

    /**
     * @return return the general category the file belongs in
     */
    virtual FileCategory getFileCategory() const {
        return UNKNOWN;
    }

protected:
    QIODevice* file;
    QString fileName;
};

archivefile.h archivefile.h

class ArchiveFile : public GenericFile
{
public:
    ArchiveFile(QIODevice* device, QString fileName, QObject* parent = nullptr);

    Q_INVOKABLE
    virtual QList<QString> listContents() = 0;
    FileCategory getFileCategory() const override { return GenericFile::ARCHIVE; }
};

FileManager.h (with relevant method implementations included) FileManager.h(包含相关的方法实现)

class FileManager : public QAbstractListModel
{
    Q_OBJECT
public:
    explicit FileManager(QObject *parent = nullptr);
    enum RoleNames {
        INDEX = Qt::UserRole + 1,
        PATH,
        TYPE,
        CATEGORY
    };

    /**
     * @brief Opens a file
     * @param filePath The path to the file
     * @return false if the opening fails, true otherwise
     * Opens a file, and if successful, returns true and adds it to this model. Otherwise, it returns false.
     */
    Q_INVOKABLE
    bool openFile(QUrl filePath);

    Q_INVOKABLE
    GenericFile* getFile(int index) {
        if (index >= 0 && index < files.length()) {
            return files[index];
        }
        return nullptr;
    }

    Q_INVOKABLE
    ArchiveFile* getArchive(int index) {
        qDebug() << "Callled getArchive";
        try {
            return dynamic_cast<ArchiveFile*>(getFile(index));
        } catch (std::bad_cast e){
            return nullptr;
        }
    }

    QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
    int rowCount(const QModelIndex& parent = QModelIndex()) const override;
    QHash<int, QByteArray> roleNames() const override;

private:
    QList<GenericFile*> files;
};

Edit: it appears that this happens every time I register a base class and a subclass of said baseclass. 编辑:似乎每次我注册基类和所述基类的子类时都会发生这种情况。

Adding the Q_OBJECT macro to the subclass ( ArchiveFile ) seems to resolve the issue. Q_OBJECT宏添加到子类( ArchiveFile )似乎可以解决此问题。 I wrongly assumed that you only had to define the Q_OBJECT macro in the base class ( GenericFile ) somehow. 我错误地认为你只需要以某种方式在基类( GenericFile )中定义Q_OBJECT宏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM