source: trunk/doc/html/grapher-nsplugin-example.html

Last change on this file was 190, checked in by rudi, 14 years ago

reference documentation added

File size: 24.2 KB
Line 
1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
2<!-- /home/espenr/tmp/qt-3.3.8-espenr-2499/qt-x11-free-3.3.8/extensions/nsplugin/examples/grapher/grapher.doc:1 -->
3<html>
4<head>
5<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
6<title>Grapher Plugin</title>
7<style type="text/css"><!--
8fn { margin-left: 1cm; text-indent: -1cm; }
9a:link { color: #004faf; text-decoration: none }
10a:visited { color: #672967; text-decoration: none }
11body { background: #ffffff; color: black; }
12--></style>
13</head>
14<body>
15
16<table border="0" cellpadding="0" cellspacing="0" width="100%">
17<tr bgcolor="#E5E5E5">
18<td valign=center>
19 <a href="index.html">
20<font color="#004faf">Home</font></a>
21 | <a href="classes.html">
22<font color="#004faf">All&nbsp;Classes</font></a>
23 | <a href="mainclasses.html">
24<font color="#004faf">Main&nbsp;Classes</font></a>
25 | <a href="annotated.html">
26<font color="#004faf">Annotated</font></a>
27 | <a href="groups.html">
28<font color="#004faf">Grouped&nbsp;Classes</font></a>
29 | <a href="functions.html">
30<font color="#004faf">Functions</font></a>
31</td>
32<td align="right" valign="center"><img src="logo32.png" align="right" width="64" height="32" border="0"></td></tr></table><h1 align=center>Grapher Plugin</h1>
33
34
35
36<p> This example graphs data from a simple text file. It
37demonstrates the use of the <a href="qnpinstance.html#writeReady">QNPInstance::writeReady</a>()
38and <a href="qnpinstance.html#write">QNPInstance::write</a>() functions.
39<p> To build the example, you must first build the
40<a href=nsplugin.html>Qt Netscape Plugin Extension</a> library.
41Then type <tt>make</tt> in <tt>extensions/nsplugin/examples/grapher/</tt>
42and copy the resulting <tt>grapher.so</tt> or <tt>npgrapher.dll</tt>
43to the Plugins directory of your WWW browser.
44<p> <EMBED ALIGN=LEFT WIDTH=49% HEIGHT=300 SRC=graph.g1n
45graphstyle=pie fontfamily=times fontsize=18>
46<p> The text file it accepts as input has a title line, then
47a sequence of lines with a number, then a string. The
48plugin displays a pie chart of the numbers, each segment
49labelled by the associated string. The user can select
50a bar chart view of the same data by selecting from the
51menu that appears when they point at the plugin.
52<p> The HTML tag used to embed the graph is:
53<small>
54<pre>
55 &lt;EMBED
56 SRC=graph.g1n
57 ALIGN=LEFT
58 WIDTH=49% HEIGHT=300
59 graphstyle=pie fontfamily=times
60 fontsize=18&gt;
61</pre><p> </small>
62Note that some HTML arguments (which we have capitalized here)
63are interpreted by the browser, while others are used by the
64plugin.
65<p> <br clear>
66With the simplicity and cross-platform nature of Qt-based plugins,
67pages like <a href="http://www.netcraft.com/survey/">Netcraft's
68Server Graphs</a> can be provided much more efficiently for both
69the service provider and consumer. Data need not be converted
70to an image at the server.
71<p> <br clear>
72<hr>
73Implementation:
74<p> <pre>// Include Qt Netscape Plugin classes.
75#include "qnp.h"
76
77// Include other Qt classes.
78#include &lt;<a href="qpainter-h.html">qpainter.h</a>&gt;
79#include &lt;<a href="qtextstream-h.html">qtextstream.h</a>&gt;
80#include &lt;<a href="qbuffer-h.html">qbuffer.h</a>&gt;
81#include &lt;<a href="qpixmap-h.html">qpixmap.h</a>&gt;
82#include &lt;<a href="qmenubar-h.html">qmenubar.h</a>&gt;
83#include &lt;<a href="qpushbutton-h.html">qpushbutton.h</a>&gt;
84#include &lt;<a href="qptrlist-h.html">qptrlist.h</a>&gt;
85#include &lt;<a href="qmessagebox-h.html">qmessagebox.h</a>&gt;
86
87// Include some C library functions.
88#include &lt;math.h&gt;
89#include &lt;stdlib.h&gt;
90
91#ifndef M_PI // Some math.h don't include this.
92#define M_PI 3.14159265358979323846264338327950288
93#endif
94
95
96
97//
98// GraphModel is a simple abstract class that describes
99// a table of numeric and text data.
100//
101
102class GraphModel {
103public:
104 enum ColType { Numeric, Label };
105
106 union Datum {
107 double dbl;
108 <a href="qstring.html">QString</a>* str;
109 };
110
111 virtual QPtrList&lt;Datum&gt;&amp; graphData()=0;
112 virtual ColType colType(int col) const=0;
113 virtual int nCols() const=0;
114};
115
116
117//
118// Graph is a widget subclass that displays a GraphModel.
119// Since the widget is a QNPWidget, it can be used as a plugin window,
120// returned by Grapher::newWindow() below.
121//
122
123class Graph : public <a href="qnpwidget.html">QNPWidget</a> {
124 <a href="metaobjects.html#Q_OBJECT">Q_OBJECT</a>
125public:
126 // Constructs a Graph to display a GraphModel
127 //
128 Graph(GraphModel&amp;);
129 ~Graph();
130
131 // Two styles are available - Pie and Bar graph
132 //
133 enum Style { Pie, Bar };
134 static const char* styleName[];
135 void setStyle(Style);
136 void setStyle(const char*);
137
138 // Timer event processing rotates the pie graph
139 //
140 void timerEvent(QTimerEvent*);
141
142 // These functions are provided by QNPWidget - we override
143 // them to hide and show the plugin menubar.
144 //
145 void enterInstance();
146 void leaveInstance();
147
148 // Paint the graph...
149 //
150 void paintEvent(QPaintEvent*);
151 //
152 // ... as either a "Loading" message, a Bar graph, a Pie graph,
153 // or an error message.
154 //
155 void paintWait(QPaintEvent*);
156 void paintBar(QPaintEvent*);
157 void paintPie(QPaintEvent*);
158 void paintError(const char*);
159
160signals:
161 // Signals emitted when the Help menus are selected.
162 void aboutPlugin();
163 void aboutData();
164
165private:
166 GraphModel&amp; model;
167 <a href="qmenubar.html">QMenuBar</a> *menubar;
168 Style style;
169 <a href="qpopupmenu.html">QPopupMenu</a>* stylemenu;
170 int pieRotationTimer;
171 int pieRotation;
172 <a href="qpixmap.html">QPixmap</a> pm;
173
174private slots:
175 void setStyleFromMenu(int id);
176};
177
178
179<a name="f564"></a>Graph::Graph( GraphModel&amp; mdl ) :
180 model(mdl),
181 <a href="qwidget.html#style">style</a>(Bar),
182 pieRotationTimer(0),
183 pieRotation(0)
184{
185 // Create a menubar for the widget
186 //
187 menubar = new <a href="qmenubar.html">QMenuBar</a>( this );
188 stylemenu = new <a href="qpopupmenu.html">QPopupMenu</a>;
189<a name="x2768"></a> stylemenu-&gt;<a href="qpopupmenu.html#setCheckable">setCheckable</a>(TRUE);
190 for ( Style s = Pie; styleName[s]; s = Style(s+1)) {
191 stylemenu-&gt;<a href="qmenudata.html#insertItem">insertItem</a>(styleName[s], s+100);
192 }
193<a name="x2767"></a> <a href="qobject.html#connect">connect</a>(stylemenu, SIGNAL(<a href="qpopupmenu.html#activated">activated</a>(int)),
194 this, SLOT(setStyleFromMenu(int)));
195 <a href="qwidget.html#setStyle">setStyle</a>(Pie);
196
197 menubar-&gt;<a href="qmenudata.html#insertItem">insertItem</a>("Style", stylemenu);
198 menubar-&gt;<a href="qmenudata.html#insertSeparator">insertSeparator</a>();
199
200 <a href="qpopupmenu.html">QPopupMenu</a>* help = new <a href="qpopupmenu.html">QPopupMenu</a>;
201 help-&gt;<a href="qmenudata.html#insertItem">insertItem</a>( "About plugin...", this, SIGNAL(aboutPlugin()) );
202 help-&gt;<a href="qmenudata.html#insertItem">insertItem</a>( "About data...", this, SIGNAL(aboutData()) );
203 menubar-&gt;<a href="qmenudata.html#insertItem">insertItem</a>("Help", help);
204<a name="x2745"></a> menubar-&gt;<a href="qmenubar.html#hide">hide</a>();
205}
206
207Graph::~Graph()
208{
209}
210
211<a name="x2778"></a>void Graph::<a href="qwidget.html#setStyle">setStyle</a>(Style s)
212{
213 if (style != s) {
214 if (pieRotationTimer)
215 <a href="qobject.html#killTimer">killTimer</a>(pieRotationTimer);
216<a name="x2749"></a> stylemenu-&gt;<a href="qmenudata.html#setItemChecked">setItemChecked</a>(100+style, FALSE);
217 style = s;
218 if ( style == Pie )
219 pieRotationTimer = <a href="qobject.html#startTimer">startTimer</a>( 80 );
220 else
221 pieRotationTimer = 0;
222 stylemenu-&gt;<a href="qmenudata.html#setItemChecked">setItemChecked</a>(100+style, TRUE);
223 <a href="qwidget.html#update">update</a>();
224 }
225}
226
227<a name="x2755"></a>void Graph::<a href="qobject.html#timerEvent">timerEvent</a>(QTimerEvent*)
228{
229 pieRotation = ( pieRotation + 6 ) % 360; repaint(FALSE);
230}
231
232void Graph::<a href="qwidget.html#setStyle">setStyle</a>(const char* stext)
233{
234 for ( Style s = Pie; styleName[s]; s = Style(s+1) ) {
235 if ( <a href="qcstring.html#qstricmp">qstricmp</a>(stext,styleName[s])==0 ) {
236 <a href="qwidget.html#setStyle">setStyle</a>(s);
237 return;
238 }
239 }
240}
241
242<a name="x2753"></a>void Graph::<a href="qnpwidget.html#enterInstance">enterInstance</a>()
243{
244<a name="x2746"></a> menubar-&gt;<a href="qmenubar.html#show">show</a>();
245}
246
247<a name="x2754"></a>void Graph::<a href="qnpwidget.html#leaveInstance">leaveInstance</a>()
248{
249 menubar-&gt;<a href="qmenubar.html#hide">hide</a>();
250}
251
252void <a name="f565"></a>Graph::paintError(const char* e)
253{
254 <a href="qpainter.html">QPainter</a> p(this);
255 int w = <a href="qwidget.html#width">width</a>();
256<a name="x2760"></a> p.<a href="qpainter.html#drawText">drawText</a>(w/8, 0, w-w/4, height(), AlignCenter|WordBreak, e);
257}
258
259void <a name="f566"></a>Graph::paintBar(QPaintEvent* event)
260{
261 if ( model.colType(0) != GraphModel::Numeric ) {
262 paintError("First column not numeric, cannot draw bar graph\n");
263 return;
264 }
265
266 <a href="qptrlist.html">QPtrList</a>&lt;GraphModel::Datum&gt;&amp; data = model.graphData();
267
268 double max = 0.0;
269
270<a name="x2772"></a> for (GraphModel::Datum* rowdata = data.<a href="qptrlist.html#first">first</a>();
271<a name="x2773"></a> rowdata; rowdata = data.<a href="qptrlist.html#next">next</a>())
272 {
273 if (rowdata[0].dbl &gt; max) max = rowdata[0].dbl;
274 }
275
276 const uint w = <a href="qwidget.html#width">width</a>();
277 const uint h = <a href="qwidget.html#height">height</a>();
278
279 <a href="qpainter.html">QPainter</a> p(this);
280
281<a name="x2762"></a> p.<a href="qpainter.html#setClipRect">setClipRect</a>(event-&gt;rect());
282
283<a name="x2771"></a> if ( w &gt; data.<a href="qptrlist.html#count">count</a>() ) {
284 // More pixels than data
285 int x = 0;
286 int i = 0;
287 <a href="qfontmetrics.html">QFontMetrics</a> fm=<a href="qwidget.html#fontMetrics">fontMetrics</a>();
288<a name="x2741"></a> int fh = fm.<a href="qfontmetrics.html#height">height</a>();
289
290 for (GraphModel::Datum* rowdata = data.<a href="qptrlist.html#first">first</a>();
291 rowdata; rowdata = data.<a href="qptrlist.html#next">next</a>())
292 {
293 <a href="qcolor.html">QColor</a> c;
294<a name="x2740"></a> c.<a href="qcolor.html#setHsv">setHsv</a>( (i * 255)/data.<a href="qptrlist.html#count">count</a>(), 255, 255 );// rainbow effect
295 p.<a href="qpainter.html#setBrush">setBrush</a>(c);
296 int bw = (w-w/4-x)/(data.<a href="qptrlist.html#count">count</a>()-i);
297 int bh = int((h-h/4-1)*rowdata[0].dbl/max);
298 p.<a href="qpainter.html#drawRect">drawRect</a>( w/8+x, h-h/8-1-bh, bw, bh );
299
300 i++;
301 x+=bw;
302 }
303 } else {
304 // More data than pixels
305 int x = 0;
306 int i = 0;
307 double av = 0.0;
308 int n = 0;
309 for (GraphModel::Datum* rowdata = data.<a href="qptrlist.html#first">first</a>(); rowdata;
310 rowdata = data.<a href="qptrlist.html#next">next</a>())
311 {
312 int bx = i*w/data.<a href="qptrlist.html#count">count</a>();
313
314 if (bx &gt; x) {
315 <a href="qcolor.html">QColor</a> c;
316 c.<a href="qcolor.html#setHsv">setHsv</a>( (x * 255)/w, 255, 255 );// rainbow effect
317 p.<a href="qpainter.html#setPen">setPen</a>(c);
318 int bh = int(h*av/n/max);
319
320 p.<a href="qpainter.html#drawLine">drawLine</a>(x,h-1,x,h-bh);
321
322 av = 0.0;
323 n = 0;
324 x = bx;
325 }
326
327 av += rowdata[0].dbl;
328 n++;
329
330 i++;
331 }
332 }
333}
334
335void <a name="f567"></a>Graph::paintPie(QPaintEvent* event)
336{
337 if ( model.colType(0) != GraphModel::Numeric ) {
338 paintError("First column not numeric, cannot draw pie graph\n");
339 return;
340 }
341
342 <a href="qptrlist.html">QPtrList</a>&lt;GraphModel::Datum&gt;&amp; data = model.graphData();
343
344 double total = 0.0;
345
346 GraphModel::Datum* rowdata;
347
348 for (rowdata = data.<a href="qptrlist.html#first">first</a>();
349 rowdata; rowdata = data.<a href="qptrlist.html#next">next</a>())
350 {
351 total += rowdata[0].dbl;
352 }
353
354 // Only use first column for pie chart
355 if ( !total ) return;
356
357 int apos = (pieRotation-90)*16;
358
359 const int w = <a href="qwidget.html#width">width</a>();
360 const int h = <a href="qwidget.html#height">height</a>();
361
362 const int xd = w - w/5;
363 const int yd = h - h/5;
364
365<a name="x2766"></a> pm.<a href="qpixmap.html#resize">resize</a>(<a href="qwidget.html#width">width</a>(),height());
366<a name="x2765"></a> pm.<a href="qpixmap.html#fill">fill</a>(<a href="qwidget.html#backgroundColor">backgroundColor</a>());
367 <a href="qpainter.html">QPainter</a> p(&amp;pm);
368<a name="x2763"></a> p.<a href="qpainter.html#setFont">setFont</a>(<a href="qwidget.html#font">font</a>());
369
370 p.<a href="qpainter.html#setClipRect">setClipRect</a>(event-&gt;rect());
371
372 int i = 0;
373
374 for (rowdata = data.<a href="qptrlist.html#first">first</a>();
375 rowdata; rowdata = data.<a href="qptrlist.html#next">next</a>())
376 {
377 <a href="qcolor.html">QColor</a> c;
378
379 c.<a href="qcolor.html#setHsv">setHsv</a>( ( i * 255)/data.<a href="qptrlist.html#count">count</a>(), 255, 255 );// rainbow effect
380 p.<a href="qpainter.html#setBrush">setBrush</a>( c ); // solid fill with color c
381
382 int a = int(( rowdata[0].dbl * 360.0 ) / total * 16.0 + 0.5);
383<a name="x2757"></a> p.<a href="qpainter.html#drawPie">drawPie</a>( w/10, h/10, xd, yd, -apos, -a );
384 apos += a;
385 i++;
386 }
387
388 if (model.colType(1) == GraphModel::Label) {
389 double apos = (pieRotation-90)*M_PI/180;
390
391 for (rowdata = data.<a href="qptrlist.html#first">first</a>();
392 rowdata; rowdata = data.<a href="qptrlist.html#next">next</a>())
393 {
394 double a = rowdata[0].dbl * 360 / total * M_PI / 180;
395 int x = int(cos(apos+a/2)*w*5/16 + w/2 + 0.5);
396 int y = int(sin(apos+a/2)*h*5/16 + h/2 + 0.5);
397
398 // ### This causes a crash, so comment out for now
399 /*p.<a href="qpainter.html#drawText">drawText</a>(x-w/8, y-h/8, w/4, h/4,
400 WordBreak|AlignCenter,
401 *rowdata[1].str);*/
402 apos += a;
403 }
404 }
405
406 <a href="qpainter.html">QPainter</a> p2(this);
407 p2.<a href="qpainter.html#setClipRect">setClipRect</a>(event-&gt;rect());
408<a name="x2758"></a> p2.<a href="qpainter.html#drawPixmap">drawPixmap</a>(0,0,pm);
409}
410
411void <a name="f568"></a>Graph::paintWait(QPaintEvent*)
412{
413 <a href="qpainter.html">QPainter</a> p(this);
414 p.<a href="qpainter.html#drawText">drawText</a>(rect(), AlignCenter, "Loading...");
415}
416
417void Graph::<a href="qwidget.html#paintEvent">paintEvent</a>(QPaintEvent* event)
418{
419 if (!model.nCols()) {
420 paintWait(event);
421 } else {
422 switch (style) {
423 case Pie:
424 paintPie(event);
425 break;
426 case Bar:
427 paintBar(event);
428 break;
429 }
430 }
431}
432
433void <a name="f569"></a>Graph::setStyleFromMenu(int id)
434{
435 setStyle(Style(id-100));
436}
437
438const char* Graph::styleName[] = { "Pie", "Bar", 0 };
439
440
441//
442// Grapher is a subclass of QNPInstance, and so it can be returned
443// by GrapherPlugin::newInstance(). A QNPInstance represents the
444// plugin, distinctly from the plugin window.
445//
446// Grapher is also a GraphModel, because it loads graph data from
447// the net. When Grapher creates a window in newWindow(), it creates
448// a Graph widget to display the GraphModel that is the Grapher itself.
449//
450
451class Grapher : public <a href="qnpinstance.html">QNPInstance</a>, GraphModel {
452 Q_OBJECT
453public:
454 // Create a Grapher - all Grapher plugins are created
455 // by one GrapherPlugin object.
456 //
457 Grapher();
458 ~Grapher();
459
460 // We override this QNPInstance function to create our
461 // own subclass of QNPWidget, a Graph widget.
462 //
463 <a href="qnpwidget.html">QNPWidget</a>* newWindow();
464
465 // We override this QNPInstance function to process the
466 // incoming graph data.
467 //
468 int write(QNPStream* /*str*/, int /*offset*/, int len, void* buffer);
469
470private:
471 // Grapher is a GraphModel, so it implements the pure virtual
472 // functions of that class.
473 //
474 <a href="qptrlist.html">QPtrList</a>&lt;Datum&gt;&amp; graphData();
475 ColType colType(int col) const;
476 int nCols() const;
477
478 void consumeLine();
479 <a href="qptrlist.html">QPtrList</a>&lt;Datum&gt; data;
480 <a href="qbuffer.html">QBuffer</a> line;
481 int ncols;
482 ColType *coltype;
483
484private slots:
485 // Slots that are connected to the Graph menu items.
486 //
487 void aboutPlugin();
488 void aboutData();
489};
490
491<a name="f570"></a>Grapher::Grapher()
492{
493<a name="x2769"></a> data.<a href="qptrcollection.html#setAutoDelete">setAutoDelete</a>(TRUE);
494 ncols = 0;
495<a name="x2743"></a> line.<a href="qiodevice.html#open">open</a>(IO_WriteOnly|IO_Truncate);
496}
497
498Grapher::~Grapher()
499{
500}
501
502QPtrList&lt;GraphModel::Datum&gt;&amp; <a name="f571"></a>Grapher::graphData()
503{
504 return data;
505}
506
507GraphModel::ColType <a name="f572"></a>Grapher::colType(int col) const
508{
509 return coltype[col];
510}
511
512int <a name="f573"></a>Grapher::nCols() const
513{
514 return ncols;
515}
516
517
518<a name="x2751"></a>QNPWidget* Grapher::<a href="qnpinstance.html#newWindow">newWindow</a>()
519{
520 // Create a Graph - our subclass of QNPWidget.
521 Graph *graph = new Graph(*this);
522
523 // Look at the arguments from the EMBED tag.
524 // GRAPHSTYLE chooses pie or bar
525 // FONTFAMILY and FONTSIZE choose the font
526 //
527 const char* style = <a href="qnpinstance.html#arg">arg</a>("GRAPHSTYLE");
528 if ( style ) graph-&gt;<a href="qwidget.html#setStyle">setStyle</a>(style);
529
530 const char* fontfamily = <a href="qnpinstance.html#arg">arg</a>("FONTFAMILY");
531 const char* fontsize = <a href="qnpinstance.html#arg">arg</a>("FONTSIZE");
532<a name="x2775"></a> int ptsize = fontsize ? atoi(fontsize) : graph-&gt;<a href="qwidget.html#font">font</a>().pointSize();
533 if (fontfamily) graph-&gt;<a href="qwidget.html#setFont">setFont</a>(QFont(fontfamily, ptsize));
534
535 <a href="qobject.html#connect">connect</a>(graph, SIGNAL(aboutPlugin()), this, SLOT(aboutPlugin()));
536 <a href="qobject.html#connect">connect</a>(graph, SIGNAL(aboutData()), this, SLOT(aboutData()));
537
538 return graph;
539}
540
541void <a name="f574"></a>Grapher::consumeLine()
542{
543<a name="x2742"></a> line.<a href="qiodevice.html#close">close</a>();
544 line.<a href="qiodevice.html#open">open</a>(IO_ReadOnly);
545
546 <a href="qtextstream.html">QTextStream</a> ts( &amp;line );
547
548 if (ncols == 0 ) {
549 ncols=0;
550 <a href="qptrlist.html">QPtrList</a>&lt;ColType&gt; typelist;
551 typelist.<a href="qptrcollection.html#setAutoDelete">setAutoDelete</a>(TRUE);
552 do {
553 <a href="qstring.html">QString</a> typestr;
554 ts &gt;&gt; typestr &gt;&gt; ws;
555 ColType* t = 0;
556 if ( typestr == "num" ) {
557 t = new ColType(Numeric);
558 } else if ( typestr == "label" ) {
559 t = new ColType(Label);
560 }
561<a name="x2770"></a> if (t) typelist.<a href="qptrlist.html#append">append</a>(t);
562<a name="x2774"></a> } while (!ts.<a href="qtextstream.html#atEnd">atEnd</a>());
563 coltype = new ColType[ncols];
564 for (ColType* t = typelist.<a href="qptrlist.html#first">first</a>(); t; t = typelist.<a href="qptrlist.html#next">next</a>()) {
565 coltype[ncols++] = *t;
566 }
567 } else {
568 int col=0;
569 Datum *rowdata = new Datum[ncols];
570 while ( col &lt; ncols &amp;&amp; !ts.<a href="qtextstream.html#atEnd">atEnd</a>() ) {
571 switch (coltype[col]) {
572 case Numeric: {
573 double value;
574 ts &gt;&gt; value &gt;&gt; ws;
575 rowdata[col].dbl = value;
576 break;
577 }
578 case Label: {
579 <a href="qstring.html">QString</a>* value = new <a href="qstring.html">QString</a>;
580 ts &gt;&gt; *value &gt;&gt; ws;
581 rowdata[col].str = value;
582 break;
583 }
584 }
585 col++;
586 }
587
588 data.<a href="qptrlist.html#append">append</a>(rowdata);
589 }
590
591 line.<a href="qiodevice.html#close">close</a>();
592 line.<a href="qiodevice.html#open">open</a>(IO_WriteOnly|IO_Truncate);
593}
594
595<a name="x2752"></a>int Grapher::<a href="qnpinstance.html#write">write</a>(QNPStream* /*str*/, int /*offset*/, int len, void* buffer)
596{
597 // The browser calls this function when data is available on one
598 // of the streams the plugin has requested. Since we are only
599 // processing one stream - the URL in the SRC argument of the EMBED
600 // tag, we assume the QNPStream is that one. Also, since we do not
601 // override QNPInstance::writeReady(), we must accepts ALL the data
602 // that is sent to this function.
603 //
604 char* txt = (char*)buffer;
605 for (int i=0; i&lt;len; i++) {
606 char ch = txt[i];
607 switch ( ch ) {
608 case '\n':
609 consumeLine();
610 break;
611 case '\r': // ignore;
612 break;
613 default:
614<a name="x2744"></a> line.<a href="qiodevice.html#putch">putch</a>(ch);
615 }
616 }
617 if ( <a href="qnpinstance.html#widget">widget</a>() )
618 <a href="qnpinstance.html#widget">widget</a>()-&gt;update();
619
620 return len;
621}
622
623void <a name="f575"></a>Grapher::aboutPlugin()
624{
625 <a href="qnpinstance.html#getURL">getURL</a>( "http://doc.trolltech.com/netscape-plugin.html", "_blank" );
626}
627
628void <a name="f576"></a>Grapher::aboutData()
629{
630 const char* page = <a href="qnpinstance.html#arg">arg</a>("DATAPAGE");
631 if (page)
632 <a href="qnpinstance.html#getURL">getURL</a>( page, "_blank" );
633 else
634<a name="x2750"></a> QMessageBox::<a href="qmessagebox.html#message">message</a>("Help", "No help for this data");
635}
636
637
638//
639// GrapherPlugin is the start of everything. It is a QNPlugin subclass,
640// and it is responsible for describing the plugin to the browser, and
641// creating instances of the plugin when it appears in web page.
642//
643
644class GrapherPlugin : public <a href="qnplugin.html">QNPlugin</a> {
645public:
646 GrapherPlugin()
647 {
648 }
649
650 <a href="qnpinstance.html">QNPInstance</a>* newInstance()
651 {
652 // Make a new Grapher, our subclass of QNPInstance.
653 return new Grapher;
654 }
655
656 const char* getMIMEDescription() const
657 {
658 // Describe the MIME types which this plugin can
659 // process. Just the concocted "application/x-graphable"
660 // type, with the "g1n" filename extension.
661 //
662 return "application/x-graphable:g1n:Graphable ASCII numeric data";
663 }
664
665 const char * getPluginNameString() const
666 {
667 // The name of the plugin. This is the title string used in
668 // the "About Plugins" page of the browser.
669 //
670 return "Qt-based Graph Plugin";
671 }
672
673 const char * getPluginDescriptionString() const
674 {
675 // A longer description of the plugin.
676 //
677 return "A Qt-based LiveConnected plug-in that graphs numeric data";
678 }
679
680};
681
682//
683// Finally, we provide the implementation of QNPlugin::create(), to
684// provide our subclass of QNPlugin.
685//
686
687QNPlugin* QNPlugin::create()
688{
689 return new GrapherPlugin;
690}
691
692#include "grapher.moc"
693</pre>
694
695<p>See also <a href="nsplugin-examples.html">Netscape Plugin Examples</a>.
696
697<!-- eof -->
698<p><address><hr><div align=center>
699<table width=100% cellspacing=0 border=0><tr>
700<td>Copyright &copy; 2007
701<a href="troll.html">Trolltech</a><td align=center><a href="trademarks.html">Trademarks</a>
702<td align=right><div align=right>Qt 3.3.8</div>
703</table></div></address></body>
704</html>
Note: See TracBrowser for help on using the repository browser.