How to create complex script

Discussion forum for C++ and script developers who are using the QCAD development platform or who are looking to contribute to QCAD (translations, documentation, etc).

Moderator: andrew

Forum rules

Always indicate your operating system and QCAD version.

Attach drawing files, scripts and screenshots.

Post one question per topic.

marekw2143
Junior Member
Posts: 10
Joined: Sat Sep 09, 2023 1:36 pm

How to create complex script

Post by marekw2143 » Sat Sep 09, 2023 1:38 pm

Hello,

Is it possible to create an QCAD plugin only using javascript?
if so, how to accomplish that, maybe there's some tutorial which I could follow?

Regards and thansk for QCAD application,

Marek

CVH
Premier Member
Posts: 3480
Joined: Wed Sep 27, 2017 4:17 pm

Re: How to create complex script

Post by CVH » Sat Sep 09, 2023 6:35 pm

Hi,

Yes, scripting under QCAD is in ECMAScript (Rather an older implementation) or in C++.
Most common QCAD tools are implemented in ECMAScript:
https://github.com/qcad/qcad/tree/master/scripts

The scripts folder of a standard installation is seemingly empty, the scripts from the above are included in compiled form.
QCAD Pro and CAM scripts are proprietary and are not listed there.

There is a good but basic scripting tutorial here:
https://www.ribbonsoft.com/en/tutorial- ... rogramming

The learning curve can be steep to start with and not everything is explained in the finest details.
In the end there is no practical limit but your imagination.
The QCAD API is quite vast and you probably won't have an overview in a matter of days.
One can always look at functional scripts or existing methods and fall back on things that work.
Then there is trial and error. The outcome is not always what you expected at first.
This forum is also the place to get help for specific cases.
Please explain your problem in details, include a partial code segment, include a data source or a test file.

One can find most classes here:
https://qcad.org/doc/qcad/3.0/developer/index.html

Regards,
CVH

marekw2143
Junior Member
Posts: 10
Joined: Sat Sep 09, 2023 1:36 pm

Re: How to create complex script

Post by marekw2143 » Mon Oct 02, 2023 10:41 am

thanks!
I think that for my current needs, it would be very helpful to just create new document and then save it. maybe you know, where is sample script, which can be loaded via "Misc --> Development --> Run Script" command, which presents how to create new document and save it? I'm looking at https://github.com/qcad/qcad/blob/dc10f ... ter.js#L78 but maybe there's some script which does just that, so that I (and maybe some other users, which want to create scripts which draw something and then export that drawing to file) can focus on "business logic" instead of finding out how to create ned document and save it?

CVH
Premier Member
Posts: 3480
Joined: Wed Sep 27, 2017 4:17 pm

Re: How to create complex script

Post by CVH » Mon Oct 02, 2023 3:53 pm

Hi,

A new file exporter is intended for supporting export to a certain file format.
There is dxf/dwg, svg, pdf, bitmap, ... Think of other 2D formats, iges, step, g-code and so on.

Creating a new document and saving it is fairly simple, see:
https://github.com/qcad/qcad/blob/maste ... drawing.js

Regards,
CVH

marekw2143
Junior Member
Posts: 10
Joined: Sat Sep 09, 2023 1:36 pm

Re: How to create complex script

Post by marekw2143 » Mon Oct 02, 2023 4:58 pm

thanks for a quick response. are you a developer of a qcad?

marekw2143
Junior Member
Posts: 10
Joined: Sat Sep 09, 2023 1:36 pm

Re: How to create complex script

Post by marekw2143 » Mon Oct 02, 2023 5:50 pm

I'm trying to perform some action: https://gist.github.com/marekw2143/4a27 ... 30e1e308a9 , new position in in "File" menu is added, but after clicking it, it seems that "beginEvent" is not called. Am I missing something?

CVH
Premier Member
Posts: 3480
Joined: Wed Sep 27, 2017 4:17 pm

Re: How to create complex script

Post by CVH » Mon Oct 02, 2023 6:23 pm

marekw2143 wrote:
Mon Oct 02, 2023 4:58 pm
Are you a developer of a qcad?
Noop, but I know a little my way around in scripting under QCAD.
A few of my projects made it to the standard release. :wink:

2 remarks:
- It is common to include the init section as last function.
Or even as a separated ***Init.js script file. Not problematic.
- 39 this.terminate(); tells QCAD to terminate the action that started your script.
I suspect that Hello World! is displayed in the Command History because that is executed just before the termination.

Regards,
CVH

marekw2143
Junior Member
Posts: 10
Joined: Sat Sep 09, 2023 1:36 pm

Re: How to create complex script

Post by marekw2143 » Mon Oct 02, 2023 6:40 pm

kk. now I have another question :)

I'm trying to add UI, following this tutorial: https://qcad.org/en/tutorial-interactive-script-actions. My code is here:
- https://gist.github.com/marekw2143/4a27 ... 30e1e308a9 - plugin's code (without init function)
- https://gist.github.com/marekw2143/609e ... df05a83cd3 - ui definition

when clicking option in the menu, `Krokus::init setUiOptions called` text is logged to the console, but no new gui widget is shown.

Maybe you know what can I do to show the widget?

CVH
Premier Member
Posts: 3480
Joined: Wed Sep 27, 2017 4:17 pm

Re: How to create complex script

Post by CVH » Mon Oct 02, 2023 7:36 pm

It is common to define the class constructor, which calls the base class constructor before deriving our class from the base class.
I think that you need to remove the first occurrence of:
14 Krokus.prototype = new EAction();

Further you need to remove the doubled starting a transaction and adding a line:

Code: Select all

function addLine(doc) {
  startTransaction( doc );
  addLine(0,0, 100, 100);
  endTransaction();
};
addLine(...) is a Simple API method, you included simple.js at the top of your script and you already call it in line 40.
I have to advice against global functions that have the same name as standard QCAD resources.

The UI is simplistic enough, it should pop up in the common Options Toolbar.
Probably you need to be more precise for the path of the UI.
I don't think that QLabel '&Length:' will work as intended.

To retrieve the value of the Radius field is another matter.

Regards,
CVH

marekw2143
Junior Member
Posts: 10
Joined: Sat Sep 09, 2023 1:36 pm

Re: How to create complex script

Post by marekw2143 » Wed Oct 04, 2023 7:52 pm

thanks CVH!

I've checked and put absolute path to .ui file, and still not working.

I've ensured given path is ok in command line (stat'ed the file, I'm using linux).

CVH
Premier Member
Posts: 3480
Joined: Wed Sep 27, 2017 4:17 pm

Re: How to create complex script

Post by CVH » Thu Oct 05, 2023 2:21 am

Please send me a link or a copy of the script in present state.

Regards,
CVH
Last edited by CVH on Sun Oct 08, 2023 5:11 am, edited 1 time in total.

marekw2143
Junior Member
Posts: 10
Joined: Sat Sep 09, 2023 1:36 pm

Re: How to create complex script

Post by marekw2143 » Thu Oct 05, 2023 8:50 am

Whole project is here: https://github.com/marekw2143/krokus .

CVH
Premier Member
Posts: 3480
Joined: Wed Sep 27, 2017 4:17 pm

Re: How to create complex script

Post by CVH » Fri Oct 06, 2023 8:23 pm

Hi, found the project.

In KrokusInit.js line 7 action.setNoState(); sets that there is no interactive state in your script.
No interaction also means no options to choose from in the Options Toolbar.
Showing the UI has no meaning because it would disappear when the script ends.
You could rule this out, but then it would only be visible for a blink of an eye.

This is caught in debugger mode:
Krokus.png
Krokus.png (11.89 KiB) Viewed 9794 times

I see an effort in creating a dialog widget.
The UI that you define within an action is intended for the Options Toolbar (see above).
For a hit and run script you could display the UI as a dialog.

Please find the main code including some remarks (see #CVH#):

Code: Select all

include("scripts/EAction.js");
include("scripts/File/File.js");    // #CVH# Further unused
//include("scripts/EAction.js");    // #CVH# Ruled out: Double
include("scripts/Tools/arguments.js");    // #CVH# Further unused
include("scripts/sprintf.js");    // #CVH# Further unused
include("scripts/simple.js");
include("scripts/WidgetFactory.js");    // #CVH# Further unused

function dbg(text) {
  var toLog = "Krokus::" + text;
  qDebug( toLog );
};

function CLOG(prefix) {    // #CVH# Question: What does the variable 'text' refer to?
  return function(text) {
    dbg(prefix + " " + text);
  }
};


function Krokus(guiAction) {
  EAction.call(this, guiAction);

  dbg("init called");
  this.setUiOptions(Krokus.includeBasePath + "/Krokus.ui");    // #CVH# Simplified
  dbg("init setUiOptions called");
};

Krokus.prototype = new EAction();
Krokus.includeBasePath = includeBasePath;

//Krokus.prototype = new EAction();    // #CVH# Ruled out: Double

Krokus.prototype.getProperties = function() {
    var dbg = CLOG("getProperties");
    dbg("getProperties called");

    var doc = EAction.getDocument();
    var layerNames = doc.getLayerNames();

    var appWin = EAction.getMainWindow();

    dbg("aa");
//    this.dialog = WidgetFactory.createDialog( Krokus.includeBasePath, "Krokus.ui", appWin);
    dbg("bb");

//    WidgetFactory.restoreState(this.dialog);
//    var widgets = getWidgets(this.dialog);
//    this.dialog.exec();
//    WidgetFactory.saveState( this.dialog);
};

Krokus.prototype.beginEvent = function() {
    qDebug("Krokus - entering beginEvent");

    EAction.prototype.beginEvent.call(this);
    this.getProperties();

  EAction.handleUserMessage("rysowanie linii!");

debugger;    // #CVH# Included to catch the UI in debugger mode with setNoState() ruled out.

    // create a document:
    var doc = EAction.getDocument();    // #CVH# Does not create a new document, it retrieves the current document

    // add something to the document:
    startTransaction(doc);

    for (var i = 0; i < 100; i += 12) {
        var x = 100 + i;
        var y = 100 - i;
        addLine(0,0, x, y);
    }

    endTransaction();

    this.terminate();    // #CVH# Added to terminate the current action.
};
I also formatted everything a bit neater. :wink:

Remark that you don't create a new document as before.
The action immediately draws 9 lines on the current active document.

Regards,
CVH
Last edited by CVH on Sun Oct 08, 2023 5:08 am, edited 1 time in total.

marekw2143
Junior Member
Posts: 10
Joined: Sat Sep 09, 2023 1:36 pm

Re: How to create complex script

Post by marekw2143 » Sat Oct 07, 2023 1:18 pm

thanks great CVH,

but how can I create a dialog ? :) using code like:

Code: Select all

var appWin = EAction.getMainWindow();

var path = "/home/marek/opt/qcad-3.28.2-trial-linux-qt5.14-x86_64/scripts/Misc/Krokus";
this.dialog = WidgetFactory.createDialog(path, "Krokus.ui", appWin);
WidgetFactory.restoreState(this.dialog);

this.dialog.exec();
WidgetFactory.saveState( this.dialog );
results in error:

Code: Select all

Warning:  RScriptHandlerEcma::eval: script engine exception:  "TypeError: Result of expression 'this.dialog.exec' [undefined] is not a function."
I just want to show the window with desired options :) I'm basing code with dialog on this code: https://github.com/schmidtw/qcad-script ... ort.js#L93

marekw2143
Junior Member
Posts: 10
Joined: Sat Sep 09, 2023 1:36 pm

Re: How to create complex script

Post by marekw2143 » Sat Oct 07, 2023 1:21 pm

and, regarding

Code: Select all

function CLOG(prefix) {    // #CVH# Question: What does the variable 'text' refer to?
  return function(text) {
    dbg(prefix + " " + text);
  }
};
CLOG is a logger factory, which generates function (defined by

Code: Select all

function(text) { dbg( prefix + " " + text ); };
which logs text with defined prefix (which is specific to given logger).

Post Reply

Return to “QCAD Programming, Script Programming and Contributing”