[Interest] Some questions on QSettings, qmlRegisterType() and setContextProperty
Jayesh Bhoot
mister.bhoot at gmail.com
Sat Aug 10 07:35:32 CEST 2013
Short, but informative reply. :)
>
> 2., but calling init in C++ componentComplete() (derive from
> QQmlParserStatus as well) automatically, taking the input from
> properties set in QML.
>
I want to clarify something here. The C++ OAuth2 class provides the data
and logic to the OAuth2Browser QML window. It has a structure something
like this:
class OAuth2 : public QObject
{
Q_OBJECT
Q_PROPERTY(QUrl oauthUrl READ oauthUrl)
public:
explicit OAuth2(QObject *parent = 0);
explicit OAuth2(QString& appId, QUrl& redirectUrl, QStringList&
permissions, QObject *parent = 0);
QUrl oauthUrl() const;
signals:
void oauthSucceeded(QString userAccessToken);
void oauthFailed();
public slots:
void onBrowsingUrlChanged(const QUrl& url);
private:
QString parseUserAccessToken(const QUrl& url) const; // called by
onBrowsingUrlChanged()
static const QString m_oauthEndPoint;
QString m_appId;
QUrl m_redirectUrl;
QStringList m_permissions;
QString m_userAccessToken;
};
This is how the QML class uses it:
Window {
id: oauth2Browser
width: 500
height: 500
ColumnLayout {
anchors.fill: parent
WebView {
objectName: "Browser"
id: browser
Layout.fillHeight: true
Layout.fillWidth: true
url: oauth2.oauthUrl
onUrlChanged: oauth2.onBrowsingUrlChanged(browser.url)
}
Label {
id: loadingStatus
Layout.fillWidth: true
text: browser.loadProgress + "% loaded."
}
}
}
Thus, its the C++ class that sets the properties, and not the QML window
that does it. By your method, I assumes that I would have to derive OAuth2
from QQmlParserStatus in order to track properties set by QML window.
However, its the other way round - QML window takes data from an instance
of the C++ class.
How should I proceed then?
Also, feel free to point out if my current design is flawed.
> qmlRegisterType is better than setContextProperty, because that way
> the flow is controlled from QML (and a lack of constructor arguments
> is correct for declarative design, you can do additional property
> based initialization in componentComplete). Good QML design has C++
> expose functionality to QML but lets QML control the entire UI flow
> (including window creation/handling).
I agree with preferring qmlRegisterType over setContextProperty. But
wouldn't your C++ QQmlParserStatus::componentComplete() approach work only
if the data comes from QML to C++? I think that would be the case most of
the time. But how should I handle the other way round, like in my case, or
say, while grabbing data from database or application settings?
>> 1. Is exposing QSettings directly to QML UI a good idea?
>
> Directly? Not a good idea, but possible. The new Qt.labs.settings API
> aims to address this deficiency:
> https://codereview.qt-project.org/#change,59149
I will look forward to using this.
On Sat, 10 Aug 2013 03:34:19 +0530, Alan Alpert <416365416c at gmail.com>
wrote:
> On Fri, Aug 9, 2013 at 8:12 AM, Jayesh Bhoot <mister.bhoot at gmail.com>
> wrote:
>> I will try explaining my confusion through the application I am
>> currently
>> developing.
>>
>> My application (based on Qt5.1 + Qt Quick Controls) interacts with
>> Facebook API to manage a Facebook Page. I am trying to keep the QML code
>> (for UI) as separate as possible from the C++ core.
>>
>> Now, an OAuth2 implementation is required to be able to interact with
>> Facebook API. For that, I have a C++ OAuth2 class, the constructor of
>> which has the following signature:
>>
>> OAuth2::OAuth2(QString appId, QString redirectUrl, QStringList
>> permissions);
>>
>> Now, as the OAuth process requires a browser, I have also implemented an
>> OAuthBrowser.qml, which uses OAuth2 to complete an authorization.
>>
>> I have the following options to expose OAuth2 class to OAuth2Browser:
>>
>> 1. Instantiate OAuth2 and use setContextProperty() to expose the
>> instance
>> to OAuth2Browser. However, this means my C++ code has to deal with the
>> UI
>> code. The more baffling issue is that OAuth2Browser is a secondary
>> window.
>> When a user clicks on a "Authorize" window on the MainWindow, then an
>> AppController C++ object (connected to MainWindow) will launch the
>> OAuth2Browser window. Thus, the instantiation code of OAuth2Browser
>> would
>> go deep down inside a AppController method. It would have been good if
>> only main.cpp had to deal with the window creation.
>>
>> 2. Use qmlRegisterType(). In this case, I can't pass parameters to the
>> constructor. So, I will have to implement an init() method that would
>> initialize an OAuth2 object. Then, I would call this init() method in
>> OAuth2Browser's Component.onCompleted() method.
>> However, in this approach, I will have to expose QSettings to the UI
>> code
>> - QML window, so that the required parameters to init() method can be
>> retrieved. I have huge skepticism on whether directly exposing
>> application
>> settings to QML UI is a good idea.
>>
>> 3. Implicitly use QSettings within the OAuth2 constructor. This way, I
>> won't have to pass any parameters, and I would be able to use
>> qmlRegisterType(). However, this means I am doing some magic stuff
>> "behind
>> the curtains". Instead of explicitly passing QSettings instance, I am
>> using it wherever the hell I want to, thus hiding the initialization
>> detail from public API.
>>
>> An alternative based on the 3rd option was advised on IRC - use an
>> initFromSettings() type of method to initialize an instance if no
>> parameter is passed to the constructor. That way, the initialization is
>> not hidden, and initFromSettings() can confidently use QSettings within
>> itself. Now, I can happily use qmlRegisterType() to instantiate OAuth2
>> in
>> QML.
>>
>> So, what is the better approach?
>
> 2., but calling init in C++ componentComplete() (derive from
> QQmlParserStatus as well) automatically, taking the input from
> properties set in QML.
>
>> Also,
>> 1. Is exposing QSettings directly to QML UI a good idea?
>
> Directly? Not a good idea, but possible. The new Qt.labs.settings API
> aims to address this deficiency:
> https://codereview.qt-project.org/#change,59149
>
>> 2. I personally prefer qmlRegisterType() to setContextProperty() - that
>> way, the lifetime of a registered class's instance is maintained solely
>> by
>> QML. However, the former is less likely to be used due to the lack of
>> support of parameterized constructors, unless some form of init() is
>> used
>> explicitly for initialization. Is that a good design?
>
> qmlRegisterType is better than setContextProperty, because that way
> the flow is controlled from QML (and a lack of constructor arguments
> is correct for declarative design, you can do additional property
> based initialization in componentComplete). Good QML design has C++
> expose functionality to QML but lets QML control the entire UI flow
> (including window creation/handling).
>
>>
>> I apologise in advance for an excruciatingly long post. But I thought it
>> best to ask here.
>
> Sorry for the excruciatingly short reply ;)
>
> --
> Alan Alpert
--
Using Opera's mail client: http://www.opera.com/mail/
More information about the Interest
mailing list