Product and Funding
-
I have been a software developer in the UK since 1984 working mainly in the Oil & Gas industry.
When the Oil & Gas industry took a down turn in 2016 I started my own company. My clients were mainly UK defence companies and this is when I started working with Qt.
I developed a GUI engine using Qt on Red Hat Linux. I created an engine where everything that could be configured was specified in XML files, the engine renders the output based on the XML content, this would allow the client to create displays and signals entirely separate from the engine with no source code changes required.
This works really well and since then I have taken the project further. In addition to the XML, logic can now be supplied in JavaScript files.
The JavaScript can be used to perform many of the functions that would be performed by a compiled language. The engine provides the abstraction layers between the native GUI and the user. For example in a JavaScript file a native GUI window can be created containing any of GUI controls that are supported by the engine.
The engine supports any plate form where Qt is available and simply requires a recompilation to provide support for that operating system, no changes are required to the XML or JavaScript, which means these are instantly portable.
Here are some samples, the root XML document:
<?xml version="1.0" encoding="utf-8"?> <xmlmpam images="~/XMLMPAM/config/images/" modules="~/XMLMPAM/config/modules/"> <include file="./lang/44"/> <include file="simon"/> </xmlmpam>
In the above the images attribute specifies the location of the image files, the modules attribute specifies where platform specific add on modules are located.
The include node pulls additional XML files. In the above language translation is provided by the 44 (UK English) file:
<!-- File: 44.xml, English language translation Notes: This file contains keys and text for english spoken language. Node: lang, a language translation node Attributes: key : The key used to lookup the translation text : Language translation To use any text wrapped in !! which will translated History: 2018/10/27 Created by Simon Platten // --> <lang key="apply" text="Apply changes..."/> <lang key="candc" text="Cancel and close..."/> <lang key="redo" text="Redo..."/> <lang key="submit" text="Submit changes..."/> <lang key="undo" text="Undo changes..."/>
simon.xml provides the main application, the thread nodes create separate threads:
<thread id="main2" desc="App demo 2" delay="50"> <init> <control type="window" id="win2" x="20%" y="20%" width="10%" height="10%" title="win2:Hi Jordan!"/> </init> </thread> <thread id="main3" desc="App demo 3" delay="50"> <init> <control type="window" id="win3" x="30%" y="30%" width="20%" height="20%" title="win3:Another world!"/> </init> </thread> <thread id="main4" desc="App demo 4" delay="50"> <init> <control type="window" id="win4" x="60%" y="40%" width="20%" height="20%" title="win4:Yet another!"/> </init> </thread> <thread id="main" desc="App demo" delay="50" globals="db=%7b'db':'test', 'host':'localhost', 'usr':'root', 'pass':'resuocra', 'driver':'QMYSQL'%7d" script="simon.js@setup();"> <init> <splash id="splash" logo="splash.png"/> <window id="win1" frameless="false" fullscreen="false" modal="true" x="10%" y="10%" width="650" height="620" properties="color: #000000; modal:true; maximize:false; minmax:false; minimize:false;" resizeable="true" title="win1:Hello World"> <frame id="frm1" x="2%" y="2%" width="96%" height="75%" properties="QFrame { background-color: #e9efef; background-image: url('meshtile_4x4.png'); border: 2px solid #cccccc; border-top-left-radius: 8px; border-top-right-radius: 8px; border-bottom-left-radius: 8px; border-bottom-right-radius: 8px;}"> <svg id="svg" xmlns="http://www.w3.org/2000/svg"> <g id="led1" transform="translate(10,20) scale(.1)"> <linearGradient id="led1.lg1" x1="0" y1="0" x2="y1" y2="0"> <stop id="led1.lg1s1" stop-color="#bfbfbf" offset="0"/> <stop id="led1.lg1s2" stop-color="#404040" offset="1"/> </linearGradient> <linearGradient id="led1.lg2" x1="0" y1="0" x2="1" y2="1" spreadMethod="pad"> <stop id="led1.lg2s1" stop-color="#000000" stop-opacity="0.992188" offset="0"/> <stop id="led1.lg2s2" stop-color="#000000" stop-opacity="0.988281" offset="1"/> </linearGradient> <linearGradient id="led1.lg3" x1="0" y1="0" x2="1" y2="1" spreadMethod="pad"> <stop id="led1.lg3s1" stop-color="#ffffff" stop-opacity="0.996094" offset="0"/> <stop id="led1.lg3s2" stop-color="#000000" stop-opacity="0.984375" offset="0.703125"/> </linearGradient> <circle id="c1" fill="url(#led1.lg1)" stroke-width="17.5" stroke-linecap="round" cx="320" cy="240" r="196.125" fill-opacity="0.77" transform="rotate(90, 320, 240)"/> <circle id="c2" fill="url(#led1.lg1)" stroke-width="17.5" stroke-linecap="round" fill-opacity="0.64" cx="319.252837" cy="239.999045" r="160"/> <circle id="c3" fill="url(#led1.lg2)" stroke-width="17.5" stroke-linecap="round" cx="320.000535" cy="240.001698" r="150"/> <circle id="c4" fill="none" stroke="black" cx="320" cy="240" r="196.125" transform="rotate(90, 320, 240)"/> <ellipse id="e1" fill="url(#led1.lg3)" stroke-width="17.5" stroke-linecap="round" cx="250.179609" cy="170.124194" rx="75.675959" ry="44.402987" transform="rotate(-47.7626, 250.18, 170.125)"/> </g> </svg> <copyof src="led1" startat="2" repeat="9" xpos="48,87,126,165,204,243,282,321,360" ypos="20,20,20,20,20,20,20,20,20" change="[led1:id:led{idx} ,c1:id:led{idx}.c1 ,c2:id:led{idx}.c2 ,c3:solid:led{idx}.c3 ,c4:solid:led{idx}.c4 ,e1:id:led{idx}.e1 ,led1.*:id:led{idx}.* ,url(#led1.*:fill:url(#led{idx}.*) ,led{idx}:transform:translate({xpos}#44;{ypos}):scale(.1)]"/> <button id="btn1" x="2%" y="2%" width="46%" height="50%" properties="QPushButton {background-color: #4cb9b3; border: 1px solid #3faca6; border-top-right-radius: 8px; border-bottom-left-radius: 8px; border-bottom-right-radius: 8px; color: #ffffff; padding: 1px 18px 1px 3px; min-width: 6em;}" shadow="3 3 8 #77000000" checkable="true"> <state data="off" text="Off"/> <state data="on" text="On"/> <subscriber signal="clicked" sid="win1" target="simon2.js@buttonHandler"/> <subscriber signal="pressed" sid="win1" target="simon2.js@buttonHandler"/> <subscriber signal="released" sid="win1" target="simon2.js@buttonHandler"/> <subscriber signal="toggled" sid="win1" target="simon2.js@buttonHandler"/> </button> <button id="btn2" x="btn1@right + 8" y="btn1@[y]" width="btn1@[width] - 8" height="btn1@[height]" properties="btn1@[properties]" shadow="btn1@[shadow]" checkable="true"> <state data="off" text="Off"/> <state data="on" text="On"/> <subscriber signal="clicked" sid="win1" target="simon2.js@buttonHandler"/> </button> <label id="lbl1" x="btn1@[x]" y="btn1@bottom + 20" text="%3ca href%3d%22http://google.com%22%3eGoogle%3c/a%3e" properties="QLabel {text-align:left; vertical-align: text-top; border:0px; color:#000000; format:rich; text-decoration:none; }"> <subscriber signal="linkActivated" sid="win2" target="simon2.js@labelHandler"/> <subscriber signal="linkHovered" sid="win2" target="simon2.js@labelHandler"/> </label> <label id="test99" x="btn1@[x] + 15" y="lbl1@bottom" text="A" properties="lbl1@[properties]"/> <label id="test100" x="btn1@[x] + 45" y="lbl1@bottom" text="B" properties="lbl1@[properties]"/> <label id="test101" x="btn1@[x] + 60" y="lbl1@bottom" text="C" properties="lbl1@[properties]"/> <textedit id="txted1" x="lbl1@right + 40" y="lbl1@top" height="lbl1@[height] + 8" width="256" properties="QTextEdit {border: 1px solid black; border-radius: 2px; padding: 1px 18px 1px 3px; min-width: 6em;}"> <subscriber signal="redoAvailable" sid="win2" target="simon2.js@textEditHandler"/> <subscriber signal="currentCharFormatChanged" sid="win2" target="simon2.js@textEditHandler"/> <subscriber signal="cursorPositionChanged" sid="win2" target="simon2.js@textEditHandler"/> <subscriber signal="redoAvailable" sid="win2" target="simon2.js@textEditHandler"/> <subscriber signal="selectionChanged" sid="win2" target="simon2.js@textEditHandler"/> <subscriber signal="textChanged" sid="win1" target="simon2.js@textEditHandler"/> <subscriber signal="textChanged" sid="win2" target="simon2.js@textEditHandler"/> <subscriber signal="textChanged" sid="win3" target="simon2.js@textEditHandler"/> <subscriber signal="textChanged" sid="win4" target="simon2.js@textEditHandler"/> <subscriber signal="undoAvailable" sid="win2" target="simon2.js@textEditHandler"/> </textedit> <combo id="cbo1" x="txted1@[x]" y="txted1@[y] + txted1@[height] + 4" properties="QComboBox {border: 1px solid black; border-radius: 2px; padding: 1px 18px 1px 3px; min-width: 6em;}"> <item text="Item 1" data="123"/> <item text="Item 2" data="456"/> <item text="Item 3" data="789"/> <subscriber signal="activated" sid="win2" target="simon2.js@comboHandler"/> <subscriber signal="currentIndexChanged" sid="win2" target="simon2.js@comboHandler"/> <subscriber signal="currentTextChanged" sid="win2" target="simon2.js@comboHandler"/> <subscriber signal="editTextChanged" sid="win2" target="simon2.js@comboHandler"/> <subscriber signal="highlighted" sid="win2" target="simon2.js@comboHandler"/> </combo> <lineedit id="lned1" x="txted1@[x]" y="cbo1@[y] + cbo1@[height] + 4" width="txted1@[width]" height="txted1@[height]" properties="QLineEdit {border: 1px solid black; border-radius: 2px; padding: 1px 18px 1px 3px; min-width: 6em;}"> <subscriber signal="cursorPositionChanged" sid="win2" target="simon2.js@labelHandler"/> <subscriber signal="editingFinished" sid="win2" target="simon2.js@labelHandler"/> <subscriber signal="returnedPressed" sid="win2" target="simon2.js@labelHandler"/> <subscriber signal="selectionChanged" sid="win2" target="simon2.js@labelHandler"/> <subscriber signal="textChanged" sid="win2" target="simon2.js@labelHandler"/> <subscriber signal="textEdited" sid="win2" target="simon2.js@labelHandler"/> </lineedit> <spinbox id="spnbx1" x="lned1@right + 8" y="lned1@top" width="48" height="lned1@[height]" properties="background-color: #0000ff;color: #ff00ff;" maximum="888" minimum="-10"> <subscriber signal="valueChangedAsInt" sid="win2" target="simon2.js@spinboxHandler"/> <subscriber signal="valueChangedAsStr" sid="win2" target="simon2.js@spinboxHandler"/> <subscriber signal="editingFinished" sid="win2" target="simon2.js@spinboxHandler"/> <subscriber signal="contextMenuRequested" sid="win2" target="simon2.js@spinboxHandler"/> </spinbox> <checkbox id="chkbx1" x="lned1@left" y="lned1@bottom + 8" width="128" height="lned1@[height]" properties="QCheckBox {}" checked="123" unchecked="999" text="Click box"> <subscriber signal="stateChanged" sid="win2" target="simon2.js@chkbxStateChange"/> </checkbox> <checkbox id="chkbx2" x="chkbx1@left" y="chkbx1@bottom + 8" width="chkbx1@[width]" height="chkbx1@[height]" properties="chkbx1@[properties]" checked="456" unchecked="888" text="Another box"> <subscriber signal="stateChanged" sid="win3" target="simon2.js@chkbxStateChange"/> </checkbox> <vertslider id="sldr1" x="spnbx1@right + 72" y="lbl1@top" width="80" height="200" min="0" max="200" multiplier="2.5" offset="111" properties="QSlider::handle:vertical { background: qlineargradient(x1:0,y1:0, x2:1, y2:1, stop:0 #eee,stop:1 #ccc); border: 1px solid #777; width: 13px; margin-top: -2px; margin-bottom: -2px; border-radius: 4px;}"> <subscriber signal="valueChanged" sid="win1" target="simon2.js@sliderHandler"/> <subscriber signal="sliderMoved" sid="win1" target="simon2.js@sliderHandler"/> </vertslider> </frame> <frame id="frm2" x="frm1@[x]" y="frm1@bottom + 8" width="frm1@[width]" height="20%" properties="QFrame { background-image: url('meshtile_4x4.png'); border: 2px solid #cccccc; border-top-left-radius: 8px; border-top-right-radius: 8px; border-bottom-left-radius: 8px; border-bottom-right-radius: 8px;}"> <label id="lblpitch" x="btn1@[x]" y="20" text="Pitch" properties="lbl1@[properties]"/> <horzslider id="pitchSlider" x="72" y="lblpitch@[y]" width="88%" height="24" min="-90" max="90" multiplier="1.0" offset="0" properties="QSlider::handle:horizontall { background: qlineargradient(x1:0,y1:0, x2:1, y2:1, stop:0 #eee,stop:1 #ccc); border: 1px solid #777; width: 13px; margin-top: -2px; margin-bottom: -2px; border-radius: 4px;}"> </horzlider> <label id="lblroll" x="btn1@[x]" y="lblpitch@bottom + 12" text="Roll" properties="lbl1@[properties]"/> <horzslider id="rollSlider" x="pitchSlider@[x]" y="lblroll@[y]" width="pitchSlider@[width]" height="pitchSlider@[height]" min="-90" max="90" multiplier="1.0" offset="0" properties="pitchSlider@[properties]"> </horzlider> <label id="lblhdg" x="btn1@[x]" y="lblroll@bottom + 12" text="Heading" properties="lbl1@[properties]"/> <horzslider id="headingSlider" x="pitchSlider@[x]" y="lblhdg@[y]" width="pitchSlider@[width]" height="pitchSlider@[height]" min="0" max="360" multiplier="1.0" offset="0" properties="pitchSlider@[properties]"> </horzlider> </frame> </window> </init> </thread>
Output created by the engine on my iMAC, the main window showing demos of some controls:
Another window from simon.xml:
Any number of modules can be added to the engine, I've presently written modules to interact with SQL database, native File IO and XML files.I am now looking for help in marketing this engine and introducing it to the world. The plan is to purchase a Qt license for each engine sold.
Anyone interested in helping me to take this to the next level, please PM me.
-
Hello,
Very interesting, could we get in touch to talk about this.
I'm eymeric o'neill and I an either available on LinkedIn or teams:
eymeric.oneill@gmail.com