Add external QML module path to QQmlApplicationEngine - qt

I have an external QML module composed of graphical elements. I'd like to find its path in order to add it to my QQmlApplicationEngine. Is there a way to do this?
QQmlApplicationEngine engine;
engine.addImportPath("externalQmlModulePath");
With this, I'll be able to import the graphical elements from my qrc's QML files (which are of course inside the project).

Take a look at QStandardpaths. Having your resources (whether your own or 3rd party) relative to those paths makes them consistently available on target systems. The suggested path for application specific data is QStandardPaths::AppDataLocation.
In CMake you could add a custom post-build command to copy all your resources (again, no difference if your own or 3rd party):
add_custom_command(TARGET ${MY_APP} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${MY_APP_RES_SOURCE_DIR} ${MY_APP_RES_DEST_DIR})
Edit
QStandardPaths::AppDataLocation is of course just an enum value to specify which standard path you are looking for. To actually get the app data path, use the standardLocations method like this:
auto appDataPath = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).first();
Finally, add your app's resource folder as import path (as you already did) and you're done:
engine.addImportPath(appDataPath + "/res_dir_name");
Note: On Mac you can get away more easily by putting resources in the application bundle.

Related

QML/qdoc : How to define inheritance and important statement for my qml components?

I am writting a documentation for my QML project with QDoc. So far, I am able to make a simple one with a description of my functions/signals/properties. Now, I would like to define the inheritance and the important statements like in the Qt doc (see below).
According to the Qt documentation, the inheritance is defined with \inherits command. However, I don't see any result when I want to make my objects inherit from Item and I don't have any warning/error when I run the qdoc.
According the Qt wiki, QDoc considers the version specified in the command as the import statement. Following the example, I tried to define my own import statement since my qml files will be available with a specific import only (let's say MyLib 2.0 here). Like the inheritance, qdoc doesn't seem to understand because I have the following result:
Any idea of what I missed? You can find below a simple example of what I have (the css file is very simple so I don't think it is relevant to show it).
My environment:
Qt 5.10.10 with msvc2015
LLVM 9.0.0 (for qdoc)
config.qdocconf
sourcedirs = .
headerdirs = .
imagedirs = .
sources.fileextensions = "*.qml"
outputdir = ./doc/
outputformats = HTML
HTML.stylesheets = style.css
HTML.headerstyles = "<link rel=\"stylesheet\" type=\"text/css\" href=\"style/style.css\"/>\n"
CustomItem.qml
import QtQuick 2.10;
/*!
MyLib 2.0 //! What should I write to get the import statement?
\qmltype CustomItem
\inherits Item //! What should I write to get the "Inherits"?
\brief A simple example of object that inherits of Item.
I can safely assume that the properties and signals work well.
*/
Item {
id: customItem;
/*!
prop1 description
*/
property color prop1;
/*!
prop2 description
*/
property int prop2: 6;
}
Thank you for your help !
I think you need to specify the QML module using the \inqmlmodule property and a module.qdoc file.
Example for the mylib.qdoc:
/*!
\qmlmodule MyLib 2.0
\title MyLib 2.0 QML types
MyLib is a collection of types ...
...
*/
In your QML type file:
import QtQuick 2.10;
/*!
\qmltype CustomItem
\inherits Item
\inqmlmodule MyLib
...
*/
Item {
...
}
For inheritance you can prefix the type with its module:
\inherits QtQuick::Item
If your type is defined in a C++ class, also add the \instanciates property:
\instanciates MyType
Full example:
/*!
\qmltype CustomType
\inqmlmodule MyLib
\inherits QtQuick::Item
\brief Provides a custom item type.
CustomType provides a component for use as ...
*/
In order for \inherits to work, the type it inherits must be defined somewhere that QDoc can find. Since Item is a type provided by Qt, your .qdocconf file must depend on the module that provides the documentation for Item.
You can do this by adding the following lines to your .qdocconf file.
depends += \
qtquick
Documentation on depends
Relevant section:
The depends variable defines a list of other documentation projects that this project depends on for resolving link targets for type inheritance and anything else the documentation needs to link to.
But you also need to tell QDoc where the index files for those dependencies are.
When invoking QDoc on a project that has dependencies and uses the depends variable, one or more -indexdir path(s) must be passed as command line option(s). QDoc uses these paths to search for the dependencies' index files.
qdoc mydoc.qdocconf -outputdir $PWD/html -indexdir $QT_INSTALL_DOCS
With above, QDoc will search for a file $QT_INSTALL_DOCS/qtquick/qtquick.index for a dependency to qtquick. If an index file for a dependency is not found, QDoc will output a warning.
Which means you need to build the Qt documentation and pass the location of the installed documentation to qdoc
Link on building the Qt documentation
Once you've done that, using \inherits Item should provide the following line in your produced documentation.
Inherits: Item

What does Gluon SceneBuilder look for in JAR files?

Using Clojure, I'm trying to write a custom JavaFX component for use in Gluon SceneBuilder, to be loaded up from a .jar file. That is, I'd like to point SceneBuilder to the .jar with my custom class, and have the thing show up in the list of draggable items on the left.
I can make the visual structure show up with FXML only, but I'd like to include some behavior as well.
After doing the (:gen-class) stuff in my Clojure source, running lein uberjar, and using the fx:root construct in the FXML, I'm able to use the resulting class in a modified version of the official Java example.
When I instantiate my custom class in the CustomControlExample, I see evidence of the Clojure init code running (via printlns and other stuff in the graphics).
So my custom class appears to work normally. It has two constructors -- with and without a String argument, and extends from HBox. I can verify these when I view the resulting .class file in NetBeans and also using JarExplorer. The class has a ton more stuff in it, due to being a Clojure constructed class, but it has at least the same number and type of constructors as the example.
The problem is my custom component does not appear in the SceneBuilder when I import the uberjar file.
So the question is: What exactly does SceneBuilder need to see in the class to make it appear as a custom draggable component?
Here is the relevant portion of my one source file (it includes a utility library for dealing with starting up the FX runtime).
src/toyui/GridSettingsPane.clj:
(ns toyui.GridSettingsPane
(:gen-class
:extends javafx.scene.layout.HBox
:post-init post-init
:init init
:constructors {[] []
[String] []})
(:use [jfxutils.core :exclude [-main]]))
(defn -init
([]
(-init "unnamed-init"))
([name]
(println "hi from -init")
[[] []]))
(defn -post-init
([this]
(-post-init this "unnamed-post-init"))
([this name]
(println "hi from -post-init")
(jfxutils.core/app-init)
(let [loader (javafx.fxml.FXMLLoader. (clojure.java.io/resource "GridSettingsPane.fxml"))]
(.setRoot loader this)
(.setController loader this)
(.load loader)
loader))))
I discovered that SceneBuilder was using some real-time class loading. Clojure defaults to *use-context-classloader* = true, so I was able to get the class to load, sort of, by modifying the scenebuilder code a little as in my comment above. However it still was having some trouble with finding some type of resource. I figured it was still probably due to class paths and the like.
In the process I also discovered that the SceneBuilder dynamically creates a little FXML file (stream, actually), which says, among other things, <?import toyui.GridSettingsPane?>, and the runs the regular FXML loader on that stream.
So I went and modified FXMLExample to import my Clojure class from within the .fxml file and it worked.
So the conclusion is yes, my class will work as-is in the FXML when running from a regular program, but for some reason doesn't load up when the jar explorer is looking.

How to import flow definitions from node_modules

I want to import immutablejs flow type definitions, but I don't want to have my flow server go through everything in node_modules. When it does, the CPU jumps to 100% and it takes forever to do anything. I have added node_modules as and ignore in flowconfig, but then immutablejs module is not being recognised. What can I do about it? My flowconfig:
[ignore]
.happypack/.*
.*node_modules/.
[include]
[libs]
flow-typed
[lints]
[options]
esproposal.class_static_fields=enable
esproposal.class_instance_fields=enable
Not sure why do you need to update the flowconfig file. ImmutableJS library already contains Flow type definitions.
For example to import Map type definition do :
import type { Map } from 'immutable'
in the file where you going to use it.

What does a bare line on its own do?

In a .sbt file, I often have copy-pasted lines from readmes, of which I have no idea what I'm actually doing. An example is, after adding sbt-revolver to plugins.sbt, writing the line
Revolver.settings
My current understanding of what this does is magically adding re-start and re-stop commands to sbt. I have been led to understand that a line in an .sbt file does not, in fact, perform magic, but rather creates a key and associates a value with it.
What keys does such a line set, and to what value? What would be the equivalent statement in a .scala build definition?
*.sbt files can take bare DslEntry which include Setting[T] and Seq[Setting[T]].
An expression like someString := "a" or someSeq += "b" is a Setting for a specific T type.
These settings are values though, they define transformation (change, add, append, etc) of different parts of the build, which get folded into the build state and structure.
In your example Revolver.settings is Seq[Setting[_]] which defines default setup of using sbt-revolver.
If setting it up in a project/*.scala you need to assign it to the root project, which is either:
the sole project in your build
the project that aggregates all other (sub) projects.
Therefore it would look something like:
import sbt._, Keys._
object Build extends Build {
val bippy = project in file(".") settings Revolver.settings
}

Flex conditional compilation-Is it possible to have conditional compilation in flex library project?

Using Flex, created a desktop and web application in that used conditional compilation. It runs successfully. Now, I Would like to have the single swc file for both Desktop and web. So created the library project for satisfying that condition. While using conditional compilation in flex library project getting many issues like conflicts variable name and duplicate functions and so on, which I haven't faced while using flex projects without swc file.
So the question arises now: Is it possible to have conditional compilation on a flex library project?
When compiling your SWC, you can specify compile constants by passing them in a -define argument. This will however, only include whatever code you've added using that constant - i.e. you can't reset the const in a project that includes the SWC to get a different result.
Below is the code for a bat file for creating an SWC. Copy it into a new file, and save it with the extension .bat. Replace the file paths as necessary.
#echo off
set flexroot=D:\Program Files\FlashDevelop\Tools\flexsdk\
set proj=D:\Dev\TestSWC\
cd %flexroot%bin\
compc.exe -source-path %proj%src -is %proj%src -optimize -define CONFIG::debug false -define CONFIG::release true -output %proj%bin\TestSWC.swc
pause
I used this to build a SWC file containing a single class, like so:
package
{
public class TestClass
{
public function sayHello():void
{
CONFIG::debug
{
trace( "Hello debug" );
}
CONFIG::release
{
trace( "Hello release" );
}
}
}
}
I then created another project, included the SWC and set the CONFIG::debug flag to true, and called the sayHello() function. It traced "Hello release" as the SWC was compiled with the CONFIG::release flag as true.
Quoting the docs:
The mxmlc compiler lets you pass the values of constants to the application at compile time
It does not mention compc, so I'm pretty sure it is not possible. I also wonder how that would work technically since you include/exclude parts of the code during compilation. The compiled SWC would no longer contain the conditional code.

Resources