3
votes

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?

Also,

  1. Is exposing QSettings directly to QML UI a good idea?
  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?

I apologise in advance for an excruciatingly long post. But I thought it best to ask here.

1

1 Answers

0
votes

It's difficult to fully follow your post since it's so long and information dense. Here are my suggestions for what they might be worth.

You want to know what is a good design but you don't specify your goals. You can't really rate something for how well it achieves goals unless you can enumerate the goals.

You're dealing with facebook's api. My crystal ball says change is something you will need to deal with. Therefore putting all the tools into qml may make you better able to respond to change. You can respond to change by rewriting javascript in a qml file instead of a recompile (hopefully). Use properties and the signal/slot design and it should be flexible enough to get the job done. Performance doesn't seem to be an issue.

I would create a settings object that exposes the stuff you want to store. Perhaps using the model/view architecture Qt provides already. The underlying storage, xml file, database, QSettings registry isn't important. You can offer a grid/list to allow users to update their settings if necessary.

Put together oauth and browser tools as objects that will let you script the behavior of the app in qml.

These tools to expose c++ objects might be something excellent to share with the community as well.

Good luck!