Graphisoft GDL - How to get layout name and number inside GDL object - gdl

I want to show the layout name and number inside a gdl object that I placed on my layout.
How can I get a layout name and number into my GDL script?

You can get the layout name in several ways inside your GDL script.
A commonly used solution is to use the autotext tags <LAYOUTNAME> or <LAYOUTID> as a string. This tag will be replaced by the layout name or layout id AFTER the gdl object has compiled.
xPos = 0;
yPos = 0;
TEXT2 xPos, yPos, '<LAYOUTNAME>'
or
TEXT2 xPos, yPos, '<LAYOUTID>'
All autotext tags can be found here in the documentation.
Note: Be aware that <LAYOUTID> and <LAYOUTNUMBER> are two different things!
The problem with this solution is that you cannot use the value in for example function to compare with a value. So this will never evaluate to true:
'<LAYOUTNAME>' = 'my layout name'
In case you want to do something like that that there is an alternative way using the GDL REQUEST options function
n = request ("HomeDB_info", "", n, LayoutId, LayoutName, n)
The values will be stored in the variables LayoutId and LayoutName
This is also documented here and mentioned here on the ArchiCAD-TALK forum
It is possible to evaluate this value and use this directly in your code:
IF LayoutName = 'my layout name' THEN
! layout name is 'my layout name'
ELSE
! layout name is something else
ENDIF

Related

I need to pull the text of an image file name from an array but am only getting "pyimage#" or "tkinter.PhotoImage object at X" as replies

I'm trying to create an array with an assortment of different randomized image files in it to display on a set of buttons in Tkinter. When a given button is clicked I'd like to add the text of that file's name to a new array. Basically, when button with imageX is clicked add "imageX" to a new array.
Unfortunately, I always get a return that isn't the image's filename, or the variable that I've set to correspond to that image, but instead either:
"tkinter.PhotoImage object at X" (where is X is a location like "0x0000020FC894D2E0") if the command is populationbeta.append (population[0])
or
"pyimage#" (where # is an integer that seems to relate to the number of images in the source file), if I change the command to populationbeta.append (str(population[0]))
I feel like there should be a simple way of doing this and I've tried every work around I can think of but I'm not getting it to work. Any help would be very much appreciated! Thanks!
Here's a shortened/simplified version of the code in question:
master=tkinter.Tk()
master.title("Not working")
a1b1c1 = PhotoImage(file = r"C:/users/jdavis319/documents/bushesoflove/BoLdraw/a1b1c1.png")
a1b1c2 = PhotoImage(file = r"C:/users/jdavis319/documents/bushesoflove/BoLdraw/a1b1c2.png")
a1b1c3 = PhotoImage(file = r"C:/users/jdavis319/documents/bushesoflove/BoLdraw/a1b1c3.png")
a1b2c1 = PhotoImage(file = r"C:/users/jdavis319/documents/bushesoflove/BoLdraw/a1b2c1.png")
a1b2c2 = PhotoImage(file = r"C:/users/jdavis319/documents/bushesoflove/BoLdraw/a1b2c2.png")
population = [a1b1c1, a1b1c2, a1b1c3, a1b2c1, a1b2c2]
populationbeta = []
populationbeta.append(population[0])
print(populationbeta)
This gives the result: "[<tkinter.PhotoImage object at 0x000001A419D4F070>]"
This gives the result: "[<tkinter.PhotoImage object at 0x000001A419D4F070>]"
Correct. That shows that you have a list of PhotoImage objects. If you want the filenames you can use .cget('file') on the objects. cget is a common tkinter method for getting the value of a configured option.
filenames = [image.cget('filename') for image in population]
Or, if you don't want to use a list comprehension to create a list of filenames, you can do it on an individual image like so:
populationbeta.append(population[0].cget("file"))

How to set a context variable with dot in name?

I am trying to add a context data variable (CDV), which has a dot in its name. According to Adobe site this is correct:
s.contextData['myco.rsid'] = 'value'
Unfortunately, after calling s.t() the variable is split into two or more:
Context Variables
myco.:
rsid: value
.myco:
How can I set the variable and prevent splitting it into pieces?
You are setting it properly already. If you are referring to what you see in the request URL, that's how the Adobe library sends it. In your example, "myco" is a namespace, and "rsid" is a variable in that namespace. And you can have other variables in that namespace. For example if you have
s.contextData['myco.rsid1'] = 'value';
s.contextData['myco.rsid2'] = 'value';
You would see in the AA request URL (just showing the relevant part):
c.&myco.&rsid1=value&rsid2=value&.myco&.c
I assume you are asking because you want to more easily parse/qa AA collection request URLs from the browser network tab, extension, or some unit tester? There is no way to force AA to not behave like this when using dot syntax (namespaces) in your variables.
But, there isn't anything particularly special about using namespaces for your contextData variables; it's just there for your own organization if you choose. So if you want all variables to be "top level" and show full names in the request URL, then do not use dot syntax.
If you want to still have some measure of organization/hierarchy, I suggest you instead use an underscore _ :
s.contextData['myco_rsid1'] = 'value';
s.contextData['myco_rsid2'] = 'value';
Which will give you:
c.&myco_rsid1=value&myco_rsid2=value&.c
Side Note: You cannot do full object/dot notation syntax with s.contextData, e.g.
s.contextData = {
foo:'bar', // <--- this will properly parse
myco:{ // this will not properly parse
rsid:'value' //
} //
};
AA library does not parse this correctly; it just loops through top level properties of contextData when building the request URL. So if you do full object syntax like above, you will end up with:
c.&foo=bar&myco=%5Bobject%20Object%5D&&.c
foo would be okay, but you end up with just myco with "[object Object]" as the recorded value. Why Adobe didn't allow for full object syntax and just JSON.stringify(s.contextData) ? ¯\_(ツ)_/¯

storing images into to a cell in matlab

I understand that similar questions have been asked before but I have tried the other solutions and had no luck. Would really appreciate some help!
I want to 1.load a file of images, 2.read them with imread, 3.put that in a cell, 4.run my function stepwise on each array in the cell.
here is my function for 1 image/file
function sym_file(filename) %this calls for the image file name
j=im2double(rgb2gray(imread(filename)));
%reads the image, turns int into grayscale and double
if rem(size(j,2),2)~=0,j(:,1)=[];
if rem(size(j,1),2)~=0,j(1,:)=[];
end
end
%this made sure the rows and columns are even
jr=fliplr(j);
left=(j(:,1:size(j,2)/2));
right=(jr(:,1:size(j,2)/2));
t=sum(left,2);
u=sum(right,2);
symmetry= (left-right)./255;
symmetry2=reshape(symmetry,1,(numel(symmetry)));
imbalance=mean(symmetry2)
asymmetry=sqrt(mean(symmetry2.^2))
%runs calculations on image
figure('Name',num2str(filename),'NumberTitle','off')
subplot(3,2,1)
histogram(symmetry2,200)
title(['symmetry:' num2str(asymmetry)])
subplot(3,2,2)
imshow(j)
title(['imbalance:' num2str(imbalance)])
subplot(3,2,3)
imshow(left)
title('left')
subplot(3,2,4)
imshow(fliplr(right))
title('right')
impixelinfo;
subplot(3,2,5)
plot(1:length(t),t,'-r',1:length(u),u,'-b')
title('results,red=left/blue=right')
%printing results in a figure
So I would like to do this with a file of images rather than doing it file by file. What's the best way? Also, if someone knows how to store the data/figures in files that would be a bonus also.
Let me see if I got this straight: you have a set of images and you store them in a cell. You then want to apply a function to each image (in other words: to each element of the cell).
If so, just use cellfun()
Example:
X = imread('http://sipi.usc.edu/database/preview/aerials/3.2.25.png','png');
Y = imread('http://sipi.usc.edu/database/preview/misc/5.3.01.png','png');
my_cell{1} = X;
my_cell{2} = Y;
my_fftcell = cellfun(#fft2,my_cell,'UniformOutput', false)
In this case I loaded 2 images X and Y and stored them into my_cell (the brackets {} indicate to MATLAB/Octave that it is a cell). I then created another cell called my_fftcell which is the fft2 applied over each image.
To get many files from a folder/directory, you can just loop over each file in that directory and store it into the cell. Something like this:
Loading multiple images in MATLAB

LoaderMax: setting array as a container (ImageLoader)

So, I have a LoaderMax instance loading images from various URLs. I want to add all loaded images to an array.
Here's my code:
var photosArray:Array = new Array(5);
var imageLoadingQueue:LoaderMax = new LoaderMax({name:"mainQueue", onComplete:completeHandler});
for (var g:uint=0; g<5; g++)
{
imageLoadingQueue.append(new ImageLoader("/img" + g + ".jpg", {name:"photo", container:photosArray[g], noCache:false, smoothing:true, width:126, height:126, scaleMode:"proportionalOutside"}));
}
imageLoadingQueue.load();
private function completeHandler(e:LoaderEvent):void
{
trace("finished loading pictures!");
//the next two lines will return an error (saying that photosArray[1] is null)
stage.addChild(photosArray[1]);
photosArray[1].x = 250;
}
A few problems:
If I set the container of the image being loaded to the Array, it won't work. I'm not being able to access the image inside the array because it says it's null.
If I set the container of the image being loaded to "this" (using the container property when appending a new ImageLoader) and, on the completeHandler, set my array equal to event.target.content, it kinda works (but it's not the ideal). The problem is that, by doing so, the images are appearing on the stage as they are loaded, and I do no want them to do so.
Any help would be heavily appreciated.
Thanks!!
David is correct, but I also wanted to mention that the LoaderMax's "content" is actually an array of all of its children's content, so you could just use that for simplicity. Keep in mind that ImageLoaders automatically create a Sprite (technically called a "ContentDisplay") to drop the image into so you probably don't need to create ANOTHER Sprite (a container for the container).
var photos:Array = imageLoadingQueue.content;
stage.addChild(photos[1]);
The other nice thing is that it creates the ContentDisplay Sprites immediately, even before any content is loaded into them, so you can place them and size them however you want while (or before or after) loading occurs.
The container needs to be a DisplayObjectContainer. ImageLoader will try to add the image to the container using addChild(), so obviously this won't work with an empty array. Create a new Sprite for each image and add it into the array first:
for (var g:uint=0; g<5; g++)
{
photosArray[g] = new Sprite();
imageLoadingQueue.append(new ImageLoader("/img" + g + ".jpg", {name:"photo", container:photosArray[g], noCache:false, smoothing:true, width:126, height:126, scaleMode:"proportionalOutside"}));
}

Create widget array using Qt Designer?

In Qt Designer I'm creating multiple labels (for instance):
my_label1
my_label2
my_label3
...
my_label n
Then if I want to hide them I do this:
ui->my_label1->hide();
ui->my_label2->hide();
ui->my_label3->hide();
...
ui->my_labeln->hide();
However I would like to define the labels like
my_label[n]
So then I would be able to do this:
for(i=0;i<n;i++)
{
ui->my_label[n]->hide();
}
I read that I can define the widget like:
QLabel* my_label[5];
but is there any way to do the same from Qt Designer?
Thanks in advance!
Finally I decided to do direct assignment:
QLabel* my_label_array[5];
my_label_array[0] = ui->my_label1;
my_label_array[1] = ui->my_label2;
my_label_array[2] = ui->my_label3;
my_label_array[3] = ui->my_label4;
my_label_array[4] = ui->my_label5;
Then I can do for instance:
for(idx=0;idx<6;idx++) my_label_array[idx]->show();
for(idx=0;idx<6;idx++) my_label_array[idx]->hide();
for(idx=0;idx<6;idx++) my_label_array[idx]->setEnabled(1);
for(idx=0;idx<6;idx++) my_label_array[idx]->setDisabled(1);
etc...
Then I was able to perform iterations. I believe is not the cleanest way to do it but given my basic knowledge of Qt is ok for me.
Thank you very much for your answers and your support! This is a great site with great people.
Instead of creating an explicit array, you may be able to name your widgets using a particular scheme and then use QObject::findChildren() on the parent widget to get a list of the widgets you are after.
If you only want to hide widgets, you can put all the widgets you want to hide in an invisible QFrame (set frameShape to NoFrame) and hide them all by calling setVisible(false) on the QFrame. This may cause some unwanted side effects with layouts so you may have to tweak some size policy settings.
In case you are wanting to hide controls so that you can simulate a wizard type UI, you may want to check into QStackedWidget.
I have another dirty workaround for this:
in header file
// .hpp
class UiBlabla : public QWidget {
...
QLabel** labels;
};
in source file
// constructor
ui->setupUi(this);
labels = new QLabel*[10]{ui->label_0, ui->label_1, ui->label_2, ui->label_3,
ui->label_4, ui->label_5, ui->label_6,
ui->label_7, ui->label_8, ui->label_9};
I haven't seen anything in QtDesigner to do that, but there are a couple of relatively easy ways to get that behavior.
1) Simply store the my_labelx pointers (from QtDesigner) in an array (or better, a QVector):
QVector<QLabel*> my_labels;
my_labels.push_back(ui->my_label1);
my_labels.push_back(ui->my_label2);
Then you can iterate through the QVector.
for(int i=0; i < my_labels.size(); ++i) {
my_labels[i]-> hide();
}
// or with QFOREACH
foreach(QLabel* label, my_labels)
label->hide();
There is a little setup needed in terms of adding all the labels to the QVector, but on the plus side you only do that once.
2) Depending on the layout of your gui, you could have all your labels be children of a container object and iterate through the children

Resources