<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>bidouillages et crustacés</title>
	<atom:link href="http://joinwww.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://joinwww.wordpress.com</link>
	<description>des trucs en pagaille</description>
	<lastBuildDate>Thu, 29 Oct 2009 22:16:12 +0000</lastBuildDate>
	<language>fr</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='joinwww.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>bidouillages et crustacés</title>
		<link>http://joinwww.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://joinwww.wordpress.com/osd.xml" title="bidouillages et crustacés" />
	<atom:link rel='hub' href='http://joinwww.wordpress.com/?pushpress=hub'/>
		<item>
		<title>On prend les mêmes et on recommence !</title>
		<link>http://joinwww.wordpress.com/2009/10/29/on-prend-les-memes-et-on-recommence/</link>
		<comments>http://joinwww.wordpress.com/2009/10/29/on-prend-les-memes-et-on-recommence/#comments</comments>
		<pubDate>Thu, 29 Oct 2009 22:16:12 +0000</pubDate>
		<dc:creator>join</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://joinwww.wordpress.com/?p=51</guid>
		<description><![CDATA[Ne cherchez plus les mises à jour sur ce blog, c&#8217;est dorénavant sur oin.name et sur dubtrip que ça se passe. Bonne visite !<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=joinwww.wordpress.com&amp;blog=4998056&amp;post=51&amp;subd=joinwww&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Ne cherchez plus les mises à jour sur ce blog, c&#8217;est dorénavant sur <a href="http://oin.name">oin.name</a> et sur <a href="http://dubtrip.fathaya.org">dubtrip</a> que ça se passe.</p>
<p>Bonne visite !</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/joinwww.wordpress.com/51/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/joinwww.wordpress.com/51/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/joinwww.wordpress.com/51/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/joinwww.wordpress.com/51/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/joinwww.wordpress.com/51/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/joinwww.wordpress.com/51/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/joinwww.wordpress.com/51/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/joinwww.wordpress.com/51/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/joinwww.wordpress.com/51/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/joinwww.wordpress.com/51/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/joinwww.wordpress.com/51/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/joinwww.wordpress.com/51/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/joinwww.wordpress.com/51/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/joinwww.wordpress.com/51/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=joinwww.wordpress.com&amp;blog=4998056&amp;post=51&amp;subd=joinwww&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://joinwww.wordpress.com/2009/10/29/on-prend-les-memes-et-on-recommence/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">join</media:title>
		</media:content>
	</item>
		<item>
		<title>Comment ranger sa chambre avec UNIX ?</title>
		<link>http://joinwww.wordpress.com/2009/02/02/comment-ranger-sa-chambre-avec-unix/</link>
		<comments>http://joinwww.wordpress.com/2009/02/02/comment-ranger-sa-chambre-avec-unix/#comments</comments>
		<pubDate>Mon, 02 Feb 2009 22:13:13 +0000</pubDate>
		<dc:creator>join</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[find]]></category>
		<category><![CDATA[rangement]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://joinwww.wordpress.com/?p=43</guid>
		<description><![CDATA[C&#8217;est en faisant joyeusement la vaisselle hier que j&#8217;eus le malheur de me poser la question suivante : mes méthodes d&#8217;organisation sont pitoyables et j&#8217;aurais besoin d&#8217;un outil facile à utiliser pour pouvoir classer mes fichiers selon la date où je les ai créés. Sans vouloir utiliser quelque chose de lourd ou une API surpuissante, [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=joinwww.wordpress.com&amp;blog=4998056&amp;post=43&amp;subd=joinwww&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>C&#8217;est en faisant joyeusement la vaisselle hier que j&#8217;eus le malheur de me poser la question suivante : mes méthodes d&#8217;organisation sont pitoyables et j&#8217;aurais besoin d&#8217;un outil facile à utiliser pour pouvoir classer mes fichiers selon la date où je les ai créés. Sans vouloir utiliser quelque chose de lourd ou une API surpuissante, je me suis donc mis en tête de faire un petit outil pour classer automatiquement mes fichiers en utilisant les ressources à disposition de la plupart d&#8217;entre nous : la ligne de commande. Bien sûr l&#8217;outil n&#8217;oblige pas à utiliser une méthode particulière pour naviguer dans ses fichiers : les adeptes de la ligne de commande pourraient autant l&#8217;utiliser que les fans de gestionnaires de fichiers plus ou moins graphiques (Nautilus, PCManFM, Thunar, Konqueror, Dolphin, Krusader, mc, Finder&#8230;).</p>
<p>Cet article vous propose donc un voyage au pays du rangement automatique à travers une petite recherche pour développer un outil suffisamment flexible pour une utilisation quotidienne. Il peut servir autant aux amateurs de rangement qu&#8217;à des gens qui ont envie d&#8217;apprendre quelques petites choses avec <em>bash</em>.<span id="more-43"></span></p>
<h2>Présentation</h2>
<p>Mon outil sans prétention est un script bash à exécuter lorsqu&#8217;on le désire (je pense au démarrage de la session X ou alors à l&#8217;outil <em>cron</em> qui permettrait de l&#8217;exécuter tous les jours). Il permet d&#8217;utiliser une hiérarchie de dossiers où on peut ranger ses affaires du jour (Documents, Notes, Downloads) de façon transparente (dans un dossier Current). Ce dossier Current est un lien symbolique vers un dossier plus compliqué du style Sorted/février/lundi_02. Un appel au script crée un nouveau dossier si le jour a changé et met à jour une hiérarchie globale où tous les fichiers que l&#8217;on trouve pour tous les jours sont centralisés (avec des liens), ce qui permet de retrouver la hiérarchie bordélique que j&#8217;utilise chaque jour lorsque je ne me souviens plus de quand j&#8217;ai fait tel fichier qui m&#8217;intéresse. C&#8217;est avant tout un outil pour traiter le travail quotidien et il ne garantit pas d&#8217;être utilisable pour archiver des documents. Mais je pense qu&#8217;avec quelques améliorations il pourrait être utilisable.</p>
<h2>Utilisation</h2>
<p>Comment utiliser ce petit script ? C&#8217;est très simple : on commence par créer un répertoire vierge et décompresser l&#8217;archive du <a title="Script joinUpdate (pre)" href="http://hardyweb.free.fr/joinUpdate-pre.tar.gz">script que l&#8217;on trouve ici</a>.</p>
<blockquote>
<pre>$ mkdir Test
$ cd Test/
$ tar xvzf &lt;chemin&gt;/joinUpdate-pre.tar.gz</pre>
</blockquote>
<p>L&#8217;archive contient deux fichiers : <em>Update</em> qui est le script à appeler, et <em>functions.sh</em> qui est un script auxiliaire contenant des fonctions utiles.</p>
<p>On commence par créer la hiérarchie de répertoires :</p>
<blockquote>
<pre>$ ./Usage
Creating the Sorted directory...
Creating the Template directory...
Creating the Global directory...
Creating current date directory...
Current directory changed to current date...</pre>
</blockquote>
<p>Que sont ces répertoires ? On en a trois bien utiles :</p>
<ul>
<li><em>Sorted</em> est le répertoire qui stocke tous les fichiers. On ne dirait pas, parce qu&#8217;on ne les utilise jamais directement, sauf pour faire ce pourquoi j&#8217;ai créé tout ça : pour naviguer dans ses fichiers classés par jour. Dans le répertoire <em>Sorted</em> on aura donc les répertoires <em>février</em> et <em>février/lundi_02</em>.</li>
<li><em>Template</em> est le répertoire que vous allez devoir remplir avec les répertoires que vous voulez centraliser : Documents, Downloads, Projet1, etc. Vous mettez vos répertoires (vides) et ils seront copiés tous les jours, vous assurant ainsi de retrouver toujours les mêmes répertoires tous les jours pour pouvoir encore plus les remplir !<br />
Si vous avez bien pigé, alors dans votre répertoire <em>Sorted/février/lundi_02</em> vous aurez les mêmes répertoires que dans <em>Template</em></li>
<li><em>Global</em> est le répertoire qui rassemblera des liens vers tous les fichiers que vous avez créé dans <em>Sorted</em> depuis le début.</li>
<li><em>Current</em> est un lien symbolique vers le répertoire du jour courant. C&#8217;est celui-là que vous utiliserez dans vos travaux journaliers pour stocker vos fichiers.</li>
</ul>
<p>On a donc une hiérarchie toute propre, il faut remplir le répertoire de <em>templates</em> :</p>
<blockquote>
<pre>$ mkdir Templates/Documents
$ mkdir Templates/ProjetJoin</pre>
</blockquote>
<p>Ensuite on doit appeler le script <em>Update</em> afin qu&#8217;il copie ces modèles dans les répertoires <em>Global</em> et <em>Current</em>.</p>
<blockquote>
<pre>$ ./Update
Documents added to Global from Template.
ProjetJoin added to Global from Template.
Documents updated in Current.
ProjetJoin updated in Current.</pre>
</blockquote>
<p>Voilà une affaire rondement menée ! Maintenant on peut utiliser le répertoire <em>Current</em> avec plusieurs programmes, on navigue un peu sur Internet, on enregistre quelques pages, tout ça tout ça&#8230; Pour l&#8217;exemple on va faire un peu plus simple, avec la ligne de commande :</p>
<blockquote>
<pre>$ echo "Idée 1" &gt; Current/ProjetJoin/idee
$ echo "Bonjour." &gt; Current/Documents/hello
$ echo "12345" &gt; "Current/Documents/Machin Bidule"</pre>
</blockquote>
<p>Une fois nos documents créés, on peut appeler <em>Update</em> pour qu&#8217;il crée les liens vers ces fichiers dans le répertoire <em>Global</em> (on doit le faire dans la journée, car le script ne crée les liens que vers les fichiers de la journée en cours).</p>
<blockquote>
<pre>$ ./Update
Checking /home/join/src/lntest/Current/Documents...
Checking file hello... Linked into Global.
Checking file Machin Bidule... Linked into Global.
Checking /home/join/src/lntest/Current/ProjetJoin...
Checking file idee... Linked into Global.</pre>
</blockquote>
<p>Et voilà ! Regardez ce qu&#8217;il y a dans <em>Global</em> :</p>
<blockquote>
<pre>$ find Global/
Global/
Global/Documents
Global/Documents/hello
Global/Documents/Machin Bidule
Global/ProjetJoin
Global/ProjetJoin/idee</pre>
</blockquote>
<p>Parfait. Si on regarde mieux, tous les fichiers sont des liens symboliques. C&#8217;est ce qui m&#8217;a amené à considérer un premier problème : dans un but d&#8217;intuitivité, il aurait fallu que lorsqu&#8217;un fichier de <em>Global</em> est enlevé, sa référence soit enlevée aussi. Malheureusement, pour faire ceci, je n&#8217;ai pas encore trouvé une solution sympatique, et puis on supprime toujours trop rapidement. À l&#8217;heure où la capacité des supports de stockage est très grande (plus d&#8217;un Gio, on va dire), on peut quand même se permettre de ne presque jamais supprimer nos fichiers, tant qu&#8217;ils sont rangés (et ils le seront, puisque c&#8217;est le but de cet outil). Il faut garder à l&#8217;esprit que cet outil est adapté à des petits fichiers comme des travaux que l&#8217;on fait (textes, code, graphisme, etc.).</p>
<h2>Mises à jour et conflits de noms</h2>
<p>Donc là tout est &laquo;&nbsp;synchronisé&nbsp;&raquo;, mais il y a une question qui pose problème (encore !) : si deux fichiers ont le même nom (dans deux jours différents), que se passe-t-il dans <em>Global</em> ? J&#8217;ai choisi la solution de facilité (laisser le premier fichier et ne pas mettre l&#8217;autre) mais elle pourrait s&#8217;avérer avantageuse ou désavantageuse selon les cas (elle force à bien nommer ses fichiers, mais en contrepartie le fait que le dernier fichier créé écrase le reste permettrait de garder des copies de sauvegarde des fichiers et ainsi de pouvoir voir <em>a posteriori</em> leur progression). Faisons un essai et forçons un nouveau <em>Update</em> :</p>
<blockquote>
<pre>$ ./Update
Checking /home/join/src/lntest/Current/Documents...
Checking file hello... <strong>Skipping (exists)</strong>.
Checking file Machin Bidule... <strong>Skipping (exists)</strong>.
Checking /home/join/src/lntest/Current/ProjetJoin...
Checking file idee... <strong>Skipping (exists)</strong>.</pre>
</blockquote>
<p>Il ne met aucun lien à jour. Le comportement est bien celui escompté. Afin de garantir l&#8217;intégrité de notre répertoire <em>Global</em>, supprimons un fichier dans <em>Current</em> :</p>
<blockquote>
<pre>$ rm "Current/Documents/Machin Bidule"</pre>
</blockquote>
<p>Le lien symbolique est maintenant invalide :</p>
<blockquote>
<pre>$ cat "Global/Documents/Machin Bidule"

<strong>cat: Global/Documents/Machin Bidule: Aucun fichier ou dossier de ce type</strong></pre>
</blockquote>
<p>Un petit appel à <em>Update</em> corrigera tous nos problèmes.</p>
<blockquote>
<pre>$ ./Update
Checking /home/join/src/lntest/Current/Documents...
Checking file hello... Skipping (exists).
Checking /home/join/src/lntest/Current/ProjetJoin...
Checking file idee... Skipping (exists).
<strong>Bad link for /home/join/src/lntest/Global/Documents/Machin Bidule. Deleting.</strong></pre>
</blockquote>
<p>Ok, très bien. Je vous laisse le soin d&#8217;apprécier un usage quotidien du script, vous pourrez même le bidouiller.</p>
<h2>Des problèmes, que des problèmes !</h2>
<p>Cet outil contre-révolutionnaire présente néanmoins quelques inconvénients :</p>
<ul>
<li>Il vérifie tous les fichiers du jour à chaque exécution. Il faut donc définir un mode où il ne fait que des vérifications, et l&#8217;exécuter soit au login et à la déconnexion, soit toutes les heures (ou toutes les 5 minutes par exemple).</li>
<li>Il ne résout pas le problème des conflits lors des mises à jours. J&#8217;attends de pouvoir trouver une solution viable (et pas de renommage de fichiers, c&#8217;est déplaisant).</li>
<li>L&#8217;utilisation de deux hiérarchies distinctes, mêmes synchronisées, pose des problèmes pour les utilisateurs qui se servent de la fonction &laquo;&nbsp;Derniers documents ouverts&nbsp;&raquo;, à moins que les programmes implémentant cette fonction suivent les liens symboliques et ne gardent que l&#8217;adresse de la source. Parce que vu que <em>Current</em> est changé tous les jours, ça pose des problèmes&#8230;</li>
<li>L&#8217;utilisation de liens symboliques, c&#8217;est bien, mais des liens en dur c&#8217;est peut-être aussi bien, voire mieux. Le problème viendra dans la réplication de hiérarchies : avec des liens symboliques, on n&#8217;a qu&#8217;à faire des liens avec tout ce qui passe, que ce soient des fichiers ou des répertoires, et ça ne pose pas de problèmes pour les répertoires. On ne peut pas faire de lien vers des répertoires en dur. Il faut soit les copier, soit en faire des liens symboliques.</li>
<li>Que dire de l&#8217;utilisation du système de fichiers ? C&#8217;est une solution simple, mais peut-être que certains systèmes de fichiers n&#8217;aiment pas l&#8217;abondance de répertoires que cela va générer.</li>
<li>Des systèmes de contrôle de version (CVS, SVN, Git&#8230;) pourraient faire ce genre de choses et plus encore, moyennant quelques lectures. C&#8217;est hélas un peu plus compliqué à appréhender, c&#8217;est pas trop fait pour ça et on perd un peu de &laquo;&nbsp;sens&nbsp;&raquo;.</li>
<li>Le système actuel est trop attaché aux chemins absolus (mais ce n&#8217;est peut-être pas si grave, finalement).</li>
<li>Au final, par rapport à un outil qui devrait scruter toutes les modifications comme un démon, on n&#8217;est pas loin. Et c&#8217;est pas très optimisé&#8230; Bref, il n&#8217;y a peut-être pas de solution qui n&#8217;impose pas d&#8217;utiliser un démon.</li>
</ul>
<p>Vous remarquez que j&#8217;ai pris le problème dans un sens particulier : le répertoire de bordel contient les liens et le répertoire rangé contient les vrais fichiers, ce qui semblait pratique au premier abord. J&#8217;aurais pu faire ça dans l&#8217;autre sens, mais une question se pose : je range les fichiers de cette façon (par date, mais j&#8217;aurais pu trouver d&#8217;autres critères pas forcément temporels) parce que les propriétés des fichiers imposées par le système de fichiers (utilisateur, date de modification, de création) ne me conviennent pas pour trier mes fichiers (et de toute façon je ne connais pas d&#8217;outil intuitif et rapide permettant de les grouper grâce à un critère). En regardant le problème dans l&#8217;autre sens, comment reconnaître dans un bordel monstre les fichiers qu&#8217;on a touché aujourd&#8217;hui, sans pouvoir regarder les critères que je viens de citer (surtout la date de modification) ? Si on laisse tomber l&#8217;idée de devoir appeler le script à chaque ajout d&#8217;un fichier dans le répertoire qu&#8217;on veut surveiller (pour le transférer directement), on peut par contre faire de la surveillance de répertoire. Cela nécessite un fichier supplémentaire mais au moins on peut directement garder la trace de toutes les modifications : les fichiers enlevés et les fichiers rajoutés. À la mise à jour (appel du script), il suffit de comparer le dernier fichier chargé de surveiller le répertoire à la hiérarchie de fichiers enregistrés et le compte est bon ! Comment faire ceci ? Voici une solution.</p>
<h2>Utiliser <em>find</em></h2>
<p>Nous pouvons obtenir la hiérarchie de fichiers à partir d&#8217;un répertoire grâce à la commande <em>find</em>. Créons une hiérarchie de test et enregistrons la hiérarchie (produite par <em>find</em>) dans un fichier à l&#8217;extérieur de cette hiérarchie.</p>
<blockquote>
<pre>$ mkdir test; cd test
$ mkdir rep1 rep2
$ touch fich1 fich2 rep1/fich1 rep1/fich2 rep2/fich1
$ find . &gt; ../hierarchie</pre>
</blockquote>
<p>Maintenant, supprimons quelques fichiers, rajoutons-en d&#8217;autres et observons le résultat.</p>
<blockquote>
<pre>$ rm rep1/fich2 fich1
$ touch rep1/nouveau pouet
$ find . &gt; ../hierarchie2</pre>
</blockquote>
<p>On compare les deux :</p>
<blockquote>
<pre>$ diff ../hierarchie ../hierarchie2 | grep [\&lt;\&gt;]
&lt; ./rep1/fich2
&lt; ./fich1
&gt; ./rep1/nouveau
&gt; ./pouet</pre>
</blockquote>
<p>Et voilà, on a toutes les modifications de la structure de la hiérarchie de fichiers qui ont été effectuées entre les deux <em>find</em>. On utilise <em>grep</em> pour ne garder que les lignes que l&#8217;on veut (<em>diff</em> produit des lignes supplémentaires qui sont des scripts <em>ed</em>, et qui ne nous intéressent pas). Donc si on veut récupérer la liste des fichiers qui ont été supprimés (et donc la liste des fichiers dont le lien symbolique doit être effacé dans la hiérarchie qu&#8217;on va maintenir), on fait comme ceci (remarquez ce qui change dans le <em>grep</em>) :</p>
<blockquote>
<pre>$ diff ../hierarchie ../hierarchie2 | grep [\&lt;] | cut -c 3-
./rep1/fich2
./fich1</pre>
</blockquote>
<p>L&#8217;appel de <em>cut</em> est nécessaire pour enlever les petits signes &lt; ou &gt; qui polluent le nom du fichier.</p>
<p>On peut même faire encore plus fort et n&#8217;utiliser que des chemins absolus grâce au programme <em>readlink</em>. Donc au lieu de :</p>
<blockquote>
<pre>$ find . &gt; ../hierarchie</pre>
</blockquote>
<p>On ferait :</p>
<blockquote>
<pre>$ find . | xargs -n1 readlink -f &gt; ../hierarchie</pre>
</blockquote>
<p>Ici on utilise <em>xargs</em> qui transforme selon des paramètres qu&#8217;on définit l&#8217;entrée standard en arguments passés à un programme. On doit faire cela car <em>readlink</em> ne joue pas avec l&#8217;entrée standard.</p>
<p>Avec tout ça, on pourrait tenter un programme sympathique.</p>
<h2>Un nouvel essai</h2>
<p>Nous allons donc essayer de suivre le développement inverse : faire un programme qui, à partir d&#8217;une hiérarchie de répertoires bordéliques, les classe dans des répertoires selon des critères. Comme critère, on va prendre la date du jour, mais on peut en réalité faire ce que l&#8217;on veut. On peut même imaginer que le critère soit une activité donnée par un nom, et qu&#8217;une applet GNOME (par exemple) puisse permettre de changer d&#8217;activité, occasionnant ainsi la classification dans la nouvelle activité de tous les nouveaux fichiers de la hiérarchie de répertoires à partir de cette date.</p>
<p>On remarque donc que cette manière de procéder est peut-être pas mal plus flexible, puisqu&#8217;on n&#8217;aurait plus besoin de <em>templates</em> à tenir à jour : tout ce qui est ajouté est pris en compte, donc la structure est extensible à l&#8217;infini.</p>
<h2>Un peu plus de classe</h2>
<p>Après une petite session développement, j&#8217;ai fini un outil qui me semble bien. Par rapport au premier jet, il est déjà un peu différent : il suit le principe inverse ! Si je suis déçu de ne pas avoir réussi à utiliser la petite astuce du répertoire <em>Current</em> dont j&#8217;étais fier jusque là, je trouve cette nouvelle solution bien plus élégante. Elle utilise une hiérarchie beaucoup moins lourde, moins de répertoires, moins de liens et juste un tout petit peu plus de code.</p>
<p>Je donne un rapide tour d&#8217;horizon de la chose. Le programme se nomme toujours <em>Usage</em> sauf que voici son fonctionnement :</p>
<blockquote>
<pre>$ ./Update -h
Usage: Update [OPTION]
Updates a sorted reference to a file hierarchy grouping them by date or label

        -s              Delete bad symlinks in the sorted reference
        -e              Delete empty directories in the sorted reference
        -l LABEL        Set a particular label

Typical call : Update

Configuration file : ~/.update_postrc
Configuration options (example) :
        SORT_DIR=/home/me/WellStoredFiles
        GLOBAL_DIR=/home/me/ReallyMessyFolder
        dir_cpt=ALabelNameIfYouDontWantToUseDates
(bash syntax)</pre>
</blockquote>
<p>Haha, ça vous la coupe, non ? Bon, ok&#8230; Alors donc voilà. On appelle <em>Update</em> comme avant, sans arguments ni rien. On peut lui passer en paramètre une option ou deux pour lui forcer à faire des opérations de maintenance, dont vérifier la validité des liens symboliques (pas mal utile si on veut garder une hiérarchie à jour), ou alors supprimer les répertoires vides (ce n&#8217;est pas obligatoire mais ça peut servir). Une option spéciale permet d&#8217;assigner une étiquette aux modifications en cours au lieu d&#8217;une date. Il est également possible de définir un fichier de configuration dans son répertoire personnel (dans <em>~/.update_postrc</em>), ce qui permet de redéfinir les répertoires par défaut de rangement (<em>SORT_DIR</em>) et source (<em>GLOBAL_DIR</em>) puisqu&#8217;ils suivent le répertoire d&#8217;exécution de <em>Update</em> par défaut. On peut aussi définir dans ce fichier la variable d&#8217;environnement <em>dir_cpt</em> qui permet de donner, si on y touche, une étiquette aux prochaines modifications. Afin de faire quelque chose avec ces étiquettes, souvenez-vous que le fichier de configuration est un fichier script <em>bash</em>, vous pouvez donc y importer un fichier, faire des calculs, regarder des dates, ou des tas d&#8217;autres choses pour déterminer l&#8217;étiquette en cours (ce script est exécuté lors de l&#8217;appel à <em>Update</em>).</p>
<p>Ainsi le fait d&#8217;utiliser des dates ou des étiquettes a peu d&#8217;importance, et ce qui compte c&#8217;est l&#8217;effet du script. Allons faire un petit essai.</p>
<h2>Essai du nouveau script</h2>
<p>Voici un petit essai peu commenté du script. D&#8217;abord, on a <a href="http://hardyweb.free.fr/joinUpdate-post.tar.gz">téléchargé l&#8217;archive contenant le script <em>Update</em></a> et on va s&#8217;apprêter à créer un dossier de test pour y enfermer ce script et des répertoires divers.</p>
<blockquote>
<pre>$ tar xvzf &lt;dossier&gt;/joinUpdate-post.tar.gz
$ ./Update
Creating the Sorted directory...
Creating the Global directory...
Creating a new snapshot...
Writing out snapshot date...
Creating a new directory in the sorted structure : 2009_février/02_lundi...</pre>
</blockquote>
<p>Content de moi, je regarde un peu mon répertoire courant : je trouve deux répertoires qui sont <em>Global</em> et <em>Sorted</em>. Le premier me sert donc pour stocker mes hiérarchies de répertoire et tout mon travail, alors que le deuxième permet de trier tout le bordel par des appels à <em>Update</em>.</p>
<p>On fait quelques fichiers puis on met à jour la structure :</p>
<blockquote>
<pre>$ mkdir Global/Documents
$ touch Global/Pouetpouet Global/NoteDirection Global/Documents/truc
$ ./Update
Adding ./Pouetpouet...
Adding ./Documents...
Adding ./Documents/truc...
Adding ./NoteDirection...</pre>
</blockquote>
<p>Génial ! Ça a tout ajouté dans <em>Sorted/2009_février/02_lundi</em>. Ah&#8230; J&#8217;ai oublié d&#8217;ajouter un fichier. Faisons-le.</p>
<blockquote>
<pre>$ touch Global/oubli
$ ./Update
Adding ./oubli...</pre>
</blockquote>
<p>Et voilà. Maintenant nous voulons faire une session de travail spécialement pour les minutes à venir. Nous allons utiliser l&#8217;option <em>-l</em> avec tous les prochains appels au script pour spécifier une étiquette.</p>
<blockquote>
<pre>$ touch Global/travailsession Global/jeusession
$ ./Update -l session
Adding ./jeusession...
Adding ./travailsession...
$ ls Sorted/session/
jeusession  travailsession</pre>
</blockquote>
<p>Ok, maintenant nous n&#8217;avons plus envie d&#8217;être dans cette session de travail. Faison un <em>Update </em>normal après quelques modifications.</p>
<blockquote>
<pre>$ rm Global/oubli Global/travailsession
$ touch Global/nouveau
$ ./Update
Creating a new snapshot...
Writing out snapshot date...
Removing ./travailsession...
Removing ./oubli...
Adding ./nouveau...</pre>
</blockquote>
<p>Voilà donc un outil qui pourrait satisfaire plusieurs utilisations.</p>
<h2>Perspectives</h2>
<p>Bien sûr, il manque à notre outil une licence un peu plus solide, la localisation (je l&#8217;ai fait en anglais pour pouvoir partager plus facilement le code si jamais il servait), et quelques fonctions, mais il m&#8217;a l&#8217;air bien parti pour une utilisation quotidienne et c&#8217;est ce que je vais tester de ce pas. Je ne livre pas la solution clés en main mais il est très facile d&#8217;utiliser l&#8217;outil pour faire des applets d&#8217;environnement de bureau, des démons et toutes sortes de choses.</p>
<p>J&#8217;attends toutes vos remarques sur cet article qui m&#8217;aura décidément pris plus de temps que prévu.</p>
<h3>Petite modification</h3>
<p>J&#8217;interviens pour une modification de parcours : j&#8217;ai rajouté quelques petites lignes pour pouvoir placer la hiérarchie rangée (répertoire Sorted) à l&#8217;intérieur de la hiérarchie bordélique (répertoire Global).</p>
<h3>Téléchargement</h3>
<ul>
<li><a href="http://hardyweb.free.fr/joinUpdate-pre.tar.gz">Version <em>pre</em></a> (la première qui utilisait les dossiers rangés comme référence)</li>
<li><a href="http://hardyweb.free.fr/joinUpdate-post.tar.gz">Version <em>post</em></a> (la deuxième qui utilise les dossiers bordéliques comme référence)</li>
</ul>
<p>Ce travail est soumis à la WTFPL. Respectez-la <img src='http://s2.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/joinwww.wordpress.com/43/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/joinwww.wordpress.com/43/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/joinwww.wordpress.com/43/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/joinwww.wordpress.com/43/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/joinwww.wordpress.com/43/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/joinwww.wordpress.com/43/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/joinwww.wordpress.com/43/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/joinwww.wordpress.com/43/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/joinwww.wordpress.com/43/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/joinwww.wordpress.com/43/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/joinwww.wordpress.com/43/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/joinwww.wordpress.com/43/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/joinwww.wordpress.com/43/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/joinwww.wordpress.com/43/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=joinwww.wordpress.com&amp;blog=4998056&amp;post=43&amp;subd=joinwww&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://joinwww.wordpress.com/2009/02/02/comment-ranger-sa-chambre-avec-unix/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">join</media:title>
		</media:content>
	</item>
		<item>
		<title>Des polices des thèmes GTK</title>
		<link>http://joinwww.wordpress.com/2008/10/20/des-polices-des-themes-gtk/</link>
		<comments>http://joinwww.wordpress.com/2008/10/20/des-polices-des-themes-gtk/#comments</comments>
		<pubDate>Mon, 20 Oct 2008 11:03:07 +0000</pubDate>
		<dc:creator>join</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[gtk]]></category>

		<guid isPermaLink="false">http://joinwww.wordpress.com/?p=30</guid>
		<description><![CDATA[Quelque peu après la rédaction de mon article De l&#8217;esprit des thèmes GTK, je me suis aperçu qu&#8217;un élément important d&#8217;une interface graphique était aussi la police d&#8217;écriture, contrôlée par la propriété font_name. Quand on voit GNOME à partir duquel on peut paramétrer une seule police pour les contrôles GTK, on se dit que c&#8217;est [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=joinwww.wordpress.com&amp;blog=4998056&amp;post=30&amp;subd=joinwww&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Quelque peu après la rédaction de mon article De l&#8217;esprit des thèmes GTK,<br />
je me suis aperçu qu&#8217;un élément important d&#8217;une interface graphique était<br />
aussi la police d&#8217;écriture, contrôlée par la propriété<br />
<code>font_name</code>. Quand on voit GNOME à partir duquel on peut<br />
paramétrer <em>une seule</em> police pour les contrôles GTK, on se dit que<br />
c&#8217;est normal que tout paraisse si gros ! Changer la police selon le widget<br />
permettrait un peu plus de souplesse et donnerait un peu de gueule à<br />
n&#8217;importe quel thème.<span id="more-30"></span></p>
<h2>Les descriptions de police Pango</h2>
<p>GTK utilise Pango pour afficher du texte. On utilise donc dans l&#8217;attribut<br />
<code>font_name</code> une description Pango (incomplète, cependant). Pango<br />
comprend ici seulement les familles de police (c&#8217;est-à-dire le nom de la<br />
police; différents noms peuvent être mis, séparés par une virgule), les<br />
styles (<code>bold</code>, <code>italic</code>, <code>condensed</code>,<br />
<code>extended</code>&#8230;), la gravité (sens d&#8217;écriture : <code>north</code>,<br />
<code>south</code>, <code>east</code>, <code>west</code>) et la taille (en<br />
points, ou la taille en pixels si elle est suffixée de <code>px</code>). Tout<br />
ça séparé par des espaces et dans cet ordre :</p>
<pre>famille1,famille2 style1 style2 taille</pre>
<p>Aucun des attributs n&#8217;est obligatoire, ce qui fait qu&#8217;on peut garder la<br />
famille de police mais changer la taille, garder le style et changer la<br />
famille de police&#8230; Ainsi, pour garder la police de l&#8217;utilisateur mais<br />
changer sa taille, on mettra :</p>
<pre>font_name = "8"</pre>
<p>Pas mal, hein ?</p>
<h2>Une super aubaine !</h2>
<p>Ceci nous permet, en plus d&#8217;avoir des thèmes génériques par rapport aux<br />
familles de polices, d&#8217;appliquer des contraintes de polices indépendamment du<br />
thème appliqué ou de la police choisie. C&#8217;est ce que j&#8217;ai expérimenté sous<br />
GNOME (mais ça marche partout) où j&#8217;ai rempli mon fichier<br />
<code>~/.gtkrc-2.0</code> avec le code ci-dessous. La particularité de ce<br />
fichier est qu&#8217;il est prioritaire par rapport à tous les autres<br />
<code>rc</code> de thèmes :</p>
<pre>############################
#   Polices                #
############################

style "label_fnt" {
font_name = "8"
}
widget_class "*&lt;GtkLabel&gt;*" style "label_fnt"
widget "gtk-tooltip*" style "label_fnt"
widget_class "*GtkExpander*" style "label_fnt"

style "menu_fnt" {
font_name = "9"
}
widget_class "*GtkMenu*" style "menu_fnt"

style "statusbar_fnt" {
font_name = "8"
}
widget_class "*Statusbar*" style "statusbar_fnt"

style "notebook_fnt" {
font_name = "Bold 8"
}
widget_class "*.GtkNotebook.GtkLabel*" style "notebook_fnt"

style "frame_fnt" {
font_name = "Bold 8"
}
widget_class "*.GtkFrame.GtkLabel*" style "frame_fnt"

style "button_fnt" {
font_name = "9"
}
widget_class "*.Gtk*Button.*Label" style "button_fnt"

style "checkradio_fnt" {
font_name = "9"
}
widget_class "*.GtkCheckButton.*Label" style "checkradio_fnt"
widget_class "*.GtkRadioButton.*Label" style "checkradio_fnt"
widget_class "*.GtkComboBox*.*Label" style "checkradio_fnt"

style "toolbar_fnt" {
  font_name = "7"
}
widget_class "*.&lt;GtkToolbar&gt;.*Label" style "toolbar_fnt"
widget_class "*.&lt;GtkToolbar&gt;.*GtkComboBox*" style "toolbar_fnt"
widget_class "*.&lt;GtkToolbar&gt;.*GtkEntry*" style "toolbar_fnt"
widget_class "*.&lt;GtkToolbar&gt;.*Gtk*Button*" style "toolbar_fnt"

# Panel items
style "panel_fnt" {
font_name = "8"
}
widget_class "*Panel*" style "panel_fnt"</pre>
<p>Génial ! Maintenant, prenez un thème, une police, et c&#8217;est parti.</p>
<h2>Un exemple</h2>
<p>Voici la différence entre un thème avec et sans ces modifications :</p>
<div id="attachment_31" class="wp-caption aligncenter" style="width: 310px"><a href="http://joinwww.files.wordpress.com/2008/10/sans.png"><img class="size-medium wp-image-31" title="Partout la même police" src="http://joinwww.files.wordpress.com/2008/10/sans.png?w=300&#038;h=174" alt="C'est moche !" width="300" height="174" /></a><p class="wp-caption-text">C&#39;est moche !</p></div>
<div id="attachment_32" class="wp-caption aligncenter" style="width: 310px"><a href="http://joinwww.files.wordpress.com/2008/10/avec.png"><img class="size-medium wp-image-32" title="Différentes polices sont mises" src="http://joinwww.files.wordpress.com/2008/10/avec.png?w=300&#038;h=174" alt="C'est mieux !" width="300" height="174" /></a><p class="wp-caption-text">C&#39;est mieux !</p></div>
<p>Bien sûr, j&#8217;avais ici une police de taille 9 par défaut, et j&#8217;ai mis du 9 sur les boutons, les checkboxes&#8230; Ce qui ne change pas beaucoup de choses ! Mais libre à vous de changer les tailles et de mettre tout sans dessus dessous (indice : <code>north</code>).</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/joinwww.wordpress.com/30/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/joinwww.wordpress.com/30/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/joinwww.wordpress.com/30/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/joinwww.wordpress.com/30/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/joinwww.wordpress.com/30/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/joinwww.wordpress.com/30/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/joinwww.wordpress.com/30/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/joinwww.wordpress.com/30/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/joinwww.wordpress.com/30/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/joinwww.wordpress.com/30/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/joinwww.wordpress.com/30/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/joinwww.wordpress.com/30/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/joinwww.wordpress.com/30/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/joinwww.wordpress.com/30/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=joinwww.wordpress.com&amp;blog=4998056&amp;post=30&amp;subd=joinwww&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://joinwww.wordpress.com/2008/10/20/des-polices-des-themes-gtk/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">join</media:title>
		</media:content>

		<media:content url="http://joinwww.files.wordpress.com/2008/10/sans.png?w=300" medium="image">
			<media:title type="html">Partout la même police</media:title>
		</media:content>

		<media:content url="http://joinwww.files.wordpress.com/2008/10/avec.png?w=300" medium="image">
			<media:title type="html">Différentes polices sont mises</media:title>
		</media:content>
	</item>
		<item>
		<title>De l&#8217;esprit des thèmes GTK</title>
		<link>http://joinwww.wordpress.com/2008/10/12/de-lesprit-des-themes-gtk/</link>
		<comments>http://joinwww.wordpress.com/2008/10/12/de-lesprit-des-themes-gtk/#comments</comments>
		<pubDate>Sun, 12 Oct 2008 00:09:46 +0000</pubDate>
		<dc:creator>join</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[gtk]]></category>

		<guid isPermaLink="false">http://joinwww.wordpress.com/?p=15</guid>
		<description><![CDATA[Voici un petit (long) article sur l'art et la manière de faire des thèmes pour GTK, le toolkit multi-plateformes.<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=joinwww.wordpress.com&amp;blog=4998056&amp;post=15&amp;subd=joinwww&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Je profite de cet article pour mettre quelques notes sur la création et<br />
l&#8217;édition de thèmes GTK&#8230; A part le fait que c&#8217;est un bon divertissement<br />
lors du week-end, j&#8217;ai pensé que se plonger là-dedans pourrait non seulement<br />
me faire apparaître les défauts de GTK, mais aussi de me confronter à un<br />
autre genre d&#8217;habillage que le CSS. Hé oui, après tout, faire du CSS c&#8217;est<br />
appliquer un thème sur un contenu aussi !<span id="more-15"></span> Outre ce fait, il est généralement<br />
plaisant de pouvoir travailler dans un environnement satisfaisant pour les<br />
yeux, et étant donné le manque cruel de productions de qualité dans le monde<br />
des thèmes GTK, et surtout de documentation unifiée, je me suis dit que<br />
j&#8217;allais noter quelques petites choses que j&#8217;avais glanées ici et là. J&#8217;ai<br />
décidé d&#8217;emprunter à droite et à gauche et surtout de pomper les exemples et<br />
les conseils du <a href="http://live.gnome.org/GnomeArt/Tutorials/GtkThemes">tutorial GtkThemes<br />
sur gnome.org</a>. Merci à son auteur.</p>
<h2>La structure d&#8217;un thème</h2>
<p>Un thème, c&#8217;est avant tout un dossier, dans la spécification Freedesktop.<br />
Le nom du dossier indique le nom du thème, et il est placé dans un répertoire<br />
themes. Dans ce dossier sont rangés un ou plusieurs dossiers portant le nom<br />
de l&#8217;application ou de la librairie qui l&#8217;utilise. Par exemple,<br />
<code>xfwm4</code> ou <code>gtk-2.0</code>. Et dans chaque dossier sont<br />
rangés des fichiers ayant une structure propre à leur application.</p>
<p>Pour GTK, on aura un fichier <code>gtkrc</code> qui sera le point de<br />
départ de ce qui sera interprété pour afficher le thème. C&#8217;est un fichier<br />
avec une &laquo;&nbsp;instruction par ligne&nbsp;&raquo;, où chaque instruction peut être :</p>
<ul>
<li>Un commentaire (on le démarre n&#8217;importe où sur la ligne, c&#8217;est tout ce<br />
qui suit le symbole <code>#</code>, ou alors il peut avoir effet sur<br />
plusieurs lignes et dans ce cas c&#8217;est tout ce qui se situe entre<br />
<code>/*</code> et <code>*/</code>)</li>
<li>Une propriété, qu&#8217;on écrit : <code>propriété = valeur</code></li>
<li>Une définition de style, qu&#8217;on écrit <code>style "nom du style"<br />
{</code>, suivi de lignes de propriétés, puis de <code>}</code>. On peut<br />
hériter d&#8217;un autre style déjà défini en écrivant plutôt <code>style "nom<br />
du style" = "nom du style hérité"</code></li>
<li>Une affectation de style, qu&#8217;on écrit : <code>class "ClasseGtkAffectée"<br />
style "style choisi"</code></li>
</ul>
<p>Cette liste pas exhaustive, nous verrons d&#8217;autres &laquo;&nbsp;instructions&nbsp;&raquo; au fil de<br />
l&#8217;article. Il est possible de séparer les styles dans plusieurs fichiers rc<br />
et de les inclures dans le gtkrc général. On verra qu&#8217;il est possible<br />
d&#8217;employer des images que l&#8217;on placera dans le répertoire du thème GTK.</p>
<p>Mettons-nous donc à l&#8217;ouvrage et construisons notre premier thème GTK sans<br />
plus attendre. Sous les systèmes apparentés aux UNIX (GNU/Linux, *BSD&#8230;), on<br />
trouvera les thèmes Freedesktop dans un dossier global au système, du genre<br />
<code>/usr/share/themes</code>, et aussi dans un dossier local à<br />
l&#8217;utilisateur, qui est <code>~/.themes</code>. Allons donc créer un dossier<br />
<code>1test</code> dans ce répertoire de thèmes (s&#8217;il n&#8217;existe pas, il faudra<br />
le créer avec la commande <code>mkdir ~/.themes</code>) :</p>
<pre>cd ~/.themes</pre>
<pre>mkdir 1test</pre>
<p>Continuons avec la création d&#8217;un répertoire <code>gtk-2.0</code> :</p>
<pre>mkdir 1test/gtk-2.0</pre>
<pre>cd 1test/gtk-2.0</pre>
<p>On peut maintenant créer un nouveau fichier <code>gtkrc</code> et l&#8217;éditer<br />
avec notre éditeur préféré (ici le mien c&#8217;est <code>vim</code>, sans<br />
concession) :</p>
<pre>vim gtkrc</pre>
<p>Vous voilà dans un fichier vide ! Avant de commencer à tapoter des lignes,<br />
voyons donc quelques bases.</p>
<h2>Une hiérarchie pour les gouverner tous</h2>
<p>Un widget, c&#8217;est un élément d&#8217;interface utilisateur dans GTK. Ça peut être<br />
un bouton, une étiquette de texte, un menu&#8230; Tous les widgets de GTK sont<br />
inscrits dans une hiérarchie et ce sont tous des objets (au sens de la<br />
programmation orientée objet). Ainsi, tous les widgets possibles et<br />
imaginables &laquo;&nbsp;descendent&nbsp;&raquo; de <code>GtkWidget</code> : peu importe sa place<br />
dans la hiérarchie, il conservera les propriétés de ce <code>GtkWidget</code><br />
(pour peu qu&#8217;on ne les modifie pas). Dans le même ordre d&#8217;idées, un<br />
<code>GtkColorButton</code> (qui est un bouton pour choisir des couleurs dans<br />
l&#8217;interface) hérite des propriétés de son père le <code>GtkButton</code>, qui<br />
lui-même hérite des propriétés de <code>GtkWidget</code>. Bien entendu, rien<br />
ne nous empêche de remettre en cause les propriétés de <code>GtkButton</code><br />
qui ont été héritées de <code>GtkWidget</code>. C&#8217;est comme ça qu&#8217;on peut<br />
tout contrôler.</p>
<p>On verra plus tard qu&#8217;il faudra séparer, comme en programmation orientée<br />
objets, le concept de <em>classe</em> de celui d&#8217;<em>instance</em> de classe.<br />
Pour faire simple, une classe est un type d&#8217;objet et une instance est un<br />
objet du type. Par exemple, Richard Stallman est une instance de la classe<br />
SuperHéros signifie que Richard est un super héros et partage donc les<br />
caractéristiques des super héros, mais il est toutefois unique. Du fait que<br />
c&#8217;est un super héros, il contribue à sauver le monde de la destruction, comme<br />
le font tous les super héros. Pour pousser plus loin notre exemple, on peut<br />
même remarquer que SuperHéros est une classe qui hérite de la classe Mec,<br />
c&#8217;est-à-dire qu&#8217;un super héros est un mec avant tout. On peut lui parler, ou<br />
lui dire &laquo;&nbsp;Hé, t&#8217;es une mauviette !&nbsp;&raquo;, comme à tous les mecs. Si on imagine que<br />
tous les super héros répondent de la même manière que les mecs normaux à mon<br />
&laquo;&nbsp;Hé, t&#8217;es une mauviette !&nbsp;&raquo;, on peut quand même imaginer qu&#8217;il y aurait une<br />
classe SuperHérosPasCool qui hérite de la classe SuperHéros et dans laquelle<br />
le comportement du super héros pas cool à mon &laquo;&nbsp;Hé, t&#8217;es une mauviette !&nbsp;&raquo;<br />
aurait été changé. Au lieu de danser la zoubida, comme tous les mecs normaux,<br />
ce genre de super héros pas cool pourrait très bien me répondre &laquo;&nbsp;Personne ne<br />
me traite de mauviette&nbsp;&raquo;. Bref, ce paragraphe était là pour rappeler aux<br />
nouveaux dans le monde objet quelques principes, et je m&#8217;excuse d&#8217;avance s&#8217;il<br />
vous a plus mis dans le flou qu&#8217;éclairci les idées. De nombreux sites et<br />
cours sont à disposition sur la toile pour poser clairement ces concepts.</p>
<p>Je parle de tout ce charabia car il est important de savoir que GTK étant<br />
programmé en objets (malgré qu&#8217;il soit en C, ce qui n&#8217;est pas une mauvaise<br />
chose en soi), la hiérarchie de ses widgets est une hiérarchie de classes qui<br />
existe dans la librairie et qui est très bien documentée. Pour vous en<br />
convaincre, installez la doc de GTK (<code>gtk-doc</code> sous la majorité<br />
des distributions) et un fabuleux lecteur de documentation nommé<br />
<code>devhelp</code>. Sinon, faites un tour sur le site de GNOME, tout est<br />
marqué <a href="http://library.gnome.org/devel/gtk/unstable/ch01.html">ici</a>. Toutes<br />
les propriétés stylistiques de ces classes, et même des instances, sont<br />
gérées par un mécanisme de propriétés changeables ou lisibles directement<br />
dans un programme, en direct live ! Nous allons nous contenter de les &laquo;&nbsp;graver<br />
dans la roche&nbsp;&raquo; pour nos familles et nos&#8230; amis.</p>
<h2>Un accès plus facile à la propriété <sup>partie 1</sup></h2>
<p>On va voir comment écrire une propriété, et ensuite on verra où la mettre.<br />
Une propriété, c&#8217;est une ligne qui définit un changement d&#8217;attribut d&#8217;un<br />
widget. Par exemple, sur la <a href="http://library.gnome.org/devel/gtk/unstable/GtkComboBox.html#GtkComboBox.properties"><br />
</a> de doc du widget <code>GtkComboBox</code>, qui définit une boîte de<br />
sélection, on peut lire tout un tas de propriétés et de propriétés<br />
stylistiques vachement intéressantes. On peut toucher à tout en respectant<br />
les types des valeurs qu&#8217;on donne aux propriétés de style. En règle générale,<br />
dans le fichier gtkrc, on va appliquer une propriété X à une classe Y en<br />
écrivant :</p>
<pre>Y::X = valeur</pre>
<p>On ne peut pas l&#8217;écrire n&#8217;importe où : <strong>on doit créer un<br />
style</strong> dans lequel on va inclure cette propriété, et appliquer le<br />
style à une classe de widgets. Ça a l&#8217;air compliqué, mais en fait c&#8217;est<br />
simple : il faut <strong>toujours</strong> mettre ses directives (propriétés<br />
de style, propriétés, couleurs, moteurs de thème&#8230;) dans des styles, sauf si<br />
ces directives sont des propriétés globales (par exemple<br />
<code>gtk_color_scheme</code>) ou des applications de style. En gros, sauf<br />
dans deux cas, on met ses propriétés dans les styles et basta.</p>
<p>Imaginons que je veuille directement modifier une propriété de<br />
<code>GtkComboBox</code> qui permet aux éléments de la liste déroulante<br />
d&#8217;être affichés comme une liste et non pas comme un menu. On va utiliser la<br />
ligne de propriété : <code>GtkComboBox::appears-as-list = 1</code>. On va<br />
devoir la mettre dans un style qu&#8217;on nommera&#8230; comme on veut ! Et on<br />
l&#8217;appliquera à la classe <code>GtkWidget</code>, comme ça on s&#8217;fait pas<br />
chier. Comment on fait ? Vous devriez pouvoir trouver avec tout ce que j&#8217;ai<br />
dit au dessus :</p>
<pre style="margin-left:0;"># Petit thème moche
# par join et &lt;entre ton nom ici&gt;

style "styleParDefaut" {
    GtkComboBox::appears-as-list = 1
}

class "GtkWidget" style "styleParDefaut"</pre>
<p>Et voilà.</p>
<h2>Interlude : Tester un thème</h2>
<p>Il existe plusieurs moyens de tester notre thème fraîchement composé. Pour<br />
les utilisateurs de GNOME, il est toujours possible, quoique très lent, de<br />
passer par les préférences de l&#8217;apparence. Je vous conseille toutefois un<br />
outil comme <a href="http://www.stellingwerff.com/?page_id=10">The Widget<br />
Factory</a> (disponible dans des dépôts pour votre distribution si vous avez<br />
de la chance). Une fois compilé et/ou installé, lancez cet outil en<br />
l&#8217;appelant par son nom, de préférence en ligne de commande :</p>
<pre>twf</pre>
<p>L&#8217;avantage d&#8217;avoir nommé notre thème de test <code>1test</code> est qu&#8217;il<br />
est possible de le charger facilement : il est normalement en première place<br />
du menu de sélection de thèmes ! Un clic sur le bouton <em>Actualiser</em> de<br />
la barre d&#8217;outils permettra d&#8217;afficher les modifications que l&#8217;on vient de<br />
faire subir à son thème. Le fait d&#8217;avoir lancé The Widget Factory en ligne de<br />
commande permet de voir dans le terminal, à l&#8217;actualisation du thème, tous<br />
les messages d&#8217;erreur qu&#8217;envoie GTK lorsqu&#8217;il lit le thème, autrement dit<br />
toutes les erreurs de votre thème.</p>
<p>Vous voyez que notre premier thème est bien moche et qu&#8217;on a du pain sur<br />
la planche. Ziva !</p>
<h2>Un accès plus facile à la propriété <sup>partie 2</sup></h2>
<p>Les propriétés de style décrites plus haut sont décrites dans <a href="http://live.gnome.org/GnomeArt/Tutorials/GtkThemes/StyleProperties#head-3a5d28200bc5dd48a13534b1a8da0907fbde9a6c">une<br />
liste</a> super sympa.</p>
<p>Il y a un autre genre de propriétés à spécifier, elles s&#8217;appliquent au<br />
style dans lesquelles elles sont et n&#8217;ont pas besoin de préfixe du genre<br />
<code>NomDeClasse::</code>. Nous allons en voir plein, mais on peut déjà<br />
s&#8217;attarder sur quelques uns. <code>xthickness</code> et<br />
<code>ythickness</code> permettent par exemple de fixer l&#8217;espacement<br />
horizontal et vertical entre le contenu du widget et ses bords. Testons donc<br />
ce thème :</p>
<pre>style "styleParDefaut" {
    xthickness = 7
    ythickness = 7
}

class "GtkWidget" style "styleParDefaut"</pre>
<p>Un petit coup de <em>Actualiser</em> dans le Widget Factory vous montrera<br />
que tous les widgets sont énormes, ce qui est le défaut qu&#8217;on prête à GTK en<br />
général. Changez les 7 par des 1 et vous allez voir un thème tout compact.<br />
Évidemment, avec la face qu&#8217;ont les widgets de GTK lorsqu&#8217;ils sont tous nus,<br />
c&#8217;est pas beau à voir, et en plus ça bouffe les bordures. Mais vous savez que<br />
vous pouvez déjà contrôler un paramètre.</p>
<h2>Ajouter de la couleur</h2>
<p>On va bientôt pouvoir peinturlurer tous nos widgets en comprenant comment<br />
on leur rajoute des couleurs. C&#8217;est une ligne à mettre dans un style qui a<br />
cette tête-là :</p>
<pre>categorie[ETAT] = couleur</pre>
<p>Quelles sont les quatre catégories, les cinq états et les différentes<br />
manières de mettre une couleur ? J&#8217;ai regardé un peu la doc de GTK pour<br />
résumer tout ça&#8230;</p>
<h3>Catégories de couleurs</h3>
<dl>
<dt>fg</dt>
<dd>C&#8217;est la couleur du premier plan (foreground color) qui définit en<br />
général la couleur du texte des widgets d&#8217;affichage (menu, label,<br />
bouton&#8230;). Il paraît que c&#8217;est utilisé parfois pour contrôler la<br />
couleur de la bordure.</dd>
<dt>bg</dt>
<dd>C&#8217;est la couleur du fond des widgets d&#8217;affichage.</dd>
<dt>text</dt>
<dd>C&#8217;est la couleur de premier plan (de texte) des widgets d&#8217;entrée<br />
(liste, boîte d&#8217;entrée de texte, tout ce qui apparaît sur fond blanc<br />
dans Widget Factory quoi).</dd>
<dt>base</dt>
<dd>C&#8217;est la couleur de fond des widgets d&#8217;entrée.</dd>
</dl>
<h3>États des widgets</h3>
<dl>
<dt>NORMAL</dt>
<dd>C&#8217;est la couleur par défaut du widget dans une catégorie donnée.</dd>
<dt>PRELIGHT</dt>
<dd>C&#8217;est la couleur lorsque la souris pointe le widget (le<br />
<em>hover</em> en quelque sorte).</dd>
<dt>ACTIVE</dt>
<dd>C&#8217;est la couleur lorsque le bouton de la souris est enfoncé.</dd>
<dt>INSENSITIVE</dt>
<dd>C&#8217;est la couleur de l&#8217;état inactif (quand on ne peut pas utiliser<br />
l&#8217;élément).</dd>
</dl>
<h3>Couleur arbitraire</h3>
<p>On peut définir une couleur de manière arbitraire en la notant entre<br />
guillemets en notation hexadécimal. J&#8217;ai l&#8217;habitude de la noter comme tout le<br />
monde fait en CSS : <code>"#RRVVBB"</code>. On peut aussi utiliser un triplet<br />
de valeurs (en format <em>virgule flottante</em>, c&#8217;est-à-dire avec un point<br />
obligatoire qui fait office de virgule) de rouge, vert et bleu de ce style :<br />
<code>{1.0, 0.45, 0.3}</code>, c&#8217;est-à-dire des valeurs réelles entre<br />
<code>0.0</code> et <code>1.0</code>. Il y a d&#8217;autres manières de noter les<br />
couleurs, pour toute l&#8217;info allez voir les liens en fin de document.</p>
<h3>Couleur symbolique</h3>
<p>Il est possible, depuis GTK+ 2.10, d&#8217;utiliser des couleurs symboliques,<br />
c&#8217;est-à-dire des variables qui vont pouvoir servir plusieurs fois (il n&#8217;est<br />
alors pas nécessaire de changer toutes les occurences d&#8217;une couleur dans un<br />
thème, il suffit de changer la valeur de la couleur symbolique). On définit<br />
une couleur symbolique à l&#8217;intérieur d&#8217;un style de cette façon :</p>
<pre>color["nom_de_la_couleur_symbolique"] = "#0F1030"</pre>
<p>On peut alors l&#8217;utiliser, par exemple dans une ligne telle que :</p>
<pre>bg[NORMAL] = @nom_de_la_couleur_symbolique</pre>
<p>Malheureusement, c&#8217;est un peu pourri, comme manière de fonctionner : la<br />
couleur n&#8217;a pas d&#8217;existence en dehors du style. C&#8217;est une limitation que l&#8217;on<br />
peut néanmoins éviter grâce aux <em>color schemes</em>. C&#8217;est un truc qui<br />
permet de changer les couleurs du thème sans changer de thème : un truc pour<br />
personnaliser un thème à sa sauce. GNOME permet de modifier ces color schemes<br />
dans la fenêtre d&#8217;apparence. On définit le color scheme par défaut en dehors<br />
d&#8217;un style, en général au début, avec une propriété nommée<br />
<code>gtk_color_scheme</code> qui se joue comme ça :</p>
<pre>gtk_color_scheme = "color1:#001\ncolor2:Blue"</pre>
<p>On n&#8217;a pas le droit de mettre d&#8217;espaces et on sépare les définitions de<br />
couleurs de leur valeur par un <code>:</code>, tandis qu&#8217;on sépare les<br />
différentes définitions entre elles par un <code>\n</code>. J&#8217;ai chopé un<br />
exemple très bien dans la doc de GTK :</p>
<pre>gtk_color_scheme = "fg_color:#000\nbg_color:#ede9e3\nbase_color:#fff\ntext_color:#000\nselected_bg_color:#5598d7\nselected_fg_color:#fff"

style "default"
{
  fg[NORMAL]        = @fg_color
  fg[PRELIGHT]      = @fg_color
  fg[SELECTED]      = @selected_fg_color
  fg[ACTIVE]        = @fg_color
}
#(le thème n'est pas écrit complètement)</pre>
<p>On utilise donc les couleurs définies là-dedans avec un <code>@</code>.</p>
<h3>Opérations sur les couleurs</h3>
<p>On peut effectuer des opérations sur ces couleurs et même les faire en<br />
cascade :</p>
<dl>
<dt>mix(valeur, couleur1, couleur2)</dt>
<dd>Mélange <code>couleur1</code> et <code>couleur2</code> selon la<br />
proportion <code>valeur</code> (entre 0.0 et 1.0).</dd>
<dt>shade(valeur, couleur)</dt>
<dd>Change la luminosité et la saturation de <code>couleur</code> avec<br />
<code>valeur</code> (si c&#8217;est 1.0, ça change rien).</dd>
<dt>lighter(couleur)</dt>
<dd>C&#8217;est un raccourci vers <code>shade(1.3, couleur)</code>.</dd>
<dt>darker(couleur)</dt>
<dd>C&#8217;est un raccourci vers <code>shade(0.7, couleur)</code>.</dd>
</dl>
<p>Les couleurs symboliques avec lesquelles on travaille habituellement sont<br />
celles qu&#8217;utilise GNOME pour ses <em>color schemes</em> personnalisés. Il est<br />
recommandé de les suivre. Il s&#8217;agit de <code>fg_color</code>,<br />
<code>bg_color</code>, <code>base_color</code>, <code>text_color</code>,<br />
<code>selected_bg_color</code>, <code>selected_fg_color</code>,<br />
<code>tooltip_bg_color</code> et <code>tooltip_fg_color</code>. Leur<br />
signification tombe sous le sens.</p>
<h2>Un pour le style, deux pour le spectacle</h2>
<p>Maintenant qu&#8217;on sait ajouter des couleurs, des propriétés de style très<br />
spécifiques et des couleurs dans tous les sens, nous allons approfondir un<br />
point que nous avons un peu délaissé. On sait donc créer des styles, qui sont<br />
des regroupements de propriétés. Il faut maintenant les appliquer à des<br />
widgets. Pour cela on a trois choix.</p>
<h3>Application à une classe</h3>
<p>On a déjà rencontré la directive <code>class</code> plus haut, par exemple<br />
dans :</p>
<pre>class "GtkWidget" style "styleParDefaut"</pre>
<p>Ici, on applique à la classe <code>GtkWidget</code> (c&#8217;est-à-dire à tous<br />
les widgets) le style <code>styleParDefaut</code>. On peut utiliser<br />
<code>*</code> dans le nom de classe pour spécifier &laquo;&nbsp;ce que tu veux&nbsp;&raquo; et<br />
<code>?</code> pour &laquo;&nbsp;le caractère que tu veux. La doc donne l&#8217;exemple de<br />
<code>"Gt?T*"</code> qui va convenir pour <code>GtkToggleButton</code>. Donc<br />
si on avait :</p>
<pre>class "Gt?T*B*n" style "style1"</pre>
<p>Alors <code>style1</code> s&#8217;appliquerait à <code>GtkToggleButton</code><br />
(et à d&#8217;autres classes qui remplissent le critère).</p>
<h3>Application à des imbrications de widgets ou à un widget particulier</h3>
<p>On va voir la directive <code>widget_class</code> qui fait la même chose<br />
que <code>class</code> sauf qu&#8217;on ne sélectionne pas les classes de la même<br />
façon. Ici on regarde l&#8217;imbrication des widgets les uns dans les autres. Par<br />
exemple, si j&#8217;ai une fenêtre dans laquelle il y a un bouton, et que dans ce<br />
bouton il y a une étiquette de texte, alors comment pourrais-je appliquer un<br />
style uniquement à l&#8217;étiquette de texte ? On regarde ce que la doc appelle le<br />
<em>Classpath</em> du widget. Celui de la fenêtre est :<br />
<code>GtkWindow</code>. Celui du bouton dans la fenêtre est :<br />
<code>GtkWidget.GtkButton</code>, et celui de l&#8217;étiquette de texte dans le<br />
bouton est : <code>GtkWidget.GtkButton.GtkLabel</code>. Avec<br />
<code>widget_class</code>, on peut utiliser <code>*</code> pour dire &laquo;&nbsp;tous<br />
les genres de classes&nbsp;&raquo; et des <code>.</code> comme séparateurs. On peut donc<br />
trouver notre étiquette de texte par la chaîne de caractères<br />
<code>"*.GtkButton.*"</code>, mais aussi par<br />
<code>"*.GtkButton.GtkLabel"</code>. Si l&#8217;on veut maintenant trouver non<br />
seulement <code>GtkWidget.GtkButton.GtkLabel</code> mais aussi<br />
<code>GtkWidget.GtkToggleButton.GtkLabel</code>, ça va pas marcher comme ça<br />
en claquant des doigts. Au lieu d&#8217;utiliser <code>"*.GtkButton.*"</code>, on<br />
va utiliser <code>"*.&lt;GtkButton&gt;.*"</code>. GTK va prendre, en seconde<br />
position, un <code>GtkButton</code> ou toute classe héritée, donc par exemple<br />
un <code>GtkToggleButton</code>. Un petit exemple :</p>
<pre>widget_class "*.&lt;GtkButton&gt;.*" style "contenu-bouton"</pre>
<p>Notons que <code>*</code> ou <code>?</code>, s&#8217;ils remplacent un ou<br />
plusieurs caractères, peuvent aussi remplacer des caractères <code>.</code>.<br />
Je m&#8217;explique : <code>"GtkW*n"</code> pourra reconnaître<br />
<code>GtkWidget.GtkButton</code> aussi !</p>
<p>Vous pouvez aussi <code>widget</code> au lieu de<br />
<code>widget_class</code>. Vous pourrez prendre un nom de widget bien défini<br />
dans le classpath.</p>
<h3>Ordre des assignations de style</h3>
<p>Lorsque plusieurs assignations de style peuvent recouvrir un même widget,<br />
on a souvent affaire à des conflits : quel style sera appliqué en premier,<br />
qu&#8217;est ce que ça va donner à la fin ? De plus, certains widgets ne peuvent<br />
pas être modifiés comme ça et on peut mettre des priorités aux assignations<br />
de style. Pour plus d&#8217;infos, je vous renvoie à la doc de GNOME.</p>
<h2>Polices ! Vos papiers !</h2>
<p>Je vous renvoie à mon <a href="http://joinwww.wordpress.com/2008/10/20/des-polices-des-themes-gtkdes-polices-des-themes-gtk/">nouvel article sur les polices</a> pour vous aider un peu.</p>
<h2>Moteurs !</h2>
<p>Super, join vous a appris à faire des thèmes avec des couleurs partout,<br />
mais il y a un problème : comment on change ces widgets en 3D au look de<br />
W?nd?ws 95 ?</p>
<p>Héhé&#8230; Je ne sais pas&#8230; Allez, je crache le morceau : vous avez très<br />
probablement déjà installé (même sans le savoir) des <em>theme engines</em>,<br />
c&#8217;est-à-dire des moteurs de thèmes qui permettent de dessiner des widgets<br />
complexes grâce à des images ou en vectoriel. Le thème par défaut sous GNOME<br />
utilise un moteur de thème du même nom : il est grand, il est beau, c&#8217;est<br />
<strong>Clearlooks</strong> ! Il en existe des autres, beaucoup d&#8217;autres, et<br />
il y a pas mal de paramètres pour chaque moteur.</p>
<p>On utilise un moteur <strong>à l&#8217;intérieur d&#8217;un style</strong>, ce qui<br />
veut dire qu&#8217;on peut tout mélanger dans tous les sens : un bout de Clearlooks<br />
par ci, un bout d&#8217;Aurora par là&#8230;</p>
<p>Comment on fait ça ? La syntaxe est simple :</p>
<pre>engine "nom_de_l'engine_en_minuscules" {
    # propriétés du moteur
}</pre>
<p>Vous avez droit à une liste d&#8217;engines (et peut-être leurs propriétés) <a href="http://live.gnome.org/GnomeArt/Tutorials/GtkEngines">sur le site de<br />
GNOME</a>.</p>
<h2>Inclusion de thèmes</h2>
<p>Avant de commencer à voir des exemples et des cas particuliers, je tiens à<br />
revenir sur un point : je parlais tout à l&#8217;heure de séparer le thème en<br />
plusieurs fichiers <code>rc</code>. Ça peut être pratique pour ne pas<br />
s&#8217;embrouiller dans les thèmes, ou alors de faire plusieurs versions du même<br />
thème sans tout réécrire. On utilise la directive globale<br />
<code>include</code> et on la met à la place où on voudrait que le fichier<br />
soit inclus :</p>
<pre>include "fichier"</pre>
<h2>Exemple : du Clearlooks !</h2>
<p>On va choisir une palette de couleurs et appliquer un moteur Clearlooks<br />
dessus. Vous devriez déjà avoir ce moteur dans votre distribution, si elle<br />
n&#8217;est pas trop vieille, et sinon il ne doit pas être difficile à trouver.</p>
<h3>Choix des couleurs</h3>
<p>Pour ce premier thème, je veux cette palette de couleurs :<a href="http://joinwww.files.wordpress.com/2008/10/couleurs.png"><img class="aligncenter size-full wp-image-16" title="Des couleurs" src="http://joinwww.files.wordpress.com/2008/10/couleurs.png?w=200&#038;h=114" alt="" width="200" height="114" /></a></p>
<p>On va déjà penser à fabriquer la ligne qui donne le ton de couleurs par<br />
défaut :</p>
<pre>gtk_color_scheme = "fg_color:#2e3436\nbg_color:#d1c7b4\nbase_color:#ede3d0\ntext_color:#000000\nselected_bg_color:#d1c7b4\nselected_fg_color:#2b64a8\ntooltip_bg_color:#b8a587\ntooltip_fg_color:#000"</pre>
<p>Maintenant qu&#8217;on a cette ligne on peut assigner à un style par défaut les<br />
couleurs ainsi choisies. Vous pouvez utiliser les lignes ci-dessous comme<br />
modèle pour vos futures compositions. Ce sont les lignes de couleurs par<br />
défaut du thème Clearlooks.</p>
<pre>fg[NORMAL]        = @fg_color
fg[PRELIGHT]      = @fg_color
fg[SELECTED]      = @selected_fg_color
fg[ACTIVE]        = @fg_color
fg[INSENSITIVE]   = darker (@bg_color)

bg[NORMAL]        = @bg_color
bg[PRELIGHT]      = shade (1.02, @bg_color)
bg[SELECTED]      = @selected_bg_color
bg[INSENSITIVE]   = @bg_color
bg[ACTIVE]        = shade (0.9, @bg_color)

base[NORMAL]      = @base_color
base[PRELIGHT]    = shade (0.95, @bg_color)
base[ACTIVE]      = shade (0.9, @selected_bg_color)
base[SELECTED]    = @selected_bg_color
base[INSENSITIVE] = @bg_color

text[NORMAL]      = @text_color
text[PRELIGHT]    = @text_color
text[ACTIVE]      = @selected_fg_color
text[SELECTED]    = @selected_fg_color
text[INSENSITIVE] = darker (@bg_color)</pre>
<p>Vous pouvez remarquer que des effets sont déjà appliqués sur les<br />
<code>PRELIGHT</code>, les <code>ACTIVE</code> et les<br />
<code>INSENSITIVE</code>. On peut bien sûr changer ces effets à volonté.</p>
<p>Vous allez remarquer que nous aurons à rajouter des directives de couleurs<br />
pour des endroits particuliers, car certains widgets n&#8217;utilisent pas les<br />
couleurs comme d&#8217;autres.</p>
<h3>Configuration du moteur Clearlooks</h3>
<p>Nous allons utiliser le moteur Clearlooks. Il nous faut un peu de<br />
documentation. Pour l&#8217;obtenir, on peut regarder sur <a><br />
href=&nbsp;&raquo;http://live.gnome.org/GnomeArt/Clearlooks&nbsp;&raquo;&gt;le site de GNOME</a> où les<br />
explications sont claires mais peu nombreuses, et en éditant le thème par<br />
défaut Clearlooks, par exemple, qui se trouve sur mon système à<br />
<code>/usr/share/themes/Clearlooks/gtk-2.0/gtkrc</code>. On peut bidouiller<br />
pour configurer le thème comme on le veut. Ici j&#8217;ai choisi quelques<br />
paramètres sympas :</p>
<pre>engine "clearlooks" {
    style = GUMMY
    radius = 3.5
    contrast = 1.0
    scrollbar_color = @selected_bg_color
    menubarstyle = 1
    animation = TRUE
}</pre>
<p>Moi, je trouve ça bien.</p>
<h3>Configuration par défaut des widgets</h3>
<p>On va changer deux ou trois petites choses qu&#8217;on peut mettre dans le style<br />
par défaut.</p>
<p>Déjà, on va faire en sorte que le contenu des boutons ne se décale pas<br />
lorsqu&#8217;on laisse la souris appuyée dessus.</p>
<pre>GtkButton::child-displacement-x = 0
GtkButton::child-displacement-y = 0</pre>
<p>Voilà. On en a fini avec le style par défaut. On l&#8217;appellera<br />
<code>base</code> et on l&#8217;assignera à tous les widgets par la sentence :</p>
<pre>class "GtkWidget" style "base"</pre>
<h3>Un petit truc</h3>
<p>On va faire comme 80% des thèmes GTK. Il faut créer des styles avec<br />
différentes valeurs pour <code>xthickness</code> et <code>ythickness</code><br />
afin de pouvoir les appliquer simplement aux widgets que l&#8217;on veut, et ce<br />
pour factoriser des paramètres.</p>
<pre>style "small" {
    xthickness = 1
    ythickness = 1
}

style "medium" {
    xthickness = 2
    ythickness = 2
}

style "large" {
    xthickness = 3
    ythickness = 3
}

style "xlarge" {
    xthickness = 4
    ythickness = 4
}</pre>
<p>Il y en a peut-être trop, mais tout dépend de ce qu&#8217;on va utiliser.</p>
<h3>Boutons</h3>
<p>On va personnaliser les boutons en leur mettant une police et en réduisant<br />
leur place sur l&#8217;écran.</p>
<pre>style "bouton" = "medium" {
    GtkButton::inner-border = {0, 0, 0, 0}
    font_name = "Arial 8"
}</pre>
<p>On applique maintenant le style aux boutons et aux textes dans les<br />
boutons. On utilise <code>widget_class</code> et non pas <code>class</code><br />
pour des raisons que l&#8217;expérience vous montrera&#8230;</p>
<pre>widget_class "*&lt;GtkButton&gt;*" style "bouton"</pre>
<h3>Menus</h3>
<p>Les textes des menus qui sont sélectionnés par la souris sont en noir sur<br />
fond bleu, c&#8217;est moche ! Mettons une couleur un peu plus pétante et<br />
élargissons un peut tout ça en faisant hériter le style du style<br />
<code>large</code> :</p>
<pre>style "menuitem" = "large" {
     fg[PRELIGHT] = lighter(@selected_fg_color)
}</pre>
<p>On applique le style façon porc :</p>
<pre>widget_class "*GtkMenu*" style "menuitem"</pre>
<h3>Zones d&#8217;édition</h3>
<p>Si on lance TWF avec notre thème, on s&#8217;aperçoit de deux choses :</p>
<ol>
<li>Il est moche</li>
<li>Les zones d&#8217;édition empiètent sur leurs bordures</li>
</ol>
<p>Hé oui, une zone d&#8217;édition est un rectangle, il lui faut un peu de place.<br />
Heureusement on peut prévoir extra-large :</p>
<pre>widget_class "*&lt;GtkEntry&gt;*" style "xlarge"</pre>
<h3>Le thème en entier</h3>
<p>Tout notre thème est contenu dans <a href="http://nopaste.info/ac3a00c645.html">ces lignes</a>. A vous de rendre<br />
ce thème beau, en utilisant toutes les ressources que vous aurez accumulées<br />
tout au long de cet article.</p>
<h2>Moralité</h2>
<p>On voit quand même que le CSS et ses sélecteurs, c&#8217;est pas si mal foutu<br />
que ça ! Je pense qu&#8217;il faudrait à GTK un parseur de thèmes plus flexible sur<br />
la syntaxe et beaucoup plus de variables. Par exemple, il serait bien de<br />
pouvoir spécifier uniquement la taille de la police d&#8217;un élément dans un<br />
style. Bref, à l&#8217;heure où aucun outil graphique ne facilite la mise en place<br />
de thèmes GTK, surtout quand on sait que le travail ne serait pas beaucoup<br />
facilité, il est nécessaire de se faire la main sur des thèmes déjà faits en<br />
comprenant les quelques règles qui ont été expliquées ici afin d&#8217;arriver à<br />
ses fins. Je ne pense pas que la création de thèmes soit sans limite à<br />
l&#8217;heure actuelle, mais en combinant toutes les bidouilles, il est possible<br />
d&#8217;arriver à quelque chose de fort sympathique et qui convient à tous les<br />
besoins. Force est de constater que dans de nombreux thèmes qui tournent très<br />
bien, une bonne part est réservée aux <em>hacks</em>, c&#8217;est-à-dire aux<br />
petites corrections d&#8217;apparence spécifiques à un seul logiciel (Evolution a<br />
donné du fil à retordre à beaucoup d&#8217;artistes, me semble-t-il).</p>
<p>Si toutefois vous aimez les bonnes nouvelles, alors tendez vos oreilles&#8230; Il paraît qu&#8217;un moteur GTK va sortir et permettra la description de thèmes en CSS. Je vous invite à <a href="http://blogs.gnome.org/theming/2008/10/01/announce-gtk-css-engine-02-available/">lire cet article</a> et à suivre régulièrement l&#8217;affaire !</p>
<p>J&#8217;espère avoir été assez clair pour permettre à des gens de s&#8217;affranchir<br />
des docs en anglais qui existent sur le sujet, et en avant pour un prochain<br />
post !</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/joinwww.wordpress.com/15/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/joinwww.wordpress.com/15/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/joinwww.wordpress.com/15/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/joinwww.wordpress.com/15/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/joinwww.wordpress.com/15/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/joinwww.wordpress.com/15/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/joinwww.wordpress.com/15/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/joinwww.wordpress.com/15/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/joinwww.wordpress.com/15/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/joinwww.wordpress.com/15/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/joinwww.wordpress.com/15/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/joinwww.wordpress.com/15/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/joinwww.wordpress.com/15/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/joinwww.wordpress.com/15/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=joinwww.wordpress.com&amp;blog=4998056&amp;post=15&amp;subd=joinwww&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://joinwww.wordpress.com/2008/10/12/de-lesprit-des-themes-gtk/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">join</media:title>
		</media:content>

		<media:content url="http://joinwww.files.wordpress.com/2008/10/couleurs.png" medium="image">
			<media:title type="html">Des couleurs</media:title>
		</media:content>
	</item>
		<item>
		<title>Gérer la position de contenus ajoutés en CSS</title>
		<link>http://joinwww.wordpress.com/2008/09/29/position-before-css/</link>
		<comments>http://joinwww.wordpress.com/2008/09/29/position-before-css/#comments</comments>
		<pubDate>Mon, 29 Sep 2008 20:11:26 +0000</pubDate>
		<dc:creator>join</dc:creator>
				<category><![CDATA[Webdesign]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[xhtml]]></category>

		<guid isPermaLink="false">http://joinwww.wordpress.com/?p=6</guid>
		<description><![CDATA[J&#8217;étais tranquillement en train de développer un site lorsque j&#8217;eus besoin d&#8217;utiliser les pseudo-éléments :before et :after en CSS. Pour rappel, ces pseudo-éléments permettent en général d&#8217;ajouter du contenu avant ou après n&#8217;importe quelle balise de cette façon : .classeDeLElement:before { content: "Madame la Marquise a dit : "; } Ce contenu a la fâcheuse [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=joinwww.wordpress.com&amp;blog=4998056&amp;post=6&amp;subd=joinwww&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>J&#8217;étais tranquillement en train de développer un site lorsque j&#8217;eus besoin d&#8217;utiliser les pseudo-éléments <code>:before</code> et <code>:after</code> en CSS. Pour rappel, ces pseudo-éléments permettent en général d&#8217;ajouter du contenu avant ou après n&#8217;importe quelle balise de cette façon :</p>
<blockquote><p><code>.classeDeLElement:before {</code></p>
<p style="padding-left:30px;"><code>content: "Madame la Marquise a dit : ";</code></p>
<p><code>}</code></p></blockquote>
<p>Ce contenu a la fâcheuse tendance à ne pas accepter de HTML, ce qui ne laisse pas libre cours à toutes les folies non validées par le W3C. Il est tout de même possible de faire des choses assez rigolotes comme rajouter une image, mettre un compteur qui s&#8217;incrémente (pour pouvoir faire de la numérotation, par exemple).<span id="more-6"></span></p>
<p>On peut tout mettre en même temps comme ceci :</p>
<blockquote><p><code>.classeDeLElement:before {</code></p>
<p style="padding-left:30px;"><code>content: url('images/icone.png') counter(compteur1);</code></p>
<p style="padding-left:30px;"><code>padding-right: 5px; /* éloigner le rajout de 5 pixels */<br />
</code></p>
<p><code>}</code></p></blockquote>
<p>Ainsi, on peut jouer avec quelque chose d&#8217;intéressant, qui peut nous donner une belle image et être repositionnée par rapport au contenu de la balise concernée. En réalité, il y a un problème, c&#8217;est qu&#8217;une image n&#8217;est pas toujours forcément bien alignée avec le texte. On peut croire être sorti(e) d&#8217;affaire en utilisant un coup de padding, mais la propriété CSS <code>padding-bottom</code> ne marche pas avec les pseudo-éléments <code>before</code> et <code>after</code>, du moins avec Gecko&#8230; Et on ne va pas mettre une balise <code>img</code> en plein dans notre code HTML, ça serait blasphématoire pour le principe de séparation du contenu et de la présentation (en admettant que les petites images qu&#8217;on mettra avant ou après ces balises sont des trucs uniquement tape-à-l&#8217;oeil, comme des petits points d&#8217;interrogation ou des petites icônes sympa, et non pas des images porteuses de contenu). Ce qu&#8217;il y a de pratique avec ce genre de balises <code>img</code> c&#8217;est la possibilité d&#8217;aligner verticalement l&#8217;image au contenu textuel l&#8217;englobant directement avec un paramètre de la balise, en bourrinant avec du HTML dont la conformité aux standards actuels émet plus que l&#8217;ombre d&#8217;un doute. Comment remplacer cette fonctionnalité en utilisant des <code>:before</code> ou des <code>:after</code> ?</p>
<p>J&#8217;ai cherché çà-et-là sur toute une tripotée de sites et pas un seul site n&#8217;a été foutu de cracher le morceau sur cette histoire. En attendant de réviser mes compétences en recherche sur goo &#8211; le &#8211; site &#8211; le &#8211; presque &#8211; plus &#8211; vu &#8211; au &#8211; monde &#8211; et &#8211; dont &#8211; les &#8211; possesseurs &#8211; seront &#8211; bientôt &#8211; les &#8211; maîtres &#8211; du &#8211; monde &#8211; gle, j&#8217;ai décidé de me mettre à bidouiller. J&#8217;ai utilisé la super astuce de la balise <code>&lt;span&gt;</code> qui arrange tous les problèmes (aussi vue dans l&#8217;affaire du remplacement de texte par une image en CSS). Je n&#8217;ai pas le temps ni l&#8217;envie de voir le résultat dans IE mais si un(e) internaute courageux/se veut se proposer, qu&#8217;il/elle se montre !</p>
<p>Voilà la marche à suivre. Ici, on a le code HTML :</p>
<blockquote><p><code>&lt;div class="faireattention"&gt;Il faut suivre la recette à la lettre !&lt;/div&gt;</code></p></blockquote>
<p>Et le CSS :</p>
<blockquote><p><code>div.faireattention {</code></p>
<p style="padding-left:30px;"><code>/* tout un tas de propriétés chouettes */</code></p>
<p><code><br />
}</code><br />
<code><br />
div.faireattention:before {</code></p>
<p style="padding-left:30px;"><code>content: url("images/attention.png") "&gt; ";</code></p>
<p><code>}</code></p></blockquote>
<p>Alors, ça marche pas ? C&#8217;est normal, il faut procéder aux changements suivants. Revoilà le bon HTML :</p>
<blockquote><p><code>&lt;div class="faireattention"&gt;&lt;span&gt;&lt;/span&gt;Il faut suivre la recette à la lettre !&lt;/div&gt;</code></p></blockquote>
<p>Et le bon CSS :</p>
<blockquote><p><code>div.faireattention { /* ... */ }</code></p>
<p><code>div.faireattention &gt; span {</code></p>
<p style="padding-left:30px;"><code>position: relative;</code></p>
<p style="padding-left:30px;"><code>top: 3px; /* baisse l'image de 3 pixels */</code></p>
<p><code><br />
}</code></p>
<p><code>div.faireattention &gt; span:after {</code></p>
<p style="padding-left:30px;"><code>content: url("images/attention.png") "&gt; ";</code></p>
<p><code>}</code></p></blockquote>
<p>Ca donne à peu près ça :</p>
<div id="attachment_12" class="wp-caption aligncenter" style="width: 505px"><a href="http://joinwww.files.wordpress.com/2008/10/position_before_css.png"><img class="size-full wp-image-12" title="position_before_css" src="http://joinwww.files.wordpress.com/2008/10/position_before_css.png?w=495&#038;h=207" alt="Aperçu sympa" width="495" height="207" /></a><p class="wp-caption-text">Aperçu sympa</p></div>
<p>Comme on peut le remarquer, il y a tout de même un problème de fond : qu&#8217;on mette un after ou un before, ça revient au même. En plus de pourrir notre HTML, on perd en flexibilité dans le CSS (&laquo;&nbsp;quoi ? le mec il nous donne des astuces et après il dit qu&#8217;elles sont pourries !&nbsp;&raquo;).</p>
<p>Néanmoins, il ne faut pas s&#8217;inquiéter, ça conviendra dans une grande partie des cas et si quelqu&#8217;un a une meilleure solution, qu&#8217;il vienne la faire partager !</p>
<p>Vous avez droit aussi au code de la <a href="http://pastebin.com/f52fbee44">page d&#8217;exemple</a> qui vous révèlera que cette astuce malhonnête de positionnement a des répercussions sur le placement des <code>div</code> qu&#8217;on voit leurs bordures. C&#8217;pas ben grave.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/joinwww.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/joinwww.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/joinwww.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/joinwww.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/joinwww.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/joinwww.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/joinwww.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/joinwww.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/joinwww.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/joinwww.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/joinwww.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/joinwww.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/joinwww.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/joinwww.wordpress.com/6/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=joinwww.wordpress.com&amp;blog=4998056&amp;post=6&amp;subd=joinwww&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://joinwww.wordpress.com/2008/09/29/position-before-css/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">join</media:title>
		</media:content>

		<media:content url="http://joinwww.files.wordpress.com/2008/10/position_before_css.png" medium="image">
			<media:title type="html">position_before_css</media:title>
		</media:content>
	</item>
	</channel>
</rss>
