qdjango foreign keys - qt

Quick googling returned no results on how to properly use QDjango's Foreign Keys - there are functions
QDjangoModel::foreignKey and QDjangoModel::setForeignKey - but I couldn't find any good examples on how to use them in practice.

Its quite old, maybe will help someone else.. I searched for FKs in QDjango for eons and found something in google group, there is also nice documentation with some basic examples(but no FK examples)
I create table models using QDjango in this way (also foreign keys):
class Role : public QDjangoModel { ... };
class User : public QDjangoModel
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(QString password READ password WRITE setPassword)
Q_PROPERTY(Role *role READ role WRITE setRole)
Q_CLASSINFO("name", "max_length=255")
Q_CLASSINFO("password", "max_length=255")
Q_CLASSINFO("role", "on_delete=cascade")
QString mName;
QString mPassword;
public:
User(QObject *parent = 0);
QString name() const { return mName; }
void setName(QString name) { mName = name; }
QString password() const { return mPassword; }
void setPassword(QString pass) { mPassword = pass; }
Role *role() const;
void setRole(Role *role);
};
You can use Q_CLASSINFO to set some attributes to columns.
The foreign keys are bound in constructor and filled in role functions.
User::User(QObject *parent)
: QDjangoModel(parent)
{
setForeignKey("role", new Role(this));
}
Role *User::role() const
{
return qobject_cast<Role *>(foreignKey("role"));
}
void User::setRole(Role *role)
{
setForeignKey("role", role);
}
When you want to select using fields from fk dependant table use two undescores and of course use selectRelated() (which just sets some flag which is later used to produce join select) like:
QDjangoQuerySet<User> matched;
matched = matched.selectRelated()
.filter(QDjangoWhere("role__rolename", QDjangoWhere::Equals, "admin"));

Related

What is the proper usage of Q_DECLARE_SMART_POINTER_METATYPE?

I tried to define a function that returns std::shared_ptr<OrderModel> as follows:
Q_DECLARE_SMART_POINTER_METATYPE(std::shared_ptr)
namespace tradeclient {
class OrderModel : public QObject
{
Q_OBJECT
public:
Q_PROPERTY(QString marketId READ marketId CONSTANT)
Q_PROPERTY(quint64 id READ id CONSTANT)
...
};
using OrderPtr = std::shared_ptr<OrderModel>;
class MarketModel : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE tradeclient::OrderPtr createLimitOrder()
{
return m_orders.front();
}
private:
//In my app I initialize OrderModel-s and add them so some container.
std::vector<OrderPtr> m_orders;
};
} //namespace tradeclient
Q_DECLARE_METATYPE(tradeclient::OrderPtr)
qRegisterMetaType<tradeclient::OrderPtr>();
and then call createLimitOrder() from QML:
var order = market.createLimitOrder()
console.log("Limit order type: %1, value: %2, id: %3".arg(typeof(order)).arg(JSON.stringify(order)).arg(order.id))
but with no success, because I can't access order.id and the console output is:
Limit order type: object, value: "", id: undefined
I also tried to define functions like this:
Q_INVOKABLE QVariant createLimitOrder()
{
return QVariant::fromValue(m_orders.front());
}
Q_INVOKABLE QSharedPointer<tradeclient::OrderModel> createLimitOrder()
{
return QSharedPointer<tradeclient::OrderModel>(new OrderModel());
}
but nothing changed.
But at least, QML treats order as a non-empty value and the following QML code:
if (order)
console.log("The order is defined.");
else
console.log("The order is not defined.");
prints:
"The order is defined."
So order is defined, but its properties are not. What did I miss?
Buy the way, the above QML code works correctly if I return naked pointer:
Q_INVOKABLE tradeclient::OrderModel* createLimitOrder()
{
return m_orders.front().get();
}
it prints
Limit order type: object, value: {"objectName":"","marketId":"BTCUSDT","id":0,"side":1,"type":0,"status":0,"price":{"precision":2},"stopPrice":{".....
Does QVariant that wraps std::shared_ptr expose object properties to QML?
EDIT1
As far as I understand, Q_DECLARE_SMART_POINTER_METATYPE is a relatively simple thing, it requires the class template to have operator -> (see ./qtbase/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp):
namespace MyNS {
template<typename T>
class SmartPointer
{
T* pointer;
public:
typedef T element_type;
explicit SmartPointer(T* t = nullptr)
: pointer(t)
{
}
T* operator->() const { return pointer; }
};
}
Q_DECLARE_SMART_POINTER_METATYPE(MyNS::SmartPointer)
so it is reasonable to expect that it behaves like a naked pointer in QML. However, I have concerns that this is one of those cases where they simply did not implement this simple thing well enough.

MQL4/5 CList Search method always returning null pointer

I'm trying to use the CList Search method in an application. I have attached a very simple example below.
In this example, I always get a null pointer in the variable result. I tried it in MQL4 and MQL5. Has anyone ever made the Search method work? If so, where is my mistake? With my question, I refer to this implementation of a linked list in MQL (it's the standard implementation). Of course, in my application, I do not want to find the first list item, but items that match specific criteria. But even this trivial example does not work for me.
#property strict
#include <Arrays\List.mqh>
#include <Object.mqh>
class MyType : public CObject {
private:
int val;
public:
MyType(int val);
int GetVal(void);
};
MyType::MyType(int val): val(val) {}
int MyType::GetVal(void) {
return val;
}
void OnStart() {
CList *list = new CList();
list.Add(new MyType(3));
// This returns a valid pointer with
// the correct value
MyType* first = list.GetFirstNode();
// This always returns NULL, even though the list
// contains its first element
MyType* result = list.Search(first);
delete list;
}
CList is a kind of linked list. A classical arraylist is CArrayObj in MQL4/5 with Search() and some other methods. You have to sort the list (so implement virtual int Compare(const CObject *node,const int mode=0) const method) before calling search.
virtual int MyType::Compare(const CObject *node,const int mode=0) const {
MyType *another=(MyType*)node;
return this.val-another.GetVal();
}
void OnStart(){
CArrayObj list=new CArrayObj();
list.Add(new MyType(3));
list.Add(new MyType(4));
list.Sort();
MyType *obj3=new MyType(3), *obj2=new MyType(2);
int index3=list.Search(obj3);//found, 0
int index2=list.Search(obj2);//not found, -1
delete(obj3);
delete(obj2);
}

Qt a nonstatic member reference must be relative to a specific object

I have a function which calls emitResult after loading data from file.
bool IpResolver::ResolvedInfo::load(QTextStream &in)
{
ResolvedInfo rf;
while (!in.atEnd())
{
QString line = in.readLine();
QStringList list = line.split(' ');
list[0] = rf.country;
list[1] = rf.ip;
if (rf.ip.isEmpty() == false)
{
emitResult(rf);
}
}
}
So here is declaration of emitResult:
private:
void emitResult(const ResolvedInfo &data);
And it gives me this error:
a nonstatic member reference must be relative to a specific object
No idea what should I do.
emitResult is a non-static member function of IpResolver, I presume. Yet you're calling it without any instance, from a subclass IpResolver::ResolvedInfo. Remember that just because the ResolvedInfo is a subclass, doesn't make it special in any other way. Specifically, if it doesn't hold a reference to the instance of the parent class, it won't work the way you expect it to.
There are two general ways to fix your issue:
You can pass a reference to IpResolver to the ResolvedInfo constructor, and retain the reference in the ResolvedInfo instance:
class IpResolver {
class ResolvedInfo {
IpResolver & q;
public:
ResolvedInfo(IpResolver & q) : q(q) { ... }
static bool load(QTextStream &in) {
ResolvedInfo rf;
while (!in.atEnd())
{
QString line = in.readLine();
QStringList list = line.split(' ');
list[0] = rf.country;
list[1] = rf.ip;
if (!rf.ip.isEmpty())
q.emitResult(rf);
}
}
};
void emitResult(const ResolvedInfo &);
...
};
Or you can make the emitResult a static method:
class IpResolver {
...
static void emitResult(const ResolvedInfo &);
};

BlackBerry iterate through selectedItems list

So I have FINALLY gotten to the point where I can select multiple items on a ListView:
ListView {
id: lv_stuffs
horizontalAlignment: HorizontalAlignment.Fill
dataModel: _app.personDataModel //REFERENCE 1
multiSelectAction: MultiSelectActionItem {
}
multiSelectHandler {
actions: [
// Add the actions that should appear on the context menu
// when multiple selection mode is enabled
ActionItem {
title: "Search for stuffs"
onTriggered: {
_app.search(lv_stuffs.selectionList());
}
...
And I am sending this selection list through to my search method:
void ApplicationUI::search(const QVariantList &list)
{
alert(QString("%1 items selected").arg(list.length()));
alert(((Person)list.at(0)).firstName);//<---- THIS IS THE PROBLEM
}
I am trying to get the "Person" object out of the GroupedDataModel that originally bound to the item... and I have to say I am more than a little stumped. The person is being added to the personDataModel via a simple insert method in a database class:
personDataModel->insert(person);
and the items are then bound to the ListView in the QML (REFERENCE 1 above). The binding is all fine and the items are visible in the list. What I can't figure out is how to now extract these "Person" objects out of the QVariantList I am sent via the MultiSelectionMethod.
My person class:
Person::Person(QObject *parent) : QObject(parent){}
Person::Person(const QString &id, const QString &firstname, const QString &lastname, QObject *parent)
: QObject(parent)
, m_id(id)
, m_firstName(firstname)
, m_lastName(lastname)
{
}
QString Person::customerID() const
{
return m_id;
}
QString Person::firstName() const
{
return m_firstName;
}
QString Person::lastName() const
{
return m_lastName;
}
void Person::setCustomerID(const QString &newId)
{
if (newId != m_id) {
m_id = newId;
emit customerIDChanged(newId);
}
}
void Person::setFirstName(const QString &newName)
{
if (newName != m_firstName) {
m_firstName = newName;
emit firstNameChanged(newName);
}
}
void Person::setLastName(const QString &newName)
{
if (newName != m_lastName) {
m_lastName = newName;
emit lastNameChanged(newName);
}
}
I have been PAINFULLY following this tutorial here, https://developer.blackberry.com/cascades/documentation/ui/lists/list_view_selection.html, which conveniently stops right where my question begins.
Are you perhaps looking for the value function?
void ApplicationUI::search(const QVariantList &list)
{
alert(QString("%1 items selected").arg(list.length()));
alert(((Person)list.value(0)).firstName);
}
(syntax of the extraction of the firstName value may not be right there, depends on your implementation)
Your Person class will be stored in a QVariant. To accomplish this, Qt has to generate some code specific to your class. It can be done by adding this right after your class definition, in the header file for example: Q_DECLARE_METATYPE(Person). You can read more about this here: http://qt-project.org/doc/qt-4.8/qmetatype.html#Q_DECLARE_METATYPE
Now, to extract the value as a Person object, you can use QVariant::value<T>() (http://qt-project.org/doc/qt-4.8/qvariant.html#value):
alert(list.at(0).value<Person>().firstName());

Can’t access public slots from QtScript

I have this class:
class JavaScript : public QObject {
Q_OBJECT
public:
JavaScript();
bool executeFromFile(QString file);
bool enabled;
public slots:
void setEnabled( bool enabled );
bool isEnabled() const;
private:
QScriptEngine engine;
};
The methods are defined like this:
#include "javascript.h"
JavaScript::JavaScript() {
executeFromFile("test.js");
}
bool JavaScript::executeFromFile(QString file) {
QFile scriptFile(file);
if (!scriptFile.open(QIODevice::ReadOnly)) return false;
QTextStream stream(&scriptFile);
QString contents = stream.readAll();
scriptFile.close();
engine.evaluate(contents, file);
return true;
}
void JavaScript::setEnabled( bool enabled ) {
JavaScript::enabled = enabled;
}
bool JavaScript::isEnabled() const {
return enabled;
}
I’m trying to access the public slots previously defined in the header file like the documentation says:
http://doc.qt.digia.com/qt/scripting.html#making-a-c-object-available-to-scripts-written-in-qtscript
The test.js file looks like this, just like the examples of the docs:
var obj = new JavaScript();
obj.setEnabled( true );
print( "obj is enabled: " + obj.isEnabled() );
But i’m not getting anything. It seems it doesn’t find the JavaScript object. What am I missing?
Doing a simple
print(1+1)
works just fine.
EDIT: An example in the qt4 webpage implements Q_PROPERTY. I tried this, but got the same result:
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
EDIT 1: Tried implementing the initializer like this:
// javascript.h:
JavaScript(QObject *parent = 0);
// javascript.cpp:
JavaScript::JavaScript(QObject *parent) : QObject(parent) {}
Still nothing...
EDIT 2: Some examples inherits from QScriptable too:
class JavaScript : public QObject, public QScriptable {}
But that makes no difference either.
You need to create QScriptClass instead of QObject. Qt contains example of how to extend script capabilites in Qt. Take a look on Custom Script Class Example
What I think you are actually missing is adding it to the script engine.
At some point you will have to declare a script engine
QScriptEngine * engine = new QScriptEngine(this);
Then you are going to want to add your object to the engine
JavaScript* js= new JavaScript();
QScriptValue jsobj = engine->newQObject(js);
engine->globalObject().setProperty("JavaScript", jsobj );
I'm by no means an expert but I think there is something else you need to do to say
var obj = new JavaScript();
at that point you probably need to take Kamil's advice and make JavaScript a subclass of QScriptClass

Resources