Using NewFile.addPostNewAction
Moderator: andrew
Forum rules
Always indicate your operating system and QCAD version.
Attach drawing files, scripts and screenshots.
Post one question per topic.
Always indicate your operating system and QCAD version.
Attach drawing files, scripts and screenshots.
Post one question per topic.
Using NewFile.addPostNewAction
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
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
Re: Using NewFile.addPostNewAction
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
Re: Using NewFile.addPostNewAction
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:
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:
Note that using -enable-script-debugger can lead to crashes as it potentially changes the order in which things are 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");
}
Code: Select all
function initNewFile(mdiChild) {
...
}
Re: Using NewFile.addPostNewAction
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:
I have labeled the trouble spots as "issue #1" and "issue #2".
For issue #2, you wrote:
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
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();
}
}
}
For issue #2, you wrote:
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.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:
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
Re: Using NewFile.addPostNewAction
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
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
Re: Using NewFile.addPostNewAction
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.
Is the script being run during startup? Perhaps you can insert a qDebug("MyFileInit"); somewhere at the top of the script to check this.
Re: Using NewFile.addPostNewAction
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
The script itself
File: ... QCAD\scripts\Misc\Examples\Ex2MyPostNew\Ex2MyPostNew.js
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
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;
}
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;
}
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
Re: Using NewFile.addPostNewAction
I've posted a minimal example at:
https://github.com/qcad/qcad/tree/2647b ... tNewAction
https://github.com/qcad/qcad/tree/2647b ... tNewAction
Re: Using NewFile.addPostNewAction
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.
Kind regards,
CVH
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.
Kind regards,
CVH
Re: Using NewFile.addPostNewAction
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!");
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!");