template <> QDate Conversion<QDate>::from(RubyValue x) { int y = x.send(RUBYQML_INTERN("year")).to<int>(); int m = x.send(RUBYQML_INTERN("month")).to<int>(); int d = x.send(RUBYQML_INTERN("day")).to<int>(); return QDate(y, m, d); }
AccessClass::AccessClass(RubyValue className, RubyValue methodInfos, RubyValue signalInfos, RubyValue propertyInfos) { setClassName(className.to<QByteArray>()); protect([&] { rb_check_array_type(methodInfos); rb_check_array_type(signalInfos); rb_check_array_type(propertyInfos); }); for (int i = 0; i < RARRAY_LEN(VALUE(methodInfos)); ++i) { RubyValue info = RARRAY_AREF(VALUE(methodInfos), i); auto nameSym = info.send("name"); addMethod(nameSym.to<QByteArray>(), nameSym.toID(), info.send("params").to<QList<QByteArray>>()); } for (int i = 0; i < RARRAY_LEN(VALUE(signalInfos)); ++i) { RubyValue info = RARRAY_AREF(VALUE(signalInfos), i); auto nameSym = info.send("name"); addSignal(nameSym.to<QByteArray>(), nameSym.toID(), info.send("params").to<QList<QByteArray>>()); } for (int i = 0; i < RARRAY_LEN(VALUE(propertyInfos)); ++i) { RubyValue info = RARRAY_AREF(VALUE(propertyInfos), i); addProperty(info.send("name").to<QByteArray>(), info.send("getter").toID(), info.send("setter").toID(), Property::Flag::Readable | Property::Flag::Writable, true, info.send("notifier").toID()); } }
template <> QRectF Conversion<QRectF>::from(RubyValue value) { auto x = value.send(RUBYQML_INTERN("x")).to<double>(); auto y = value.send(RUBYQML_INTERN("y")).to<double>(); auto w = value.send(RUBYQML_INTERN("width")).to<double>(); auto h = value.send(RUBYQML_INTERN("height")).to<double>(); return QRectF(QPointF(x, y), QSizeF(w, h)); }
ListModel::ListModel(RubyValue rubyModel, QObject *parent) : QAbstractListModel(parent), mRubyModel(rubyModel) { auto columns = rubyModel.send("columns").to<QList<QByteArray>>(); for (int i = 0; i < columns.size(); ++i) { auto role = Qt::UserRole + i; mColumnNames[role] = columns[i]; mColumnIDs[role] = rb_intern(columns[i]); } rubyModel.send("qt_models").send("push", RubyValue::fromQObject(this, false)); }
QVariant ListModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } QVariant result; withGvl([&] { RubyValue value; rescueNotify([&] { auto subscribe = RUBYQML_INTERN("[]"); auto record = rb_funcall(mRubyModel, subscribe, 1, INT2NUM(index.row())); value = rb_funcall(record, subscribe, 1, ID2SYM(mColumnIDs[role])); }); result = value.toVariant(); }); return result; }
template <> QDateTime Conversion<QDateTime>::from(RubyValue time) { int offset; if (time.isKindOf(rb_cTime)) { offset = time.send(RUBYQML_INTERN("gmt_offset")).to<int>(); } else { // DateTime VALUE dayOffset = time.send(RUBYQML_INTERN("offset")); offset = RubyValue(RRATIONAL(dayOffset)->num).to<int>() * 24 * 60 * 60 / RubyValue(RRATIONAL(dayOffset)->den).to<int>(); time = time.send(RUBYQML_INTERN("to_time")); } timeval at = rb_time_timeval(time); QDateTime dateTime; dateTime.setOffsetFromUtc(offset); dateTime.setMSecsSinceEpoch(at.tv_sec * 1000 + at.tv_usec / 1000); return dateTime; }
template <> QVariant Conversion<QVariant>::from(RubyValue x) { return x.toVariant(); }
template <> QSizeF Conversion<QSizeF>::from(RubyValue value) { auto width = value.send(RUBYQML_INTERN("width")).to<double>(); auto height = value.send(RUBYQML_INTERN("height")).to<double>(); return QSizeF(width, height); }
template <> QPointF Conversion<QPointF>::from(RubyValue value) { auto x = value.send(RUBYQML_INTERN("x")).to<double>(); auto y = value.send(RUBYQML_INTERN("y")).to<double>(); return QPointF(x, y); }
template <> RubyValue Conversion<QDateTime>::to(const QDateTime &dateTime) { RubyValue sec = rb_rational_new(RubyValue::from(dateTime.toMSecsSinceEpoch()), RubyValue::from(1000)); RubyValue time = rb_time_num_new(sec, RubyValue::from(dateTime.offsetFromUtc())); return time.send(RUBYQML_INTERN("to_datetime")); }