Комментарии 12
Предложил бы еще так же сказать пару слов о макросе Q_DECLARE_OPAQUE_POINTER и смежных.
Не совсем согласен с утверждением:
Почему то мы не можем использовать ValueType в методах помеченными Q_INVOKABLE.
Утверждаю, что следующий код будет работать в 5.6.1:
// record.h
class Record
{
Q_GADGET
...
}
// listener.h
class Listener: public QObject
{
Q_OBJECT
...
Q_INVOKABLE Record foo ();
}
//main.cpp
...
qRegisterMetaType<Record>();
qmlRegisterType<Listener>("MyModule", 1, 0, "Listener");
...
// main.qml
...
Component.onCompleted: {
var r = someListener.foo();
print(r)
print(typeof r)
print(Qt.isQtObject(r))
r.text = "hooray";
print(r.text)
}
...
// output:
qml: Record()
qml: object
qml: false
qml: hooray
п.с. В моделях всё-таки лучше использовать не одну роль, возвращающую объект, а много ролей, возвращающих простые значения. Производительнее и нагляднее
Например если делать клиент для сервиса(на скриншоте клиент futuron.tv), то сервер использует пагинацию, что уменьшает число элементов, то вопрос производительности особо не стоит. А вот когда количество полей у структуры очень много:
{
"id" : 1708722,
"type" : 0,
"rate" : 3,
"creationTime" : 1460376607027,
"downloads" : 0,
"rusName" : "Пришельцы 3: Взятие Бастилии",
"engName" : "Les Visiteurs: La Révolution",
"releaseYear" : 2016,
"description" : "В третьей части граф с оруженосцем отправляются в самое сложное для Франции время период Французской революции.",
"youtubeId" : "FmpaphvPiTY",
"imdbRate" : "4.4",
"kpRate" : "5.8",
"duration" : "1ч.50мин.",
"officialSite" : "http://lesvisiteurs-lefilm.com/,http://vk.com/lesvisiteurs",
"video3d" : false,
"nextSeazonId" : 0,
"rusAgeRate" : "12+",
"studies" : "Ciné, TF1 Films Production, Canal+ [fr], Nexus Factory, Gaumont, Gaumont, The Czech Republic State Fund for Support and Development of Cinematography, La Wallonie, Okko Productions, Ouille Productions, BNP Paribas Fortis Film Finance",
"directors" : "Жан-Мари Пуаре",
"actors" : "Сильви Тестю, Кристиан Клавье, Жан Рено, Эри Абиттан, Карин Вьяр, Лоран Дойч, Франк Дюбоск, Фредерик Бель, Мари-Анн Шазель, Алекс Лутс, Вероника Буланжер, Стефани де Крэенкур",
"countries" : "Франция",
"genres" : "Комедии",
"translationTypes" : "Проф. многоголосый",
"translationAuthors" : "",
"videoQuality" : "HD",
"audioQuality" : "чистый звук",
"languages" : "",
"coverURL" : "http://static-gw.futuron.name/static/mobile/71/CF/71CF47394B5BA22ADDA68C66F29019E5.jpeg",
"coverMaxiURL" : "http://static-gw.futuron.name/static/mobile/71/CF/71CF47394B5BA22ADDA68C66F29019E5.jpeg",
"posterURL" : "http://static-gw.futuron.name/static/torrents/DA/69/DA69912E9EE01738090984132A70DEBA.jpg",
"screenshotsURL" : [ "http://static-gw.futuron.name/static/torrents/32/5A/325A0ADEABE689251170180309FFF167.jpg", "http://static-gw.futuron.name/static/torrents/2D/2E/2D2E3DC8B83DA2FF7764BB6AE4E50398.jpg", "http://static-gw.futuron.name/static/torrents/D7/71/D771B2DA86EDE8EC444D80E7E2D6BA1B.jpg", "http://static-gw.futuron.name/static/torrents/F0/E6/F0E6AB1DCA3366E0E1C3BE3C5A09E11B.jpg", "http://static-gw.futuron.name/static/torrents/6F/C0/6FC0895E1E265C0D3DBF4671FD330595.jpg", "http://static-gw.futuron.name/static/torrents/D3/05/D3059FCE4D46B868ADB88FD4FC1C0241.jpg" ]
}
то создавать роли может быть неудобно. Тут как всегда, нужно смотреть по ситуации.
В этом случае оборачивание в QVariant повлечет за собой:
- написание Q_GADGET wrapper-а с пачкой Q_PROPERTY, которые будет также неудобно описывать (если я правильно Вас понял.);
- копирование данных при выполнении QVariant::fromValue(), что при большой структуре отразится на производительности;
- необходимость в qml-коде обращаться к конкретному свойству через объект:
model.object.property
(сахар, конечно, но это будет раздражать).
С другой стороны, сохранение значения model.object
позволит минимизировать обращение к QAbstractItemModel::data() со всеми вытекающими.
Так что соглашусь: нужно смотреть по ситуации.
Преждевременная оптимизация — корень всех зол.
Д. Кнут.
Часть типов в Qt implicitly shared, а значит копирование приводит к увеличению атомарных счетчиков, а не выделение и перемещение(std::memmove) памяти. А если уж хочется минимезировать инкриментирование атомарных счетчиков, то можно pimpl применить:
class Film
{
Q_GADGET
Q_PROPERTY(quint64 id READ id)
Q_PROPERTY(QString endName READ engName CONSTANT FINAL)
Q_PROPERTY(QString rusName READ rusName CONSTANT FINAL)
Q_PROPERTY(QUrl coverUrl READ coverUrl CONSTANT FINAL)
Q_PROPERTY(QUrl coverMaxiURL READ coverMaxiURL CONSTANT FINAL)
Q_PROPERTY(QStringList screenshotsURL READ screenshotsURL CONSTANT FINAL)
Q_PROPERTY(QString duration READ duration CONSTANT FINAL)
Q_PROPERTY(QString description READ description CONSTANT FINAL)
Q_PROPERTY(quint32 year READ year CONSTANT FINAL)
Q_PROPERTY(QString countries READ countries CONSTANT FINAL)
Q_PROPERTY(QString actors READ actors CONSTANT FINAL)
Q_PROPERTY(QString genres READ genres CONSTANT FINAL)
Q_PROPERTY(bool isValid READ isValid CONSTANT FINAL)
public:
typedef QList<QUrl> Urls;
Film();
Film(Film&& obj);
Film(const Film& obj) = default;
static Film formJson(const QJsonObject& obj);
quint64 id() const noexcept ;
const QString& engName() const noexcept;
const QString& rusName() const noexcept;
const QUrl& coverUrl() const noexcept;
const QUrl& coverMaxiURL() const noexcept;
const QStringList& screenshotsURL() const noexcept;
const QString& duration() const noexcept;
const QString& description() const noexcept;
quint32 year() const noexcept;
const QString& countries() const noexcept;
const QString& actors() const noexcept;
const QString& genres() const noexcept;
bool isValid() const noexcept;
bool operator==(const Film& film) const noexcept;
private:
struct FilmImpl;
std::shared_ptr<FilmImpl> m_impl;
};
#include <QtCore/QDebug>
#include <QtCore/QVariant>
#include <QtCore/QJsonArray>
#include <QtCore/QJsonObject>
#include "Film.h"
struct Film::FilmImpl
{
bool m_isValid = false;
quint64 m_id = 0;
QString m_engName;
QString m_russName;
QUrl m_coverURL;
QUrl m_coverMaxiURL;
QStringList m_screenshotsURL;
QString m_duration;
QString m_description;
QString countries;
QString actors;
QString genres;
quint32 year;
};
Film::Film()
: m_impl(std::make_shared<FilmImpl>())
{
}
Film::Film(Film&& obj):
m_impl(std::move(obj.m_impl))
{
}
quint64 Film::id() const noexcept
{
return m_impl->m_id;
}
const QStringList& Film::screenshotsURL() const noexcept
{
return m_impl->m_screenshotsURL;
}
const QString& Film::rusName() const noexcept
{
return m_impl->m_russName;
}
const QString& Film::engName() const noexcept
{
return m_impl->m_engName;
}
const QUrl& Film::coverUrl() const noexcept
{
return m_impl->m_coverURL;
}
const QUrl& Film::coverMaxiURL() const noexcept
{
return m_impl->m_coverMaxiURL;
}
bool Film::isValid() const noexcept
{
return m_impl->m_isValid;
}
const QString& Film::duration() const noexcept
{
return m_impl->m_duration;
}
const QString& Film::description() const noexcept
{
return m_impl->m_description;
}
bool Film::operator==(const Film& film) const noexcept
{
return m_impl->m_id == film.m_impl->m_id;
}
Film Film::formJson(const QJsonObject &obj)
{
Film film;
film.m_impl->m_isValid = true;
film.m_impl->m_id = obj.value("id").toVariant().toULongLong();
film.m_impl->m_russName = obj.value("rusName").toString();
film.m_impl->m_engName = obj.value("engName").toString();
film.m_impl->m_description = obj.value("description").toString();
film.m_impl->countries = obj.value("countries").toString();
film.m_impl->m_coverURL = QUrl(obj.value("coverURL").toString());
film.m_impl->m_coverMaxiURL = QUrl(obj.value("coverMaxiURL").toString());
film.m_impl->m_duration = obj.value("duration").toString();
film.m_impl->year = obj.value("releaseYear").toVariant().toUInt();
film.m_impl->actors = obj.value("actors").toString();
film.m_impl->genres = obj.value("genres").toString();
for(const auto& val : obj.value("screenshotsURL").toArray())
{
film.m_impl->m_screenshotsURL.push_back(val.toString());
}
return film;
}
quint32 Film::year() const noexcept
{
return m_impl->year;
}
const QString& Film::countries() const noexcept
{
return m_impl->countries;
}
const QString& Film::actors() const noexcept
{
return m_impl->actors;
}
const QString& Film::genres() const noexcept
{
return m_impl->genres;
}
Есть QML профайлер, всегда можно посмотреть что подтормаживает.
удали-меня
Применение Q_GADGET в C++&QtQuick