Scripting question, open template

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
User avatar
hungerburg
Premier Member
Posts: 160
Joined: Fri May 28, 2010 7:35 pm

Scripting question, open template

Post by hungerburg » Thu Jun 16, 2011 8:38 pm

Before spending hours on what is bothering me now, I will just be bold and ask for a hint ;)

If in QCad2 I wanted to draw on a template, a single line of code was sufficient app.fileOpen("Vorlage.dxf");

I looked at the files in the script directory, there is of course a "load template" script. I wonder, how to wrap this into a function, that I can call in my own script as convenient as that one. Please share your ideas!

Regards

Peter

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

Post by andrew » Thu Jun 16, 2011 9:25 pm

Since a lot of the GUI part is implemented in ECMAScript (all MDI related things, how a document window looks like, scroll bars, rulers, etc.), you need to call that same script in order to get the same effect as when the user opens a file through the menu or tool button.

The script to open a file is located in scripts/File/Open/Open.js and can be used as follows in QCAD TP1:

Code: Select all

include("scripts/File/Open/Open.js");
...
var action = new Open();
action.openFile("Vorlage.dxf");
action.finishEvent();
You might want to create a wrapper function for this, so it can be easily ported if the script API changes for the final QCAD version. Class 'Open' will be called 'OpenFile' in the next QCAD release since we had some problems with class names like 'Open' or 'New'. So the code above will change for QCAD TP2 to:

Code: Select all

include("scripts/File/OpenFile/OpenFile.js");
...
var action = new OpenFile();
action.openFile("Vorlage.dxf");
action.finishEvent();

User avatar
hungerburg
Premier Member
Posts: 160
Joined: Fri May 28, 2010 7:35 pm

on the right track?

Post by hungerburg » Fri Jun 17, 2011 1:20 pm

I started with the wrapper. It currently looks like this:

Code: Select all

include("scripts/File/Open/Open.js"); // TP2 // include("scripts/File/OpenFile/OpenFile.js");

/**
 * Hilfsfunktion Vorlage öffnen, Namen der neuen Datei festlegen.
 * @constructor
 * @param {String} nameV Name/Pfad der Vorlage
 * @param {String} nameF Name/Pfad der neuen Datei
 */
function Vorlage(nameV, nameF) {
	this.openFile(nameV);
	this.finishEvent();
	this.document.setFileName(nameF);
	this.mdiChild.setWindowTitle(nameF);
}
Vorlage.prototype = new Open(); // TP2 // Vorlage.prototype = new OpenFile();
I can use it from my code like this:

Code: Select all

var Zeichnung = new Vorlage("Vorlage.dxf", "Zeichnung");
debugger; // inspect this

var operation = new RAddObjectsOperation(false);
var r = 10;
var off = 2 * Math.PI / 2000;
var c = 0;
for ( var a = 0.0; a < 2 * Math.PI; a += off) {
	var lineData = new RLineData(
		new RVector(Math.cos(a)*r, Math.sin(a)*r, 0),
		new RVector(Math.cos(a + off) * r, Math.sin(a + off) * r, 0)
	);
	var line = new RLineEntity(Zeichnung.document, lineData);
	operation.addObject(line);
	++c;
}

Zeichnung.documentInterface.applyOperation(operation);
The drawing functions are taken from simple.js in the samples directory. Notice that "new RLineEntity()" takes two parameters, unlike in the example.

Am I on the right track?

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

Post by andrew » Fri Jun 17, 2011 1:33 pm

Yes, that looks good.

A small detail: we always start class names with a capital letter and variable names with a small letter (e.g. 'var zeichnung = new Vorlage(...)').

User avatar
hungerburg
Premier Member
Posts: 160
Joined: Fri May 28, 2010 7:35 pm

Start from "New()"

Post by hungerburg » Fri Jun 17, 2011 2:11 pm

Will it be better to start from "New()" ?

Code: Select all

include("scripts/File/New/New.js"); // TP2 // include("scripts/File/NewFile/NewFile.js");

/**
 * Hilfsfunktion Vorlage öffnen, Namen der neuen Datei festlegen.
 * @constructor
 * @param {String} template Name/Pfad zur Vorlage
 * @param {String} path Pfad der neuen Datei
 * @param {String} name Name der neuen Datei
 */
function Vorlage(template, path, name) {
	New.prototype.beginEvent.call(this, false);
	if (this.documentInterface.importFile(template) != RDocumentInterface.IoErrorNoError) {
		var dlg = new QMessageBox(QMessageBox.Warning,
								  "Vorlage nicht gefunden",
								  "Vorlage nicht gefunden\n\n'%1'\n".arg(template),
								  QMessageBox.OK);
		dlg.exec();
		this.terminate();
		return;
	}
	this.documentInterface.regenerateScenes();
	this.documentInterface.autoZoom();
	this.document.setFileName(path + "/" + name);
	this.mdiChild.setWindowTitle(name);
}
Vorlage.prototype = new New(); // TP2 // Vorlage.prototype = new NewFile();
When inspecting in the debugger I see that the object created from "Vorlage()" is of type "ActionAdaptor" - will that make problems?

(Peter Happy Hacking :)

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

Re: Start from "New()"

Post by andrew » Fri Jun 17, 2011 4:01 pm

hungerburg wrote:Will it be better to start from "New()" ?
In my opinion, both solutions are equally good. Opening a template is indeed somewhere between New and Open.
hungerburg wrote:When inspecting in the debugger I see that the object created from "Vorlage()" is of type "ActionAdaptor"
This is normal for all actions (tools). The complete inheritance hierarchy is:

Code: Select all

RAction
RActionAdapter
EAction
New
Vorlage
The debugger calls the toString() function to display information about an object. toString() is implemented for all C++ class wrappers (classes starting with an R) to return the class name. Of course, you can also overwrite toString for your ECMAScript class, for example:

Code: Select all

Vorlage.prototype.toString = function() {
   return 'Vorlage';
}
The debugger will then identify objects of that class with 'Vorlage'.

User avatar
hungerburg
Premier Member
Posts: 160
Joined: Fri May 28, 2010 7:35 pm

save template

Post by hungerburg » Fri Jun 17, 2011 6:42 pm

Thank you Andrew for your attentiveness. Slowly I am getting the knack:

Code: Select all

Vorlage.prototype.save = function() {
	 return new Save().save(this.document.getFileName());
}
Will save the file. Can I depend upon it, that this will be dxf? Is this determined by extension?

User avatar
hungerburg
Premier Member
Posts: 160
Joined: Fri May 28, 2010 7:35 pm

Re: Scripting question, open template

Post by hungerburg » Wed Aug 29, 2012 8:53 am

Sorry for waking up this old thread. Yet, the method in here, to programmatically open a template and use it as a base for further scripted drawing, got broken between release candidate 5 and qcad 3 final.

Code: Select all

NewFile.prototype.beginEvent.call(this, false);
will no longer stuff the callers "this" with all the "documentInterface", "mdiChild" etc. properties.

As NewFile does quite a lot of initializations, I hesitate to reproduce all of its functionality in my own code, and would like to "inherit" again most of that.

Please advise, how in qcad 3, to open a template programmatically.

Thank You

Peter

User avatar
hungerburg
Premier Member
Posts: 160
Joined: Fri May 28, 2010 7:35 pm

Re: Scripting question, open template

Post by hungerburg » Wed Aug 29, 2012 9:56 am

Got it sorted out by looking at "NewFromTemplate":

Code: Select all

NewFile.createMdiChild();
this.documentInterface = EAction.getDocumentInterface();
this.document = EAction.getDocument();
in place of "NewFile.prototype.beginEvent.call(this, false);" seems to do what I want.

Though I do not understand, why this works without passing some handles, it works flawlessly, creating several tabs in sequence, even from the same template.

--
Peter

Post Reply

Return to “QCAD Programming, Script Programming and Contributing”