How to build QT QML / Quick Application using WAF? - qt

I'm trying to build a QT Quick application using WAF. However, it looks like WAF doesn't know what to do with .qml files.
I can build a QT Widget application in WAF using: https://waf.io/apidocs/tools/qt5.html
def options(opt):
opt.load('compiler_cxx qt5')
def configure(conf):
conf.load('compiler_cxx qt5')
def build(bld):
bld(
features = 'qt5 cxx cxxprogram',
uselib = 'QT5CORE QT5GUI QT5OPENGL QT5SVG',
source = 'main.cpp textures.qrc aboutDialog.ui',
target = 'window',
)
But trying to modify the above for a QT Quick App, by say adding the .qml file to source causes the program to fail to compile due to .qml being unrecognized.
Does anyone know how to do this? I know WAF supports '#extensions'. But I'd rather not have to re-create QT's QML build system in WAF if possible. If that even is possible.
If it helps, at the end of the day what I want to do is use the '-platform webgl' feature to get a QT Quick Web Page up that can run my native C++ .dll's (Making WebAssembly out of the question).

Related

Robot Framework and testing windows GUI tool - select menu or other options and buttons

We have a Windows 7 GUI tool just like MS Paint and need to test this application using Robot Framework.
Is there a possible way that we can select / execute different menu options by of the GUI tool - I have no code to share as I am not sure even how to implement it
You could use robotframework-autoitlibrary it allows us to automate desktop application.
AutoItLibrary is a Robot Framework keyword library wrapper for for the
freeware AutoIt tool,
using AutoIt's AutoItX.dll COM object. The AutoItLibrary class
provides a proxy for the AutoIt keywords callable on the AutoIt COM
object and provides additional high-level keywords implemented as
methods in this class.
This link contains all the information you need about keywords, how it works etc.
You could also write keywords in python and then use them in robot-framework for that you could use pywinauto library
Example code:
from pywinauto.application import Application
def Open_And_Click:
app = Application()
app.start_("C:\\Temp\\setup.exe")
mainWindow = app.SampleApplication
mainWindow.Wait('ready')
mainWindow['&Next'].ClickInput()
mainWindow['&Next'].ClickInput()
mainWindow['&Finish'].ClickInput()
mainWindow.WaitNot('visible')

SBT - watch different sources depending on Task

In a cross Scala JS server / client project, I want changes of some sources to restart the server and other sources to trigger the packaging process, but without the restart. Different tasks will not help because they will simply do one or the other and I want both at the same time.
In more detail:
I've got a Scala.js crossProject. I'm using the following to ensure the server can serve the built JavScript:
val app = crossProject.settings(...)
lazy val appJS = app.js
lazy val jsFile = fastOptJS in(appJS, Compile)
lazy val appJVM = app.jvm.settings(
(resources in Compile) += jsFile.value.data,
(resources in Compile) += jsFile.value.data.toPath.resolveSibling(jsFile.value.data.name+".map").toFile,
(resources in Compile) += (packageJSDependencies in(appJS, Compile)).value
)
If I run ~ appJVM/compile:packageBin::packageConfiguration then changes to the JavaScript source are immediately compiled and placed in the appJVM target/classes dir, so a refresh of the browser gets my new code - brilliant.
However, I would also like to use the sbt-revolver plugin to restart the server if I edit server-side code. But there's the rub - if I use ~ ;appJVM/compile:packageBin::packageConfiguration;appJVM/reStart then changes to the client side source restart the server, which I don't want. But if I remove the client side project from the transitive watch then it no longer notices if I change the client side project.
Is there a way to define watchTransitiveSources differently per task?
~ is actually a command that watches the transitive sources of the base project and then synchronously runs everything passed as an argument to it when those change, before re-running the original input (including ~). It does not make any information about what has changed available to those command line inputs (difficult to see how it could).
Consequently the solution I came to is to write a new watch command. It also needs to watch all sources, but then conditionally choose what to do based on which files have changed.
I've hacked something ugly as anything together that does this, but will look at making it more legible, general, tested and a Plugin. However, in the meantime anyone trying to follow my path can use this public gist: https://gist.github.com/LeisureMonitoringAdmin/0eb2e775e47b40f07d9e6d58d17b6d52
Are you sure you are using sbt-resolver not sbt-revolver ?
Because the second one allows controlling the triggered resources using
watchSources - defines the files for a single project that are
monitored for changes. By default, a project watches resources and
Scala and Java sources.
watchTransitiveSources - then combines the
watchSources for the current project and all execution and classpath
dependencies (see .scala build definition for details on interProject
dependencies).
Source: http://www.scala-sbt.org/0.13/docs/Triggered-Execution.html

Qt5 is it possible to define more than one build configuration?

I am working on application for Mac OS written in C++ using Qt5.7.1, which is distributed both as direct download from website and through App Store.
Now I have a new requirement to add self-update to the application. Which would require building two different versions of application - one for App Store (without self-update mechanism) and one for direct download (with self-update).
I have no problem to implement the self-update, but I am stuck with making a separate build configuration. So the question is -- in Qt5 is it possible to define two separate Release configurations (in a single .pro file) and if yes, then how? It also needs to work with qmake since the builds are automatic (with Jenkins).
You cannot really define 2 Release configurations in a .pro file.
However you can define different configuration options in your .pro file like this:
foo {
#something
DEFINES += FOO
} else {
#something else
DEFINES += NOT_FOO
}
bar {
#another thing
DEFINES += BAR=42
}
And then when you run qmake, add either CONFIG+=foo or CONFIG+=bar or both.
Finally in QtCreator you can define as many build profile as you want and customize the call to qmake for each profile by adding or not CONFIG+=foo options.
For more information check qmake's CONFIG documentation, especially the last example.

How to develop a PySide application plugin?

As I understand it Qt provides 2 main plugin mechanisms:
Plugins that extend Qt "Qt Extensions"
Plugins that extend applications developed with Qt
I'm interested in developing plugins for my application (2).
I use PySide but can't find any resources about developing application plugins using PySide/PyQt.
Following the C++ Qt documentation I understand that the application has to use the Q_DECLARE_INTERFACE() macro and the plugins have to use both Q_INTERFACES() and Q_EXPORT_PLUGIN2() macros but I don't know the code they represent to try and translate it to python. Or is there another way I've missed?
Update:
The closest thing to a solution I could find so far is Alex Martelli's answer to a similar question. Although it looks like it would work I'd rather use an official Qt approach to avoid any cross-platform issues.
I think Qt's plugin system is intended to allow people to write C++ plugins compiled as binaries. I don't even know if it's theoretically possible to write plugins in Python that will use a C++ binary interface like that.
If you want to support Python plugins your best bet would be to use one of the many pure python plugin systems out there. I have written a PySide app that uses YAPSY to load plugin scripts. YAPSY is a very simple, compact plugin module. It's very easy to include directly in your app as it's a single file, and is BSD licensed so you can use it commercially. Just search for it on Google. I was even able to package my app using py2exe and still retain the ability to import python source file plugins from a plugin directory.
I'm a fan of the Roll Your Own approach.
By a plugin, I mean:
Plugin: a module or package loaded during runtime which augments or modifies the main module's behavior
I see two requirements for a plugin:
Can the main module load the plugin during runtime?
Is data accessible between the main module and the plugin?
Assumptions
Developing a plugin system is highly subjective. There are many design decisions to make and there is no One True Way. The usual constraints are time, effort, and experience. Be aware that assumptions must be made and that the implementation often defines terminology (e.g. "plugin" or "package"). Be kind and document those as best as possible.
This plugin implementation assumes:
A plugin is either a Python file or a directory (i.e. "plugin package")
A plugin package is a directory with structure:
plugin_package/
plugin_package.py <-- entry point
other_module.py <-+
some_subdir/ |- other files
icon.png <-+
Note that a Plugin package isn't necessarily a Python package. Whether or not a plugin package is a Python package depends on how you want to handle imports.
The plugin name is the same as the plugin entry point's file name, as well as the plugin package directory
The QApplication's QMainWindow is the primary source of data to share from the main module
1. Loading a plugin module
Two pieces of information are required to load a plugin module: the path to the entry point and the plugin's name. How these are obtained can vary and getting them usually requires string/path parsing. For what follows, assume:
plugin_path is the absolute path of the plugin entry point and,
plugin_name is the plugin name (which is the module name by the above assumptions).
Python has implemented and re-implemented the import mechanism numerous times. The import method used at the time of writing (using Python 3.8) is:
import importlib
from importlib.util import spec_from_loader, module_from_spec
from importlib.machinery import SourceFileLoader
loader = SourceFileLoader(plugin_name, plugin_path)
spec = spec_from_loader(plugin_name, loader)
plugin_module = module_from_spec(spec)
spec.loader.exec_module(plugin_module)
# Required for reloading a module
sys.modules[plugin_name] = plugin_module
# # This is how to reload a module
# importlib.reload(plugin_module)
It's probably a good idea to include error handling and a record of which modules have been loaded (e.g. by storing them in a dict). Those details are excluded here for brevity.
2. Sharing data
There are two directions which data may be shared:
Can the main module access the plugin module's data?
Can the plugin module access the main module's data?
The main module can access plugin data for free after import (by definition). Simply access the plugin module's __dict__:
# Accessing plugin data from the main module
some_data = plugin_module.__dict__.get('data')
Accessing the main module's data from within the plugin is a trickier problem.
As stated above, I usually consider the QMainWindow as synonymous with the end-user's notion of "the application". It's the primary widget users interact with and, as such, typically houses most of the data or has easy access to it. The challenge is sharing the QMainWindow instance.
The solution to sharing QMainWindow instance data is to make it a singleton. This forces any QMainWindow to be the main window users interact with. There are several ways to create singletons in Python. The two most common ways are probably using metaclasses or modules. I've had the most success using the module singleton approach.
Break the QMainWindow code into a separate Python module. At the module level, create but don't initialize a QMainWindow. Create a module-level instance so that other modules can access the instance as a module attribute. Don't initialize it because init requires a QApplication (and because the main window module is not the application entry point).
# main_window.py
from PySide2 import QtWidgets
class MyMainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
main_window_instance = MyMainWindow.__new__(MyMainWindow)
Use a separate module, such as main.py, for the application entry point. Import the main window instance, create the QApplication, and initialize the main window.
# main.py
import sys
# Importing the instance makes it a module singleton
from main_window import main_window_instance
from PySide2 import QtWidgets
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
main_window_instance.__init__()
main_window_instance.show()
sys.exit(app.exec_())
Importing the main window instance is what makes it a singleton. Creating the QApplication here isn't strictly necessary (it's a singleton, too), but feels cleaner to me.
Now, when plugins are loaded during runtime, they can import the main_window_instance. Because the main_window module has already been loaded by the main.py entry point, it's the main window used by the main module (and not a new instance). Data from the main module can now be accessed from the plugin module.
# plugin.py
# The plugin can now access the main module's data
from main_window import main_window_instance
main_window_instance.setWindowTitle('Changed from plugin')
Comments
The minimum setup requires three files: main.py, main_window.py, and plugin.py. The main_window.py defines and instantiates the main window, the main.py makes it a singleton and initializes it, and the plugin.py imports and uses the instance.
Lots of details were left out in hopes that the primary components could be made apparent. Ideally, the Qt and Python documentation should be enough to fill in the gaps...
There are further considerations, such as how to distribute and manage plugins. Plugins could be hosted remotely, packaged as (zip) archives, bundled as proper Python packages, etc. Plugins can be as simple (or as complex) as you want. Hopefully this answer provides ample inspiration for how you want your plugin system to look.

Is it possible to create a 'command line' swf?

I'd like to be able to write a .swf file that is runnable as a command line app. In other words, I would be able to create actionscript classes which can interact with stdin and stdout, and could then execute that .swf directly in the command line.
I suspect that this isn't really possible. Can anyone confirm that?
EDIT:
A couple of the answers pointed out that using Flash for command line work probably isn't the best choice. I wholeheartedly agree in most situations. The reason I am asking about this is because I want to do some AS3 code generation, and reflecting on AS3 classes within the runtime would be easier than parsing the code or walking the intermediary XML that asdoc produces. I'm doing the XML approach now in Ruby, but would love to have a cleaner solution!
YES! It actually is possible.
You can create a pure AS3 AIR project (without any application window) and run from the command line using ADL (AIR Debug Launcher).
ADL will execute your SWF and will pass whatever arguments you give it directly to your application at runtime—all from the command line! To read the arguments from AS3 just add this code to your main class:
package
{
import flash.desktop.NativeApplication;
import flash.display.Sprite;
import flash.events.InvokeEvent;
public class CmdLine extends Sprite
{
public function CmdLine()
{
NativeApplication.nativeApplication.addEventListener(
InvokeEvent.INVOKE, onInvokeEvent);
function onInvokeEvent(invocation:InvokeEvent):void {
trace(invocation.arguments);
}
}
}
}
Your main class will still extend Sprite, but you won't see any UI unless you create NativeWindow objects. If you're using Flash Builder, just create a new AIR project and rename the extension of the main .mxml file to .as (before you finish the wizard).
Here is more about ADL: Using the AIR Debug Launcher (ADL)
Also, this will be very useful: AIR application invocation and termination
You can do all your output using trace(), write files, or even write directly to stdout, as seen here.
Apparently there is the Tamarin project which aims to create an open source implementation of AS3. This page gives a little detail of compiling an AS3 script and running it from a command line.
I'm not getting a good idea of how stable Tamarin is, but it might be your best bet for now. On the other hand, I have to strongly agree with #zenazn that you would be better off long-term learning a language more designed for general purposes, but if really want to just use Actionscript, don't let anyone stop you :)
There's no way to do this with a bare SWF right now.
However, you can publish your Flash content as an AIR app. The app can then be invoked from the command line, and you can collect the arguments from the arguments property of an InvokeEvent. The basic idea looks like this:
NativeApplication.nativeApplication.addEventListener(
InvokeEvent.INVOKE, onInvoke );
// ...
function onInvoke( e:InvokeEvent ) {
var numArguments:int = e.arguments.length;
// ...
}
Note, however, that this is essentially a one-way street. You can grab the command-line arguments, but Flash still doesn't grok the idea of stdin and stdout.
Actually, there is a project that makes it possible. RedTamarin is a project that extends AS3 (technically, the Tamarin project which is the Adobe/Mozilla ECMAScript project) to have access to low-level libraries (ie. POSIX). In its current state it appears to be good for stuff like shell-scripting-like programs which is what it sounds like what you're looking for.
Give it a try:
http://code.google.com/p/redtamarin/
You can interact with stdin, stdout and stderr with redtamarin
http://code.google.com/p/redtamarin/
see examples/docs here
http://code.google.com/p/redtamarin/wiki/System#stdout
http://code.google.com/p/redtamarin/wiki/System#stderr
http://code.google.com/p/redtamarin/wiki/System#stdin
there is a difference between Flash and ActionScript 3
Flash is a runtime, AS3 is a language
I don't see why AS3 would not be a good programming language
for the command line and/or the server side
Now, redtamarin is just that, a runtime that allow you to
run your AS3 source code on the command line.
Also, depending on your needs, you can use it in different ways
to run script on the command line
$ ./redshell myscript.as
run ABC or SWF files on the command line
$ ./redshell myscript.abc
$ ./redshell myscript.swf
run an exectuable
$ ./myscript
When you will run an AS3 script it will be dynamically interpreted,
using ASC you will be able to compile this same script to an ABC file
that can also be run from the command line.
If for example you need to assemble numerous ABC files together,
you can use swfmake to merge them into SWF file and the runtime
will run that SWF file too from the command line.
Finally, if you need to bundle everything in one executable,
you can use createprojector to take your ABC or SWF file
and merge it with the runtime itself to obtain an independent
executable.
Redtamarin provide native API that cover file system access,
sockets, operating system info, etc.
Now it is possible with AIR 2.0. Check this article to start.
If you are really that inclined, you could open a local socket, and then have a helper program, running from the command-line communicate with the open SWF.
This might be a good time to learn another language. May I suggest Java?
I had a similar question recently. It took me a few days to answer it for myself, but you can create a .swf and execute it entirely from the command line.
AS3 Filesystem Hello World
You could have a look at Haxe with is very similar to AS3 and could compile NekoVM Bytecode, which could be run on the command line.
Also interesting could be HippoHX, it is a kind of framework to create desktop applications out of flash movies. (similar to AIR, but with full access to the system.)
Nope--not possible. The best you can do is a standalone app (which can be made in Flash or with a Projector version of flash player, available from the Adobe website).
And why would you want to--Flash is awesome because of the great GUI capabilities. There are plenty of other programming languages that are much better suited for the command line (Python or Ruby or, god forbid, even Perl)

Resources