[Solved]Listing Entity's Properties

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
Ghost_of_Magellan
Full Member
Posts: 58
Joined: Wed Mar 16, 2016 5:10 pm

[Solved]Listing Entity's Properties

Post by Ghost_of_Magellan » Wed Mar 16, 2016 5:43 pm

Windows 7, Qcad 3.12.4

Greetings.

I am a fair noob in JavaScript, but wanted to make a plugin for QCad. I have been poking about in Qt Designer so I'm fairly sure I can make a reasonable UI for it, but having explored the code of Property Editor, I have failed to fully grasp how to even understand how to read the property values of entities. I also don't quite grasp all the properties available and how to use them to get data.

In short, I wanted to make a plugin that acted like the widget plugins (those that appear on the right side of the screen, Property Editor, Layer List, Block List, etc) that read the properties of every entity on the drawing board and listed them on a listview, organized according to their printing order on, for example, a laser printer. (I may be wrong, but i think this order is defined by the 'Handle' variable)

Here's an example:
3 entities on the drawing board. A Line (0;0 to 10;10), an arc (10;10 to 20;10 with 15;10 as center), and a line (20;10 to 20;20). Entities should not need to be selected.
The listview should show:
Line Xi Yi Xf Yf Cx Cy
1 0 0 10 10 - -
2 10 10 20 10 15 10
3 20 10 20 20 - -

This should be enough for me to grasp how this works and point me towards where I want to evolve the plugin.

Thanks in advance.
Last edited by Ghost_of_Magellan on Fri Apr 15, 2016 7:06 pm, edited 1 time in total.

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

Re: Listing Entity's Properties

Post by andrew » Thu Mar 17, 2016 7:49 am

I'd start by implementing a text display widget with a button to manually update its contents. You can always later trigger the update automatically whenever something changes in the drawing (this will of course slow down the drawing process for larger drawings).

To iterate over all visible entities in the document and list some of their properties:
var doc = EAction.getDocument();
var entityIds = doc.queryAllVisibleEntities();
// order entities back to front:
entityIds = doc.getStorage().orderBackToFront(entityIds);
for (var i = 0; i < entityIds.length; ++i) {
    var entity = doc.queryEntity(entityIds);
    var line = "" + entity.getId() + " ";
    if (isLineEntity(entity)) {
        line += entity.getStartPoint().x + " ";
        line += entity.getStartPoint().y + " ";
        line += entity.getEndPoint().x + " ";
        line += entity.getEndPoint().y;
    }

    // handle other entity types...

    // add string in 'line' to widget...
}

Ghost_of_Magellan
Full Member
Posts: 58
Joined: Wed Mar 16, 2016 5:10 pm

Re: Listing Entity's Properties

Post by Ghost_of_Magellan » Thu Mar 17, 2016 10:25 am

Greetings, and thank you for the example, andrew.
I will attempt to make it work later in the day and will report on my progress as soon as I do.

Thank you once again.

Ghost_of_Magellan
Full Member
Posts: 58
Joined: Wed Mar 16, 2016 5:10 pm

Re: Listing Entity's Properties

Post by Ghost_of_Magellan » Tue Mar 22, 2016 1:19 pm

Greetings. I apologize for the delay in responding, I was away for most of the week and weekend.

I have successfully tested your example, though I printed the results only in command line, and I have a few questions.
This is the code so far:

Code: Select all

var doc = EAction.getDocument();
var entityIds = doc.queryAllVisibleEntities();
entityIds = doc.getStorage().orderBackToFront(entityIds);

	for (var i = 0; i < entityIds.length; ++i) {
		var entity = doc.queryEntity(entityIds[i]);
		var line = "" + entity.getId() + " ";

		if (isLineEntity(entity)) {
			line += entity.getStartPoint().x + " ";
			line += entity.getStartPoint().y + " ";
			line += entity.getEndPoint().x + " ";
			line += entity.getEndPoint().y;
		}
		if (isArcEntity(entity)) {
			line += entity.getStartPoint().x + " ";
			line += entity.getStartPoint().y + " ";
			line += entity.getEndPoint().x + " ";
			line += entity.getEndPoint().y + " "; 
			line += entity.getRadius();
		}
		appWin.handleUserMessage(line);
	}
	appWin.handleUserMessage("********** End **********");
Not much differing from the given code.
So here begin my questions. Imagine that we make a drawing with two entities, two lines with coordinates: 0;0 to 10;0 and 10;0 to 20;10. The script will print:

Code: Select all

53 0 0 10 0
54 10 0 20 10
********** End **********
So far so good, everything perfect. Then I copy ythose two entities and paste them twice over, so I have a drawing with 6 entities. The script will print the following:

Code: Select all

53 0 0 10 0
58 50 0 60 10
56 30 0 40 10
54 10 0 20 10
55 20 0 30 0
57 40 0 50 0
********** End **********
The Id atributed to each entity is correct, there is no problem there. However, when I save the dxf file and put into my printing program, it prints exactly in the listing order of the command lines, meaning that it will print Id 53, then 58 (when i wanted it to print 54) and then 56 (when it should print 55), and so on.
I have thought to create a sorting function that would create a temporary copy of entityIds and reorganize it before overwriting entityIds with it, unfortunately, I understand that it will serve of nothing because entityIds is not what actually controls this process but only a variable that holds the data for my observation. I'm assuming the original data, relevant to this issue is in doc.queryAllVisibleEntities();, or any such functions that likely include the doc. class.
Is there any way I can control the printing order through this list so as to allow me to copy and paste segments of the same drawing IN ORDER? I can't find anything like it in the Qcad library functions, though i will admit most of them go a bit over my head.

Thank you once again.

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

Re: Listing Entity's Properties

Post by andrew » Tue Mar 22, 2016 1:49 pm

The property that controls display order is called 'draw order':
Screen Shot 2016-03-22 at 13.40.13.png
Screen Shot 2016-03-22 at 13.40.13.png (68.94 KiB) Viewed 10625 times
Copy / paste should preserve draw order, although I just noticed, there's a bug with the very first entity that is drawn or loaded:
http://www.qcad.org/bugtracker/index.ph ... sk_id=1404

This will be fixed in the next release. For now, you can simply assign another draw order to that entity using the property editor.

You might want to print the draw order in your list for debugging:
entity.getDrawOrder()

Ghost_of_Magellan
Full Member
Posts: 58
Joined: Wed Mar 16, 2016 5:10 pm

Re: Listing Entity's Properties

Post by Ghost_of_Magellan » Tue Mar 22, 2016 5:39 pm

Thank you andrew, for the help and the swift reply.
I'll work on it and request additional assistance if necessary.
Should this be my last post until then, then a happy Easter for you and your family.

Juat for the sake of information, this is what the console prints out when I add the printing order as the second column:

Code: Select all

ID DrawOrder xi yi xf yf
53 0 0 0 10 0
60 1 50 0 60 10
58 1 30 0 40 10
54 1 10 0 20 10
57 3 20 0 30 0
59 4 40 0 50 0
********** End **********

Ghost_of_Magellan
Full Member
Posts: 58
Joined: Wed Mar 16, 2016 5:10 pm

Re: Listing Entity's Properties

Post by Ghost_of_Magellan » Tue Apr 05, 2016 11:11 pm

Given that this is still on the same matter of printing to a listview, I'll keep it on the same post.

I have been trying to find examples on how to build arrays to put in the data on the entities list and then pass the desired properties onto a listview I have created on Qt designer, but I have been unsuccessful so far in applying it to QCad scripting.
I would apreciate if an example could be provided on how to do it.

To clarify. I have:

Code: Select all

var entityIds = doc.queryAllVisibleEntities();
entityIds = doc.getStorage().orderBackToFront(entityIds);
that holds the entire data of the whole document and then I have:

Code: Select all

var entity = doc.queryEntity(entityIds[i]);
that holds the data on a single entity.

What I want is to add the properties of

Code: Select all

entity.getStartPoint().x;
 entity.getStartPoint().y;
 entity.getEndPoint().x;
 entity.getEndPoint().y; 
To a list.

I am assuming to achieve this I first have to prepare the listview or list widget (haven't yet figured out what's the diference between the two) to receive specific data types in a specific number by line, but this too, I'm not sure how to do it.
And then there is the proper way to add the data to the object. I have named the listview "Obj_listview " and the ListWidget "Obj_ListWidget".

My apologies for the basic questions, and thank you.

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

Re: Listing Entity's Properties

Post by andrew » Wed Apr 06, 2016 8:20 am

If you have a list widget (type QListWidget), you don't need a list view (QListView).

QListWidget is generally easier to handle since it hides the model behind the view from you.

To add an item to a QListWidget, create the QListWidgetItem first:
var item = new QListWidgetItem("some text");
Where "some text" is the string to be displayed, for example "x: " + entity.getStartPoint().x + ", y: " + entity.getStartPoint().y...

Then use addItem to add the item to the QListWidget:
myListWidget.addItem(item);
Note that this is all Qt API, not QCAD specific. You can find the complete Qt class reference documentation at:
http://doc.qt.io/qt-4.8/classes.html

Ghost_of_Magellan
Full Member
Posts: 58
Joined: Wed Mar 16, 2016 5:10 pm

Re: Listing Entity's Properties

Post by Ghost_of_Magellan » Wed Apr 06, 2016 9:33 am

Thank you for the reply andrew.

I am assuming then that the list widget and listview only allow one column. Meaning that I cannot define the different pieces of data through diferent columns. Is this correct?
If this is correct, would you recomend using multiple lists to simulate this in a more orderly fashion or do you know of a better method?

Another question, if possible.
In the example you have given me previously, where I use

Code: Select all

var entityIds = doc.queryAllVisibleEntities();
to retrieve the entire data table and then

Code: Select all

var entity = doc.queryEntity(entityIds[i]);
to retrieve the line array for the entity in question.

Is it possible for me to, in code and after reordering the var entityIds to my needs, to replace the original data in

Code: Select all

doc.queryAllVisibleEntities();
(Wherever the hell that is)
with my own reordered entityIds?


In the meantime, I have tested the code and failed. What am I doing wrong?
This is my for cycle:
var doc = EAction.getDocument();
		var entityIds = doc.queryAllVisibleEntities();
	
		entityIds = doc.getStorage().orderBackToFront(entityIds);	
			
		for (var i = 0; i < entityIds.length; ++i) {
			var entity = doc.queryEntity(entityIds);
			var line = "" + entity.getId() + " ";	

			line += entity.getDrawOrder() + " ";	
			
			if (isLineEntity(entity)) {	
				line += entity.getStartPoint().x + " ";
				line += entity.getStartPoint().y + " ";
				line += entity.getEndPoint().x + " ";
				line += entity.getEndPoint().y;
			}
			if (isArcEntity(entity)) {	
				line += entity.getStartPoint().x + " ";
				line += entity.getStartPoint().y + " ";
				line += entity.getEndPoint().x + " ";
				line += entity.getEndPoint().y + " "; 
				line += entity.getRadius();
			}
			appWin.handleUserMessage(line);
			
			var item = new QListWidgetItem(line);
			Obj_listWidget.addItem(item);
		}
		appWin.handleUserMessage("Refresh Successful");


When the script runs it prints the "line" string on the command line, but it does does nothing below that. In this case, not even the appWin.handleUserMessage("Refresh Successful"); appears.

Thank you very much.
Last edited by Ghost_of_Magellan on Wed Apr 06, 2016 9:44 am, edited 1 time in total.

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

Re: Listing Entity's Properties

Post by andrew » Wed Apr 06, 2016 9:43 am

Ghost_of_Magellan wrote:I am assuming then that the list widget and listview only allow one column. Meaning that I cannot define the different pieces of data through diferent columns.
Yes, lists have one column. If you need multiple columns, perhaps QTableWidget if what you are looking for.
Is it possible for me to, in code and after reordering the var entityIds to my needs, to replace the original data in

Code: Select all

doc.queryAllVisibleEntities();
(Wherever the hell that is)
with my own reordered entityIds?
If I understand your question correctly, you are looking for a way to reorder entities, i.e. change the drawing order of entities, is that correct?

Ghost_of_Magellan
Full Member
Posts: 58
Joined: Wed Mar 16, 2016 5:10 pm

Re: Listing Entity's Properties

Post by Ghost_of_Magellan » Wed Apr 06, 2016 9:48 am

If I understand your question correctly, you are looking for a way to reorder entities, i.e. change the drawing order of entities, is that correct?
That is correct. Some other option that does not require me to change the order on properties editor by hand. I can think of several ways to reorganize the array, but do not know how to send that order into the core data.

I have edited my previous post, since I didnt manage to make your example on the adding to the list a success. (You were too fast in replying =D)

Thank you for the advice and I do believe I will follow the suggestion of the table widget.

Ghost_of_Magellan
Full Member
Posts: 58
Joined: Wed Mar 16, 2016 5:10 pm

Re: Listing Entity's Properties

Post by Ghost_of_Magellan » Wed Apr 06, 2016 10:00 am

Code: Select all

var item = new QListWidgetItem(line);
widgets["Obj_listWidget"].addItem(item);
Seems this is the right way to do it. =D

Thank you andrew.

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

Re: Listing Entity's Properties

Post by andrew » Wed Apr 06, 2016 10:06 am

Hint: You might want to start QCAD with the -enable-script-debugger switch to enable the script debugger. The script debugger then pops up whenever there is an error in your script or whenever it reaches a

Code: Select all

 debugger;
statement. You can then step through your code, investigate variables, etc.

The disadvantage of the script debugger is that there can be unexpected behavior or even crashes due to events being processed in different order, so only use this for debugging.


You can change entities (for example change drawing order) using operations:
var op = new RModifyObjectsOperation();
// iterate through entities:
for (...) {
    // query entity from storage (this gives you a clone of the original entity):
    var entity = ...;
    // modify clone of entity:
    entity.setDrawOrder(7);
    // add entity to operation:
    op.addObject(entity, false);
}
// apply operation, this triggers a transaction which records the change for undo, redo:
di.applyOperation(op);

Ghost_of_Magellan
Full Member
Posts: 58
Joined: Wed Mar 16, 2016 5:10 pm

Re: Listing Entity's Properties

Post by Ghost_of_Magellan » Wed Apr 06, 2016 10:12 am

Thank you for the swift reply, as always, andrew.

I do believe I have enough to keep me going for awhile. Eventually, I'll call back with another ridiculous questions, hopefully on another subject and, therefore, on another topic.

Thank you.

Post Reply

Return to “QCAD Programming, Script Programming and Contributing”