File: plugin_howto.html

package info (click to toggle)
scribus-doc 1.2.1-2
  • links: PTS
  • area: non-free
  • in suites: sarge
  • size: 2,920 kB
  • ctags: 374
  • sloc: makefile: 387; xml: 110
file content (276 lines) | stat: -rw-r--r-- 12,194 bytes parent folder | download
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
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
<qt>
<title>How to write a Scribus Plugin</title>
<h2>How to write a Scribus Plugin</h2>

<h3>Preface</h3>

<p>This article shows you how to write plugins for Scribus. Plugins are dynamic loaded libraries in "so" format.</p>

<h3>Where do I find Scribus Plugins?</h3>

<p>Your Scribus, if manually installed in the following manner:
<blockquote><table width="100%" border="1" bgcolor="#eeeeee"><tr><td border="0"><small>
<pre>
#./configure [--prefix=/your/selected/path]
#make
#make install
</pre>
</small></td></tr></table></blockquote>
</p>
<p>Substituting <code>/your/selected/path</code> with the one appropriate for your system, eg. <code>/usr</code>, change directory to <code>/your/selected/path/lib/Scribus/plugins</code> and list its files. You should see a lot of *.la and *.so* files and some *.qm too. Qm files contain language translations and localisation, la and so are loadable libraries which are topic of this article.</p>

<h3>Before you start coding</h3>

<p>Let's suppose you've got a great idea to improve Scribus and you cannot wait to start writing some excellent C++ constructs.</p>

<p>
<h4>Important</h4>

Wait here for a while! Maybe you are at the edge of "reinventing the wheel" - so join the mailing-list or #scribus channel at irc.freenode.net. Your topic will be discussed and you'll get support too. We cannot stop you to write anything you want - sure. :)))
</p>

<h3>Example Plugin</h3>

<h4>myplugin.h</h4>
<blockquote><table width="100%" border="1" bgcolor="#eeeeee"><tr><td border="0"><small>
<pre>
#ifndef MYPLUGIN_H
#define MYPLUGIN_H

#include &#060;scribus.h&#062;

/** Calls the Plugin with the main Application window as parent
  * and the main Application Class as parameter */
extern "C" void Run(QWidget *d, ScribusApp *plug);


/** Returns the Name of the Plugin.
  * This name appears in the relevant Menu-Entries */
extern "C" QString Name();


/** Returns the Type of the Plugin.
  * 1 = the Plugin is a normal Plugin, which appears in the Extras Menu
  * 2 = the Plugin is a Import Plugin, which appears in the Import Menu
  * 3 = the Plugin is a Export Plugin, which appears in the Export Menu
  * 4 = the Plugin is a resident Plugin   */
extern "C" int Type();

#endif
</pre>
</small></td></tr></table></blockquote>

<p>Now let's describe the source code. MYPLUGIN_H declaration is the standard way to ensure only one insertion of the header file. Scribus.h is required to access Scribus objects. The function <code>Run()</code> is called when the plugin is loaded, ie. called from Scribus menu - depending on <code>Type()</code> return value.</p>

<p><code>Name()</code> returns the string to display in menu.</p>

<p>In this example we're working on normal plugin (type 1). Import and Export plugins (types 2, 3) you can study by reading the code of e.g. SVG import/export plugin that is distributed in Scribus tarball and resident plugin (type 4) is e.g. Python scripting plugin aka. Scripter from the distribution.</p>

<p>You can use a very special type of plugin when you use number not listed in the example above - e.g. 5. In this case you have to handle the plugin integration into Scribus menus yourself. The <code>newfromtemplate</code> addon with its:</p>

<blockquote><table width="100%" border="1" bgcolor="#eeeeee"><tr><td border="0"><small>
<pre>plug->fileMenu->insertItem(QObject::tr("New &from Template..."));</pre>
</small></td></tr></table></blockquote>

<p>is a good example.</p>

<h4>myplugin.cpp</h4>
<blockquote><table width="100%" border="1" bgcolor="#eeeeee"><tr><td border="0"><small>
<pre>
#include "myplugin.h"
#include &#060;qstring.h&#062;

QString Name()
{
    return QObject::tr("Do Nothing Plugin");
}

int Type()
{
    return 1;
}

void Run(QWidget *d, ScribusApp *plug)
{
}
</pre>
</small></td></tr></table></blockquote>

<p>To explain the source code again. Qt <code>qtstring.h</code> is required as the function <code>Name()</code> returns a <code>QString</code> instance - text for the user interface. It should be prepared for translations with <code>QObject::tr()</code>.</p>

<p>As said above - Type() of this plugin is 1.</p>

<p><code>Run(QWidget*, ScribusApp*)</code> is empty while we write a plugin that does nothing. In a real plugin there has to be the code that is the plugin logic, custom class initializations, dialog calling etc.</p>

<h3>Compile it!</h3>

<b>Warning</b>

<p>Beware - a qmake project easy to use but isn't necessarily the most standard way to distribute software on the Linux platform. This process is an example only for development. When you create your bug-free functional package then save the time to prepare full featured automagic (autoconf, automake) distributon as described in the next section.</p>

<p>Let's compile it, but it isn't so easy as typing in <code>gcc myplugin.cpp</code> ;). One easy way to build it - Qt qmake (because some people really really hate autoconf and automake in their complexity). Note: you will need to create an empty <code>config.h</code> file before running these steps</p>

<blockquote><table width="100%" border="1" bgcolor="#eeeeee"><tr><td border="0"><small>
<pre>
#qmake -project
</pre>
</small></td></tr></table></blockquote>

<p>Now the project file is created and we'll make just a few changes into it.</p>
<blockquote><table width="100%" border="1" bgcolor="#eeeeee"><tr><td border="0"><small>
<pre>
######################################################################
# Automatically generated by qmake (1.06c) Sun Dec 14 13:32:11 2003
######################################################################

#change TEMPLATE = app. We aren't working on application just plugin
TEMPLATE = lib
INCLUDEPATH += .
#As working with Scribus, we need Scribus includes too.
INCLUDEPATH += /home/subzero/devel/Scribus/include/Scribus/
#And Scribus have to use freetype2.
#So we should link it too. Use paths returned from
##freetype-config --cflags and --libs
INCLUDEPATH += /usr/include/freetype2
LIBS += -lfreetype -lz

# Input
#create empty config.h file
HEADERS += myplugin.h config.h
SOURCES += myplugin.cpp
</pre>
</small></td></tr></table></blockquote>

<p>After these changes you're ready to compile</p>

<blockquote><table width="100%" border="1" bgcolor="#eeeeee"><tr><td border="0"><small>
<pre>
#qmake
#make
</pre>
</small></td></tr></table></blockquote>

<p>Running Qmake creates the Makefile and by running make you compile your plugin.</p>

<p>Then just copy *so* files into Scribus plugin directory and run Scribus. You'll see "Do Nothing Plugin" in the Extras menu.</p>

<p>It is clear that you have to use some other way to distribute your source code to others - some use autogenerated qmake pro files, other use the autoconf/automake combination.</p>

<h3>Distribute it! (a.k.a. Compile it! 2nd edition)</h3>

<p>Qmake is user frendly and useful for rapid development, but there is one standard way to compile/distribute software for Linux, *BSD etc. - autoconf and automake. Lets call these two programs by the automagic acronym in the following text.</p>

<p>To use automagic successfully you'll need chalk drawn to the north oriented pentagram on the floor (Carrefour, 2&#8364;), red-black daemonic dress (Hugo Boss, 2000&#8364;) and a sacrificed penguin on the home altar (one hour of the fear in your local Zoo). Err, only joking.. dont harm any nice little penguins, you wont need to.</p>


<h4>Back to business...</h4>

<p>Download the <code>donothingplugin-1.0.tar.gz</code> example from http://docs.scribus.net, unpack it and browse it.</p>
<p>When you enter the main directory you can see a lot of files and directories. <b>Warning</b>, do not change anything in the admin directory. It's content is TABOO for you!</p>
<p>As you read the automagic docs (surely) you know that there is an important file in every directory of your project called <code>Makefile.am</code>. Here is a short commented example:</p>

<blockquote><table width="100%" border="1" bgcolor="#eeeeee"><tr><td border="0"><small>
<pre>
# set where will be plugin installed
pluginsdir = $(prefix)/lib/scribus/plugins
# specify additional includes for compilation
AM_CPPFLAGS = -I$(prefix)/include/scribus
# specify directories to dive in
SUBDIRS = translation doc
# name of the plugin = library
plugins_LTLIBRARIES = libscribusvlna.la
# join all includes
INCLUDES = $(LIBFREETYPE_CFLAGS) $(all_includes)
# library related trash - symlinks etc.
libscribusvlna_la_LDFLAGS = -version-info 0:0:0
libscribusvlna_la_METASOURCES = AUTO
#
# list of the source files of your project
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$
# how to compile
KDE_OPTIONS = qtonly
AM_LDFLAGS =    -s $(LIBFREETYPE_LIBS)
</pre>
</small></td></tr></table></blockquote>

<p>Shortly - if you take the <code>donothingplugin-1.0.tar.gz</code> file and parse the content (and rename it of course :)) of <code>Makefile.am</code> files you'll get a functional package.</p>
<p>There is one more thing to do. You have to specify directory structure in <code>configure.in</code> in the project root directory too:</p>

<blockquote><table width="100%" border="1" bgcolor="#eeeeee"><tr><td border="0"><small>
<pre>
AC_CONFIG_FILES([Makefile])
AC_CONFIG_FILES([svlna/Makefile])
AC_CONFIG_FILES([svlna/translation/Makefile])
AC_CONFIG_FILES([svlna/doc/Makefile])
</pre>
</small></td></tr></table></blockquote>

<p>And now to how it works...</p>
<p>First run <code>make -f Makefile.dist</code> in the root directory. It creates <code>Makefile.in</code> templates (some kind of the black magic).</p>
<p>And then obligatory <code>./configure ; make ; make install</code> should work for you. Enjoy.</p>

<h3>Scribus Object Model</h3>
<p>Read doxygen documentation for Scribus-API and Scribus source code in the same time.</p>

<h3>Some (useful) code examples</h3>

<p>Some pieces of the code fromn the source code follows.</p>
<h4>How to show what are you doing to the user in Scribus's statusbar:</h4>
<blockquote><table width="100%" border="1" bgcolor="#eeeeee"><tr><td border="0"><small>
<pre>
plug->FMess->setText(QString(aText));
</pre>
</small></td></tr></table></blockquote>

<h4>Item is a text frame:</h4>
<blockquote><table width="100%" border="1" bgcolor="#eeeeee"><tr><td border="0"><small>
<pre>
PageItem *aFrame;
if (aFrame->PType==4) {}
</pre>
</small></td></tr></table></blockquote>

<h4>Navigation through the pages:</h4>
<blockquote><table width="100%" border="1" bgcolor="#eeeeee"><tr><td border="0"><small>
<pre>
for (uint i=0; i<plug->view->Pages.count(); i++) {
    plug->FMess->setText(QObject::tr("Page: ")
            + i
            + plug->view->Pages.at(i)->PageNam);
    // do something with active page
    parse(plug->view->Pages.at(i));
}
</pre>
</small></td></tr></table></blockquote>   

<h4>Storing your plugin's preferences:</h4>

<p>Scribus provides a preferences api for plugin writers to store data between Scribus launches. There are two types of storage formats available: key-value pairs and tables.</p>
<p>First you will need to get the <code>PrefsContext</code> object for your plugin. Then you can query <code>PrefsContext</code> to get the value for a specific key or you can ask for a <code>PrefsTable</code> by it's name. Here is a short example using key-value pairs.</p>

<pre>
#include &lt;prefsfile.h&gt;
#include &lt;prefscontext.h&gt;

extern PrefsFile* prefsFile;

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

// default value -1 will be used if "i" doesn't already exist
int i = myPluginPrefs->getInt("i");

// default value "dog" will be used if "s" doesn't already exist
QString s = myPluginPrefs->get("s", "dog");

myPluginPrefs->set("i", 221);
myPluginPrefs->set("s", "cat");
</pre>


<h3>Plugin related links</h3>
<a href="http://doc.trolltech.com/">Qt documentation from Trolltech</a><br />
<a href="http://doc.trolltech.com/3.2/qmake-manual.html">QMake documentation from Trolltech</a><br />
<a href="http://www.murrayc.com/learning/linux/automake/automake.shtml">Automake/autoconf example</a><br />
</qt>