<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://techbase.kde.org/skins/common/feed.css?0.2"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://techbase.kde.org/api.php?action=feedcontributions&amp;user=Vmax0770&amp;feedformat=atom</id>
		<title>KDE TechBase - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="http://techbase.kde.org/api.php?action=feedcontributions&amp;user=Vmax0770&amp;feedformat=atom"/>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Special:Contributions/Vmax0770"/>
		<updated>2013-06-19T21:59:37Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.20.2</generator>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KWin/Scripting/API</id>
		<title>Development/Tutorials/KWin/Scripting/API</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KWin/Scripting/API"/>
				<updated>2011-12-15T11:02:17Z</updated>
		
		<summary type="html">&lt;p&gt;Vmax0770: Finished&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= workspace[singleton] =&lt;br /&gt;
== Events ==&lt;br /&gt;
'''workspace.currentDesktopChanged'''&lt;br /&gt;
*Emitted when the user switches from a virtual desktop to another.&lt;br /&gt;
**'''old_desk {integer}''': The number of the virtual desktop the user switched from.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''workspace.desktopPresenceChanged'''&lt;br /&gt;
*Emitted whenever a client is moved across virtual desktops. The client's previous desktop is available through the old_desk parameter, whereas the current desktop can be fetched using moved_client.desktop&lt;br /&gt;
**'''moved_client {client}''': The client which was moved from desktop old_desk to the new one&lt;br /&gt;
**'''old_desk {integer}''': The previous desktop on which the client was present&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''workspace.clientAdded'''&lt;br /&gt;
*Emitted whenever a new client is added to the workspace. This generally occurs when a new window is opened which includes dialog boxes, windows etc. However, it is NOT emitted for unmanaged clients like the Alt+Tab switcher.&lt;br /&gt;
**'''added_client {client}''': The client which was added.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''workspace.clientManaging'''&lt;br /&gt;
*Emitted whenever a client is being managed by the KWin subsystem. The difference between workspace.clientManaging and workspace.clientAdded is that clientManaging is emitted BEFORE clientAdded. Also, if KWin is restarted with a list of clients C, then the clientManaging event will be emitted for every client in C, but clientAdded will not.&lt;br /&gt;
**'''managing_client {client}''': The client which is being managed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''workspace.clientMinimized'''&lt;br /&gt;
*Emitted whenever a client is minimized.&lt;br /&gt;
**'''minimized_client {client}''': The client which was minimized.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''workspace.clientMaximizeSet'''&lt;br /&gt;
*Emitted whenever a client is maximized in a particular orientation. The orientation i.e. the rectangular direction in which the client was specified to occupy the entire available space is specified by the two parameters horizontally and vertically. If both are true, the client was maximized fully i.e. asked to occupy the entire workspace are available.&lt;br /&gt;
**'''maximized_client {client}''': The client which was maximized (in a certain orientation).&lt;br /&gt;
**'''horizontally {boolean}''': (true) if the client was maximized horizontally, (false) otherwise.&lt;br /&gt;
**'''vertically {boolean}''': (true) if the client was maximized vertically, (false) otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''workspace.killWindowCalled'''&lt;br /&gt;
*Emitted whenever the user requests a Kill Window [generally using the Ctrl+Esc combination]. The parameter killwindow_client is not completely safe and may return kill windows out of order of invocation. This is just a fancy function, avoid using. Instead, use workspace.clientAdded and filter for incoming Kill Windows.&lt;br /&gt;
**'''killwindow_client {client}''': The client handle to the kill window that was called.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''workspace.clientActivated'''&lt;br /&gt;
*Emitted whenever a client is given focus or 'activated'.&lt;br /&gt;
**'''activated_client {client}''': The client which was activated (or received focus).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''workspace.clientFullScreenSet'''&lt;br /&gt;
*Emitted whenever a client is set to full screen or unset. The fss_set parameter can be used to determine whether the client was set or unset.&lt;br /&gt;
**'''fss_set {boolean}''': (true) if the client was switched to full screen mode, (false) if it was switched from full screen mode.&lt;br /&gt;
**'''fss_client {client}''': The client which was set/unset to fullscreen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''workspace.clientUnminimized'''&lt;br /&gt;
*Emitted whenever a client is Unminimized (or restored).&lt;br /&gt;
**'''unm_client {client}''': The client which was unminimzed.&lt;br /&gt;
&lt;br /&gt;
== Methods ==&lt;br /&gt;
'''workspace.getAllClients[ret: Array(client)]'''&lt;br /&gt;
&lt;br /&gt;
'''workspace.getAllClients(desktop_no {integer})'''&lt;br /&gt;
*Gets all clients on the virtual desktop desktop_no. If no desktop number is specified then it fetches all the clients. To specifically isolate clients which are on 'All desktops', set the desktop_no parameter to -1.&lt;br /&gt;
*'''desktop_no {integer}''': The desktop number belonging to which the clients are to be fetched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''workspace.dimensions[ret: qsize]'''&lt;br /&gt;
&lt;br /&gt;
'''workspace.dimensions()'''&lt;br /&gt;
*Returns the dimensions of the workspace in pixels.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''workspace.desktopGridSize[ret: qsize]'''&lt;br /&gt;
&lt;br /&gt;
'''workspace.desktopGridSize()'''&lt;br /&gt;
*Returns the desktop size in grid units. In essence, it returns the order of a rectangular matrix, where each element is a virtual desktop and the rows and columns specify the number of virtual desktops and the way of arrangement.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''workspace.activeClient[ret: client]'''&lt;br /&gt;
&lt;br /&gt;
'''workspace.activeClient()'''&lt;br /&gt;
*Returns the client which currently has focus.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''workspace.clientGroups[ret: Array(clientgroup)]'''&lt;br /&gt;
&lt;br /&gt;
'''workspace.clientGroups()'''&lt;br /&gt;
*Returns an array of all the ClientGroups from the current workspace.&lt;br /&gt;
&lt;br /&gt;
== Properties ==&lt;br /&gt;
'''workspace.currentDesktop [ret: integer] [GO]'''&lt;br /&gt;
*Returns the current desktop number of the workspace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= toplevel[floating] =&lt;br /&gt;
== Methods ==&lt;br /&gt;
'''toplevel.x[ret: integer]'''&lt;br /&gt;
&lt;br /&gt;
'''toplevel.x()'''&lt;br /&gt;
*Returns the x co-ordinate of the toplevel client (or the client).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''toplevel.y[ret: integer]'''&lt;br /&gt;
&lt;br /&gt;
'''toplevel.y()'''&lt;br /&gt;
*Returns the y co-ordinate of the toplevel client (or the client).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''toplevel.width[ret: integer]'''&lt;br /&gt;
&lt;br /&gt;
'''toplevel.width()'''&lt;br /&gt;
*Returns the width of the toplevel client (or the client).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''toplevel.height[ret: integer]'''&lt;br /&gt;
&lt;br /&gt;
'''toplevel.height()'''&lt;br /&gt;
*Returns the height of the toplevel client (or the client).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''toplevel.size[ret: qsize]'''&lt;br /&gt;
&lt;br /&gt;
'''toplevel.size()'''&lt;br /&gt;
*Returns the size of the toplevel client (or the client).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''toplevel.pos[ret: qpoint]'''&lt;br /&gt;
&lt;br /&gt;
'''toplevel.pos()'''&lt;br /&gt;
*Returns the position of the toplevel client (or the client).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''toplevel.opacity[ret: decimal]'''&lt;br /&gt;
&lt;br /&gt;
'''toplevel.opacity()'''&lt;br /&gt;
*Returns the opacity (or 1 - transperency) of the toplevel client (or the client).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''toplevel.hasAlpha[ret: bool]'''&lt;br /&gt;
&lt;br /&gt;
'''toplevel.hasAlpha()'''&lt;br /&gt;
*Returns (true) if the client can be made translucent i.e. opacity can be set to values other than 0 or 1, (false) otherwise. NOTE: If compositing is OFF, then clients may still show that translucency is possible, but translucency is not possible without compositing being ON.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''toplevel.setOpacity'''&lt;br /&gt;
&lt;br /&gt;
'''toplevel.setOpacity(opacity_v {decimal})'''&lt;br /&gt;
*Sets the opacity of the client to opacity_v or sets transperency to (1 - opacity_v). NOTE: If compositing is OFF, this function has no effect for any values between 0 and 1 (exclusive).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''setOpacity(opacity_v {decimal})'''&lt;br /&gt;
*opacity_v {decimal}: The opacity to be set (on a scale of 0-1).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= client[floating] =&lt;br /&gt;
== Events ==&lt;br /&gt;
'''client.clientMoved'''&lt;br /&gt;
*Emitted whenever the client is moved or it's geometry changed. This includes when a client is resized.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.minimized'''&lt;br /&gt;
*Emitted whenever a client is minimized. Equivalent to workspace.clientMinimized, but for a specific client. Use wherever possible instead of workspace.clientMinimzed to improve performance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.maximizeSet'''&lt;br /&gt;
*Emitted when the client is maximized in a particular orientation. The orientation i.e. the rectangular direction in which the client was specified to occupy the entire available space is specified by the two parameters horizontally and vertically. If both are true, the client was maximized fully i.e. asked to occupy the entire workspace are available. Equivalent to workspace.clientMaximizeSet, but for a specific client. Use wherever possible instead of workspace.clientMaximizeSet to improve performance.&lt;br /&gt;
**'''horizontally {boolean}''': (true) if the client was maximized horizontally, (false) otherwise.&lt;br /&gt;
**'''vertically {boolean}''': (true) if the client was maximized vertically, (false) otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.activated'''&lt;br /&gt;
*Emitted whenever the client is activated (or gets focus). Equivalent to workspace.clientActivated but for a specific client. Use wherever possible instead of workspace.clientActivated to improve performance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.unminimized'''&lt;br /&gt;
*Emitted whenever the given client is unminimized. Equivalent of workspace.clientUnminimzed but for a specific client. Use wherever possible instead of workspace.clientUnminimized to improve performance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.fullScreenSet'''&lt;br /&gt;
*Emitted whenever the client's fullscreen mode is toggled. fss_set specifies whether the client was set to or from fullscreen mode.&lt;br /&gt;
**'''fss_set {boolean}''': (true) if the client was set to full screen mode, (false) if the client was set from full screen mode.&lt;br /&gt;
&lt;br /&gt;
== Methods ==&lt;br /&gt;
'''client.caption[ret: string]'''&lt;br /&gt;
&lt;br /&gt;
'''client.caption()'''&lt;br /&gt;
*Returns the caption of the caption (or the title) of the window.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.close'''&lt;br /&gt;
&lt;br /&gt;
'''client.close()'''&lt;br /&gt;
*Closes the given client using killClient.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.move[variable parameter styles]'''&lt;br /&gt;
&lt;br /&gt;
'''client.move(location {qpoint}, emitjs {boolean})'''&lt;br /&gt;
&lt;br /&gt;
'''client.move(x {integer}, y {integer}, emitjs {boolean})'''&lt;br /&gt;
*Moves the client to the specified location keeping the height and width of the client same.&lt;br /&gt;
**'''location {qpoint}''': The (x, y) point to where the top left corner of the client must be moved to keeping the current height and width same.&lt;br /&gt;
**'''emitjs {boolean}''': EmitJS value (defaults to true).&lt;br /&gt;
**'''x {integer}''': The x co-ordinate value of the point to where the top left corner of the client must be moved to keeping the current height and width same.&lt;br /&gt;
**'''y {integer}''': The y co-ordinate value of the point to where the top left corner of the client must be moved to keeping the current height and width same.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.resize[variable parameter styles]'''&lt;br /&gt;
&lt;br /&gt;
'''client.resize(size {qsize}, emitJS {boolean})'''&lt;br /&gt;
&lt;br /&gt;
'''client.resize(w {integer}, h {integer}, emitJS {boolean})'''&lt;br /&gt;
*Resizes the client to the specified size without changing its position.&lt;br /&gt;
**'''size {qsize}''': The size to which the client is to be resized.&lt;br /&gt;
**'''emitJS {boolean}''': EmitJS value (defaults to true).&lt;br /&gt;
**'''w {integer}''': New width for the client.&lt;br /&gt;
**'''h {integer}''': New height for the client.&lt;br /&gt;
**'''emitJS {boolean}''': EmitJS value (defaults to true).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.setGeometry[variable parameter styles]'''&lt;br /&gt;
&lt;br /&gt;
'''client.setGeometry(geometry {qrect}, emitJS {boolean})'''&lt;br /&gt;
&lt;br /&gt;
'''client.setGeometry(x {integer}, y {integer}, w {integer}, h {integer})'''&lt;br /&gt;
*Sets the geometry of the client i.e. sets is size and location according to the provided parameters.&lt;br /&gt;
**'''geometry {qrect}''': The new geometry which is to be set for the client.&lt;br /&gt;
**'''emitJS {boolean}''': EmitJS value (defaults to true).&lt;br /&gt;
**'''x {integer}''': The x co-ordinate of the new geometry.&lt;br /&gt;
**'''y {integer}''': The y co-ordinate of the new geometry.&lt;br /&gt;
**'''w {integer}''': The width of the new geometry.&lt;br /&gt;
**'''h {integer}''': The height of the new geometry.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.getWindowInfo[ret: windowinfo]'''&lt;br /&gt;
&lt;br /&gt;
'''client.getWindowInfo()'''&lt;br /&gt;
*Returns a windowinfo object which can be used to get further information about the client. Wherever possible, directly use the client properties than calling for a windowinfo object. NOTE: The windowinfo object is a 'snapshot' object and hence the data provided by it is not modified when the properties of the client are changed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.isTransient[ret: boolean]'''&lt;br /&gt;
&lt;br /&gt;
'''client.isTransient()'''&lt;br /&gt;
*Returns (true) is 'client' is transient, (false) otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.isTransientFor[ret: client]'''&lt;br /&gt;
&lt;br /&gt;
'''client.isTransientFor()'''&lt;br /&gt;
*If the given client is transient, returns it's parent client, otherwise returns an undefined scriptvalue.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.activate'''&lt;br /&gt;
'''client.activate()'''&lt;br /&gt;
*Attempt to activate (focus) the client. By attempt, it means that focus stealing prevention still is activated and the rules for activation are in place. Hence, the client actually may nor may not be activated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.setCaption'''&lt;br /&gt;
&lt;br /&gt;
'''client.setCaption(caption_string {string})'''&lt;br /&gt;
*Sets the caption for the specified client to caption_string.&lt;br /&gt;
**'''caption_string {string}''': The caption to be set for the specified.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.unminimize'''&lt;br /&gt;
&lt;br /&gt;
'''client.unminimize()'''&lt;br /&gt;
*Unminimizes (or restores) the given client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.setFullScreen'''&lt;br /&gt;
&lt;br /&gt;
'''client.setFullScreen( {fss_set})'''&lt;br /&gt;
*Sets the client to or from full screen mode.&lt;br /&gt;
**'''{fss_set}''': If (true), then the client is set to full screen or else, it is unset from fullscreen mode. If no parameter is provided, it toggles the full screen state.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.isShade[ret: boolean]'''&lt;br /&gt;
&lt;br /&gt;
'''client.isShade()'''&lt;br /&gt;
*Returns (true) of the client is shaded, (false) otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.isShadeable[ret: boolean]'''&lt;br /&gt;
&lt;br /&gt;
'''client.isShadeable()'''&lt;br /&gt;
*Returns (true) of the client is shadeable (can be shaded), (false) otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.isMinimized[ret: boolean]'''&lt;br /&gt;
&lt;br /&gt;
'''client.isMinimized()'''&lt;br /&gt;
*Returns (true) of the client is minimized, (false) otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.isMinimizable[ret: boolean]'''&lt;br /&gt;
&lt;br /&gt;
'''client.isMinimizable()'''&lt;br /&gt;
*Returns (true) of the client can be minimized, (false) otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.isMaximizable[ret: boolean]'''&lt;br /&gt;
&lt;br /&gt;
'''client.isMaximizable()'''&lt;br /&gt;
*Returns (true) of the client can be mazimized, (false) otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.isResizable[ret: boolean]'''&lt;br /&gt;
&lt;br /&gt;
'''client.isResizable()'''&lt;br /&gt;
*Returns (true) of the client can be resized (changable size), (false) otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.isMovable[ret: boolean]'''&lt;br /&gt;
&lt;br /&gt;
'''client.isMovable()'''&lt;br /&gt;
*Returns (true) of the client can be moved (non-fixed location), (false) otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.isMovableAcrossScreens[ret: boolean]'''&lt;br /&gt;
&lt;br /&gt;
'''client.isMovableAcrossScreens()'''&lt;br /&gt;
*Returns (true) of the client can be moved across screens (only valid in a multiple monitor setup), (false) otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.isCloseable[ret: boolean]'''&lt;br /&gt;
&lt;br /&gt;
'''client.isCloseable()'''&lt;br /&gt;
*Returns (true) of the client can be closed by user action (or any other action other than the system or the application itself), (false) otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.isFullScreen[ret: boolean]'''&lt;br /&gt;
&lt;br /&gt;
'''client.isFullScreen()'''&lt;br /&gt;
*Returns (true) of the client is in fullscreen mode, (false) otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.isFullScreenable[ret: boolean]'''&lt;br /&gt;
&lt;br /&gt;
'''client.isFullScreenable()'''&lt;br /&gt;
*Returns (true) of the client can be set to fullscreen mode, (false) otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.clientGroup[ret: clientgroup]'''&lt;br /&gt;
&lt;br /&gt;
'''client.clientGroup()'''&lt;br /&gt;
*Returns the client group the client belongs to. If it belongs to no client, it returns an undefined script value.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''client.desktop[ret: integer]'''&lt;br /&gt;
&lt;br /&gt;
'''client.desktop()'''&lt;br /&gt;
*Returns the desktop number that the client is on. If it is on all desktops, it returns -1.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= clientgroup[instantiable] =&lt;br /&gt;
== Methods ==&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.ClientGroup[constructor]'''&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.ClientGroup(seed_client {client})'''&lt;br /&gt;
*Creates a new clientgroup object. A clientgroup in essence refers to a group of tabbed clients and an object refers to a specific group of such tabbed clients. It returns a clientgroup object which can be then manipulated using the various accessor functions.&lt;br /&gt;
**'''seed_client {client}''': The client to be added to the newly formed clientgroup. This is a mandatory argument for the creation of a new clientgroup object.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.add'''&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.add(new_client {client}, beforeClient {integer}, becomeVisible {boolean})'''&lt;br /&gt;
*Adds new_client to the clientgroup at the index specified by beforeClient and if becomeVisible is true, makes it visible.&lt;br /&gt;
**'''new_client {client}''': A client object to be added to the clientgroup.&lt;br /&gt;
**'''beforeClient {integer}''': An index as to where the client is to be added to the clientgroup. It is an optional argument and if not specified, it will be added at the last position in the clientgroup.&lt;br /&gt;
becomeVisible {boolean}: If (true), makes the added client visible.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.remove[variable parameter styles]'''&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.remove(index {integer}, set_geom {qrect})'''&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.remove(rem_client {client}, set_geom {qrect})'''&lt;br /&gt;
*Removes the client from the clientgroup and then sets it's geometry according to set_geom. This parameter is optional.&lt;br /&gt;
**'''index {integer}''': The client index which is to be removed.&lt;br /&gt;
**'''set_geom {qrect}''': The geometry to be set after removeal. This parameter is optional.&lt;br /&gt;
**'''rem_client {client}''': The client which is to be removed.&lt;br /&gt;
**'''set_geom {qrect}''': The geometry to be set after removal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.clients[ret: Array(client)]'''&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.clients()'''&lt;br /&gt;
*Returns an array of all the member clients of the clientgroup.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.contains[ret: boolean]'''&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.contains(needle_client {client})'''&lt;br /&gt;
*Returns (true) if needle_client is a member of the clientgroup, (false) otherwise.&lt;br /&gt;
**'''needle_client {client}''': The client to be searched for&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.indexOf[ret: integer]'''&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.indexOf(needle_client {client})'''&lt;br /&gt;
*Searches for needle_client in the clientgroup and returns the position at which it exists. If needle_client is not found, then it returns -1.&lt;br /&gt;
**'''needle_client {client}''': The client whose index is to be found&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.move[variable parameter styles]'''&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.move(index_a {integer}, index_b {integer})'''&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.move(move_client {integer}, index {integer})'''&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.move(move_client {integer}, before_client {integer})'''&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.move(index_a {integer}, before_client {integer})'''&lt;br /&gt;
*Move a client within the group. Accepts move(client, client), move(index, index), move(index, client), move(client, index). All calls except move(client, client) are eventually mapped to move(index, index) using indexOf(client)&lt;br /&gt;
**'''index_a {integer}''': The index of the client to be moved.&lt;br /&gt;
**'''index_b {integer}''': The index of the position to move the client to.&lt;br /&gt;
**'''move_client {integer}''': The client to be moved.&lt;br /&gt;
**'''index {integer}''': The index of the position to move the client to.&lt;br /&gt;
**'''move_client {integer}''': The client to be moved.&lt;br /&gt;
**'''before_client {integer}''': The client before which the client is to moved.&lt;br /&gt;
**'''index_a {integer}''': The index of the client to be moved.&lt;br /&gt;
**'''before_client {integer}''': The client before which the client is to moved.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.removeAll'''&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.removeAll()'''&lt;br /&gt;
*Removes all the clients from the clientgroup i.e. completely disassembles the clientgroup into its proponents.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.closeAll'''&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.closeAll()'''&lt;br /&gt;
*Closes all the clients presents in the clientgroup.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.minSize[ret: qsize]'''&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.minSize()'''&lt;br /&gt;
*Returns the minimum size acceptable for the clientgroup computed from the minimum sizes of all its present members.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.maxSize[ret: qsize]'''&lt;br /&gt;
&lt;br /&gt;
'''clientgroup.maxSize()'''&lt;br /&gt;
*Returns the maximum size acceptable for the clientgroup computed from the minimum sizes of all its present members.&lt;br /&gt;
&lt;br /&gt;
= windowinfo[floating] =&lt;br /&gt;
== Properties ==&lt;br /&gt;
'''windowinfo.isValid [ret: boolean] [GO]'''&lt;br /&gt;
*Returns (true) if the client is valid, (false) otherwise.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''windowinfo.visibleName [ret: string] [GO]'''&lt;br /&gt;
*Returns the visible name of the client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''windowinfo.isMinimized [ret: boolean] [GO]'''&lt;br /&gt;
*Returns (true) if client is minimized. Redundant with client.isMinimized. For client, the subclass property is called, not the toplevel one.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''windowinfo.state [ret: integer] [GO]'''&lt;br /&gt;
*Returns an integeral state for the client. Prefer other methods like isShaded, isFullScreenSet etc. over this.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''windowinfo.windowRole [ret: string] [GO]'''&lt;br /&gt;
*Returns the window role of the toplevel client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''windowinfo.windowClassClass [ret: string] [GO]'''&lt;br /&gt;
*Returns the windowclass class of the client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''windowinfo.windowClassName [ret: string] [GO]'''&lt;br /&gt;
*Returns the windowclass name of the client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= config[singleton] =&lt;br /&gt;
== Methods ==&lt;br /&gt;
&lt;br /&gt;
'''config.exists'''&lt;br /&gt;
&lt;br /&gt;
'''config.exists(config_key {string})'''&lt;br /&gt;
*Searches for config_key in the configuration array and returns (true) if a corresponding value exists, (false) otherwise.&lt;br /&gt;
**'''config_key {string}''': The configuration key to be seeked.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''config.get[variable parameter styles]'''&lt;br /&gt;
&lt;br /&gt;
'''config.get()'''&lt;br /&gt;
&lt;br /&gt;
'''config.get(key1, key2 ... keyN {string})'''&lt;br /&gt;
&lt;br /&gt;
'''config.get(key {string})'''&lt;br /&gt;
&lt;br /&gt;
'''config.get(keyArray {Array(string)}, showNonAssoc {boolean})'''&lt;br /&gt;
*If called without parameters, returns an associative array in the format [&amp;quot;key&amp;quot; : &amp;quot;value&amp;quot;] of all available key value pairs. If only a single key is requested for (passing 1 string parameter), then the corresponding value is returned and NOT an array. If multiple keys are provided as multiple arguments, an associative array is returned. If multiple keys (or a single) key is provided as an Array, then an associative array is present (if showNonAssoc is false or it is not specified), otherwise returns an integer indexed array.&lt;br /&gt;
**'''key1, key2 ... keyN {string}''': A list of keys to search the values for.&lt;br /&gt;
**'''key {string}''': The key to search the value for.&lt;br /&gt;
**'''keyArray {Array(string)}''': An array of keys to search the corresponding values for.&lt;br /&gt;
**'''showNonAssoc {boolean}''': If (true) causes the function to return an integer-indexed array, otherwise returns an associative array in the form [&amp;quot;key&amp;quot; : &amp;quot;value&amp;quot;]. This parameter is optional, defaults to false&lt;br /&gt;
&lt;br /&gt;
== Properties ==&lt;br /&gt;
'''config.loaded [ret: boolean] [GO]'''&lt;br /&gt;
*Returns (true) if a configuration file was found and loaded, (false) otherwise.&lt;/div&gt;</summary>
		<author><name>Vmax0770</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Thread:Talk:Development/Tutorials/KWin/Scripting/Copyright/reply</id>
		<title>Thread:Talk:Development/Tutorials/KWin/Scripting/Copyright/reply</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Thread:Talk:Development/Tutorials/KWin/Scripting/Copyright/reply"/>
				<updated>2011-12-15T10:26:58Z</updated>
		
		<summary type="html">&lt;p&gt;Vmax0770: Reply to Copyright&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I think, yes, because it's a Google Code-In task (http://www.google-melange.com/gci/task/view/google/gci2011/7127225). If you need, I can contact the author.&lt;/div&gt;</summary>
		<author><name>Vmax0770</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KWin/Scripting/API</id>
		<title>Development/Tutorials/KWin/Scripting/API</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KWin/Scripting/API"/>
				<updated>2011-12-14T23:19:34Z</updated>
		
		<summary type="html">&lt;p&gt;Vmax0770: /* unfinished */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= workspace[singleton] =&lt;br /&gt;
== Events ==&lt;br /&gt;
'''workspace.currentDesktopChanged'''&lt;br /&gt;
*Emitted when the user switches from a virtual desktop to another.&lt;br /&gt;
**'''old_desk {integer}''': The number of the virtual desktop the user switched from.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''workspace.desktopPresenceChanged'''&lt;br /&gt;
*Emitted whenever a client is moved across virtual desktops. The client's previous desktop is available through the old_desk parameter, whereas the current desktop can be fetched using moved_client.desktop&lt;br /&gt;
**'''moved_client {client}''': The client which was moved from desktop old_desk to the new one&lt;br /&gt;
**'''old_desk {integer}''': The previous desktop on which the client was present&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''workspace.clientAdded'''&lt;br /&gt;
*Emitted whenever a new client is added to the workspace. This generally occurs when a new window is opened which includes dialog boxes, windows etc. However, it is NOT emitted for unmanaged clients like the Alt+Tab switcher.&lt;br /&gt;
**'''added_client {client}''': The client which was added.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''workspace.clientManaging'''&lt;br /&gt;
*Emitted whenever a client is being managed by the KWin subsystem. The difference between workspace.clientManaging and workspace.clientAdded is that clientManaging is emitted BEFORE clientAdded. Also, if KWin is restarted with a list of clients C, then the clientManaging event will be emitted for every client in C, but clientAdded will not.&lt;br /&gt;
**'''managing_client {client}''': The client which is being managed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''workspace.clientMinimized'''&lt;br /&gt;
*Emitted whenever a client is minimized.&lt;br /&gt;
**'''minimized_client {client}''': The client which was minimized.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''workspace.clientMaximizeSet'''&lt;br /&gt;
*Emitted whenever a client is maximized in a particular orientation. The orientation i.e. the rectangular direction in which the client was specified to occupy the entire available space is specified by the two parameters horizontally and vertically. If both are true, the client was maximized fully i.e. asked to occupy the entire workspace are available.&lt;br /&gt;
**'''maximized_client {client}''': The client which was maximized (in a certain orientation).&lt;br /&gt;
**'''horizontally {boolean}''': (true) if the client was maximized horizontally, (false) otherwise.&lt;br /&gt;
    vertically {boolean}: (true) if the client was maximized vertically, (false) otherwise.&lt;br /&gt;
&lt;br /&gt;
workspace.killWindowCalled&lt;br /&gt;
&lt;br /&gt;
Emitted whenever the user requests a Kill Window [generally using the Ctrl+Esc combination]. The parameter killwindow_client is not completely safe and may return kill windows out of order of invocation. This is just a fancy function, avoid using. Instead, use workspace.clientAdded and filter for incoming Kill Windows.&lt;br /&gt;
&lt;br /&gt;
    killwindow_client {client}: The client handle to the kill window that was called.&lt;br /&gt;
&lt;br /&gt;
workspace.clientActivated&lt;br /&gt;
&lt;br /&gt;
Emitted whenever a client is given focus or 'activated'.&lt;br /&gt;
&lt;br /&gt;
    activated_client {client}: The client which was activated (or received focus).&lt;br /&gt;
&lt;br /&gt;
workspace.clientFullScreenSet&lt;br /&gt;
&lt;br /&gt;
Emitted whenever a client is set to full screen or unset. The fss_set parameter can be used to determine whether the client was set or unset.&lt;br /&gt;
&lt;br /&gt;
    fss_set {boolean}: (true) if the client was switched to full screen mode, (false) if it was switched from full screen mode.&lt;br /&gt;
    fss_client {client}: The client which was set/unset to fullscreen.&lt;br /&gt;
&lt;br /&gt;
workspace.clientUnminimized&lt;br /&gt;
&lt;br /&gt;
Emitted whenever a client is Unminimized (or restored).&lt;br /&gt;
&lt;br /&gt;
    unm_client {client}: The client which was unminimzed.&lt;/div&gt;</summary>
		<author><name>Vmax0770</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials/KWin/Scripting</id>
		<title>Development/Tutorials/KWin/Scripting</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials/KWin/Scripting"/>
				<updated>2011-12-14T23:13:31Z</updated>
		
		<summary type="html">&lt;p&gt;Vmax0770: Adapted from http://rohanprabhu.com/?p=116&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= KWin Scripting Tutorial =&lt;br /&gt;
&lt;br /&gt;
== The KWin script loading procedure ==&lt;br /&gt;
&lt;br /&gt;
When KWin loads it looks in a folder for scripts it should run. This folder is given by: ''$KDEHOME/share/apps/kwin/scripts/''. Let’s call this directory ''KWINSCRIPTS'' for now.&lt;br /&gt;
&lt;br /&gt;
Now, here is how KWin loads the scripts:&lt;br /&gt;
&lt;br /&gt;
*Locate the ''$KWINSCRIPTS'' directory.&lt;br /&gt;
*Make a list of all the files in the ''$KWINSCRIPTS'' directory. For a file to be recognized and executed as a script, it must meet the following conditions:&lt;br /&gt;
**It must have one of the following extensions: ''.kwinscript'', ''.kws'' or ''.kwinqs''&lt;br /&gt;
**It must have the executable flag set.&lt;br /&gt;
*For every file with name as ''scriptfile.kwinscript'', ''scriptfile.kwinqs'' or ''scriptfile.kws'', a configuration file ''scriptfile.kwscfg'' is loaded as its configuration file and all its keys and values are loaded.&lt;br /&gt;
*All files recognized as scripts are executed one after the other.&lt;br /&gt;
&lt;br /&gt;
In this tutorial, configuration files and it’s loading is not covered. Details about configuring your KWin scripts are available [http://rohanprabhu.com/?p=85 here].&lt;br /&gt;
&lt;br /&gt;
== Setting up your development environment ==&lt;br /&gt;
&lt;br /&gt;
For the purposes of this tutorial, we’ll create a script file ''tutorial.kwinscript'' or anything you may prefer. Save it to the ''KWINSCRIPTS'' folder. Also, do set the executable bit for the scripting file using &amp;lt;code&amp;gt;chmod +x tutorial.kwinscript&amp;lt;/code&amp;gt;. In the script ''tutorial.kwinscript'', enter the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
print(&amp;quot;Hello World&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The phrase '''‘Hello World’''' may have become too old and repetitive, but we may break laws, we may break promises, but we never ever break tradition. So, Hello World it is. You may either have another account for KDE-development or you may be a KWin user having a single KDE installation. If you have a single KDE installation, I would suggest that you create another account for KDE-development, the details for which can be found [http://techbase.kde.org/Getting_Started/Build/KDE4.x here]. This is so because KWin scripting is still in development and some nasty scripts may cause a crash or some other similarly crippling behaviour. Whenever testing a script or changes to a script, use a terminal to reload kwin. The reason to do so is so that you can read the output from a script on the terminal. Any scripting errors are also reported to the stdout, so it is helpful if you run it within a terminal. To load KWin, open '''Konsole''' and just type in:&lt;br /&gt;
&amp;lt;code&amp;gt;kwin --replace &amp;amp;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will reload the scripts and execute them again. For your first script, let us follow these steps:&lt;br /&gt;
&lt;br /&gt;
*First create a file in KWINSCRIPTS called ‘tutorial.kwinscript’.&lt;br /&gt;
*Edit ''tutorial.kwinscript'' and add the following line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
print(&amp;quot;Hello World&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Save the file, and set executable permissions on the file using &amp;lt;code&amp;gt;chmod +x tutorial.kwinscript&amp;lt;/code&amp;gt;.&lt;br /&gt;
*Open up '''Konsole''' (or switch to the user account you develop on and then start up '''Konsole''') and type in the following line: &amp;lt;code&amp;gt;kwin --replace &amp;amp;&amp;lt;/code&amp;gt;&lt;br /&gt;
*In the terminal, you should see the line '''‘Hello World’''' printed. If you see it, Congrats! You’ve just written and run your first KWin script.&lt;br /&gt;
&lt;br /&gt;
Output from the terminal is pretty useful when it comes to debugging your script. Here is how my terminal looks after attaching an event which prints a line everytime a client is minimized alongwith its caption:&lt;br /&gt;
&lt;br /&gt;
[[File:Kwintut1.png]]&lt;br /&gt;
&lt;br /&gt;
This is the development environment you’ve setup and this is what we’ll be using for the rest of this tutorial. If KWin crashes, you can try moving your mouse over the '''Konsole''' window which launched KWin. This will most probably return focus to the window and then you can try entering &amp;lt;code&amp;gt;kwin --replace &amp;amp;&amp;lt;/code&amp;gt; again. Since focusing is handled by the Window manager, when KWin crashes focus issues are common and you need a little bit of experience and luck at times. I suggest you read the KWin/HACKING file located [http://community.kde.org/KWin/Hacking here].&lt;br /&gt;
&lt;br /&gt;
== KWin scripting basics ==&lt;br /&gt;
&lt;br /&gt;
To follow this tutorial, you must have some idea about [http://en.wikipedia.org/wiki/ECMAScript ECMAScript] (or [http://en.wikipedia.org/wiki/JavaScript JavaScript]. A quick introduction can be found in the [http://techbase.kde.org/Development/Tutorials/Plasma#JavaScript Plasma scripting tutorial].&lt;br /&gt;
&lt;br /&gt;
===Types===&lt;br /&gt;
In KWin scripting, there are three kinds of variables:&lt;br /&gt;
&lt;br /&gt;
*Floating&lt;br /&gt;
*Singleton&lt;br /&gt;
*Instantiable&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Instantiable''' objects are your regular objects, instances of which you can create using the &amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var x = new X();&amp;lt;/syntaxhighlight&amp;gt; syntax. Examples of instantiable objects would be ''QTimer'' and ''ClientGroup''.&lt;br /&gt;
&lt;br /&gt;
'''Singletong''' objects are those objects who have only one instance of their type. For example, there is only one ''‘workspace’'' objects.&lt;br /&gt;
&lt;br /&gt;
'''Floating''' objects, quite unique to the KWin scripting itself are objects that although have many instances, but none of them can be created. These can only be obtained as the return values of various methods.&lt;br /&gt;
&lt;br /&gt;
===Events===&lt;br /&gt;
KWin scripting is completely ''event-driven''. Now there are quite a number of events within KWin scripting, and a lot more to be added. The thing to note here is that some events are availabe both system-wide and specific only. The previous sentence might seem a little confusing. Allow me to explain. Take the case of an event ''‘A client is minimized’''. KWin scripting provides two kinds of events:&lt;br /&gt;
*'''workspace.clientMinimized''' is emitted system-wide i.e. whenever any client is minimized throughout the workspace.&lt;br /&gt;
*'''myclient.minimized''' is specific to the object it is called from, in this case '''‘myclient’'''. It is emitted only and only when '''‘myclient’''' is minimized.&lt;br /&gt;
&lt;br /&gt;
To handle events, one must simply use the &amp;lt;syntaxhighlight lang=javascript&amp;gt;object.event.connect()&amp;lt;/syntaxhighlight&amp;gt; syntax. Let’s say, whenever I minimize a client, I want to print it’s caption. Here’s the code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=javascript&amp;gt;&lt;br /&gt;
workspace.clientMinimized.connect(function(client) {&lt;br /&gt;
    print(client.caption());&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The '''print''' function prints to your terminal and is extremely useful for debugging. In the code snippet above, an anonymous function is connected to the event '''workspace.clientMinimized''', which is emitted whenever a client is minimized. The function which is called is passed as a parameter the client that was minimized. In case of the other event, no such parameter is passed, as we obviously know the specific client which is being called:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=javascript&amp;gt;&lt;br /&gt;
myclient.minimized.connect(function() {&lt;br /&gt;
    print(&amp;quot;Minimize a client!!&amp;quot;);&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To understand which parameters are passed to the event handlers (i.e. the functions we connect to), one can always refer the [[Development/Tutorials/KWin/Scripting/API]].&lt;br /&gt;
&lt;br /&gt;
== Your first (useful) script ==&lt;br /&gt;
&lt;br /&gt;
In this tutorial we will be creating a script based on a suggestion by Eike Hein. In Eike’s words: ''“A quick use case question: For many years I’ve desired the behavior of disabling keep-above on a window with keep-above enabled when it is maximized, and re-enabling keep-above when it is restored. Is that be possible with kwin scripting? It’ll need the ability to trigger methods on state changes and store information above a specific window across those state changes, I guess.”''&lt;br /&gt;
&lt;br /&gt;
Other than the really function and useful script idea, what is really great about this is that it makes for a perfect tutorial example. I get to cover most of the important aspects of KWin scripting while at the same time creating something useful.&lt;br /&gt;
&lt;br /&gt;
So let’s get on with it…&lt;br /&gt;
&lt;br /&gt;
=== The basic outline ===&lt;br /&gt;
'''Design statement''': For every window that is set to '''‘Keep Above’''' others, the window should not be above all windows when it is maximized.&lt;br /&gt;
&lt;br /&gt;
To do so, this is how we’ll proceed:&lt;br /&gt;
#Create an array of clients whose '''‘Keep Above’''' property is set.&lt;br /&gt;
#Whenever a script loads, make a list of all clients whose '''‘Keep Above’''' property is set and add it to the array.&lt;br /&gt;
#Whenever a client is maximized, if it’s ''''‘Keep Above’''' property is set, remove the '''‘Keep Above’''' property.&lt;br /&gt;
#Whenever a client is restored, if it is in the ‘array’, set it’s '''‘Keep Above’''' property.&lt;br /&gt;
#Whenever a new client is added, check and see if it needs to be added to the array (depending on whether it’s '''‘Keep Above’''' property is set or not).&lt;br /&gt;
&lt;br /&gt;
==== The basic framework ====&lt;br /&gt;
So, for first steps, let us just create an array:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=javascript&amp;gt;&lt;br /&gt;
var ka_clients = new Array();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Now, we need to make a list of all available clients whose '''‘Keep Above’''' property is set. From the [[Development/Tutorials/KWin/Scripting/API|KWin API docs]] you can lookup the '''workspace.getAllClients()''' method:&lt;br /&gt;
&lt;br /&gt;
[[File:Kwintut2.png]]&lt;br /&gt;
&lt;br /&gt;
Allow me to present a small primer on how to read the KWin API docs. Here, the first line mentions the method, which is '''‘workspace.getAllClients’'''. The '''‘ret’''' specifies the type of value that will be returned by the method. Here, it says ''ret: Array(client)'', which means that an array of client objects will be returned. It takes one parameter '''desktop_no''', which specifies which desktop to fetch the clients from. The rest is clear from the description itself. So, to check all the clients whose '''‘Keep Above’''' property is set, we will use the following piece of code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=javascript&amp;gt;&lt;br /&gt;
var c = workspace.getAllClients();&lt;br /&gt;
&lt;br /&gt;
for(var i=0; i&amp;lt;c.length; i++) {&lt;br /&gt;
    if(c[i].keepAbove()) {&lt;br /&gt;
        print(client.caption() + &amp;quot; (yes)&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Explanation:'''&lt;br /&gt;
*First, it gets a list of all clients available from all the desktops and stores it in a variable '''‘c’'''.&lt;br /&gt;
*Then it loops over the entire array and checks for clients whose '''‘keepAbove’''' property is set. To do this, one can use the '''client.keepAbove''' method. It returns true if the given clients '''‘Keep Above’''' property is set.&lt;br /&gt;
*Then it simply prints the clients caption.&lt;br /&gt;
&lt;br /&gt;
Here, every element of '''‘c’''' is an object of type '''‘client’'''. Every '''‘client’''' object represents a window. Here is how my terminal looks after writing this script:&lt;br /&gt;
&lt;br /&gt;
[[File:Kwintut3.png]]&lt;br /&gt;
&lt;br /&gt;
Now, what we need to do, is add every such client to the array '''ka_clients'''. So this is how our code will look:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=javascript&amp;gt;&lt;br /&gt;
var ka_clients = new Array();&lt;br /&gt;
var c = workspace.getAllClients();&lt;br /&gt;
&lt;br /&gt;
for(var i=0; i&amp;lt;c.length; i++) {&lt;br /&gt;
    if(c[i].keepAbove()) {&lt;br /&gt;
        ka_clients[ka_clients.length] = c[i];&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What '''ka_clients[ka_clients.length]''' does is append an element to that array.&lt;br /&gt;
&lt;br /&gt;
==== Manage maximization for clients ====&lt;br /&gt;
Now that we have added it to an array, we need to make a provision that whenever the client is maximized, it’s '''‘Keep Above’''' property does not stay. So, we’ll modify the previous code a little:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=javascript&amp;gt;&lt;br /&gt;
function manageKeepAbove(type) {&lt;br /&gt;
    if((type.h == 1) &amp;amp;&amp;amp; (type.v == 1)) {&lt;br /&gt;
        this.setKeepAbove(0);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
for(var i=0; i&amp;lt;c.length; i++) {&lt;br /&gt;
    if(c[i].keepAbove()) {&lt;br /&gt;
        ka_clients[ka_clients.length] = c[i];&lt;br /&gt;
        ka_clients.onMaximizeSet.connect(c[i], manageKeepAbove);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For all events, there are two ways to connect it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=javascript&amp;gt;&lt;br /&gt;
object.event.connect(h_function);&lt;br /&gt;
object.event.connect(f_this, h_function);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In either case, '''h_function''' is called whenever the event occurs, but in the second case, the function’s '''‘this’''' object is set to '''f_this'''. We use the second way because as you can see, multiple clients connect to the same function. So whenever a function is called, how does it know which client it must handle? Hence, we must specify the object it must ‘act on’, or in the other words, it’s ‘this object’.&lt;br /&gt;
&lt;br /&gt;
'''client.onMaximizeSet''' is an event whenever a client is maximized. There are two parameters while specifying a maximization: horizontal maximization and vertical maximization. The function is passed only one value which has two properties '''‘h’''' and '''‘v’'''. It specifies in which direction the client occupied the workspace dimension. We want the property to be triggered only when the client is maximized in both the directions. Note here that it is not necessary to write a function of our own in the global scope since we can use anonymous functions also. However, we are writing a function in the global scope so that we can even disconnect this slot later if needed.&lt;br /&gt;
&lt;br /&gt;
Save and run this script and see if it works as one would expect it to.&lt;br /&gt;
&lt;br /&gt;
==== Managing clients whose properties which are dynamically set ====&lt;br /&gt;
At this point however, if you set the '''‘Keep Above’''' property for a client, its property won’t be removed on maximization. This is because currently we are only covering the clients which are already present. To cover clients whose property is set after a script has been loaded, we’ll use the event '''workspace.clientSetKeepAbove'''. What we’ll do is, for every client whose '''‘Keep Above’''' property is changed, we’ll add it to the array if it is set, and we’ll remove it from the array if it is unset. This is how we’ll proceed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=javascript&amp;gt;&lt;br /&gt;
workspace.clientSetKeepAbove.connect(function(client, set) {&lt;br /&gt;
    var found = ka_clients.indexOf(client);&lt;br /&gt;
&lt;br /&gt;
    if(set == 1) {&lt;br /&gt;
        if(found == -1) {&lt;br /&gt;
            ka_clients[ka_clients.length] = client;&lt;br /&gt;
            client.maximizeSet.connect(client, manageKeepAbove);&lt;br /&gt;
        }&lt;br /&gt;
    } else if(set == 0) {&lt;br /&gt;
        ka_clients.splice(found, 1);&lt;br /&gt;
        client.maximizeSet.disconnect(manageKeepAbove);&lt;br /&gt;
    }&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Explanation:'''&lt;br /&gt;
*In the event handler for '''workspace.clientSetKeepAbove''', we’ve used an anonymous function, as I mentioned was also possible previously. This is because we want this event handler to be alive throughout the execution of the script i.e. we don’t want to ever disconnect it. In such cases, anonymous functions can be used.&lt;br /&gt;
*Here, we simply check for a client. If its property was set, we add it to the array (if it isn’t already there) and it was unset, we remove it from the array (if it is there in the array).&lt;br /&gt;
*Also, whenever it is added to the array, we need to connect it’s '''maximizeSet''' event as we did previously.&lt;br /&gt;
*Do note that we also disconnect the function if the '''‘Keep Above’''' property was unset. To disconnect, we need to provide a function name. This is the reason why we wrote a named function in the global scope instead of an anonymous function.&lt;br /&gt;
&lt;br /&gt;
One point to note there is that, the client object is merely a ''‘wrapper’'' for an actual '''Client''' object (in C++). So then how does the ‘==’ operator work for the same object that was wrapped separately (the == relation is used to lookup up a value using the '''Array.indexOf()''' method)? Even though the object they wrap is the same, shouldn’t their wrapper be different? The answer is no. A scripting object to a kwin scripting object follows a strict 1:1 relation. Just as a wrapper can be mapped to a client, a client can be mapped back to a unique wrapper. This is achieved using script caching, details for which are [http://rohanprabhu.com/?p=14 here]. This is why the ‘==’ and the ‘!=’ operator can be used safely to check if two variables actually wrap the same object or not.&lt;br /&gt;
&lt;br /&gt;
==== Restoring it all ====&lt;br /&gt;
&lt;br /&gt;
Now the last and most important part of it all. Whenver the client is restored, we must set it’s '''‘Keep Above’''' property if it was set earlier. To do this, we must simply extend our '''manageKeepAbove''' code to handle this scenario. In case the client is not maximized both vertically and horizontally, we check if the client is in our '''ka_clients''' arrray and if it is, we set its '''‘Keep Above’''' property, otherwise we don’t bother:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=javascript&amp;gt;&lt;br /&gt;
function manageKeepAbove(type) {&lt;br /&gt;
    if((type.h == 1) &amp;amp;&amp;amp; (type.v == 1)) {&lt;br /&gt;
        this.setKeepAbove(0);&lt;br /&gt;
    } else {&lt;br /&gt;
        if(ka_clients.indexOf(this)) {&lt;br /&gt;
            this.setKeepAbove(1);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the end, our entire script looks like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=javascript&amp;gt;&lt;br /&gt;
var ka_clients = new Array();&lt;br /&gt;
var c = workspace.getAllClients();&lt;br /&gt;
&lt;br /&gt;
workspace.clientSetKeepAbove.connect(function(client, set) {&lt;br /&gt;
    var found = ka_clients.indexOf(client);&lt;br /&gt;
&lt;br /&gt;
    if(set == 1) {&lt;br /&gt;
        if(found == -1) {&lt;br /&gt;
            ka_clients[ka_clients.length] = client;&lt;br /&gt;
            client.maximizeSet.connect(client, manageKeepAbove);&lt;br /&gt;
        }&lt;br /&gt;
    } else if(set == 0) {&lt;br /&gt;
        ka_clients.splice(found, 1);&lt;br /&gt;
        client.maximizeSet.disconnect(manageKeepAbove);&lt;br /&gt;
    }&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
function manageKeepAbove(type) {&lt;br /&gt;
    if((type.h == 1) &amp;amp;&amp;amp; (type.v == 1)) {&lt;br /&gt;
        this.setKeepAbove(0);&lt;br /&gt;
    } else {&lt;br /&gt;
        if(ka_clients.indexOf(this)) {&lt;br /&gt;
            this.setKeepAbove(1);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
for(var i=0; i&amp;lt;c.length; i++) {&lt;br /&gt;
    if(c[i].keepAbove()) {&lt;br /&gt;
        ka_clients[ka_clients.length] = c[i];&lt;br /&gt;
        c[i].maximizeSet.connect(c[i], manageKeepAbove);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Try out this script and check if it works according to your wishes. Before going, let me give you a small excercise. Although we’ve covered all the cases, we surely have left one. Whenever I launch a new window, what if its '''‘Keep Above’''' property is already set? We surely need to manage that also.. ''HINT:'' Use the '''workspace.clientAdded''' property.&lt;/div&gt;</summary>
		<author><name>Vmax0770</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/File:Kwintut3.png</id>
		<title>File:Kwintut3.png</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/File:Kwintut3.png"/>
				<updated>2011-12-14T23:00:00Z</updated>
		
		<summary type="html">&lt;p&gt;Vmax0770: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Vmax0770</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/File:Kwintut2.png</id>
		<title>File:Kwintut2.png</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/File:Kwintut2.png"/>
				<updated>2011-12-14T22:56:17Z</updated>
		
		<summary type="html">&lt;p&gt;Vmax0770: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Vmax0770</name></author>	</entry>

	<entry>
		<id>http://techbase.kde.org/Development/Tutorials</id>
		<title>Development/Tutorials</title>
		<link rel="alternate" type="text/html" href="http://techbase.kde.org/Development/Tutorials"/>
				<updated>2011-12-14T21:59:32Z</updated>
		
		<summary type="html">&lt;p&gt;Vmax0770: /* Application Automation and Scripting */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:I18n/Language Navigation Bar|Development/Tutorials}}&lt;br /&gt;
&lt;br /&gt;
Tutorials are the fastest way of finding out what KDE will do for you, and how to do it. Here is a list of currently available tutorials '''for KDE4'''. Material for KDE3 and KDE2 is available on the bottom of this page.&lt;br /&gt;
&lt;br /&gt;
== Basics of KDE 4 Programming ==&lt;br /&gt;
Are you interested in writing applications with KDE 4? This tutorial series is aimed at those completely new to KDE programming.&lt;br /&gt;
;[[Development/Tutorials/First program|Hello World]]&lt;br /&gt;
:''An introduction to the very basics of KDE4 programming''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Using KXmlGuiWindow|Creating the Main Window]]&lt;br /&gt;
:''This tutorial shows you the magic of an application's most important thing: The main window.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Using KActions|Using KActions]]&lt;br /&gt;
:''How to add actions to the menus and toolbars.'' Based on the MainWindow tutorial.&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Saving and loading|Saving and Loading]]&lt;br /&gt;
:''Introduces the KIO library while adding loading and saving support to our application.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/SqLite|Using SqLite databases and QtSql]]&lt;br /&gt;
: integrated databases without the need for a database server&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/KCmdLineArgs|Command line arguments]]&lt;br /&gt;
:''Adds the ability to specify which file to open from the command line to our text editor.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/CMake|Introduction to CMake]]&lt;br /&gt;
:''How to use the CMake build system used by KDE4.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Common Programming Mistakes|Common Programming Mistakes]]&lt;br /&gt;
:''Various common mistakes made while developing Qt and KDE applications and how to avoid them.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Debugging Linker Errors|Debugging Linker Errors]]&lt;br /&gt;
:''How to understand and debug errors from the linker, at compile time.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Using Qt Creator|Using Qt Creator to develop your KDE program]]&lt;br /&gt;
:''How to use Qt Creator as an [http://en.wikipedia.org/wiki/Integrated_development_environment IDE] to develop KDE programs''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Creating Libraries|Creating Libraries to share code]]&lt;br /&gt;
:''How to add the library to the buildsystem and how to prepare the source code.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Session_Management|Session Management]]&lt;br /&gt;
:''Make your application aware of X sessions''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorial/Icons|Icons]]&lt;br /&gt;
:''Deliver your application with icons that are automatically installed to the right places''. Based on the [[Development/Tutorials/Using_KActions|Kaction Tutorial]].&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Desktop_File|Desktop File]]&lt;br /&gt;
:''Let your application show up in the K menu and in application menus''. Based on the Icons Tutorial.&lt;br /&gt;
&lt;br /&gt;
== Testing And Debugging ==&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Debugging|Debugging your application]]&lt;br /&gt;
:''Tips, tools and techniques to apply when debugging your KDE application''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Unittests|Writing Unittests for Qt4 and KDE4 with QTestLib]] ([http://developer.kde.org/documentation/tutorials/writingunittests/writingunittests.html Original link])&lt;br /&gt;
:''Tutorial by [mailto:bradh@frogmouth.net Brad Hards] that describes how to write unit tests using the QTestLib framework. It is presented as an example based tutorial, and is still under development.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Code_Checking|Semi-automatic ways to detect code errors]]&lt;br /&gt;
:''Techniques you can use to detect errors in KDE code''&lt;br /&gt;
&lt;br /&gt;
== Managing Configuration Data With KConfig ==&lt;br /&gt;
;[[Development/Tutorials/KConfig|Introduction To KConfig]]&lt;br /&gt;
:''An overview of the KConfig classes and how to use them in your application code''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Using KConfig XT|Using KConfig XT]]&lt;br /&gt;
:''Tutorial on how to efficiently use the KConfig XT framework.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Updating KConfig Files|Updating KConfig Files]]&lt;br /&gt;
:''Tutorial on how to write an update script to keep changes in your application's config file format in sync with the user's already existing config file''&lt;br /&gt;
&lt;br /&gt;
== Services: Applications and Plugins ==&lt;br /&gt;
;[[Development/Tutorials/Services/Introduction|Introduction to the Services Framework]]&lt;br /&gt;
:''An overview of the services framework in KDE and what it provides the application developer. Covers the system configuration cache (SyCoCa), the source data files and what the indexed information can be used for.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Services/Traders|Finding Services Using Trader Queries]]&lt;br /&gt;
:''How to find services, such as plugins or mimetypes, that are indexed in the SyCoCa using Trader Query Syntax''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Services/Plugins|Creating and Loading Plugins Using KService]]&lt;br /&gt;
:''Learn how to define custom plugin types, find installed plugins (including 3rd party plugins) and load them in an easy and portable fashion using KService.''&lt;br /&gt;
&lt;br /&gt;
== Localization ==&lt;br /&gt;
See also [[Localization|Localization portal]].&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Localization/Unicode|Introduction To Unicode]]&lt;br /&gt;
:''An introduction to what Unicode is as well as how to handle Unicode data in KDE applications.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Localization/i18n|Writing Applications With Localization In Mind]]&lt;br /&gt;
:''This tutorial covers what localization is, why it's important and how to ensure your application is ready to be localized. A must read for all application developers.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Localization/i18n Mistakes|Avoiding Common Localization Pitfalls]]&lt;br /&gt;
:''There are several common mistakes that prevent applications from being properly localized. Find out what they are and how to easily avoid them in this tutorial.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Localization/Building KDE's l10n Module|Building KDE's Localization Module]]&lt;br /&gt;
:''Building and installing language support from KDE's localization (l10n) module is a good idea for those working on applications in the main KDE repository. Doing so will allow you to test your application in another language and spot problem areas. Learn how to do just that in this tutorial.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Localization/i18n Build Systems|Incorporating i18n Into the Build System]]&lt;br /&gt;
:''Once your application is ready to be localized, the next step is to ensure that translation files are built automatically and kept up to date. This tutorial covers the necessary CMakeFiles.txt additions as well the process of distributing the resulting message catalogs with your application.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Localization/i18n Challenges|Common i18n Challenges and Solutions]]&lt;br /&gt;
:''This tutorial covers challenges that you may eventually run into such as translating handbooks and other data that exists outside of the source code, merging and handling obsolete .po files, dealing with freezes, coding in languages other than English and creating independent releases of or moving applications between KDE modules.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Localization/i18n_Semantics|Semantic Markup of Messages]]&lt;br /&gt;
:''To ensure consistent presentation and more meaningful representations of messages in applications, semantic markup can be applied to messages marked for translation using the KUIT system. This tutorial describes how this system works.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Localization/i18n Krazy|Automated i18n Code Checking]]&lt;br /&gt;
:''The Krazy code checker scans KDE's code and reports common i18n mistakes.''&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/API_Documentation|API Documentation]]&lt;br /&gt;
:''This tutorial explains how to document your APIs properly.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Man_Pages|Man Pages]]&lt;br /&gt;
:''Writing and Generating Reference Manual Pages.''&lt;br /&gt;
&lt;br /&gt;
;Source Code&lt;br /&gt;
: http://gitweb.kde.org&lt;br /&gt;
: http://websvn.kde.org&lt;br /&gt;
&lt;br /&gt;
== Accessibility ==&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Accessibility|Accessibility]]&lt;br /&gt;
:''This tutorial will explain how to make your application accessible.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Text-To-Speech|Text-To-Speech]]&lt;br /&gt;
:''How to utilize Jovie text-to-speech service in your application.''&lt;br /&gt;
&lt;br /&gt;
== Application Automation and Scripting ==&lt;br /&gt;
&lt;br /&gt;
=== D-Bus ===&lt;br /&gt;
; [[Development/Tutorials/D-Bus/Introduction|Introduction to D-Bus]]&lt;br /&gt;
:''A straight-forward introduction to the core concepts in D-Bus from an application developer's perspective, this tutorial covers what D-Bus is and how it can be used by applications.''&lt;br /&gt;
; [[Development/Tutorials/D-Bus/Accessing Interfaces|Accessing D-Bus Interfaces]]&lt;br /&gt;
:''A step-by-step guide to calling D-Bus methods and connecting to D-Bus signals using QtDBus.''&lt;br /&gt;
; [[Development/Tutorials/D-Bus/Intermediate_D-Bus|Intermediate D-Bus]]&lt;br /&gt;
:''Tips to make use of QtDBus when faced with problematic real-world interfaces.''&lt;br /&gt;
; [[Development/Tutorials/D-Bus/Creating Interfaces|Creating D-Bus Interfaces]]&lt;br /&gt;
:''Learn how to expose functionality in your application by creating and using custom D-Bus interfaces. Covers generating the XML descriptions, instantiating interfaces at run time and setting up the build system with CMake.''&lt;br /&gt;
; [[Development/Tutorials/D-Bus/CustomTypes|Using Custom Types with D-Bus]]: ''Learn how to use your own types in classes exported on D-Bus. Covers marhaling and unmarshaling of objects, the integration of custom types into XML descriptions and registering the custom types with the Qt Meta Object system.''&lt;br /&gt;
; [[Development/Tutorials/D-Bus/Autostart Services|D-Bus Autostart Services]]&lt;br /&gt;
:''Turn your application into a D-Bus autostart service with this tutorial. This D-Bus feature, also known as &amp;quot;D-Bus service activation&amp;quot;, will ensure that even when your application isn't running that D-Bus calls made to it will work by relying on the D-Bus daemon itself to start your app if and when needed.''&lt;br /&gt;
; [[Development/Tutorials/Porting_to_D-Bus|Porting from DCOP to D-Bus]]&lt;br /&gt;
: ''Port your applications from DCOP to D-Bus with this handy guide.''&lt;br /&gt;
&lt;br /&gt;
=== Konqueror ===&lt;br /&gt;
; [[Development/Tutorials/Creating Konqueror Service Menus|Creating Konqueror Service Menus]]&lt;br /&gt;
:''This tutorial shows you how to create mimetype-specific actions in Konqueror's context menu (aka &amp;quot;servicemenus&amp;quot;).''&lt;br /&gt;
&lt;br /&gt;
=== Kross ===&lt;br /&gt;
; [[Development/Tutorials/Kross/Introduction|Introduction to Kross]]&lt;br /&gt;
:''An introduction to the Kross Scripting Framework.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Kross/Hello_World|Hello World]]&lt;br /&gt;
:''A first application with working kross code.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Kross/Call_Functions_in_Kross|Calling Functions in Kross]]&lt;br /&gt;
:''Simple demonstration of calling scripting functions''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Kross/Connecting_Signals_and_slots_in_Kross|Connecting Signals and Slots in Kross]]&lt;br /&gt;
:''Simple demonstration of connecting object signals with script slots''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Kross/Scripts-as-Plugins|Scripts as Plugins with Kross]]&lt;br /&gt;
:''This tutorial provides a step-by-step introduction how to integrate scripts as plugins into a KDE application.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Kross/Script-Actions|Placing script actions in your application menus ]]&lt;br /&gt;
:''Simple demonstration on how to extend you application menus to execute script files.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Kross/ActionCollections|How to use an ActionCollection ]]&lt;br /&gt;
:''A small Tutorial on How to use Kross::ActionCollections.''&lt;br /&gt;
{{:KOffice/Plugin Tutorials}}&lt;br /&gt;
&lt;br /&gt;
=== SuperKaramba ===&lt;br /&gt;
; [[Development/Tutorials/SuperKaramba|SuperKaramba Tutorial]]&lt;br /&gt;
:''This tutorial provides an overview of SuperKaramba, theme files and scripting with Python, Ruby and JavaScript.''&lt;br /&gt;
&lt;br /&gt;
=== System Activity ===&lt;br /&gt;
&lt;br /&gt;
: [[Development/Tutorials/SystemActivity/Scripting|Writing script actions for the process's context menu]]&lt;br /&gt;
:''This tutorial shows how to add a context menu action to show custom information about a process.&lt;br /&gt;
&lt;br /&gt;
=== KWin ===&lt;br /&gt;
: [[Development/Tutorials/KWin/Scripting|KWin Scripting Tutorial]]&lt;br /&gt;
:''This tutorial shows how to write a useful script for KWin.&lt;br /&gt;
&lt;br /&gt;
== Plugins and KParts ==&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Using KParts|Using KParts]]:''A kPart is a plugin that you can just load into your application. For example, it is easy to integrate an editor (the katePart) or a console (the konsolePart) into your application's window.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Writing kontact plugins|Writing kontact plugins]]:''Kontact plugins are KParts. This tutorial describes how you can write one.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Writing Qt Designer Plugins|Writing Qt Designer Plugins]]:''Add your widgets to Qt Designer and thus make them usable in UI files.''&lt;br /&gt;
&lt;br /&gt;
== Search and Metadata ==&lt;br /&gt;
&lt;br /&gt;
=== Strigi ===&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Writing file analyzers|Writing file analyzers]]&lt;br /&gt;
:''File analyzers extract data from files to display in the file dialogs and file managers. The data gathered this way is also used to search for files. KDE4 allows the use of multiple analyzers per file type. This tutorial describes how you can write new analyzers.''&lt;br /&gt;
&lt;br /&gt;
=== [http://nepomuk.kde.org Nepomuk] ===&lt;br /&gt;
&lt;br /&gt;
See [[Development/Tutorials/Metadata/Nepomuk|Nepomuk tutorials]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hardware Awareness (Solid) ==&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Solid/Introduction|Introduction to Solid]]&lt;br /&gt;
:''An introduction to the Solid effort in general and it library in particular.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Solid/Device_Discovery|Listing Devices]]&lt;br /&gt;
:''How to use the Solid core library to discover the hardware and interact with the system.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Solid/Network_Management|Accessing Network Information]]&lt;br /&gt;
:''How to use the Solid system to get information about the network''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Solid/Device_Actions|Creating a Device Action]]&lt;br /&gt;
:''When your application is interested in registering actions with the system for removable hardware''&lt;br /&gt;
&lt;br /&gt;
== Authorization and Privilege escalation (KAuth) ==&lt;br /&gt;
; [[Development/Tutorials/KAuth/KAuth_Basics|KAuth Basics]]&lt;br /&gt;
:''An overview of concepts and basic knowledge required to understand and use KAuth effectively''&lt;br /&gt;
; [[Development/Tutorials/KAuth/KAuth_Actions|Using KAuth actions in your application]]&lt;br /&gt;
:''How to execute KAuth actions in your application, and how to integrate them tightly into your UI''&lt;br /&gt;
; [[Development/Tutorials/KAuth/Helper_HowTo|Creating a KAuth helper to perform a privileged action]]&lt;br /&gt;
:''You will learn how to use KAuth's helpers and escalation facilities, and how to seamlessly make a privileged and non privileged portion of your application interact''&lt;br /&gt;
; [[Development/Tutorials/KAuth/KCM_HowTo|Creating a KCM requiring authorization upon saving]]&lt;br /&gt;
:''Learn how to use the high level KCModule API to create KCModules handling authorization, and its UI integration, on their own''&lt;br /&gt;
&lt;br /&gt;
== Multimedia (Phonon) ==&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Phonon/Introduction|Phonon]]&lt;br /&gt;
:''How to start with the multimedia API''&lt;br /&gt;
&lt;br /&gt;
:''How to compile and use Phonon and its GStreamer backend on Linux using Qt 4.3.x''&lt;br /&gt;
::''This article gives you a quick brief of how you can use checkout, compile Phonon and its GStreamer backend on GNU/Linux with just Qt 4.3.x. Towards the end, the article also describes how a developer can make use of Phonon to create simple audio and video players. You can read the article [http://www.vcreatelogic.com/oss/docs/CompilingPhononOnLinux.pdf here]. You can download the editable OpenDocumentText file from [http://www.prashanthudupa.com/phonon/CompilingPhononOnLinux.odt here].''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Phonon/Backends|Writing Backends]]&lt;br /&gt;
:''How to start creating a new backend for the multimedia API''&lt;br /&gt;
&lt;br /&gt;
;Resources&lt;br /&gt;
:''Please have a look at the [http://api.kde.org/kdesupport-api/kdesupport-apidocs/phonon-git/html/ online documentation] for information on the Phonon API. If you prefer using Qt Assistant or Qt Creator you can also use our [http://mts.ms/phonon-4.4.2.qch offline documentation].''&lt;br /&gt;
&lt;br /&gt;
== Plasma ==&lt;br /&gt;
&lt;br /&gt;
See [[Development/Tutorials/Plasma|Plasma tutorials]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Personal Information Management (Akonadi) ==&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Akonadi/Application|Using Akonadi in Applications]]&lt;br /&gt;
:''Displaying and modifying data provided by Akonadi''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Akonadi/Resources|Developing Akonadi Resources]]&lt;br /&gt;
:''Akonadi Resources are agent programs which transport PIM data between Akonadi and a backend (files, servers, etc)''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Akonadi/SerializerPlugin|Using custom data types with Akonadi]]&lt;br /&gt;
:''Akonadi can handle arbitrary data as item payloads through the use of a plugin based serialization framework''&lt;br /&gt;
&lt;br /&gt;
;[[Development/AkonadiPorting|Porting Applications which use KResource API]]&lt;br /&gt;
:''Applications using KDE's now deprecated KResource APIs, e.g. KABC or KCal, need to be ported to use their Akonadi equivalents''&lt;br /&gt;
&lt;br /&gt;
== Kate / Kwrite ==&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Kate/KTextEditor Plugins|Getting started with KTextEditor plugins]]&lt;br /&gt;
:''Creating your first KTextEditor plugin''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Kate/KTextEditor_Plugins_Advanced|Developing a plugin with configuration dialog]]&lt;br /&gt;
:''Adding a configuration dialog to the Time &amp;amp; Date example''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Kate/KTextEditor_Example|A small Editor]]&lt;br /&gt;
:''Create a small application using KTextEditor''&lt;br /&gt;
&lt;br /&gt;
== KDevelop ==&lt;br /&gt;
&lt;br /&gt;
;[[Development/KDevelop-PG-Qt_Introduction|KDevelop-PG-Qt Introduction]]&lt;br /&gt;
:''Information on the KDevelop parser generator, useful for language plugins.''&lt;br /&gt;
&lt;br /&gt;
==Printing==&lt;br /&gt;
&lt;br /&gt;
KDE mostly uses the [http://doc.qt.nokia.com/latest/printing.html Qt Printing infrastructure].&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Printing Hello World|Hello World]]&lt;br /&gt;
:''Introduction to the KDE printing system''&lt;br /&gt;
&lt;br /&gt;
== kioslaves ==&lt;br /&gt;
* [[Development/Tutorials/KIO Slaves/Using KIO Slaves in your Program|Using kioslaves in your Program]]&lt;br /&gt;
* [[Development/Tutorials/KIO Slaves/Hello World|Creating a Hello-World kioslave]]&lt;br /&gt;
&lt;br /&gt;
== Collaboration ==&lt;br /&gt;
&lt;br /&gt;
=== Open Collaboration Services (libattica) ===&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Collaboration/Attica/Introduction|Introduction to Attica]]&lt;br /&gt;
:''In this tutorial a simple widget showing information about a Person on the server is created.''&lt;br /&gt;
&lt;br /&gt;
=== Get Hot New Stuff  ===&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Collaboration/HotNewStuff/Introduction|Get Hot New Stuff 3 - Download]] &lt;br /&gt;
:''How to use KHotNewStuff3 in your application.''&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Collaboration/HotNewStuff/Updates|Get Hot New Stuff 3 - Checking for Updates]] &lt;br /&gt;
:''How to check if updates for installed stuff are available without showing the dialog/widget.''&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Collaboration/HotNewStuff/Upload|Get Hot New Stuff 3 - Upload]] &lt;br /&gt;
:''How to add an upload dialog to your application.''&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Old links for KNS2 and KNS1 content:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/K Hot New Stuff2|Introduction to Get Hot New Stuff 2]] &lt;br /&gt;
:''A short tutorial about how to use KHotNewStuff2 in your application. Deprecated, use version 3'' &lt;br /&gt;
;[[Development/Tutorials/Introduction to Get Hot New Stuff|Introduction to Get Hot New Stuff]] &lt;br /&gt;
:''An introduction to the developer-friendly network update system that allows KDE applications to fetch new application data at runtime in a user friendly manner.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/KNewStuffSecure|KNewStuff Secure]] ([http://developer.kde.org/documentation/tutorials/knewstuffsecure/index.html Original Link]) &lt;br /&gt;
:''Tutorial showing how to share resources in a secured way (KDE 3.4 and later).'' By András Mantia &amp;amp;lt;amantia@kde.org&amp;amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Goya ==&lt;br /&gt;
; [[Development/Tutorials/Introduction to Goya usage|Introduction to Goya usage]]&lt;br /&gt;
:''An introduction for the Goya subsystem usage, which allows you to easily add widgets to your itemviews and connect their signals to your code, as they were real widgets.''&lt;br /&gt;
&lt;br /&gt;
; [[Development/Tutorials/Introduction to Goya usage 2|Introduction to Goya usage (part 2)]]&lt;br /&gt;
:''The second part of the tutorial, with a slightly more complex example than the first part.''&lt;br /&gt;
&lt;br /&gt;
== Other programming languages ==&lt;br /&gt;
&lt;br /&gt;
=== Python ===&lt;br /&gt;
&lt;br /&gt;
;[http://www.learningpython.com/2008/09/20/an-introduction-to-pyqt/ An Introduction to PyQt]&lt;br /&gt;
:''Starting off''&lt;br /&gt;
&lt;br /&gt;
;[http://lateral.netmanagers.com.ar/stories/BBS47.html PyQt by Example]&lt;br /&gt;
:''Another introduction to PyQt''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Languages/Python/PyKDE_WebKit_Tutorial|PyKDE WebKit Tutorial]]&lt;br /&gt;
:''A simple web browser application in PyKDE''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Python introduction to signals and slots|101 Introduction to signals and slots]]&lt;br /&gt;
:''A simple introduction to Qt's signal and slot architecture.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Languages/Python/PyKDE_DBus_Tutorial|PyKDE DBus Tutorial]]&lt;br /&gt;
:''An introduction to DBus communication using PyKDE''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Languages/Python/PyKDE_Knotify_Tutorial|PyKDE KNotify Tutorial]]&lt;br /&gt;
:''An introduction to Knotify (Notifications and KJobs) using PyKDE''&lt;br /&gt;
&lt;br /&gt;
=== Ruby ===&lt;br /&gt;
&lt;br /&gt;
;[http://developer.kde.org/language-bindings/ruby/kde3tutorial/index.html KDE Ruby Korundum tutorial]&lt;br /&gt;
:''A ruby version of Antonio Larrosa Jim&amp;amp;eacute;nez's KDE tutorial by Richard Dale. See the [[Development/Languages/Ruby|Ruby Developers Corner]] for Qt tutorials and other info.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Qt4_Ruby_Tutorial|Qt4 Ruby Tutorial]]&lt;br /&gt;
:''Nokia's fabulous introductory tutorial to Qt, translated to Ruby.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Plasma/RubyApplet|Creating a Plasma Widget in Ruby]]&lt;br /&gt;
:''Tutorial that shows how to create your first Plasma Applet using the Ruby language.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Developing_Qt4_Applications_using_Qt_Designer_and_Ruby_on_Kubuntu|Developing Qt4 Applications using Qt Designer and Ruby on Kubuntu]]&lt;br /&gt;
:''Tutorial that shows how to design a simple User Interface in Qt Designer and then use the resulting widget in a Qt Ruby application we build from scratch.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Languages/Ruby/Ruby-Qt/KDE_Book|Ruby-Qt/KDE Book]]&lt;br /&gt;
:''There is also an approach to create an Ruby-Qt/KDE Book under a free license. The content will be created in this wiki.''&lt;br /&gt;
&lt;br /&gt;
=== Shell ===&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Shell_Scripting_with_KDE_Dialogs|Shell Scripting with KDE dialogs]] ([http://developer.kde.org/documentation/tutorials/kdialog/t1.html Original Link]) &lt;br /&gt;
:''Tutorial by [mailto:bradh@frogmouth.net Brad Hards] that describes how to use KDE dialogs in shell scripts with kdialog. It is presented as an example based tutorial.''&lt;br /&gt;
&lt;br /&gt;
== Graphics Programming ==&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/Graphics/Performance|QPainter Perfomance]]&lt;br /&gt;
:''Hints on avoiding common mistakes leading to poor performance when using QPainter''&lt;br /&gt;
&lt;br /&gt;
== Using the KDE Games Libraries ==&lt;br /&gt;
;[[Development/Tutorials/Games/KStandardGameAction| KStandardGameAction]]&lt;br /&gt;
:''Using libkdegames to make your game fit the kdegames standard''&lt;br /&gt;
;[[Development/Tutorials/Games/Highscores| Highscores]]&lt;br /&gt;
:''Implementing a simple highscore table into your game''&lt;br /&gt;
;[[Development/Tutorials/Games/Theme Selector| Theme Selector]]&lt;br /&gt;
:''Using the libkdegames theme selection dialog''&lt;br /&gt;
;[[Development/Tutorials/Games/Palapeli Patterns| Palapeli Slicers]]&lt;br /&gt;
:''Creating a slicer plugin for Palapeli''&lt;br /&gt;
&lt;br /&gt;
=== KGLEngine ===&lt;br /&gt;
;[[Development/Tutorials/Games/kglengine/kglengine-simpleBox| installation and your first KGLItem]]&lt;br /&gt;
:''start your first kglengine application''&lt;br /&gt;
;[[Development/Tutorials/Games/KGLEngine2d| kglpong]]&lt;br /&gt;
:''Now use our knowledge to make a pong''&lt;br /&gt;
&lt;br /&gt;
== Using the KDE PIM Libraries ==&lt;br /&gt;
;[[Development/Tutorials/PIM/ical| iCalendar functionality]]&lt;br /&gt;
:''Using kcal to manage iCalendar files''&lt;br /&gt;
&lt;br /&gt;
== Other tutorials ==&lt;br /&gt;
&lt;br /&gt;
=== 2D Plotting (KPlotWidget) ===&lt;br /&gt;
;[[Development/Tutorials/KPlotWidget|Using the KDE data-plotting widget]]&lt;br /&gt;
:''This tutorial introduces KPlotWidget, which is used for 2-D data plotting.  It includes information on simple usage of the widget (including adding and modifying data sets, and customizing the plot axes and labels), and advanced customization (including extending the widget through sub-classing).''&lt;br /&gt;
&lt;br /&gt;
=== Spelling and Grammar Checking (Sonnet) ===&lt;br /&gt;
;[[Development/Tutorials/Sonnet/SonnetTutorial|Adding spell-checking or grammar-checking to KDE applications]]&lt;br /&gt;
:''This tutorial introduces Sonnet and how one may use it to add language correction to your KDE application. Sonnet's auxiliary features shall be described in a separate tutorial.''&lt;br /&gt;
&lt;br /&gt;
=== Pixmap cache (KPixmapCache) ===&lt;br /&gt;
;[[Development/Tutorials/KPixmapCache|Using the KDE pixmap cache]]&lt;br /&gt;
:''This tutorial shows how to use KPixmapCache to cache e.g. pixmaps generated from SVGs or some data.''&lt;br /&gt;
&lt;br /&gt;
=== Using MarbleWidget (Marble) ===&lt;br /&gt;
;[[Development/Tutorials/MarbleWidget|Using MarbleWidget]]&lt;br /&gt;
:''This short tutorial describes how to use the MarbleWidget in your project''&lt;br /&gt;
&lt;br /&gt;
=== Using local SCM for KDE development ===&lt;br /&gt;
;[[Development/Git|Using Git to develop for KDE]]&lt;br /&gt;
:''Here you find how to use Git to develop for KDE''&lt;br /&gt;
&lt;br /&gt;
=== Kwin effect tutorial (blog) ===&lt;br /&gt;
;[http://blog.martin-graesslin.com/blog/?p=258 blog by Martin Graesslin]&lt;br /&gt;
:''This tutorial guides you through the development of a simple KWin effect''&lt;br /&gt;
&lt;br /&gt;
=== Implementing KSysGuard sensors and adding them ===&lt;br /&gt;
;[[Development/Tutorials/Sensors]]&lt;br /&gt;
:''This tutorial shows how to write and KSysGuard sensor and connect it to the systray.''&lt;br /&gt;
Runners&lt;br /&gt;
&lt;br /&gt;
=== Porting an application from KSystemTrayIcon to KStatusNotifierItem ===&lt;br /&gt;
;[[Development/Tutorials/PortToKStatusNotifierItem]]&lt;br /&gt;
:''This tutorials shows how to port an application using KSystemTrayIcon to KStatusNotifierItem''&lt;br /&gt;
&lt;br /&gt;
=== Using the KDE Wallet API for safe storage ===&lt;br /&gt;
;[[Development/Tutorials/KWallet]]&lt;br /&gt;
:&amp;quot;Brief introduction to the KWallet API which can be used for storing all kinds of sensitive information.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===How to edit a wiki with Libmediawiki ===&lt;br /&gt;
;[[Development/Tutorials/Libmediawiki]]&lt;br /&gt;
:''This tutorial present how to edit a wiki with Libmediawiki.''&lt;br /&gt;
&lt;br /&gt;
== KDE2 and KDE3 Materials ==&lt;br /&gt;
;[[Development/Tutorials/KDE4 Porting Guide|Porting Your Application from KDE 3 to KDE 4]]&lt;br /&gt;
:''These tutorials cover topics related to the migration from KDE 3 to KDE 4.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/KDE3|KDE3 Tutorials]]&lt;br /&gt;
:''These tutorials cover topics related to KDE3.''&lt;br /&gt;
&lt;br /&gt;
;[[Development/Tutorials/KDE2|KDE2 Tutorials]]&lt;br /&gt;
:''These tutorials cover topics related to KDE2.''&lt;br /&gt;
&lt;br /&gt;
[[Category:KDE4]]&lt;/div&gt;</summary>
		<author><name>Vmax0770</name></author>	</entry>

	</feed>