File: scripter-extensions.html

package info (click to toggle)
scribus-doc 1.5.6.1%2Bdfsg-1
  • links: PTS, VCS
  • area: non-free
  • in suites: bullseye
  • size: 59,640 kB
  • sloc: xml: 767; python: 157; makefile: 14
file content (232 lines) | stat: -rw-r--r-- 18,613 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
<html>
<head>
    	<title>Scripteur : scripts d'extension</title>
</head>
<body>
</head>
<body>

<h2>Scripteur : scripts d'extension</h2>

<p>Auteur : Craig Ringer</p>

<p>L'extension Python de Scribus offre des caractristiques additionnelles permettant de doter l'application de nouvelles fonctionnalits,plut&ocirc;t que d'automatiser des tches. En particulier, il est possible d'utiliser des 'scripts d'extension' pour crer de nouvelles palettes et des fentres encastrables qui peuvent tre utilises comme si elles faisaient partie de Scribus.</p>

<h3>Scripts d'extension</h3>

<p>Les scripts d'extension ressemblent beaucoup aux scripts Python normaux de Scribus.
Ils comportent quelques variantes pour pouvoir tre
lancs avec la caractristique "script d'extension", qui leur donne
accs au support PyQt et  d'autres caractristiques spciales du
scripteur. Les diffrences les plus importantes entre les scripts normaux et les scripts d'extensions sont les suiantes :
</p>

<ul>

	<li>Les scripts d'extension peuvent crer des objets Python qui continuent d'exister aprs la fin de l'excution du script. Les objets continueront d'exister seulement s'ils sont rfrencs, la plupart du temps parce qu'ils sont associs  une entre dans l'espace de noms global. Cela signifie que les fonctions Python peuvent tre appeles par Scribus; par exemple : insertion PyQt ou encore fonction de rappel sur vnement.</li>

	<li>Les scripts d'extension peuvent crer du code qui fonctionne sans bloquer l'excution de Scribus, vous pouvez donc crer des palettes flottantes qui sont prsentes pendant que l'utilisateur travaille normalement avec Scribus (c'est--dire des palettes non modales).</li>

	<li>PyQt fonctionne correctement dans les scripts d'extension, contrairement  son comportement avec les scripts normaux.</li>

	<li>Les scripts d'extension peuvent effectuer des changements  l'environnement Python, lesquels affecteront les scripts conscutifs. Les modules imports par un script peuvent tre vus par un autre script, les paramtres changs par l'un restent changs, etc. Conclusion : vous devez crire vos scripts d'extension avec vigilance. En particulier, les noms globaux lis  un script d'extension peuvent tre modifis par un autre script, de telle sorte que l'objet associ  ces noms risque d'tre libr par l'interprteur. En d'autes mots, avec les scripts d'extension, vous pouvez rencontrer des conflits et des interactions qui n'existent pas dans les scripts normaux.</li>

</ul>

<h4>Le volet technique</h4>

<p>Les scripts normaux sont lancs dans un nouveau sous-interprteur Python qui est utilis exclusivement pour ce script et se trouve ensuite libr. Cela signifie que, quels que soient les objets Python qu'ils crent ou les paramtres qu'ils modifient, ces changements sont automatiquement annuls lorsque le script se termine. Parce que Scribus prend soin de librer votre script, vous n'avez pas  vous proccuper de la mmoire ni
des conflits avec d'autres scripts, etc., et vous pouvez vous concentrer sur l'criture des instructions.</p>

<p>Les scripts d'extension, par contre, s'excutent dans un seul interprteur Python qui dmarre au chargement du module de gestion des extensions. Cet
interprteur continue  tourner jusqu' ce que le script qui gre les extensions soit dsactiv  la fermeture de Scribus. Quand Scribus excute un script d'extension, il le charge dans l'interprteur courant - un peu comme <code>execfile</code> charge un script Python dans un autre script Python. Ainsi, les scripts d'extension peuvent crer de nouveaux objets au cours de leur excution puis terminer et redonner le contr&ocirc;le  Scribus sans que objets qu'ils ont crs ne soient dtruits. Si un autre script s'excute alors, il peut voir les objets crs par le premier script.</p>

<p>Il y a plusieurs situations o&ugrave; il est utile de crer des objets Python qui subsistent aprs le script. Le cas le plus pertinent rside dans la programmation graphique avec PyQt, o&ugrave; les objets PyQt sont crs au dmarrage du script et ne deviennent oprationnels que lorsque le script termine, retournant le contr&ocirc;le  la boucle vnementielle de Scribus. Autres cas de figure : les macros, les vnements de rappel et les temporisateurs, o&ugrave; Scribus doit pouvoir appeler le code Python. Vous pouvez raliser ces fonctions ds maintenant avec PyQt, mais il n'existe pas encore de support direct pour les temporisateurs et les rappels dans Scribus.</p>

<p>Voici quelques inconvnients des objets persistants aprs la fin du script.
Les scripts interagissent parfois d'une manire imprvue par l'auteur, ce qui donne des rsultats souvent intressants mais cause aussi des bogues inattendus et tonnants. Les auteurs de scripts doivent par ailleurs considrer l'effet de leur code sur la consommation de la mmoire de Scribus.<p>

<h4>Construire des ajouts graphiques dans Python </h4>

<p>Construire de nouvelles palettes et dialogues dans PyQt constitue un moyen simple d'enrichir l'interface utilisateur de Scribus et de fournir des fonctionnalits supplmentaires pour les scripts avancs. Python
est bien adapt aux entres et sorties  partir de bases de donnes, de systmes de gestion de contenu et d'autres rfrentiels externes; la capacit de btir des interfaces personnalises  cette fin peut s'avrer trs utile.</p>

<p>Dans la plupart des cas, PyQt fonctionne de la mme manire  l'intrieur de Scribus ou dans un interprteur Python autonome. Il y a cependant des diffrences, et il est important de les comprendre.</p>

<ul>

    <li>Une instance de <code>QApplication</code> existe dj, et le fait d'en crer une autre aura des consquences indsirables. Au besoin, vous pouvez
accder  l'instance de <code>QApplication</code> en tant que <code>qt.qApp</code>. </li>

    <li>Scribus excute la boucle d'vnements Qt. Le chargement de la boucle d'vnements Qt dans PyQt empchera probablement l'excution de Scribus jusqu' ce que votre code finisse de s'excuter et peut provoquer d'autres comportements tranges. Les explications suivantes dcrivent l'approche approprie pour intgrer votre code  la boucle d'vnements. En bref, il suffit de crer toutes vos instances, d'afficher vos fentres et de laisser votre script se terminer. Qt
intgrera automatiquement vos fentres dans la boucle d'vnements
et tout "fonctionnera", mme les insertions et les widgets Python. En gnral, tout ce que vous voulez conserver doit tre mis dans l'espace de noms global (comme expliqu ci-dessus). </li>

</ul>

<h4>Les bases - Convertir Hello World</h4>

<p>Le premier tutoriel est l'application classique Hello World. Pour montrer les diffrences entre PyQt et Scribus, nous convertirons le programme pour qu'il s'excute dans Scribus. Voici l'original :</p>

<pre>
#!/usr/bin/env python
import sys
import qt

a = qt.QApplication(sys.argv)

hello = qt.QPushButton("Hello world!", None)
hello.resize(100, 30)

a.setMainWidget(hello)
hello.show()
sys.exit(a.exec_loop())
</pre>

<p>Premirement, nous avons besoin de dsactiver la cration de <code>QApplication</code> puisque, dans Scribus, on trouve une instance de <code>QApplication</code> dj active; rappelez-vous qu'une seule instance est permise par application. PyQt nous fournit l'accs  <code>QApplication</code>, cr pralablement par Scribus au dmarrage en tant que <code>qt.qApp</code>. Donc, il suffit de remplacer :</p>

<pre>
a = qt.QApplication(sys.argv)
</pre>

<p>par</p>

<pre>
a = qt.qApp
</pre>

<p>et nous avons termin la modification.</p>

<p>Ensuite, nous devons empcher le script d'essayer d'excuter sa propre boucle d'vnements. Comme Scribus possde une boucle d'vnements, si le script dmarre la sienne, l'application sera perturbe jusqu' sa fermeture. Qt est assez fut pour associer toute fentre que vous crez  la boucle d'vnements exsitante; il n'y a donc pas grand chose  faire. Pendant l'excution du script, Scribus est sous le contr&ocirc;le de Python, de sorte qu'il nous suffit de raliser notre installation (dans ce cas, il s'agit de crer une fentre simple et de l'afficher), pour ensuite <i>laisser notre script se terminer</i> plut&ocirc;t que de dclencher la boucle d'vnements. Tous les scripts
d'extension s'excutent dans le mme interprteur Python, ce qui implique que les  objets crs par vos soins ne sont pas dtruits  la fin de l'excution. C'est un peu comme charger un module. Quand votre script se termine, Scribus prend le contr&ocirc;le et reprend l'excution de la boucle d'vnements de Qt. Comme
vos fentres sont des widgets Qt, la boucle d'vnements de Scribus les prend en charge, et elles deviennent une partie intgrante normale de Scribus. Quand une insertion Python est dclenche ou qu'une fonction Python est appele, PyQt se charge automatiquement de l'excution de la fonction Python et passe ensuite la main  Scribus.</p>

<p>Le seul hic de cette mthode est qu' la fin de votre script, tous les objets crs dans une fonction ou un domaine local seront librs par Python lorsque le domaine est abandonn (par exemple  la sortie de main()). Vous devez conserver une rfrence au niveau global pour viter que ces lments ne soient librs. Le support pour PyQt dans Scribus est trs rcent et il n'y a pas encore de mthode clairement dfinie comme "correcte" d'accomplir cela. Les options incluent :</p>

<ul>
    <li>La cration de tout ce que vous voulez conserver dans l'espace de noms global. Des prcautions sont de mise si votre script s'excute plusieurs fois.</li>

    <li>Le stockage d'objets que vous voulez conserver dans un dictionnaire ou une classe dans l'espace de noms global. La plupart des problmes sont identiques  ceux poss par le stockage d'objets directement en tant que noms globaux.</li>

    <li>Insertion de votre script dans un module, pour que le script lanc par l'utilisateur importe simplement le module et excute la fonction incluse. C'est l'approche que nous privilgions. Notez que le corps du module n'est pas recharg  chaque importation;
vous devez donc placer chaque fois le code  excuter dans une fonction du module plut&ocirc;t que dans le niveau principal du module. Ou encore, vous pouvez vrifier si le module est dj charg, pour utiliser reload() au lieu de l'importer de nouveau.</li>
</ul>

<p>Pour l'instant, parce que ce script cre dj tous les lments au niveau global, nous allons procder comme cela. Les scripts volumineux devraient tre crits comme des modules.</p>

<p>&Eacute;tant donn que les
objets dont nous avons besoin seront dj prsents lorsque le script se terminera, il nous suffit d'empcher l'entre dans la boucle d'vnements. C'est facile - mettez simplement en commentaire la dernire ligne :</p>

<pre>
# sys.exit(a.exec_loop())
</pre>

<p>et nous avons presque termin. Le script s'excutera maintenant correctement, mais,  la fermeture, il aura un effet non dsir -l'interruption de Scribus. Ce n'est probablement pas ce que vous voulez. Voil l'explication : normalement, une application Qt se termine lorsque son widget principal (fentre principale) se ferme. Nous
appelons <code>qt.setMainWidget(...)</code> pour transformer notre nouvelle fentre en fentre principale; donc,  la fermeture, Scribus s'interrompt aussi. Pour empcher cela, mettez simplement en commentaire <code>qt.setMainWidget</code>.</p>

<p>Le nouveau script ressemble  ceci :</p>

<pre>
#!/usr/bin/env python
import sys
import qt

a = qt.qApp

hello = qt.QPushButton("Hello world!", None)
hello.resize(100, 30)

#a.setMainWidget(hello)
hello.show()
#sys.exit(a.exec_loop())
</pre>

<p>Vous trouverez le script dj enregistr sous le nom <code>pyqt_tut1.py</code> dans le rpertoire 'examples' du scripteur. Essayez de l'excuter comme un script d'extension. Vous devriez obtenir un bouton 'hello world'. Notez que vous pouvez continuer  travailler dans Scribus comme  l'accoutume;  lorsque vous fermez la fentre 'hello world', elle dispara&icirc;t lgamment, sans incidence sur Scribus.</p>

<p>Si vous jetez un coup d'oeil  l'exemple de ce script tutoriel, vous remarquerez quelques ajouts. Ils sont accompagns de commentaires explicatifs et ne seront donc pas explors plus avant ici.</p>

<h4>Amusons-nous avec les noms globaux et les interprteurs partags </h4>

<p>Vous vous rappelez que j'ai mentionn plus t&ocirc;t certains 'problmes' concernant le stockage d'objets  conserver au niveauglobal ? &Eacute;videmment, j'ai pass sous silence quelque chose que je ne voulais pas expliquer  ce moment. </p>

<p>Le stockage d'objets en tant que noms globaux fonctionne bien... jusqu' ce que l'utilisateur excute votre script  nouveau, ou qu'il excute un autre script qui reprend les mmes noms.
Python utilise le comptage de rfrences : un objet continue d'exister tant qu'un ou plusieurs noms y font rfrence. Lorsqu'un nom global cr antrieurement est remplac par un autre script ou par une autre excution de votre script, il n'y a plus de rfrence  cet objet (peut-tre une fentre que l'utilisateur continue d'utiliser). Python fait son travail scrupuleusement et supprime l'objet pour vous, sans savoir s'il est                                                                                                                                      encore affich ou s'il s'agit d'un composant de votre fentre. Dans beaucoup de cas, une fentre dispara&icirc;t tout simplement, mais il peut y avoir des consquences plus ennuyeuses. </p>

<p>Essayez ceci. Excutez le script 'hello world' (en utilisant "Load Extension Script..."). Puis, sans fermer la fentre "Hello world", excutez le script  nouveau. La fentre originale devrait dispara&icirc;tre et tre remplace par la nouvelle.</p>

<p>Aucune solution idale n'est prvue pour ce problme, et tout dpend de ce que vous voulez faire exactement. J'aimerais donner des recommandations plus claires, mais chaque cas est diffrent. Si vous recontrez ce problme, entrez une description de votre projet sur la liste de diffusion de Scribus, et mes collgues ou moi-mme vous fourniront quelques suggestions.</p>

<p>La meilleure solution jusqu' prsent consiste  utiliser un script enveloppe pour excuter votre script et de placer votre script rel dans un module. Le script enveloppe importe votre module et excute une fonction du module pour afficher les fentres. Puisque le module est excut uniquement la premire fois qu'il est import, la(les) fentre(s) seront affiches si elles ne sont pas dj visibles, mais ne seront pas perturbes si elles sont dj affiches. Vous pouvez appeler reload() pour recharger le module si vous voulez vraiment le relancer, peut-tre aprs l'excution de code de nettoyage.</p>

<p>Les suggestions appropries sont bienvenues. N'hsitez pas  entrer vos questions et ides sur la liste de diffusion.</p>

<h4>Autres astuces</h4>

<p>Mme si vous ne btissez pas une interface graphique personnalise, il est possible d'utiliser les scripts d'extension. Par exemple, vous pouvez utiliser PyQt pour excuter une fonction temporise. Un autre usage pourrait tre de vrifier l'existence de mises  jour d'un article dans une base de donnes et d'inviter l'utilisateur  actualiser son document avec le nouveau texte (ou  constater les diffrences). Vous
trouverez un exemple trs simple de mise en place d'un temporisateur
avec PyQt dans le rpertoire d'exemples, appel <code>pyqt_timer.py</code>.</p>

<p>Une autre ide, suggre par un membre de la liste de
diffusion, tait d'crire un serveur XML-RPC pour exposer le
scripteur API  des programmes externes. Cette approche pourrait tre ralise  l'aide
des classes PyQt pour la mise en rseau et la gestion des
vnements.</p>

<h4>Autres sources d'information</h4>

<p>Le prsent document n'est pas un tutoriel PyQt ou Qt. Voici quelques
sources d'information fiables sur Qt et PyQt :
</p><ul>
	<li>Le tutoriel et les exemples PyQt  partir de la documentation PyQt </li>
	<li><a href="http://www.opendocs.org/pyqt/">Programmation graphique avec Python - &Eacute;dition Qt</a></li>
	<li><a href="http://doc.trolltech.com/">Documentation Qt de TrollTech (C++)</a></li>
	<li>Le
<a href="http://www.digitalfanatics.org/projects/qt_tutorial/"> tutoriel Qt indpendant</a></li>
	<li><a href="http://www.qtforum.org/">QtForum.org</a></li>
</ul>

<h3>Grer correctement l'excution hors Scribus </h3>

<pre>
Essayer ceci:
    import scribus
except ImportError:
    print "Ce script peut seulement s'excuter comme un script d'extension  partir de Scribus."
    sys.exit(1)
</pre>

<p>Cette squence essaie de charger l'interface de script de Scribus et, en cas
d'chec, suppose que celle-ci ne peut s'excuter sous Scribus. Veillez  placer ce message dans tous vos scripts pour ne pas
drouter les utilisateurs qui essaient de les excuter avec
l'interprteur Python autonome. Essayez d'excuter le script avec
<code>python pyqt_tut1.py</code>, et notez comment il signale son chec avant de fermer. C'est
beaucoup plus prcis qu'une erreur d'importation ou qu'un comportement bizarre.</p>

<h3>Questions sans rponse et caractristiques manquantes </h3>

<p>Le support pour tendre Scribus  partir de Python est
encore en chantier. Plusieurs composants fonctionnent
bien, mais il reste beaucoup  explorer.
Les ractions, suggestions, requtes, ides et offres d'aide
seront grandement apprcies et peuvent tre diriges vers la
liste de diffusion ou vers les auteurs du prsent document. </p>

<p>Notamment, il n'existe aucun support pour :
</p><ul>
	<li>L'utilisation de PyQt  partir de scripts normaux (par opposition aux scripts d'extension)</li>
	<li>L'utilisation de PyGtk ou de wxPython</li>
	<li>L'utilisation de threads (les threads PyQt peuvent
fonctionner dans les limites du support des threads de Qt)</li>
	<li>L'accrochage dans le menu activ par un clic droit (pas encore !)</li>
	<li>L'appel de scripts par certains vnements (dveloppement envisag) </li>
	<li>La connexion facile et fiable dans les menus </li>
	<li>L'extension des dialogues de Scribus </li>
	<li>L'utilisation de widgets et de classes personnaliss </li>
	<li>Toute approche consistant  passer le contr&ocirc;le  une boucle d'vnements sans retour de donnes (fonctionne mais bloque Scribus).</li>
</ul>

<p>Certains de ces lments ne sont pas encore implments, d'autres sont extrmement difficiles  grer; dans d'autres cas, nous sommes tout simplement dpourvus d'ides ou ne prvoyons pas d'essayer.</p>

</body>

</html>