Page 1 of 1

Scripting question, open template

Posted: Thu Jun 16, 2011 8:38 pm
by hungerburg
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

Posted: Thu Jun 16, 2011 9:25 pm
by andrew
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();

on the right track?

Posted: Fri Jun 17, 2011 1:20 pm
by hungerburg
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?

Posted: Fri Jun 17, 2011 1:33 pm
by andrew
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(...)').

Start from "New()"

Posted: Fri Jun 17, 2011 2:11 pm
by hungerburg
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 :)

Re: Start from "New()"

Posted: Fri Jun 17, 2011 4:01 pm
by andrew
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'.

save template

Posted: Fri Jun 17, 2011 6:42 pm
by hungerburg
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?

Re: Scripting question, open template

Posted: Wed Aug 29, 2012 8:53 am
by hungerburg
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

Re: Scripting question, open template

Posted: Wed Aug 29, 2012 9:56 am
by hungerburg
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