【问题标题】:Qt model drag & drop - Unable to save type QJsonValueQt 模型拖放 - 无法保存类型 QJsonValue
【发布时间】:2019-11-26 11:49:41
【问题描述】:

我有一个QAbstractListModel 来显示一个QJsonArray,与drag & drop implementation

class NoteListModel : public QAbstractListModel
{
    Q_OBJECT

public:
    explicit NoteListModel(QObject *parent = nullptr);
    ~NoteListModel() override;
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    Qt::ItemFlags flags(const QModelIndex& index) const override;
    // Drag & Drop:
    bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const override;
    bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
    QStringList mimeTypes() const override {
        QStringList mimes = QAbstractListModel::mimeTypes();
        mimes.prepend("application/flynote_json");
        return mimes;
    }
    QMimeData *mimeData(const QModelIndexList &indexes) const override;
    Qt::DropActions supportedDropActions() const override;

private:
    QJsonArray noteArray;

};

当我在 mimeData() 方法中调用基本实现时,出现以下错误:

QVariant::save: 无法保存类型“QJsonValue”(类型 ID:45)
QVariant::save 中的 ASSERT 失败:“要保存的类型无效”

QMimeData *NoteListModel::mimeData(const QModelIndexList &indexes) const
{
    QMimeData *ret = nullptr;
    if (indexes.size() == 1){
        QModelIndex mi = indexes.first();
        if (mi.isValid()){
            ret = QAbstractListModel::mimeData(indexes);
            QJsonDocument json_mime(noteArray.at(mi.row()).toObject());
            ret->setData("application/flynote_json", json_mime.toJson());
        }
    }
    return ret;
}

所以没问题,就像在doc 中描述的那样,我添加了这些行:

// In the header (outside the class)
Q_DECLARE_METATYPE(QJsonValue)
QDataStream &operator<<(QDataStream &out, const QJsonValue &myObj){ /*...*/ }
QDataStream &operator>>(QDataStream &in, QJsonValue &myObj){ /*...*/ }

// In the constructor
qRegisterMetaType<QJsonValue>("QJsonValue");
qRegisterMetaTypeStreamOperators<QJsonValue>("QJsonValue");

但我有同样的问题,我做错了什么?

【问题讨论】:

  • 你的mimeTypes()是如何实现的?
  • @SilvanoCerza 我已经更新了

标签: c++ qt qdatastream qt5.9 qmetatype


【解决方案1】:

我试图重现您的示例,因为我真的无法通过查看您的代码来解释这种行为。我使用 Qt 5.5 编译了该项目,并且能够重现错误消息:

QVariant::save: unable to save type 'QJsonValue' (type id: 45).

有趣的是,这个错误在 Qt 5.13 中消失了,因为QVariant 已经在这个版本中包含了 QJson-Types。

看来,我为这种defect 找到了一种可能的解决方法,如下所示:

#include <QApplication>
#include <QDebug>
#include <QDataStream>
#include <QJsonDocument>

QDataStream& operator<<(QDataStream& out, const QJsonDocument& myObj) {
    return out;
}

QDataStream& operator >> (QDataStream & in, QJsonDocument& myObj) {
    return in;
}
Q_DECLARE_METATYPE(QJsonDocument)


int main(int argc, char** args) {
    qDebug() << qRegisterMetaTypeStreamOperators<QJsonDocument>();
    QVariant var = QVariant::fromValue(QJsonDocument());
    qDebug() << var.type();
    qDebug() << var.typeName();
    QDataStream stream;
    var.load(stream);   // Workaround: Just call load at least once before any save 
    var.save(stream);
    var.save(stream);
}

如果在所有调用save 之前至少调用一次load,错误就会消失。至少对于 Qt 5.5。

不幸的是,我手头没有 Qt 5.5 的资源来真正找到这种奇怪行为的原因。我也不知道是什么让QJsonDocument 在其他类中如此特别,不需要调用load

【讨论】:

  • 谢谢你的帮助,你用的是哪个qt版本?因为我认为在 5.13 中,QJsonValue 已经在 qmetatype 中定义但在 5.9 中没有定义,但也许我错了。我去看看
  • @ThibautB.:这是一个很好的观点。我正在使用 Qt 5.13.0 并且没有考虑旧版本中可能发生的情况。在这种情况下,您可能需要为所有 QJson-Kind 对象定义所有这些运算符。他们有很多。也许您可以尝试运行我的示例。它应该是独立的。
  • 这不是问题,在5.9源码中,QJsonValue被声明为here,我要试试你的例子
  • 哦,对不起,我最后的评论是假的,在cpp文件中,当它是QJsonValue时,开关返回false in 5.9,但在5.13中,实现不同,只有当指针未分配,这解释了为什么它在你的情况下工作。
  • @ThibautB。我更新了我的答案。你可能想看看它。
猜你喜欢
  • 2019-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-16
  • 1970-01-01
  • 2020-05-04
相关资源
最近更新 更多