<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>muhuk.com &#187; tutorial</title>
	<atom:link href="http://www.muhuk.com/tag/tutorial/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.muhuk.com</link>
	<description>know thyself</description>
	<lastBuildDate>Wed, 07 Jul 2010 10:26:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>How To Create A Debian VM With Qemu</title>
		<link>http://www.muhuk.com/2010/07/how-to-create-a-debian-vm-with-qemu/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=how-to-create-a-debian-vm-with-qemu</link>
		<comments>http://www.muhuk.com/2010/07/how-to-create-a-debian-vm-with-qemu/#comments</comments>
		<pubDate>Wed, 07 Jul 2010 10:26:39 +0000</pubDate>
		<dc:creator>Atamert Ölçgen</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[qemu]]></category>
		<category><![CDATA[share]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[vm]]></category>

		<guid isPermaLink="false">http://www.muhuk.com/?p=375</guid>
		<description><![CDATA[I would like to post my notes as a little tutorial here. I am usually using these virtual machines as cheap staging servers. The first part of this tutorial, you hopefully need to do only once: creating a fresh Debian system. In the second part we will build on this image to create many different [...]]]></description>
			<content:encoded><![CDATA[<p>I would like to post my notes as a little tutorial here. I am usually using these virtual machines as cheap staging servers. The first part of this tutorial, you hopefully need to do only once: creating a fresh Debian system. In the second part we will build on this image to create many different servers.</p>

<h2>Creating A Base Debian System</h2>

<p>We will create a Qemu machine and install Debian Lenny on it first:</p>

<pre><code># Download Debian image
wget http://debian.osuosl.org/debian-cdimage/current/i386/iso-cd/debian-504-i386-businesscard.iso

# Create base VM image
qemu-img create -f qcow2 debian.qcow2 2G
</code></pre>

<p>Our disk image will have a 2 Gigabyte size limit. You can pick a different size if you need.</p>

<p>Now we need to power on our VM and install Debian:</p>

<pre><code># Install Debian
qemu -enable-kvm -k tr -cdrom debian-504-i386-businesscard.iso -hda debian.qcow2 -boot d
</code></pre>

<p>You don&#8217;t need to allocate a large swap disk, 128MB should do just fine for a file/web server. Also I wouldn&#8217;t bother creating a seperate partition for <code>/home/</code>.</p>

<p>Next let&#8217;s log in as the user (<code>www</code> here) we have created to make final changes:</p>

<pre><code># logged in as user
dpkg-reconfigure console-data
aptitude install ssh sudo
echo "www ALL=(ALL) ALL" &gt;&gt; /etc/sudoers
</code></pre>

<p>At this point you might want to take a backup of <code>debian.qcow2</code>. (Even though we will open it only read-only from now on)</p>

<h2>Creating The Actual VM</h2>

<p>To save time and space we will use copy-on-write disks and re-use <code>debian.qcow2</code>.</p>

<pre><code># Create the actual VM's disk
qemu-img create -f qcow2 -o backing_file=debian.qcow2 actual.qcow2
</code></pre>

<p>Actually we are done. You can log in to your VM using the following command and start installing/configuring/running:</p>

<pre><code>qemu -enable-kvm -k tr -hda actual.qcow2 -net user -net nic \
                                         -redir tcp:5022::22 \
                                         -redir tcp:9080::80
</code></pre>

<p>A few things to note about the command above:</p>

<ul>
<li><code>-enable-kvm</code> is meaningful only if you have <code>kvm</code> kernel module installed. It improves performance a great deal, so it&#8217;s highly recommended.</li>
<li>You probably need to change <code>-k tr</code> according to your keyboard&#8217;s layout.</li>
<li>We are setting up two TCP redirections. 22 is for SSH and 80 is for HTTP. You can add more ports if you need.</li>
</ul>

<p>Finally, I suggest you to prefer SSHing your VM instead of logging in directly:</p>

<pre><code># SSH into the VM
ssh -p 5022 www@localhost
</code></pre>

<p>I hope some of you find this useful.</p>


<p>Related posts:<ol><li><a href='http://www.muhuk.com/2009/04/galfthw-style-tutorial-on-python-coroutines/' rel='bookmark' title='Permanent Link: GALFTHW Style Tutorial On Python Coroutines'>GALFTHW Style Tutorial On Python Coroutines</a></li>
<li><a href='http://www.muhuk.com/2009/04/using-layouts-in-qooxdoo-index/' rel='bookmark' title='Permanent Link: Using Layouts In Qooxdoo &#8211; Index'>Using Layouts In Qooxdoo &#8211; Index</a></li>
<li><a href='http://www.muhuk.com/2009/05/freedays09-videos/' rel='bookmark' title='Permanent Link: Freedays&#8217;09 Videos'>Freedays&#8217;09 Videos</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.muhuk.com/2010/07/how-to-create-a-debian-vm-with-qemu/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Serving Static Media In Django Development Server</title>
		<link>http://www.muhuk.com/2009/05/serving-static-media-in-django-development-server/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=serving-static-media-in-django-development-server</link>
		<comments>http://www.muhuk.com/2009/05/serving-static-media-in-django-development-server/#comments</comments>
		<pubDate>Mon, 25 May 2009 09:30:10 +0000</pubDate>
		<dc:creator>Atamert Ölçgen</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[media]]></category>
		<category><![CDATA[template]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.muhuk.com/?p=225</guid>
		<description><![CDATA[There is a misconception about how static files (a.k.a media files) are handled in Django. Actually it is quite clearly documented here and here. Nevertheless a question about this comes up in the mailing-list or IRC channel frequently: Where do I put my media files? Django can&#8217;t find my foo.gif! How can I link my [...]]]></description>
			<content:encoded><![CDATA[<p>There is a misconception about how static files (a.k.a media files) are handled in Django. Actually it is quite clearly documented <a href="http://docs.djangoproject.com/en/dev/howto/static-files/#module-django.views.static">here</a> and <a href="http://docs.djangoproject.com/en/dev/howto/deployment/modpython/#id1">here</a>. Nevertheless a question about this comes up in the mailing-list or IRC channel frequently:</p>

<blockquote>
  <p>Where do I put my media files?</p>
  
  <p>Django can&#8217;t find my <code>foo.gif</code>!</p>
  
  <p>How can I link my CSS?</p>
</blockquote>

<p>First of all, just to make it clear; <strong>just because a server returns a response body with an internal URL doesn&#8217;t necessarily mean it will be available on that server</strong>. It is one thing that your templates produce the correct URL to a media file and another thing that your server actually serves that resource on that URL. <strong>Django development server doesn&#8217;t automagically serve media files</strong><sup>1</sup>.</p>

<h3>Settings</h3>

<p>There are three settings to get right: <code>MEDIA_ROOT</code>, <code>MEDIA_URL</code> and <code>ADMIN_MEDIA_PREFIX</code>. <code>MEDIA_ROOT</code> is the <em>absolute filesystem path</em> where your media files are. I usually set it like:</p>

<pre><code>MEDIA_ROOT = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'media')
</code></pre>

<p>This will set <code>MEDIA_ROOT</code> to point to the <code>media</code> directory in your project directory<sup>2</sup>. <code>MEDIA_URL</code> and <code>ADMIN_MEDIA_PREFIX</code> are <em>URL&#8217;s</em>:</p>

<pre><code>MEDIA_URL = '/media/'
ADMIN_MEDIA_PREFIX = '/media/admin/'
</code></pre>

<p>With this setup, to serve admin media in production, all I need to do is to symlink media folder of admin app into my media directory. Of course you can set <code>MEDIA_URL</code> to point to another domain/subdomain. Such as <code>http://media.mydomain.com/</code>. But this way you can&#8217;t serve your media from development server.</p>

<h3>URL Configuration</h3>

<p>Add the following code snipplet at the end of your root <code>urls.py</code>:</p>

<pre><span style="color:#555555">   1 </span><span style="color:#000000; font-weight:bold">if</span> settings<span style="color:#000000">.</span>DEBUG<span style="color:#000000">:</span>
<span style="color:#555555">   2 </span>    <span style="color:#000000; font-weight:bold">from</span> django<span style="color:#000000">.</span>views<span style="color:#000000">.</span>static <span style="color:#000000; font-weight:bold">import</span> serve
<span style="color:#555555">   3 </span>    _media_url <span style="color:#000000">=</span> settings<span style="color:#000000">.</span>MEDIA_URL
<span style="color:#555555">   4 </span>    <span style="color:#000000; font-weight:bold">if</span> _media_url<span style="color:#000000">.</span><span style="color:#010181">startswith</span><span style="color:#000000">(</span><span style="color:#ff0000">'/'</span><span style="color:#000000">):</span>
<span style="color:#555555">   5 </span>        _media_url <span style="color:#000000">=</span> _media_url<span style="color:#000000">[</span><span style="color:#2928ff">1</span><span style="color:#000000">:]</span>
<span style="color:#555555">   6 </span>        urlpatterns <span style="color:#000000">+=</span> <span style="color:#010181">patterns</span><span style="color:#000000">(</span><span style="color:#ff0000">''</span><span style="color:#000000">,</span>
<span style="color:#555555">   7 </span>                                <span style="color:#000000">(</span>r<span style="color:#ff0000">'^%s(?P&lt;path&gt;.*)$'</span> <span style="color:#000000">%</span> _media_url<span style="color:#000000">,</span>
<span style="color:#555555">   8 </span>                                serve<span style="color:#000000">,</span>
<span style="color:#555555">   9 </span>                                <span style="color:#000000">{</span><span style="color:#ff0000">'document_root'</span><span style="color:#000000">:</span> settings<span style="color:#000000">.</span>MEDIA_ROOT<span style="color:#000000">}))</span>
<span style="color:#555555">  10 </span>    <span style="color:#000000; font-weight:bold">del</span><span style="color:#000000">(</span>_media_url<span style="color:#000000">,</span> serve<span style="color:#000000">)</span>
</pre>

<p><code>settings.DEBUG == True</code> doesn&#8217;t necessarily mean development server is running. But it is a good indicator since deploying with development server is not a good idea for many reasons. Notice here we don&#8217;t serve media unless <code>MEDIA_URL</code> is an absolute URL on our server.</p>

<h3>Templates</h3>

<p>Finally we need to specify media URL&#8217;s correctly. To avoid hard-coding media path we will be using <code>{{ MEDIA_URL }}</code> context variable in our templates. To have <code>{{ MEDIA_URL }}</code> included automatically in each template we need to do two things:</p>

<ol>
<li>Make sure you have <code>django.core.context_processors.media</code> in your <code>TEMPLATE_CONTEXT_PROCESSORS</code>.</li>
<li>Make sure each view is using a <a href="http://docs.djangoproject.com/en/dev/ref/templates/api/#id1"><code>RequestContext</code></a>.</li>
</ol>

<p>Afterwards all we need to do is to specify our media URL&#8217;s like this:</p>

<pre><code>&lt;img src="<b>{{ MEDIA_URL }}</b>img/header.jpeg" /&gt;</code></pre>

<p>This will be translated to:</p>

<pre><code>&lt;img src="/media/img/header.jpeg" /&gt;
</code></pre>

<h3>Bonus</h3>

<p>While we are at it, why not serve our <code>500</code> and <code>404</code> pages statically. When <code>DEBUG == True</code>, 500 (server error) and 404 (not found) situations are handled with special debugging views. So there&#8217;s no chance to test your error pages. Add the following code, just like static serving code:</p>

<pre><span style="color:#555555">   1 </span><span style="color:#000000; font-weight:bold">if</span> settings<span style="color:#000000">.</span>DEBUG<span style="color:#000000">:</span>
<span style="color:#555555">   2 </span>    urlpatterns <span style="color:#000000">+=</span> <span style="color:#010181">patterns</span><span style="color:#000000">(</span><span style="color:#ff0000">''</span><span style="color:#000000">,</span>
<span style="color:#555555">   3 </span>                            <span style="color:#000000">(</span>r<span style="color:#ff0000">'^404/'</span><span style="color:#000000">,</span>
<span style="color:#555555">   4 </span>                                <span style="color:#ff0000">'django.views.generic.simple.'</span> \
<span style="color:#555555">   5 </span>                                <span style="color:#ff0000">'direct_to_template'</span><span style="color:#000000">,</span>
<span style="color:#555555">   6 </span>                                <span style="color:#000000">{</span><span style="color:#ff0000">'template'</span><span style="color:#000000">:</span> <span style="color:#ff0000">'404.html'</span><span style="color:#000000">}),</span>
<span style="color:#555555">   7 </span>                            <span style="color:#000000">(</span>r<span style="color:#ff0000">'^500/'</span><span style="color:#000000">,</span>
<span style="color:#555555">   8 </span>                                <span style="color:#ff0000">'django.views.generic.simple.'</span> \
<span style="color:#555555">   9 </span>                                <span style="color:#ff0000">'direct_to_template'</span><span style="color:#000000">,</span>
<span style="color:#555555">  10 </span>                                <span style="color:#000000">{</span><span style="color:#ff0000">'template'</span><span style="color:#000000">:</span> <span style="color:#ff0000">'500.html'</span><span style="color:#000000">}))</span>
</pre>

<p>Now when you visit <code>/500/</code> and <code>/404/</code> on your development server you will be served a fake error page.</p>

<hr />

<p><strong>1</strong>: There is an exception here. If you configured your settings correctly, development server will serve admin media.</p>

<p><strong>2</strong>: Assuming your <code>settings.py</code> is directly inside your project directory, hence the <code>__file__</code>.</p>


<p>Related posts:<ol><li><a href='http://www.muhuk.com/2009/05/sad-state-of-web-development-industry-in-turkiye/' rel='bookmark' title='Permanent Link: Sad State of Web Development Industry in Türkiye'>Sad State of Web Development Industry in Türkiye</a></li>
<li><a href='http://www.muhuk.com/2009/05/django-formfieldset/' rel='bookmark' title='Permanent Link: django-formfieldset'>django-formfieldset</a></li>
<li><a href='http://www.muhuk.com/2009/07/django-renderformplain/' rel='bookmark' title='Permanent Link: django-renderformplain'>django-renderformplain</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.muhuk.com/2009/05/serving-static-media-in-django-development-server/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Using Layouts In Qooxdoo &#8211; Index</title>
		<link>http://www.muhuk.com/2009/04/using-layouts-in-qooxdoo-index/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=using-layouts-in-qooxdoo-index</link>
		<comments>http://www.muhuk.com/2009/04/using-layouts-in-qooxdoo-index/#comments</comments>
		<pubDate>Thu, 30 Apr 2009 15:25:01 +0000</pubDate>
		<dc:creator>Atamert Ölçgen</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[layout]]></category>
		<category><![CDATA[qooxdoo]]></category>
		<category><![CDATA[ria]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.muhuk.com/?p=192</guid>
		<description><![CDATA[Using Layouts In Qooxdoo tutorial series is finished. I tried my best to explain how layout managers work and how they differ from each other. This tutorial is for those who have little or no object oriented GUI programming experience. Especially JavaScript/DOM programmers learning Qooxdoo. I hope it is helpful. Complete list of parts: Introduction [...]]]></description>
			<content:encoded><![CDATA[<p>Using Layouts In Qooxdoo tutorial series is finished. I tried my best to explain how layout managers work and how they differ from each other. This tutorial is for those who have little or no object oriented GUI programming experience. Especially JavaScript/DOM programmers learning <a href="http://qooxdoo.org/">Qooxdoo</a>. I hope it is helpful.</p>

<p>Complete list of parts:</p>

<ol>
<li><a href="http://www.muhuk.com/2009/01/using-layouts-in-qooxdoo-part-1/">Introduction</a></li>
<li><a href="http://www.muhuk.com/2009/02/using-layouts-in-qooxdoo-part-2-vbox-layout/">VBox Layout</a></li>
<li><a href="http://www.muhuk.com/2009/02/using-layouts-in-qooxdoo-part-3-hbox-layout/">HBox Layout</a></li>
<li><a href="http://www.muhuk.com/2009/02/using-layouts-in-qooxdoo-part-4-grid-layout/">Grid Layout</a></li>
<li><a href="http://www.muhuk.com/2009/04/using-layouts-in-qooxdoo-part-5-basic-canvas/">Basic &amp; Canvas Layouts</a></li>
</ol>


<p>Related posts:<ol><li><a href='http://www.muhuk.com/2009/01/using-layouts-in-qooxdoo-part-1/' rel='bookmark' title='Permanent Link: Using Layouts In Qooxdoo &#8211; Part 1'>Using Layouts In Qooxdoo &#8211; Part 1</a></li>
<li><a href='http://www.muhuk.com/2009/02/using-layouts-in-qooxdoo-part-2-vbox-layout/' rel='bookmark' title='Permanent Link: Using Layouts In Qooxdoo &#8211; Part 2: VBox Layout'>Using Layouts In Qooxdoo &#8211; Part 2: VBox Layout</a></li>
<li><a href='http://www.muhuk.com/2009/02/using-layouts-in-qooxdoo-part-3-hbox-layout/' rel='bookmark' title='Permanent Link: Using Layouts In Qooxdoo &#8211; Part 3: HBox Layout'>Using Layouts In Qooxdoo &#8211; Part 3: HBox Layout</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.muhuk.com/2009/04/using-layouts-in-qooxdoo-index/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>GALFTHW Style Tutorial On Python Coroutines</title>
		<link>http://www.muhuk.com/2009/04/galfthw-style-tutorial-on-python-coroutines/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=galfthw-style-tutorial-on-python-coroutines</link>
		<comments>http://www.muhuk.com/2009/04/galfthw-style-tutorial-on-python-coroutines/#comments</comments>
		<pubDate>Mon, 06 Apr 2009 07:05:18 +0000</pubDate>
		<dc:creator>Atamert Ölçgen</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[coroutines]]></category>
		<category><![CDATA[hello world]]></category>
		<category><![CDATA[pep]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[share]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.muhuk.com/?p=160</guid>
		<description><![CDATA[An excellent tutorial explaining yield expression and coroutines with examples like data processing pipelines and cooperative multitasking1. I loved it for the following reasons: It is written well and examples are clean and to the point. I&#8217;ve just read the slides and I have a much better understanding about coroutines now. It aims to give [...]]]></description>
			<content:encoded><![CDATA[<p>An <a href="http://www.dabeaz.com/coroutines/">excellent tutorial</a> explaining <a href="http://www.python.org/dev/peps/pep-0342/"><code>yield</code> expression and coroutines</a> with examples like data processing pipelines and cooperative multitasking<sup>1</sup>. I loved it for the following reasons:</p>

<ul>
<li>It is written well and examples are clean and to the point. I&#8217;ve just read the slides and I have a much better understanding about coroutines now.</li>
<li>It aims to give a better understanding about the subject. But doesn&#8217;t just <code>Hello World</code> the examples, all code included is practical and useful. (Death to Fibonacci! LOL)</li>
<li><a href="http://www.dabeaz.com/about.html">Author</a> explains thing from a wide perspective, including counter-arguments and possible bottlenecks and necessary warnings&#8230;</li>
</ul>

<p>All in all I really enjoyed this tutorial. Highly recommended.</p>

<hr />

<p><strong>1</strong>: Multitasking possibly within a single thread/process.</p>


<p>Related posts:<ol><li><a href='http://www.muhuk.com/2009/05/django-formfieldset/' rel='bookmark' title='Permanent Link: django-formfieldset'>django-formfieldset</a></li>
<li><a href='http://www.muhuk.com/2009/07/django-renderformplain/' rel='bookmark' title='Permanent Link: django-renderformplain'>django-renderformplain</a></li>
<li><a href='http://www.muhuk.com/2010/03/whats-new-in-django-formfieldset-1-1/' rel='bookmark' title='Permanent Link: What&#8217;s New in django-formfieldset 1.1'>What&#8217;s New in django-formfieldset 1.1</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.muhuk.com/2009/04/galfthw-style-tutorial-on-python-coroutines/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Extending Kate With Pâté</title>
		<link>http://www.muhuk.com/2008/11/extending-kate-with-pate/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=extending-kate-with-pate</link>
		<comments>http://www.muhuk.com/2008/11/extending-kate-with-pate/#comments</comments>
		<pubDate>Wed, 12 Nov 2008 16:39:22 +0000</pubDate>
		<dc:creator>Atamert Ölçgen</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[kate]]></category>
		<category><![CDATA[pate]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.muhuk.com/?p=60</guid>
		<description><![CDATA[Pâté is a plugin for Kate (of KDE Desktop) that exposes editor&#8217;s functionality to Python. In short; with Pâté, you can write Kate plugins in Python. I use Kate for (almost) all my text editing. I think it suits my needs perfectly. It is both as simple as I would be comfortable with and has [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://paul.giannaros.org/pate/">Pâté</a> is a plugin for <a href="http://kate-editor.org/">Kate</a> (of KDE Desktop) that exposes editor&#8217;s functionality to <a href="http://www.python.org/">Python</a>. In short; with Pâté, you can write Kate plugins in Python.</p>

<p>I use Kate for (almost) all my text editing. I think it suits my needs perfectly. It is both as simple as I would be comfortable with and has as many features (such as multi document interface, regex search and replace, etc.) as I need to be productive. I am not an <a href="http://en.wikipedia.org/wiki/Integrated_development_environment">IDE</a> person. Nothing against IDE&#8217;s, I have just never been comfortable with them. On the other side I have never taken the time to learn the classic (read antique) editors such as Emacs and Vim. I am sure learning them would be <a href="http://steve-yegge.blogspot.com/2008/04/xemacs-is-dead-long-live-xemacs.html">worth my time</a>. But I doubt I will ever take the time for that. At present, I just fire up my Kate and it works pretty well.</p>

<p>Meanwhile, I keep hearing about these neat hacks with Emacs that when you do <code>C-t</code>, <code>C-M-w</code> and then <code>C-k</code> your active buffer is translated to Chinese and then automatically sent to your grandmother&#8217;s cell phone as SMS. Wow! And you can write your own macros (in Lisp, <a href="http://en.wikipedia.org/wiki/Emacs_Lisp">elisp</a>) to extend the editor&#8217;s capabilities. There is virtually no limit to what you can do and it is not rare that these extensions exceed the borders of an editor. Of course you have to use (and learn) Emacs to take advantage.</p>

<p>This was true, before I discovered Pâté. It was always possible to write plugins for Kate, but Kate was not <em>scriptable</em>. Now using Pâté, you can extend Kate with ease (at least much much easier than writing C). The only thing that bugs me is I couldn&#8217;t figure out a way to reload my plugins without restarting Kate.</p>

<h3>Creating Simple Pâté Plugins</h3>

<p>The first plugin we write will turn the selection into a Django password hash. I use this when I want to create initial_data fixtures for <code>User</code>&#8216;s quickly.</p>

<p>Since we do not want to instantiate a complete Django environment we won&#8217;t be able to import anything from <code>django.contrib.auth.models</code>. Instead let us copy a dumbed down version of <code>get_hexdigest</code> into our own module.</p>

<pre><code>import random


def get_hexdigest(algorithm, salt, raw_password):
    try:
        import hashlib
    except ImportError:
        import sha
        return sha.new(salt + raw_password).hexdigest()
    else:
        return hashlib.sha1(salt + raw_password).hexdigest()
</code></pre>

<p>It should be clear enough, it returns a hash of the given password using the given salt[1]. Now we simply add <code>kate</code> to our imports (remember <code>kate</code> and not <code>pate</code>):</p>

<pre><code>import kate
</code></pre>

<p>And add our own callback code:</p>

<pre><code>@kate.onAction('Django Password', 'Shift+Alt+P')
def setPassword():
    v = kate.view()
    raw_password = v.selection.text
    v.selection.removeSelectedText()
    algo = 'sha1'
    salt = get_hexdigest(algo, str(random.random()), \
        str(random.random()))[:5]
    hsh = get_hexdigest(algo, salt, raw_password)
    v.insertText('%s$%s$%s' % (algo, salt, hsh))
</code></pre>

<p>The first line makes our function kate-aware. <code>'Django Password'</code> will be the label for our menu item (it will be listed under <code>Tools</code>) and <code>Shift-Alt-P</code> will be the keyboard shortcut. The rest of the code should be self-explanatory.[2]</p>

<p>Now we copy our module into ~/.kde/share/apps/kate/pyplugins/ and restart Kate. It should show up in the menu and work now.</p>

<p>Second example is a JSON prettifier. I use JSON format for my fixtures, but valid JSON is not very readable. So I have this small plugin to convert a document between JSON and Python literals:</p>

<pre><code>import sys, pprint
import kate
from django.utils import simplejson


HEADER = '# Pretty Printed\\n'

@kate.onAction('Django Pretty Json', 'Shift+Alt+J')
def togglePrettyJsonFormat():
    d = kate.document()
    source = d.text
    if source.startswith(HEADER):
        target = simplejson.dumps(eval(source))
    else:
        pp = pprint.PrettyPrinter(indent=2)
        target = HEADER + pp.pformat(simplejson.loads(source))
    d.text = target
</code></pre>

<p>I need <code>HEADER</code> to distinguish between two states. It can actually be anything, but it would be a good idea to make it a quote to have valid Python just in case.</p>

<h3>Pâté Is Fun</h3>

<p>I have enjoyed experimenting with Pâté. I hope it gets more attention and therefore ends up a much better plugin. If you ask me it should already ship with Kate. Kate is a nice editor, and empowering the users would only make it nicer and more popular.</p>

<p>If you have any ideas for pâté plugins, especially stuff that is useful in Django context, please add it to the comments. I would love to play a little more with pâté.</p>

<hr />

<p><strong>1</strong>: If it is not clear, take a look at <a href="http://code.djangoproject.com/browser/django/tags/releases/1.0/django/contrib/auth/models.py"><code>django.contrib.auth.models</code></a>.</p>

<p><strong>2</strong>: To learn API, you can fire up <code>Interactive Console</code> under <code>View</code> and type <code>help(kate)</code>.</p>


<p>Related posts:<ol><li><a href='http://www.muhuk.com/2009/04/galfthw-style-tutorial-on-python-coroutines/' rel='bookmark' title='Permanent Link: GALFTHW Style Tutorial On Python Coroutines'>GALFTHW Style Tutorial On Python Coroutines</a></li>
<li><a href='http://www.muhuk.com/2009/08/a-civilized-way-display-lots-of-data/' rel='bookmark' title='Permanent Link: A Civilized Way Display Lots Of Data'>A Civilized Way Display Lots Of Data</a></li>
<li><a href='http://www.muhuk.com/2010/02/web-site-performance-optimizations/' rel='bookmark' title='Permanent Link: Web Site Performance Optimizations'>Web Site Performance Optimizations</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.muhuk.com/2008/11/extending-kate-with-pate/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Getting A Little Further Than Hello World With Qooxdoo</title>
		<link>http://www.muhuk.com/2008/10/getting-a-little-further-than-hello-world-with-qooxdoo/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=getting-a-little-further-than-hello-world-with-qooxdoo</link>
		<comments>http://www.muhuk.com/2008/10/getting-a-little-further-than-hello-world-with-qooxdoo/#comments</comments>
		<pubDate>Fri, 17 Oct 2008 17:14:54 +0000</pubDate>
		<dc:creator>Atamert Ölçgen</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[hello world]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[object oriented]]></category>
		<category><![CDATA[qooxdoo]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.muhuk.com/?p=39</guid>
		<description><![CDATA[I have mentioned about Rich Internet Applications in a previous post. Qooxdoo is an AJAX framework, especially strong on creating desktop-like GUI&#8217;s. It allows you to build your interface in an object oriented manner. Like tkinter or GTK, and much more than the others it is like swing. Qooxdoo is well documented and has a [...]]]></description>
			<content:encoded><![CDATA[<p>I have <a href="http://www.muhuk.com/2008/09/v-for-volatile/">mentioned</a> about <a href="http://en.wikipedia.org/wiki/Rich_internet_application">Rich Internet Applications</a> in a previous post. <a href="http://qooxdoo.org">Qooxdoo</a> is an AJAX framework, especially strong on creating desktop-like GUI&#8217;s. It allows you to build your interface in an object oriented manner. Like <a href="http://wiki.python.org/moin/TkInter">tkinter</a> or <a href="http://www.gtk.org/">GTK</a>, and much more than the others it is like <a href="http://en.wikipedia.org/wiki/Java_Swing">swing</a>.</p>

<p>Qooxdoo is <a href="http://demo.qooxdoo.org/0.8.x/apiviewer/">well</a> <a href="http://qooxdoo.org/documentation">documented</a> and has a clean API. It <a href="http://qooxdoo.org/download">comes</a> with a Python program to help with builds. Because it is such a big framework you test on a partially compiled source and when finished this build program generates a single (actually two, it also generates a loader), compact (and somewhat obfuscated) file for performance. I strongly advise you to give it a try. The following is a small introductory tutorial. It aims to go little further than Hello World. <strong>This is not a tutorial explaining object oriented programming concepts, I assume you are already fluent in <a href="http://en.wikipedia.org/wiki/Object-oriented_programming">OOP</a></strong>.</p>

<h3>Create The Skeleton</h3>

<div id="attachment_52" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.muhuk.com/wp-content/uploads/2008/10/snapshot2.jpeg"><img src="http://www.muhuk.com/wp-content/uploads/2008/10/snapshot2-300x77.jpg" alt="Screenshot of finished application" title="Screenshot of finished application" width="300" height="77" class="size-medium wp-image-52" /></a><p class="wp-caption-text">Screenshot of finished application</p></div>

<p>We&#8217;ll create a simple calculator-like application. I am assuming you have downloaded (latest version is 0.8 for today) and extracted the source into a directory. Let&#8217;s call it <code>qxtut</code>. The first thing we will do is to create a skeleton of our application with the following command;</p>

<pre><code>./qooxdoo-0.8-sdk/tool/bin/create-application.py --name basicmath
</code></pre>

<p>This command has created the following directory structure under ./basicmath;</p>

<pre><code>qxtut/
  qooxdoo-0.8-sdk/
  basicmath/
    source/
    build/
    cache/
    api/
    config.json
    Manifest.json
</code></pre>

<p>Well, some of the directories (<code>build</code> &amp; <code>cache</code>) are not there yet. But as we go on they will appear, I just wanted you to see how the application is organized. <code>config.json</code> and <code>Manifest.json</code> files are configuration files for the build tool. We don&#8217;t need to change them for this tutorial, but you are welcome to check their contents.</p>

<p>Let us build our source for the first time;</p>

<pre><code>cd basicmath
./generate.py source
</code></pre>

<p>Now if you open <code>./source/index.html</code> in your browser you can see a Hello World application in action. We&#8217;ll replace this with our own program. But before we proceed I&#8217;d like to point out a few things;</p>

<ul>
<li>When we define our classes, we call a class method <code>define</code> on <code>qx.Class</code> and pass our class&#8217; name (along with its namespace) and its contents as arguments. We don&#8217;t define our classes using prototypes, in order to take advantage of Qooxdoo&#8217;s object oriented programming features.</li>
<li>Qooxdoo supports <a href="http://qooxdoo.org/documentation/0.8/classes#inheritance">single inheritance</a> (with <a href="http://qooxdoo.org/documentation/0.8/mixins">mixins</a>). We define our base class, if we have one, using <code>extend</code> key.</li>
<li>Instance members are defined inside the <code>members</code> key and class members are defined inside the <code>statics</code> key.</li>
<li><code>construct</code> and <code>destruct</code> are two special functions for initialization and cleanup of the class.</li>
<li>Qooxdoo supports [properties](http://en.wikipedia.org/wiki/Property_(programming&#41;) as well, but it is outside of this tutorial&#8217;s scope.</li>
<li>Finally, &#8220;<code>#asset(basicmath/*)</code>&#8221; line tells the build program to include assets (images etc) in <code>qxtut/basicmath/source/resource/basicmath</code> directory.</li>
</ul>

<h3>Custom Classes</h3>

<p>Let&#8217;s start building our application now. Here is a compact version of Application.js;</p>

<pre><code>/* ************************************************************************
#asset(basicmath/*)
************************************************************************ */

qx.Class.define("basicmath.Application", {
    extend: qx.application.Standalone,
    members: {
        main: function()
        {
            this.base(arguments);
            if (qx.core.Variant.isSet("qx.debug", "on")) {
                qx.log.appender.Native;
                qx.log.appender.Console;
            }
            // Our code will come here
        }
    }
});
</code></pre>

<p>Now we will create a custom class named <code>Operation</code>. This class will take two operands and perform an operation on them, and then later we will add it the ability to report the result of the operation. Paste this as <code>Operation.js</code>;</p>

<pre><code>/* ************************************************************************
#asset(basicmath/*)
************************************************************************ */

qx.Class.define("basicmath.Operation", {
    extend: qx.ui.container.Composite,
    construct: function() {
        this.base(arguments);
        var layout = new qx.ui.layout.HBox(6);
        this.setLayout(layout);
        this.operand1 = new qx.ui.form.TextField("0");
        this.operator = new qx.ui.form.SelectBox();
        this.operator.add(new qx.ui.form.ListItem("add"));
        this.operator.add(new qx.ui.form.ListItem("subtract"));
        this.operator.add(new qx.ui.form.ListItem("multiply"));
        this.operator.add(new qx.ui.form.ListItem("divide"));
        this.operand2 = new qx.ui.form.TextField("0");
        this.result = new qx.ui.basic.Label("0");
        this.add(this.operand1);
        this.add(this.operator);
        this.add(this.operand2);
        this.add(this.result);
    },
    members: {
        operand1: null,
        operator: null,
        operand2: null,
        result: null
    }
});
</code></pre>

<p>The code should be self explanatory. Notice here, we define <code>operand1</code>, <code>operator</code>, <code>operand2</code> and <code>result</code> as members of the class. Also notice we initialize those members in the constructor and not in the class body<sup>1</sup>. This is because their respected values (classes) are derived from the non-primitive <code>Object</code> type. Therefore if we have assigned them a non-primitive type (such as the array [1, 2, 3]) in the members section; all instances would point to the same object.</p>

<p>Let us now plug this object in our application. Replace the comment line &#8220;<code>// Our code will come here</code>&#8221; with the following;</p>

<pre><code>this.getRoot().add(new basicmath.Operation);
</code></pre>

<p>Now, when we compile the source and run index.html we should see our widgets in place.</p>

<div id="attachment_51" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.muhuk.com/wp-content/uploads/2008/10/snapshot1.jpeg"><img src="http://www.muhuk.com/wp-content/uploads/2008/10/snapshot1-300x40.jpg" alt="Screenshot of an Operation widget we have just created" title="Screenshot of an Operation widget we have just created" width="300" height="40" class="size-medium wp-image-51" /></a><p class="wp-caption-text">Screenshot of an Operation widget we have just created</p></div>

<h3>Simple Behaviour</h3>

<p>We want our widget to calculate the operation and show us the result. Let&#8217;s update the members section of <code>Operation</code> with the following;</p>

<pre><code>members: {
    operand1: null,
    operator: null,
    operand2: null,
    result: null,
    updateResult: function() {
        var v1 = this.cleanField(this.operand1);
        var v2 = this.cleanField(this.operand2);
        var r;
        switch(this.operator.getValue()) {
            case "add": r = v1+v2; break;
            case "subtract": r = v1-v2; break;
            case "multiply": r = v1*v2; break;
            case "divide": r = v1/v2; break;
        }
        this.result.setContent(String(r));
        this.operand1.setValue(String(v1));
        this.operand2.setValue(String(v2));
    },
    cleanField: function(field) {
        var val = parseInt(field.getValue());
        return isNaN(val) ? 0 : val;
    }
}
</code></pre>

<p>We have added two functions here <code>updateResult</code> and <code>cleanField</code>. Now we make use of them, change the <code>construct</code> with the following;</p>

<pre><code>construct: function() {
    this.base(arguments);
    var layout = new qx.ui.layout.HBox(6);
    this.setLayout(layout);
    this.operand1 = new qx.ui.form.TextField("0");
    this.operand1.addListener("input", this.updateResult, this);
    this.operator = new qx.ui.form.SelectBox();
    this.operator.add(new qx.ui.form.ListItem("add"));
    this.operator.add(new qx.ui.form.ListItem("subtract"));
    this.operator.add(new qx.ui.form.ListItem("multiply"));
    this.operator.add(new qx.ui.form.ListItem("divide"));
    this.operator.addListener("changeValue", this.updateResult, this);
    this.operand2 = new qx.ui.form.TextField("0");
    this.operand2.addListener("input", this.updateResult, this);
    this.result = new qx.ui.basic.Label("0");
    this.add(this.operand1);
    this.add(this.operator);
    this.add(this.operand2);
    this.add(this.result);
}
</code></pre>

<p>We just added these three listeners to update the result when an operand or the operator changes;</p>

<pre><code>this.operand1.addListener("input", this.updateResult, this);
this.operator.addListener("changeValue", this.updateResult, this);
this.operand2.addListener("input", this.updateResult, this);
</code></pre>

<p>The last parameter (<code>this</code>) for <code>addListener</code> (even though it is sometimes unnecessary) set the scope within the listener code (the second parameter). Qooxdoo handles most of the binding automatically, I think this is included for flexibility.</p>

<p>Let&#8217;s compile and run again. The result of the operation should update as you change the values now.</p>

<h3>Events To Tie All Together</h3>

<p>I&#8217;ll give you the finished code first and then we can go over the details. Here is <code>Operation.js</code>;</p>

<pre><code>/* ************************************************************************
#asset(basicmath/*)
#asset(qx/icon/Oxygen/*)
************************************************************************ */

qx.Class.define("basicmath.Operation", {
    extend: qx.ui.container.Composite,
    construct: function() {
        this.base(arguments);
        var layout = new qx.ui.layout.HBox(6);
        this.setLayout(layout);
        this.operand1 = new qx.ui.form.TextField("0");
        this.operand1.addListener("input", this.updateResult, this);
        this.operator = new qx.ui.form.SelectBox();
        this.operator.add(new qx.ui.form.ListItem("add"));
        this.operator.add(new qx.ui.form.ListItem("subtract"));
        this.operator.add(new qx.ui.form.ListItem("multiply"));
        this.operator.add(new qx.ui.form.ListItem("divide"));
        this.operator.addListener("changeValue", this.updateResult, this);
        this.operand2 = new qx.ui.form.TextField("0");
        this.operand2.addListener("input", this.updateResult, this);
        this.result = new qx.ui.form.TextField("0");
        this.result.setReadOnly(true);
        var close_button = new qx.ui.form.Button(
            null,
            "qx/icon/Oxygen/16/actions/application-exit.png"
        );
        close_button.addListener("execute", function(e) {
            this.fireDataEvent(
                "changeResult",
                0,
                parseFloat(this.result.getValue()),
                false
            );
            this.destroy();
        }, this);
        this.add(this.operand1);
        this.add(this.operator);
        this.add(this.operand2);
        this.add(new qx.ui.basic.Label("="));
        this.add(this.result);
        this.add(new qx.ui.core.Spacer(8));
        this.add(close_button);
    },
    events: {
        "changeResult": "qx.event.type.Data"
    },
    members: {
        operand1: null,
        operator: null,
        operand2: null,
        result: null,
        updateResult: function() {
            var v1 = this.cleanField(this.operand1);
            var v2 = this.cleanField(this.operand2);
            var r;
            switch(this.operator.getValue()) {
                case "add": r = v1+v2; break;
                case "subtract": r = v1-v2; break;
                case "multiply": r = v1*v2; break;
                case "divide": r = v1/v2; break;
            }
            this.fireDataEvent("changeResult",
                r,
                parseFloat(this.result.getValue()),
                false
            );
            this.result.setValue(String(r));
            this.operand1.setValue(String(v1));
            this.operand2.setValue(String(v2));
        },
        cleanField: function(field) {
            var val = parseInt(field.getValue());
            return isNaN(val) ? 0 : val;
        }
    }
});
</code></pre>

<p>And <code>Application.js</code>;</p>

<pre><code>/* ************************************************************************
#asset(basicmath/*)
#asset(qx/icon/Oxygen/*)
************************************************************************ */

qx.Class.define("basicmath.Application", {
    extend : qx.application.Standalone,
    members : {
        main : function()
        {
            this.base(arguments);
            if (qx.core.Variant.isSet("qx.debug", "on")) {
                qx.log.appender.Native;
                qx.log.appender.Console;
            }
            var layout = new qx.ui.container.Composite(
                new qx.ui.layout.VBox(8)
            );
            var layout_footer = new qx.ui.container.Composite(
                new qx.ui.layout.HBox(6)
            );
            var total = new qx.ui.basic.Label("0");
            var add_button = new qx.ui.form.Button(
                "Add New",
                "qx/icon/Oxygen/16/actions/list-add.png"
            );
            add_button.addListener("execute", function(e) {
                var new_operation = new basicmath.Operation();
                layout.addBefore(new_operation, layout_footer);
                new_operation.addListener("changeResult", function(e) {
                    var old_total = parseFloat(total.getContent());
                    var new_total = old_total - e.getOldData() + e.getData();
                    total.setContent(String(new_total));
                }, this);
            }, this);
            layout_footer.add(add_button);
            layout_footer.add(total);
            layout.add(layout_footer);
            add_button.execute();
            this.getRoot().add(layout);
        }
    }
});
</code></pre>

<p>Let&#8217;s go top-down and begin with the changes in the <code>Application.js</code>;</p>

<pre><code>var layout = new qx.ui.container.Composite(new qx.ui.layout.VBox(8));
this.getRoot().add(layout);
</code></pre>

<p>We don&#8217;t necessarily need to subclass everytime we need specialized behaviour. Since I had intented to re-use <code>Operation</code> I have it as a seperate class. But for the layout of the application I just instanciated some classes and tweaked them inside <code>Application.main</code>. <code>layout</code> here is the topmost widget, we will put everything else in it. Basically one or more <code>Operation</code>&#8216;s and a footer to dispay the grand total. <code>VBox</code> layout is by the way a layout manager that stacks children vertically, and a <code>HBox</code> stacks horizontally.</p>

<pre><code>var layout = new qx.ui.container.Composite(new qx.ui.layout.VBox(8));
var layout_footer = new qx.ui.container.Composite(new qx.ui.layout.HBox(6));
var total = new qx.ui.basic.Label("0");
var add_button = new qx.ui.form.Button(
    "Add New",
    "qx/icon/Oxygen/16/actions/list-add.png"
);
add_button.addListener("execute", function(e) {
    var new_operation = new basicmath.Operation();
    layout.addBefore(new_operation, layout_footer);
    new_operation.addListener("changeResult", function(e) {
        var old_total = parseFloat(total.getContent());
        var new_total = old_total - e.getOldData() + e.getData();
        total.setContent(String(new_total));
    }, this);
}, this);
</code></pre>

<p>We define a label <code>total</code> to hold the grand total of all operations and an add button for new operations. Notice the closures work on 7th line. Although we limit ourselves a little bit to take advantage of OOP, we are still in a dynamic environment. Finally we tie all these components together and finally add the <code>layout</code> to the application root.</p>

<pre><code>add_button.execute();
</code></pre>

<p>This instantiates the first <code>Operation</code> for us. We execute the button instead of creating the widget programmatically to avoid the code duplication (see the &#8220;execute&#8221; listener on the <code>add_button</code>).</p>

<p>Now let&#8217;s take a look at the changes in <code>Operation.js</code>. I have replaced the <code>result</code> <code>Label</code> with a <code>TextField</code> (remember to run &#8220;<code>generate.py source</code>&#8221; each time dependencies change). I wanted to take advantage of the getOldData function on <code>TextField</code>&#8216;s <code>changeValue</code> event. But appereantly it doesn&#8217;t supply the old data. But I kept it as a <code>TextField</code> anyway, setting it read-only.</p>

<p>Then I decided that <code>Operation</code> should signal for a result change (maybe this is more politically correct) and added a custom event <code>changeResult</code> on it.</p>

<pre><code>events: {
    "changeResult": "qx.event.type.Data"
}
</code></pre>

<p>This event is fired inside <code>Operation.updateResult</code>;</p>

<pre><code>this.fireDataEvent(
    "changeResult",
    r,
    parseFloat(this.result.getValue()),
    false
);
</code></pre>

<p>The second parameter is returned from e.getData() and the third is from e.getOldData(). Therefore we can calculate the grand total without iterating all <code>Operation</code>s;</p>

<pre><code>var new_total = old_total - e.getOldData() + e.getData();
</code></pre>

<p>An important point here is to fire <code>changeResult</code> to correct the grand total before we destroy an <code>Operation</code>;</p>

<pre><code>close_button.addListener("execute", function(e) {
    this.fireDataEvent(
        "changeResult",
        0,
        parseFloat(this.result.getValue()),
        false
    );
    this.destroy();
}, this);
</code></pre>

<h3>Wrapping Up</h3>

<p>Now it should work correctly, if I haven&#8217;t made a typo of course. Let us build it with;</p>

<pre><code>./generate.py build
</code></pre>

<p>It generates a loader (~150kb) and an application script (~400kb). You don&#8217;t need the Qooxdoo source anymore, you can just upload the contents of the <code>build</code> directory and your application would run.</p>

<p>This concludes my <em>a little further than Hello World</em> tutorial. If you find errors or typos, or have any questions please leave a comment here or contact me at muhuk@jabber.org.</p>

<hr />

<p><strong>1</strong>: Here is an explanation in <a href="http://qooxdoo.org/documentation/0.8/classes#instance_members">Qooxdoo manual</a>.</p>


<p>Related posts:<ol><li><a href='http://www.muhuk.com/2009/04/using-layouts-in-qooxdoo-index/' rel='bookmark' title='Permanent Link: Using Layouts In Qooxdoo &#8211; Index'>Using Layouts In Qooxdoo &#8211; Index</a></li>
<li><a href='http://www.muhuk.com/2009/01/using-layouts-in-qooxdoo-part-1/' rel='bookmark' title='Permanent Link: Using Layouts In Qooxdoo &#8211; Part 1'>Using Layouts In Qooxdoo &#8211; Part 1</a></li>
<li><a href='http://www.muhuk.com/2009/02/using-layouts-in-qooxdoo-part-2-vbox-layout/' rel='bookmark' title='Permanent Link: Using Layouts In Qooxdoo &#8211; Part 2: VBox Layout'>Using Layouts In Qooxdoo &#8211; Part 2: VBox Layout</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.muhuk.com/2008/10/getting-a-little-further-than-hello-world-with-qooxdoo/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
