Using NewFile.addPostNewAction

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.

Post Reply
jcn
Newbie Member
Posts: 7
Joined: Thu Apr 08, 2021 8:14 pm

Using NewFile.addPostNewAction

Post by jcn » Wed May 19, 2021 2:25 am

64 bit Win10, QCAD Version 3.26.2

Javascript is new to me (I'm not a programmer, but my background is in C going back to days at Bell Labs, some C++ and VisualBasic), but I've been managing to write a number of very useful scripts for my application with QCAD using the Forum, example code, the tutorials, and Google.

At this point, I want to have a custom script run whenever a new file or an existing file is opened. I have found:

NewFile.addPostNewAction("scripts/MyStuff/MyFileInit.js");

(and also NewFile.addPostOpenAction)

which appears that it should do what I want, but I haven't been able to make it work and haven't been able to find examples or documentation on this.

The main question is where would I include the command above (assuming that is the correct step)?

When I put it into a command line script loaded with -exec, "addPostNewAction" will run correctly (as seen by single-stepping in the debugger), but when a new file is launched, the NewFile.postNewActions[k] array that is used when QCAD calls NewFile.js is empty.

I also tried putting it into NewFile.js directly, but I'm thinking that isn't the correct approach. When I did run the command there, my script would run when a new file was opened (verified with the debugger), but then QCAD would crash. The script which ran simply put out a message with QMessageBox.

Any help will be appreciated. I'm expecting that it is straightforward when done correctly, but after much searching, I haven't found an example.

Thanks.

jcn

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

Re: Using NewFile.addPostNewAction

Post by CVH » Wed May 19, 2021 5:58 am

jcn wrote:
Wed May 19, 2021 2:25 am
I've been managing to write a number of very useful scripts for my application with QCAD using the Forum, example code, the tutorials, and Google.
Two sources of interest:
Github: https://github.com/qcad/qcad I have a full copy stored local as data to search in textual.
QCAD Resources: https://qcad.org/doc/qcad/3.0/developer/annotated.html

Maybe a stab in the dark ... Shouldn't there be a full path? Or a relative one?
Something as: NewFile.addPostNewAction(MyFile.includeBasePath + "/MyFileInit.js");

Instead of "/" or "\" literal one finds rather more the use of "+ QDir.separator +"

Another stab:
"..."+Init.js scripts are used by QCAD to initiate tools on startup.

Regards,
CVH

User avatar
andrew
Site Admin
Posts: 9037
Joined: Fri Mar 30, 2007 6:07 am

Re: Using NewFile.addPostNewAction

Post by andrew » Wed May 19, 2021 6:59 am

There are multiple script engines in QCAD in which a script can run:
- scripts that concern a particular document or drawing run in the script engine of that document (e.g. to add to or modify the drawing, Draw > Line > Line 2P, etc.)
- scripts that concern the application as a whole run in a global script engine (e.g. File > New, File > Close, etc.)

Since File > New runs in the global script engine, you also need to call NewFile.addPostNewAction in the global script engine. This can for example be in the init function of your script tool which is always run in the global script engine during initialization:

Code: Select all

function init(basePath) {
    ...

    NewFile.addPostNewAction("scripts/MyStuff/MyFileInit.js");
}
Your file MyFileInit.js can be of type EAction (i.e. a class with beginEvent) or it can contain a function initNewFile which will be called:

Code: Select all

function initNewFile(mdiChild) {
    ...
}
Note that using -enable-script-debugger can lead to crashes as it potentially changes the order in which things are run.

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

Re: Using NewFile.addPostNewAction

Post by CVH » Wed May 19, 2021 8:32 am

andrew wrote:
Wed May 19, 2021 6:59 am
This can for example be in the init function of your script tool
That figures, only found 'NewFile.add ...' in 2 out of 3 in the init function of a script tool.
And then all with full paths.

Regards,
CVH

jcn
Newbie Member
Posts: 7
Joined: Thu Apr 08, 2021 8:14 pm

Re: Using NewFile.addPostNewAction

Post by jcn » Wed May 19, 2021 6:51 pm

Andrew, thank you for the helpful information, but I am not yet getting it to work.

The key step comes down to the code in NewFile.js:

Code: Select all

        for (k=0; k<NewFile.postNewActions.length; k++) {    //<<<<<<<<<<<<<<<<< issue #1
            if (!isNull(NewFile.postNewActions[k])) {
                include(NewFile.postNewActions[k]);
                if (isFunction(initNewFile)) {		// <<<<<<<<<<<<<<<<<< issue #2
                    initNewFile(mdiChild);
                }
                action = RGuiAction.getByScriptFile(NewFile.postNewActions[k]);
                if (!isNull(action)) {
                    action.slotTrigger();
                }
            }
        }
I have labeled the trouble spots as "issue #1" and "issue #2".

For issue #2, you wrote:
Your file MyFileInit.js can be of type EAction (i.e. a class with beginEvent) or it can contain a function initNewFile which will be called:
When I used a functional MyFileInit.js file with a beginEvent, I still couldn't get past the if statement at issue #2. But when I added the "initNewFile" function to the EAction script, it would work. So that was a positive step.

Now, for issue #1, the trouble is that the NewFile.postNewActions.length is always zero. Based on my original diagnostics, I had suspected that this was related to running in the "global script engine" that you described, but didn't know the terminology or exactly what to do about it. So far, I have only gotten past issue #1 by directly modifying NewFile.js and putting the addPostNewAction call in that file. This seems to be a reasonable option for diagnostics (for example to confirm that the relative path is working and if the MyFileInit.js file is well behaved), but not a good long term solution.

For the startup command line script run with "-exec", I haven't had any success. My original attempt just used a simple script (with no beginEvent) and the for loop at issue #1 would happen before the "-exec" script would even run. I have now also used "-exec" with an Eaction script with the addPostNewAction call in beginEvent and also in a "function init(basePath)" as in your original reply.

In testing with and without the debugger, my attempts with "-exec" always result in an empty array at issue #1.

It would seem that I'm missing something about how to put the addPostNewAction call into the init function of the script tool which is always run in the global script engine during initialization.

Can you offer additional insight? Thanks in advance.

jcn

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

Re: Using NewFile.addPostNewAction

Post by CVH » Thu May 20, 2021 5:27 am

Hi,
It would be helpful if you posted a snippet with the key lines of code of your script itself and of your script init function.

I suspect a mixup between MyFile.js and MyFileInit.js
Before it was common that the init function was part of MyFile.js
More recently the init function is placed in a separated file MyFileInit.js
(Works just the same as far as I can tell.)

It also could be a naming issue:
If MyFileInit.js is the script itself ....
The init function is then MyFileInit.init = function(basePath) {...}

This init function is called once at startup.
(Andrew: "during initialization","in the global script engine")
In there should be the addPostNewAction with "My.....js"

Newfile would then:
- Include your script
- call the initNewFile function if existing
- call the GuiAction (beginevent) if existing

Regards,
CVH

User avatar
andrew
Site Admin
Posts: 9037
Joined: Fri Mar 30, 2007 6:07 am

Re: Using NewFile.addPostNewAction

Post by andrew » Thu May 20, 2021 8:09 am

Is your script MyFileInit.js stored somewhere where QCAD can find it during startup (i.e. in a folder called "MyFile" in the "scripts" directory of QCAD)?

Is the script being run during startup? Perhaps you can insert a qDebug("MyFileInit"); somewhere at the top of the script to check this.

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

Re: Using NewFile.addPostNewAction

Post by CVH » Thu May 20, 2021 8:37 am

Andrew,
Can't get it to work eighter

This code below in an initialization script seems to add a postNewActions.
File: ... QCAD\scripts\Misc\Examples\Ex2MyPostNew\Ex2MyPostNewInit.js

Code: Select all

function init(basePath) {
    if (!isNull(NewFile)) {
        NewFile.addPostNewAction(basePath + "/Ex2MyPostNew.js");
    }
// Verifying at startup:
var test = NewFile.postNewActions;
debugger;
}
The script itself
File: ... QCAD\scripts\Misc\Examples\Ex2MyPostNew\Ex2MyPostNew.js

Code: Select all

function initNewFile(mdiChild){
debugger;
    var appWin = EAction.getMainWindow();
    QMessageBox.warning(appWin,
            "Post NewFile:",
            "........ Hello World.");
    EAction.handleUserMessage(qsTr("Hello World."));
    return;
}
When starting a new file after startup the postNewActions array is empty.

The other trial I made was Ex1MyPostNew and of type EAction with beginEvent.
This adds an entry to Misc..Scripts Examples, what is functional.
It also seems to add a second entry in postNewActions.
Again on a new file the postNewActions array is empty.

Regards,
CVH

User avatar
andrew
Site Admin
Posts: 9037
Joined: Fri Mar 30, 2007 6:07 am

Re: Using NewFile.addPostNewAction

Post by andrew » Thu May 20, 2021 9:33 am


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

Re: Using NewFile.addPostNewAction

Post by CVH » Thu May 20, 2021 11:37 am

Thanks, Andrew.

It also works with the ExNewFileHandler.js code merged in ExPostNewAction.js
And referring to that script:
NewFile.addPostNewAction(basePath + "/ExPostNewAction.js");

I am now trying to explain why my other trial with a beginEvent is failing.
include? check, EAction.call? check, prototype? check, beginEvent? check ...
Seems to be something fundamentally different with common scripts.
Not my cup of thee. :oops:

Kind regards,
CVH

jcn
Newbie Member
Posts: 7
Joined: Thu Apr 08, 2021 8:14 pm

Re: Using NewFile.addPostNewAction

Post by jcn » Thu May 20, 2021 10:00 pm

To everyone, thank you for the tips and suggestions. I am pretty new to QCAD and still on the steep part of the scripting learning curve, so every bit helps!

Andrew, thank you for the code. At this point, I've decided to change my approach to use what is working in your example code and not try to use the command line script, so my original trouble has been avoided.

My original thought had been to call the NewFile.addPostNewAction() function as part of an external script called with "-exec" on the QCAD command line. After seeing your code work, I did play with the command line approach some more, but was still unable to make it work. I expect I'm just missing something, but I will leave it for another time and continue with what is working. Thanks again for the code, it has given me what appears to be a viable alternative to my original approach!

To all, continue reading only if you are interested in some debugging checks on Andrew's code.

When QCAD is launched using the following (which is the 'Target' in a Windows shortcut):

"C:\Program Files\QCAD\qcad.exe"

the QCAD Command History shows (I added line numbers to clarify the notes below):

1) QCAD 3.26.1 / Windows x86_64
2) Calling: NewFile.addPostNewAction()
3) Command: new
4) NewFile.postNewActions[0] = scripts/Misc/Examples/IOExamples/ExPostNewAction/ExNewFileHandler.js
5) New file created

Line 1: automatically generated
Line 2: my debug statement in: ExPostNewActionInit.js
Line 3: automatically generated
Line 4: my debug statement in: NewFile.js when it is calling the external script
Line 5: Andrew's debug statement : ExNewFileHandler.js

It can be seen that ExPostNewActionInit.js is run early at Line 2, the relative path is called in Line 4, and ExNewFileHandler.js runs as expected at Line 5. For each new file that is opened, lines 3-5 all run again.

One discovery was that the "-always-load-scripts" option apparently prevents ExNewFileHandler.js from being called. In that case, there is no line 5 and line 4 becomes:

4) NewFile.postNewActions[0] = undefined

This happens even though Line 2 is run successfully.

But it all appears to work with only the "-enable-script-debugger" flag set.

Next, I launched QCAD with a script using "-exec", but there were no surprises.

Here is the command line:
"C:\Program Files\QCAD\qcad.exe" -exec D:\MyScripts\_HelloWorld.js

Command History:
1) QCAD 3.26.1 / Windows x86_64
2) Calling: NewFile.addPostNewAction()
3) Command: new
4) NewFile.postNewActions[0] = scripts/Misc/Examples/IOExamples/ExPostNewAction/ExNewFileHandler.js
5) New file created
6) Hello World! // _HelloWorld.js is just: EAction.handleUserMessage("Hello World!");

Post Reply

Return to “QCAD Programming, Script Programming and Contributing”