Jump to content

Qt Quick Tutorial Components: Difference between revisions

From Qt Wiki
No edit summary
Marked as outdated
 
(10 intermediate revisions by 3 users not shown)
Line 1: Line 1:
[[Category:Developing_with_Qt::Qt Quick]]<br />[[Category:Developing_with_Qt::Qt Quick::Tutorial]]<br />[toc align_right=&quot;yes&amp;quot; depth=&quot;3&amp;quot;]
{{Outdated|reason=Qt Quick 1}}
[[Category:Developing_with_Qt::Qt Quick]]
[[Category:Developing_with_Qt::Qt Quick::Tutorial]]


= Qt Quick Tutorial: Module 2 - Components =
= Qt Quick Tutorial: Module 2 - Components =
Line 5: Line 7:
== Creating a Custom Component ==
== Creating a Custom Component ==


We still have some work left to do from [[Qt_Quick_Tutorial_Basics | Module 1]]. If we look at our final QML document [[BasicSteps_4 | ''BasicSteps_4.qml'']], we still see too much code duplication. The code for the three photo rectangles is nearly identical. It only differs in the x-position, the image file and the title. In C+'', we would introduce a class &lt;code&amp;gt;Photo&amp;lt;/code&amp;gt;, instantiate it three times and initialize it with the different values of the x-position, image file and title. And, this is actually what we do in QML, too - except that a class is called a component in QML.
We still have some work left to do from [[Qt_Quick_Tutorial_Basics | Module 1]]. If we look at our final QML document [[BasicSteps_4 | ''BasicSteps_4.qml'']], we still see too much code duplication. The code for the three photo rectangles is nearly identical. It only differs in the x-position, the image file and the title. In C+'', we would introduce a class <code>Photo</code>, instantiate it three times and initialize it with the different values of the x-position, image file and title. And, this is actually what we do in QML, too - except that a class is called a component in QML.  
<br />A '''component''' is always defined in a file that has the component's name as its base name and that has the extension ''.qml''. For example, our &lt;code&amp;gt;Photo&amp;lt;/code&amp;gt; component will be defined in the file ''Photo.qml''. A component name always starts with an uppercase letter and is continued by zero or more letters (uppercase or lowercase), digits or underscores.
<br />We perform the following steps to create the &lt;code&amp;gt;Photo&amp;lt;/code&amp;gt; component.<br />* We copy the QML file [[BasicSteps_4 | BasicSteps_4.qml]] into the file ''Components.qml''.<br />* We create a new QML file ''Photo.qml'' in the same directory as ''Components.qml''.<br />* We copy the &lt;code&amp;gt;Rectangle&amp;lt;/code&amp;gt; for photo 1 into ''Photo.qml''.
<br />We are fairly close to the final &lt;code&amp;gt;Photo&amp;lt;/code&amp;gt; component. We only have to introduce properties for the variable parameters of the &lt;code&amp;gt;Photo&amp;lt;/code&amp;gt; component: the x-position, image file and image title. We will assign concrete values to these properties in the instantiations of the &lt;code&amp;gt;Photo&amp;lt;/code&amp;gt; component in ''Components.qml''.
<br />We don't have to do anything for the x-position, because a &lt;code&amp;gt;Rectangle&amp;lt;/code&amp;gt; already has a property &lt;code&amp;gt;x&amp;lt;/code&amp;gt;. We simply remove the code fragment &lt;code&amp;gt;x: 0;&lt;/code&amp;gt;. While we are at it, we also remove the code fragment &lt;code&amp;gt;y: 0&amp;lt;/code&amp;gt;, because the default value for the y-position is 0 anyway.
<br />For the image file and title, we introduce two properties &lt;code&amp;gt;imageFile&amp;lt;/code&amp;gt; and &lt;code&amp;gt;imageTitle&amp;lt;/code&amp;gt; at the beginning of the &lt;code&amp;gt;Rectangle&amp;lt;/code&amp;gt;. Finally, we replace the value of &lt;code&amp;gt;source&amp;lt;/code&amp;gt; in &lt;code&amp;gt;Image&amp;lt;/code&amp;gt; by &lt;code&amp;gt;imageFile&amp;lt;/code&amp;gt; and the value of &lt;code&amp;gt;text&amp;lt;/code&amp;gt; in &lt;code&amp;gt;Text&amp;lt;/code&amp;gt; by &lt;code&amp;gt;imageTitle&amp;lt;/code&amp;gt;. With all these changes, the &lt;code&amp;gt;Photo&amp;lt;/code&amp;gt; component looks as follows.
<br /><code><br />// File: Photo.qml<br />import QtQuick 1.0
<br />Rectangle {<br /> property url imageFile<br /> property string imageTitle
<br /> width: frameSize; height: frameSize<br /> color: frameColor
<br /> Image {<br /> x: leftMargin; y: topMargin<br /> source: imageFile<br /> }
<br /> Text {<br /> x: 0; y: frameSize - bottomMargin<br /> text: imageTitle<br /> font.pixelSize: fontSize<br /> width: frameSize; horizontalAlignment: Text.AlignHCenter<br /> height: bottomMargin; verticalAlignment: Text.AlignVCenter<br /> }<br />}<br /></code>
<br />We can now use our brand new &lt;code&amp;gt;Photo&amp;lt;/code&amp;gt; component in the main QML document ''Components.qml'' (formerly ''BasicSteps_4.qml''), which shows three photos side by side. The resulting code looks as follows.
<br /><code><br />// File: Components.qml<br />import QtQuick 1.0
<br />Rectangle {<br /> property int frameSize: 300<br /> property int leftMargin: 10<br /> property int topMargin: 25<br /> property int bottomMargin: 65<br /> property int fontSize: 20<br /> property color frameColor: &quot;#FFF8DC&amp;quot; // cornsilk
<br /> width: 3 * frameSize; height: frameSize
<br /> Photo {<br /> x: 0<br /> imageFile: &quot;voringsfossen1.jpg&amp;quot;<br /> imageTitle: &quot;Voringsfossen&amp;quot;<br /> }
<br /> Photo {<br /> x: frameSize<br /> imageFile: &quot;bergen.jpg&amp;quot;<br /> imageTitle: &quot;Bergen&amp;quot;<br /> }
<br /> Photo {<br /> x: 2 * frameSize<br /> imageFile: &quot;cotton_grass.jpg&amp;quot;<br /> imageTitle: &quot;Cotton Grass&amp;quot;<br /> }<br />}<br /></code>
<br />In the three instances of the &lt;code&amp;gt;Photo&amp;lt;/code&amp;gt; component, we only assign values to the three variable parameters: x-position, image file and image title. The values of the other properties like &lt;code&amp;gt;frameSize&amp;lt;/code&amp;gt; or &lt;code&amp;gt;leftMargin&amp;lt;/code&amp;gt; are propagated from the root &lt;code&amp;gt;Rectangle&amp;lt;/code&amp;gt; instance to the &lt;code&amp;gt;Photo&amp;lt;/code&amp;gt; instances and to their child instances &lt;code&amp;gt;Image&amp;lt;/code&amp;gt; and &lt;code&amp;gt;Text&amp;lt;/code&amp;gt;.
<br />We can now admire our work by running QML viewer in the directory of ''Components.qml'' and ''Photo.qml'':<br /><code>qmlviewer Components.qml &amp;#38;<code>
<br />How does QML viewer know where to find the &lt;code&amp;gt;Photo&amp;lt;/code&amp;gt; component? By default, QML viewer looks for a QML file with the same base name as the component and with the extension ''.qml'' in the directory, where it is started. In our case, it finds the file ''Photo.qml''. We'll show in the module [[Qt_Quick_Tutorial_Modules | Modules]] how to place components in other directories than the current one.
<br />h2. Property Aliases and Property id
<br />We can still improve the code of the &lt;code&amp;gt;Photo&amp;lt;/code&amp;gt; component a little bit. The URL of the image file and the image title are stored in two places each. The image file is stored in the newly introduced property &lt;code&amp;gt;imageFile&amp;lt;/code&amp;gt; and in the property &lt;code&amp;gt;source&amp;lt;/code&amp;gt; of &lt;code&amp;gt;Image&amp;lt;/code&amp;gt;. Similarly, the image title is stored in &lt;code&amp;gt;imageTitle&amp;lt;/code&amp;gt; and in &lt;code&amp;gt;text&amp;lt;/code&amp;gt; of &lt;code&amp;gt;Text&amp;lt;/code&amp;gt;. This means that memory is allocated twice for the image file and twice for the image title. It is not a big problem in this example. If, however, the duplicated objects are bigger, it becomes a problem. The other problem is that the we must make sure that the two occurrences of image file and of image title are in sync with each other. Again, it is fairly simple for our little program but it becomes trickier for bigger programs.
<br />Fortunately, property aliases come to our rescue. A '''property alias''' says that two properties share the same value and store it at one memory location. The C''+ equivalent would be a reference to an existing variable. The syntax of a property alias is<br /></code><br /> property alias property1: property2<br /><code><br />where &lt;code&amp;gt;property1&amp;lt;/code&amp;gt; is the newly introduced alias and &lt;code&amp;gt;property2&amp;lt;/code&amp;gt; is the already existing property to be aliased.


In our &lt;code&amp;gt;Photo&amp;lt;/code&amp;gt; component, we want to define &lt;code&amp;gt;imageFile&amp;lt;/code&amp;gt; as an alias for the property &lt;code&amp;gt;source&amp;lt;/code&amp;gt; of &lt;code&amp;gt;Image&amp;lt;/code&amp;gt; and &lt;code&amp;gt;imageTitle&amp;lt;/code&amp;gt; as an alias for the property &lt;code&amp;gt;text&amp;lt;/code&amp;gt; of &lt;code&amp;gt;Text&amp;lt;/code&amp;gt;. There is only one little problem: How can we uniquely address the properties &lt;code&amp;gt;source&amp;lt;/code&amp;gt; and &lt;code&amp;gt;text&amp;lt;/code&amp;gt;? If there were several &lt;code&amp;gt;Image&amp;lt;/code&amp;gt; or &lt;code&amp;gt;Text&amp;lt;/code&amp;gt; components in the &lt;code&amp;gt;Photo&amp;lt;/code&amp;gt; component (a fairly usual scenario, by the way), we would have no way distinguish them.
A '''component''' is always defined in a file that has the component's name as its base name and that has the extension ''.qml''. For example, our <code>Photo</code> component will be defined in the file ''Photo.qml''. A component name always starts with an uppercase letter and is continued by zero or more letters (uppercase or lowercase), digits or underscores.  


The special QML '''property &lt;code&amp;gt;id&amp;lt;/code&amp;gt;''' solves this problem. The property &lt;code&amp;gt;id&amp;lt;/code&amp;gt; is a unique name or identifier for a component instance. Using the notation &lt;code&amp;gt;instName.propName&amp;lt;/code&amp;gt; we can access the property &lt;code&amp;gt;propertyName&amp;lt;/code&amp;gt; of the instance, whose &lt;code&amp;gt;id&amp;lt;/code&amp;gt; property has the value &lt;code&amp;gt;instName&amp;lt;/code&amp;gt;.
We perform the following steps to create the <code>Photo</code> component.
* We copy the QML file [[BasicSteps_4 | BasicSteps_4.qml]] into the file ''Components.qml''.
* We create a new QML file ''Photo.qml'' in the same directory as ''Components.qml''.
* We copy the <code>Rectangle</code> for photo 1 into ''Photo.qml''.


Now, we can finally introduce the two property aliases and use them. In ''Photo.qml'', we replace the two property definitions in lines 5 and 6 by<br /></code><br /> property alias imageFile: picture.source<br /> property alias imageTitle: title.text<br /><code>
We are fairly close to the final <code>Photo</code> component. We only have to introduce properties for the variable parameters of the <code>Photo</code> component: the x-position, image file and image title. We will assign concrete values to these properties in the instantiations of the <code>Photo</code> component in ''Components.qml''.


We assign the identifier &lt;code&amp;gt;photo&amp;lt;/code&amp;gt; to the &lt;code&amp;gt;Image&amp;lt;/code&amp;gt; component and remove the line for the &lt;code&amp;gt;source&amp;lt;/code&amp;gt; property. Then, &lt;code&amp;gt;Image&amp;lt;/code&amp;gt; looks as follows:<br /></code><br /> Image {<br /> id: picture<br /> x: leftMargin; y: topMargin<br /> }<br /><code>
We don't have to do anything for the x-position, because a <code>Rectangle</code> already has a property <code>x</code>. We simply remove the code fragment <code>x: 0;</code>. While we are at it, we also remove the code fragment <code>y: 0</code>, because the default value for the y-position is 0 anyway.


Similarly, we assign the identifier &lt;code&amp;gt;title&amp;lt;/code&amp;gt; to the &lt;code&amp;gt;Text&amp;lt;/code&amp;gt; component and remove the line for the &lt;code&amp;gt;text&amp;lt;/code&amp;gt; property. Then, &lt;code&amp;gt;Text&amp;lt;/code&amp;gt; looks as follows:<br /></code><br /> Text {<br /> id: title<br /> x: 0; y: frameSize - bottomMargin<br /> font.pixelSize: fontSize<br /> width: frameSize; horizontalAlignment: Text.AlignHCenter<br /> height: bottomMargin; verticalAlignment: Text.AlignVCenter<br /> }<br /><code>
For the image file and title, we introduce two properties <code>imageFile</code> and <code>imageTitle</code> at the beginning of the <code>Rectangle</code>. Finally, we replace the value of <code>source</code> in <code>Image</code> by <code>imageFile</code> and the value of <code>text</code> in <code>Text</code> by <code>imageTitle</code>. With all these changes, the <code>Photo</code> component looks as follows.


The complete code for the modified &lt;code&amp;gt;Photo&amp;lt;/code&amp;gt; component can be found in [[PhotoQml | ''Photo.qml'']].
<code>
// File: Photo.qml
import QtQuick 1.0


It is important to note that the value of &lt;code&amp;gt;id&amp;lt;/code&amp;gt; is '''not''' enclosed in double quotes. It is not quoted at all because it is an identifier, not a string.
Rectangle {
property url imageFile
property string imageTitle


Go back to &quot;Module 1 - Basics&amp;quot;:http://developer.qt.nokia.com/wiki/Qt_Quick_Tutorial_Basics
width: frameSize; height: frameSize
color: frameColor


&quot;Tutorial Main Page&amp;quot;:http://developer.qt.nokia.com/wiki/Qt_Quick_Tutorial
Image {
x: leftMargin; y: topMargin
source: imageFile
}
 
Text {
x: 0; y: frameSize - bottomMargin
text: imageTitle
font.pixelSize: fontSize
width: frameSize; horizontalAlignment: Text.AlignHCenter
height: bottomMargin; verticalAlignment: Text.AlignVCenter
}
}
</code>
 
We can now use our brand new <code>Photo</code> component in the main QML document ''Components.qml'' (formerly ''BasicSteps_4.qml''), which shows three photos side by side. The resulting code looks as follows.
 
<code>
// File: Components.qml
import QtQuick 1.0
 
Rectangle {
property int frameSize: 300
property int leftMargin: 10
property int topMargin: 25
property int bottomMargin: 65
property int fontSize: 20
property color frameColor: "#FFF8DC" // cornsilk
 
width: 3 * frameSize; height: frameSize
 
Photo {
x: 0
imageFile: "voringsfossen1.jpg"
imageTitle: "Voringsfossen"
}
 
Photo {
x: frameSize
imageFile: "bergen.jpg"
imageTitle: "Bergen"
}
 
Photo {
x: 2 * frameSize
imageFile: "cotton_grass.jpg"
imageTitle: "Cotton Grass"
}
}
</code>
 
In the three instances of the <code>Photo</code> component, we only assign values to the three variable parameters: x-position, image file and image title. The values of the other properties like <code>frameSize</code> or <code>leftMargin</code> are propagated from the root <code>Rectangle</code> instance to the <code>Photo</code> instances and to their child instances <code>Image</code> and <code>Text</code>.
 
We can now admire our work by running QML viewer in the directory of ''Components.qml'' and ''Photo.qml'':
<code>qmlviewer Components.qml &<code>
 
How does QML viewer know where to find the <code>Photo</code> component? By default, QML viewer looks for a QML file with the same base name as the component and with the extension ''.qml'' in the directory, where it is started. In our case, it finds the file ''Photo.qml''.
 
== Property Aliases and Property id ==
We can still improve the code of the <code>Photo</code> component a little bit. The URL of the image file and the image title are stored in two places each. The image file is stored in the newly introduced property <code>imageFile</code> and in the property <code>source</code> of <code>Image</code>. Similarly, the image title is stored in <code>imageTitle</code> and in <code>text</code> of <code>Text</code>. This means that memory is allocated twice for the image file and twice for the image title. It is not a big problem in this example. If, however, the duplicated objects are bigger, it becomes a problem. The other problem is that the we must make sure that the two occurrences of image file and of image title are in sync with each other. Again, it is fairly simple for our little program but it becomes trickier for bigger programs.
 
Fortunately, property aliases come to our rescue. A '''property alias''' says that two properties share the same value and store it at one memory location. The C''+ equivalent would be a reference to an existing variable. The syntax of a property alias is
</code>
property alias property1: property2
<code>
where <code>property1</code> is the newly introduced alias and <code>property2</code> is the already existing property to be aliased.
 
In our <code>Photo</code> component, we want to define <code>imageFile</code> as an alias for the property <code>source</code> of <code>Image</code> and <code>imageTitle</code> as an alias for the property <code>text</code> of <code>Text</code>. There is only one little problem: How can we uniquely address the properties <code>source</code> and <code>text</code>? If there were several <code>Image</code> or <code>Text</code> components in the <code>Photo</code> component (a fairly usual scenario, by the way), we would have no way distinguish them.
 
The special QML '''property <code>id</code>''' solves this problem. The property <code>id</code> is a unique name or identifier for a component instance. Using the notation <code>instName.propName</code> we can access the property <code>propertyName</code> of the instance, whose <code>id</code> property has the value <code>instName</code>.
 
Now, we can finally introduce the two property aliases and use them. In ''Photo.qml'', we replace the two property definitions in lines 5 and 6 by
</code>
property alias imageFile: picture.source
property alias imageTitle: title.text
<code>
 
We assign the identifier <code>photo</code> to the <code>Image</code> component and remove the line for the <code>source</code> property. Then, <code>Image</code> looks as follows:
</code>
Image {
id: picture
x: leftMargin; y: topMargin
}
<code>
 
Similarly, we assign the identifier <code>title</code> to the <code>Text</code> component and remove the line for the <code>text</code> property. Then, <code>Text</code> looks as follows:
</code>
Text {
id: title
x: 0; y: frameSize - bottomMargin
font.pixelSize: fontSize
width: frameSize; horizontalAlignment: Text.AlignHCenter
height: bottomMargin; verticalAlignment: Text.AlignVCenter
}
<code>
 
The complete code for the modified <code>Photo</code> component can be found in [[PhotoQml | ''Photo.qml'']].
 
It is important to note that the value of <code>id</code> is '''not''' enclosed in double quotes. It is not quoted at all because it is an identifier, not a string.
 
Go back to [[Qt Quick Tutorial Basics | Module 1 - Basics]]
 
[[Qt Quick Tutorial | Tutorial Main Page]]

Latest revision as of 01:19, 24 March 2016

IMPORTANT: The content of this page is outdated. Reason: Qt Quick 1
If you have checked or updated this page and found the content to be suitable, please remove this notice.

Qt Quick Tutorial: Module 2 - Components

Creating a Custom Component

We still have some work left to do from Module 1. If we look at our final QML document BasicSteps_4.qml, we still see too much code duplication. The code for the three photo rectangles is nearly identical. It only differs in the x-position, the image file and the title. In C+, we would introduce a class Photo, instantiate it three times and initialize it with the different values of the x-position, image file and title. And, this is actually what we do in QML, too - except that a class is called a component in QML.

A component is always defined in a file that has the component's name as its base name and that has the extension .qml. For example, our Photo component will be defined in the file Photo.qml. A component name always starts with an uppercase letter and is continued by zero or more letters (uppercase or lowercase), digits or underscores.

We perform the following steps to create the Photo component.

  • We copy the QML file BasicSteps_4.qml into the file Components.qml.
  • We create a new QML file Photo.qml in the same directory as Components.qml.
  • We copy the Rectangle for photo 1 into Photo.qml.

We are fairly close to the final Photo component. We only have to introduce properties for the variable parameters of the Photo component: the x-position, image file and image title. We will assign concrete values to these properties in the instantiations of the Photo component in Components.qml.

We don't have to do anything for the x-position, because a Rectangle already has a property x. We simply remove the code fragment x: 0;. While we are at it, we also remove the code fragment y: 0, because the default value for the y-position is 0 anyway.

For the image file and title, we introduce two properties imageFile and imageTitle at the beginning of the Rectangle. Finally, we replace the value of source in Image by imageFile and the value of text in Text by imageTitle. With all these changes, the Photo component looks as follows.

// File: Photo.qml
import QtQuick 1.0

Rectangle {
 property url imageFile
 property string imageTitle

 width: frameSize; height: frameSize
 color: frameColor

 Image {
 x: leftMargin; y: topMargin
 source: imageFile
 }

 Text {
 x: 0; y: frameSize - bottomMargin
 text: imageTitle
 font.pixelSize: fontSize
 width: frameSize; horizontalAlignment: Text.AlignHCenter
 height: bottomMargin; verticalAlignment: Text.AlignVCenter
 }
}

We can now use our brand new Photo component in the main QML document Components.qml (formerly BasicSteps_4.qml), which shows three photos side by side. The resulting code looks as follows.

// File: Components.qml
import QtQuick 1.0

Rectangle {
 property int frameSize: 300
 property int leftMargin: 10
 property int topMargin: 25
 property int bottomMargin: 65
 property int fontSize: 20
 property color frameColor: "#FFF8DC" // cornsilk

 width: 3 * frameSize; height: frameSize

 Photo {
 x: 0
 imageFile: "voringsfossen1.jpg"
 imageTitle: "Voringsfossen"
 }

 Photo {
 x: frameSize
 imageFile: "bergen.jpg"
 imageTitle: "Bergen"
 }

 Photo {
 x: 2 * frameSize
 imageFile: "cotton_grass.jpg"
 imageTitle: "Cotton Grass"
 }
}

In the three instances of the Photo component, we only assign values to the three variable parameters: x-position, image file and image title. The values of the other properties like frameSize or leftMargin are propagated from the root Rectangle instance to the Photo instances and to their child instances Image and Text.

We can now admire our work by running QML viewer in the directory of Components.qml and Photo.qml:

qmlviewer Components.qml &<code>

How does QML viewer know where to find the <code>Photo

component? By default, QML viewer looks for a QML file with the same base name as the component and with the extension .qml in the directory, where it is started. In our case, it finds the file Photo.qml.

Property Aliases and Property id

We can still improve the code of the Photo component a little bit. The URL of the image file and the image title are stored in two places each. The image file is stored in the newly introduced property imageFile and in the property source of Image. Similarly, the image title is stored in imageTitle and in text of Text. This means that memory is allocated twice for the image file and twice for the image title. It is not a big problem in this example. If, however, the duplicated objects are bigger, it becomes a problem. The other problem is that the we must make sure that the two occurrences of image file and of image title are in sync with each other. Again, it is fairly simple for our little program but it becomes trickier for bigger programs.

Fortunately, property aliases come to our rescue. A property alias says that two properties share the same value and store it at one memory location. The C+ equivalent would be a reference to an existing variable. The syntax of a property alias is

property alias property1: property2
where <code>property1

is the newly introduced alias and property2 is the already existing property to be aliased.

In our Photo component, we want to define imageFile as an alias for the property source of Image and imageTitle as an alias for the property text of Text. There is only one little problem: How can we uniquely address the properties source and text? If there were several Image or Text components in the Photo component (a fairly usual scenario, by the way), we would have no way distinguish them.

The special QML property id solves this problem. The property id is a unique name or identifier for a component instance. Using the notation instName.propName we can access the property propertyName of the instance, whose id property has the value instName.

Now, we can finally introduce the two property aliases and use them. In Photo.qml, we replace the two property definitions in lines 5 and 6 by

property alias imageFile: picture.source
property alias imageTitle: title.text
We assign the identifier <code>photo

to the Image component and remove the line for the source property. Then, Image looks as follows:

Image {
id: picture
x: leftMargin; y: topMargin
}
Similarly, we assign the identifier <code>title

to the Text component and remove the line for the text property. Then, Text looks as follows:

Text {
id: title
x: 0; y: frameSize - bottomMargin
font.pixelSize: fontSize
width: frameSize; horizontalAlignment: Text.AlignHCenter
height: bottomMargin; verticalAlignment: Text.AlignVCenter
}
The complete code for the modified <code>Photo

component can be found in Photo.qml.

It is important to note that the value of id is not enclosed in double quotes. It is not quoted at all because it is an identifier, not a string.

Go back to Module 1 - Basics

Tutorial Main Page