Comment écrire une extension pour Scribus

Comment écrire une extension pour Scribus

Préface

La présente section vous montre comment écrire une extension pour Scribus. Les extensions sont des librairies qui sont chargées dans l'application principale au moment de l'exécution. Les extensions peuvent étendre, voire modifier le comportement de l'application sans nécessiter de réécriture ni de recompilation. Elles permettent d'ajouter des outils supplémentaires, de nouvelles fonctions d'importation et d'exportation, et plusieurs autres fonctionnalités évoluées.

Ce document présuppose une connaissance de base du langage C++. Vous devez savoir ce qu'est un fichier d'en-tête et comment fonctionne l'inclusion de fichier;aussi, vous devez posséder des connaissance sur l'héritage des classes et une certaine maîtrise du langage C++. La connaissance de Qt - principalement QString et QObject - sera également utile. Des questions comme les fonctions virtuelles et purement virtuelles, les déclarations "extern C", les détails de la gestion de mémoire, etc. sont éludées dans ce document. Vous n'avez pas à les connaître, mais elles pourraient vous aider à mieux suivre ce qui ce passe.

Nous n'allons pas tenter d'expliquer ici les détails du fonctionnement du système d'extensions de Scribus. Le présent document explique seulement comment écrire une extension. La documentation des texte d'aide scplugin.h et pluginmanager.h explique le fonctionnement du système.

Où puis-je trouver les extensions Scribus ?

Scribus est livré avec un certain nombre d'extensions standard. Celles-ci seront installées en même temps que le programme Scribus et ses autres fichiers. Sous UNIX, les extensions seront installées sous le même préfixe que l'application principale. Sous Mac OS X elles sont incluses avec l'application. Si vous voulez savoir ce que font ces extensions, le meilleur moyen de le découvrir est de démarrer Scribus et d'aller dans Fichier->Préférences puis de cliquer sur l'icône "extensions". À partir de là, vous obtiendrez une liste des extensions installées, des types d'extensions associés et des emplacements des fichiers.

En plus des extensions livrées en standard avec Scribus, il est possible de compiler et d'installer des extensions obtenues ailleurs, ou d'écrire et d'ajouter la vôtre.

Avant de commencer à coder

Supposons que vous avez eu une bonne idée pour améliorer Scribus et que vous êtes impatient d'écrire un code C++ de qualité. Patientez quelques minutes et lisez la présente section; vous pourriez gagner du temps et vous éviter des problèmes.

Important

Peut-être que vous êtes sur le point de "réinventer la roue", c'est-à-dire de ré-écrire ce que quelqu'un d'autre a déjà fait. Vous devriez vous joindre à la liste de diffusion et afficher votre idée, ou vous connecter au canal #scribus sur irc.freenode.net. Votre sujet sera soumis à l'étude, et vous obtiendrez probablement de l'aide et des idées des développeurs et des utilisateurs. Comme Scribus est distribué sous licence libre, vous pouvez travailler en solitaire, mais vous devriez au moins avoir une conversation d'introduction sur IRC ou envoyer un courriel à la liste de diffusion, ce qui pourrait vous éviter des heures de travail et des maux de tête. Nous voulons faciliter l'écriture d'extensions le plus possible pour les personnes intéressées.

Compatibilité

Scribus n'a pas une API fixe en C++ pour accommoder les extensions. Les versions ne sont pas compatibles en binaire, et les versions instables enfreignent souvent la compatibilité avec le code source. La compatibilité source n'est pas garantie actuellement, même entre des versions stables, lorsque des changements sont requis pour corriger un problème. Nous espérons redresser la situation dans l'avenir et fournir une API C++ stable pour le code externe. Pour l'instant, vous devez tenter d'intégrer l'essentiel de vos fonctionnalités dans un module séparé qui dépend le moins possible des rouages internes de Scribus.

Ce document traite de la mise en oeuvre d'une extension pour Scribus 1.3.1cvs. Les exigences sont radicalement différentes de celles des versions 1.2.x. Les changements futurs devraient être moins importants.

Il est peu pratique de prévoir l'écriture d'une extension pouvant fonctionner sous les versions 1.2.x et 1.3.x de Scribus.

Démarrage rapide

Il n'est pas trop difficile de se mettre à écrire une extension. La documentation ci-dessous décrit l'implantation d'une extension et vous renvoie à des compléments d'information au besoin. Un "modèle d'extension" vous est fourni, et vous pouvez en faire une copie au moment de débuter la programmation. Des instructions de base sont incluses dans le fichier et, en cas doute, vous pouvez consulter ce document.

Nous allons bâtir l'extension comme un composant de Scribus. C'est la manière la plus simple de commencer, même si vous prévoyez de la distribuer séparément plus tard (voir plus loin). Pour commencer à travailler sur une extension (de type Action) :

Vous êtes maintenant prêt à commencer à travailler sur votre extension. Premièrement, vous devez entrer des renseignements à propos de votre extension dans pluginname.cpp :

Vous avez terminé la mise en place de l'extension et vous pouvez maintenant commencer à programmer. Votre code doit être placé dans pluginnameimpl.cpp et pluginnameimpl.h. Le code existant devrait afficher une boîte de dialogue contenant un message.

Pour compiler l'extension, il suffit d'exécuter une nouvelle fois make -f Makefile.cvs, ./configure, et make dans le répertoire supérieur de Scribus. Une fois la compilation terminée, exécutez make install et démarrez Scribus. Votre extension doit maintenant figurer dans le gestionnaire d'extensions (dans les préférences) et doit être associée à un élément de menu. Si vous appuyez sur l'élément de menu, vous devriez obtenir une boîte de dialogue.

Bâtir les extension en dehors de la hiérarchie de Scribus

Utilisation rapide et directe de QMake

Avertissement

Attention, il est facile d'utiliser un projet qmake, mais il ne s'agit pas nécessairement de la méthode standard pour distribuer un logiciel sur une plateforme Linux. Le processus sert à titre d'exemple seulement, pour le développement. Quand vous créerez votre progiciel opérationnel, sans bogues, prenez le temps de préparer la distribution complète automagic (autoconf, automake) tel que décrit dans la prochaine section.

Compilons maintenant l'extension (ce n'est pas aussi simple que de taper gcc myplugin.cpp ;). Voici un procédé simple : qmake de Qt (parce que certaines personnes hésitent à utiliser autoconf et automake en raison de leur complexité). Nota : vous devrez créer un fichier vide config.h avant d'exécuter ces étapes.

#qmake -project

Maintenant que le fichier projet est créé, nous allons y apporter quelques petits changements.

######################################################################
# Automatically generated by qmake (1.06c) Sun Dec 14 13:32:11 2003
######################################################################

#change TEMPLATE = app. Nous ne travaillons pas sur l'application, seulement sur l'extension
TEMPLATE = lib
INCLUDEPATH += .
#Comme nous travaillons avec Scribus, nous avons besoin des inclusions de Scribus aussi.
INCLUDEPATH += /home/subzero/devel/Scribus/include/Scribus/
#Et Scribus doit utiliser freetype2.
#Donc nous devons le lier aussi. Utilisez les chemins retournés par
##freetype-config --cflags and --libs
INCLUDEPATH += /usr/include/freetype2
LIBS += -lfreetype -lz

# Entrée
#crée un fichier config.h vide
HEADERS += myplugin.h config.h
SOURCES += myplugin.cpp

Après ces changements, vous êtes prêt à compiler

#qmake
#make

Exécuter Qmake crée le Makefile et, en l'exécutant, vous compilez votre extension.

Ensuite : Copiez seulement les fichiers *so* dans le répertoire d'extensions de Scribus et lancez Scribus. Vous lirez "Do Nothing Plugin" dans le menu Extra.

Il est clair que vous devez utiliser une autre méthode pour distribuer votre code aux autres utilisateurs - certains utilisent les fichiers autogénérés qmake pro, d'autres, la combinaison autoconf/automake.

Distribuez-le! (autrement dit compilez-le! 2e édition)

Qmake est facile à utiliser et convient bien à un développement rapide, mais il y a une manière standard de compiler ou de distribuer un logiciel pour Linux, *BSD, etc. : autoconf et automake. Nous désignerons ces deux programmes sous l'acronyme automagic dans le texte qui suit.

Pour utiliser automagic avec succès, vous aurez besoin d'un pentagramme dessiné à la craie sur le sol et orienté au nord (Carrefour, 2€), d'un costume de diablotin rouge et noir (Hugo Boss, 2000€) et d'un pingouin sacrifié sur l'autel domestique (une heure de frayeur au zoo le plus proche). Ce n'était qu'une blague... ne faites pas de mal aux mignons pingouins, ce n'est pas nécessaire!!

Téléchargez l'exemple donothingplugin-1.0.tar.gz à partir de http://docs.scribus.net, décomprimez-le et parcourez son contenu.

Quand vous accédez au répertoire principal, vous apercevez beaucoup de fichiers et de répertoires. Attention : Ne changez rien dans le répertoire admin. Ce contenu vous est INTERDIT!

Puisque vous avez lu la documentation d'automagic (sûrement), vous savez que chaque répertoire de votre projet contient un fichier important appelé Makefile.am. Voici un court exemple commenté :

# indique où l'extension sera installée
pluginsdir = $(prefix)/lib/scribus/plugins
# spécifie les inclusions additionnelles pour la compilation
AM_CPPFLAGS = -I$(prefix)/include/scribus
# spécifie les répertoires à parcourir (avec les sous-niveaux) 
SUBDIRS = translation doc
# nom de l'extension = librairie
plugins_LTLIBRARIES = libscribusvlna.la
# join toutes les inclusions
INCLUDES = $(LIBFREETYPE_CFLAGS) $(all_includes)
# divers relatifs à la librairie - symlinks, etc.
libscribusvlna_la_LDFLAGS = -version-info 0:0:0
libscribusvlna_la_METASOURCES = AUTO
#
# liste des fichiers source de votre projet
libscribusvlna_la_SOURCES = frame.cpp selection.cpp vlnadialog.cpp vlnapage.cpp svlna.cpp
EXTRA_DIST = frame.cpp selection.cpp svlna.cpp vlnadialog.cpp vlnapage.cpp frame.h /
  selection.h svlna.h vlnadialog.h vlnapage$
# comment compiler
KDE_OPTIONS = qtonly
AM_LDFLAGS =    -s $(LIBFREETYPE_LIBS)

Pour récapituler : Si vous prenez le fichier donothingplugin-1.0.tar.gz (si vous le renommez, bien sûr) et si vous analysez le contenu des fichiers Makefile.am, vous obtiendrez un progiciel opérationnel.

Il reste une dernière chose à faire. Vous devez aussi spécifier la structure de répertoire dans le fichier configure.in du répertoire racine du projet :

AC_CONFIG_FILES([Makefile])
AC_CONFIG_FILES([svlna/Makefile])
AC_CONFIG_FILES([svlna/translation/Makefile])
AC_CONFIG_FILES([svlna/doc/Makefile])

Et maintenant, comment ça marche?

Premièrement lancez make -f Makefile.dist dans le répertoire racine. Les modèles de Makefile.in sont créés (comme par magie).

Ensuite, ./configure ; make ; make install devrait fonctionnner pour vous. Profitez-en.

Complément d'information

À ce stade, vous devriez lire scplugin.h et comprendre le texte d'aide. Pour des précisions sur le fonctionnement du système d'extensions ici. Surtout, vous apprendrez la procédure en lisant les autres extensions et le code central de Scribus.

Comment conserver les préférences de votre extension :

Scribus fournit une API de préférences pour les développeurs d'extensions qui permet de conserver les données entre les démarrages de Scribus. Il y a deux types de formats disponibles : Paires "clé-valeur" et Tables.

Tout d'abord, vous devrez obtenir l'objet PrefsContext pour votre extension. Ensuite, vous pouvez extraire de PrefsContext une valeur de clé spécifique ou vous pouvez solliciter PrefsTable par son nom. Voici un court exemple qui utilise les paires clé-valeur.

#include <prefsfile.h>
#include <prefscontext.h>

extern PrefsFile* prefsFile;

PrefsContext *myPluginPrefs = prefsFile->getPluginContext("MyPlugin");

// la valeur par défaut 1 sera utilisée si "i" n'existe pas déjà
int i = myPluginPrefs->getInt("i");

// la valeur par défaut "chien" sera utilisée si "s" n'existe pas
QString s = myPluginPrefs->get("s", "chien");

myPluginPrefs->set("i", 221);
myPluginPrefs->set("s", "chat");

Modèle objet de Scribus

Le code source de Scribus n'est pas documenté en détail. Beaucoup d'efforts sont déployés pour corriger la situation, mais étant donné la taille du code, cela prend du temps. Essayez de suivre l'évolution en vous basant sur les fichiers d'en-tête et sur le code. En cas de doute, n'hésitez pas à consulter le canal IRC ou à poser des questions via la liste de diffusion, et vous obtiendrez probablement une réponse. Soyezpatient, car nous ne sommes pas toujours disponibles ou présents sur IRC.

Si vous souhaitez améliorer la documentation ou corriger l'API de génération doxygen api, nous vous en saurons gré.

Il est important de noter que l'accès au coeur de l'application Scribus passe par l'aide du pointeur statique global ScApp, déclaré dans scribus.h. Attention à la confusion : c'est aussi une sous-classe de QMainWindow. Vous pouvez également aller à la sous-classe QApplication utilisée comme ScQApp à partir de scribusapp.h.

Certains sous-systèmes majeurs sont des classes uniques qui sont accessibles via ClassName::instance() . Il y a par exemple PluginManager, ScPaths, ainsi qu'un nombre croissant d'autres classes. L'avantage de cette approche est de vous permettre d'interagir avec ces classes sans pénétrer dans les rouages de ScApp.

Liens associés aux extensions

Documentation de Qt par Trolltech
Documentation de QMake par Trolltech
Exemple automake/autoconf
o