1 /****************************************************************************
3 ** Copyright (C) 2003-2008 Trolltech ASA. All rights reserved.
5 ** This file is part of a Qt Solutions component.
7 ** This file may be used under the terms of the GNU General Public
8 ** License version 2.0 as published by the Free Software Foundation
9 ** and appearing in the file LICENSE.GPL included in the packaging of
10 ** this file. Please review the following information to ensure GNU
11 ** General Public Licensing requirements will be met:
12 ** http://www.trolltech.com/products/qt/opensource.html
14 ** If you are unsure which license is appropriate for your use, please
15 ** review the following information:
16 ** http://www.trolltech.com/products/qt/licensing.html or contact the
17 ** Trolltech sales department at sales@trolltech.com.
19 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
20 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22 ****************************************************************************/
24 #include <kapplication.h>
28 #include "qtbrowserplugin.h"
29 #include "qtbrowserplugin_p.h"
33 # define WINAPI __stdcall
45 static void debuginfo(const QString &str)
47 static bool inited = false;
48 QFile file("/tmp/qnsdebug.txt");
49 if (file.open(QFile::WriteOnly | QFile::Append)) {
51 file.write("\n\n*** New run started ***\n");
54 file.write(qtNPFactory()->pluginName().toLatin1() + ": " + str.toLatin1() + '\n');
62 static QtNPFactory
*qNP
= 0;
63 static NPNetscapeFuncs
*qNetscapeFuncs
= 0;
65 // The single global plugin
66 QtNPFactory
*qtNPFactory()
68 extern QtNPFactory
*qtns_instantiate();
71 qNP
= qtns_instantiate();
77 // NPN functions, forwarding to function pointers provided by browser
78 void NPN_Version(int* plugin_major
, int* plugin_minor
, int* netscape_major
, int* netscape_minor
)
80 Q_ASSERT(qNetscapeFuncs
);
81 *plugin_major
= NP_VERSION_MAJOR
;
82 *plugin_minor
= NP_VERSION_MINOR
;
83 *netscape_major
= qNetscapeFuncs
->version
>> 8; // Major version is in high byte
84 *netscape_minor
= qNetscapeFuncs
->version
& 0xFF; // Minor version is in low byte
87 #define NPN_Prolog(x) \
88 Q_ASSERT(qNetscapeFuncs); \
89 Q_ASSERT(qNetscapeFuncs->x); \
92 const char *NPN_UserAgent(NPP instance)
95 return FIND_FUNCTION_POINTER(NPN_UserAgentFP
, qNetscapeFuncs
->uagent
)(instance
);
98 void NPN_Status(NPP instance
, const char* message
)
101 FIND_FUNCTION_POINTER(NPN_StatusFP
, qNetscapeFuncs
->status
)(instance
, message
);
104 NPError
NPN_GetURL(NPP instance
, const char* url
, const char* window
)
107 return FIND_FUNCTION_POINTER(NPN_GetURLFP
, qNetscapeFuncs
->geturl
)(instance
, url
, window
);
110 NPError
NPN_GetURLNotify(NPP instance
, const char* url
, const char* window
, void* notifyData
)
112 if ((qNetscapeFuncs
->version
& 0xFF) < NPVERS_HAS_NOTIFICATION
)
113 return NPERR_INCOMPATIBLE_VERSION_ERROR
;
115 NPN_Prolog(geturlnotify
);
116 return FIND_FUNCTION_POINTER(NPN_GetURLNotifyFP
, qNetscapeFuncs
->geturlnotify
)(instance
, url
, window
, notifyData
);
119 NPError
NPN_PostURLNotify(NPP instance
, const char* url
, const char* window
, uint32 len
, const char* buf
, NPBool file
, void* notifyData
)
121 if ((qNetscapeFuncs
->version
& 0xFF) < NPVERS_HAS_NOTIFICATION
)
122 return NPERR_INCOMPATIBLE_VERSION_ERROR
;
124 NPN_Prolog(posturlnotify
);
125 return FIND_FUNCTION_POINTER(NPN_PostURLNotifyFP
, qNetscapeFuncs
->posturlnotify
)(instance
, url
, window
, len
, buf
, file
, notifyData
);
128 void* NPN_MemAlloc(uint32 size
)
130 NPN_Prolog(memalloc
);
131 return FIND_FUNCTION_POINTER(NPN_MemAllocFP
, qNetscapeFuncs
->memalloc
)(size
);
134 void NPN_MemFree(void* ptr
)
137 FIND_FUNCTION_POINTER(NPN_MemFreeFP
, qNetscapeFuncs
->memfree
)(ptr
);
140 uint32
NPN_MemFlush(uint32 size
)
142 NPN_Prolog(memflush
);
143 return FIND_FUNCTION_POINTER(NPN_MemFlushFP
, qNetscapeFuncs
->memflush
)(size
);
146 NPError
NPN_GetValue(NPP instance
, NPNVariable variable
, void *ret_value
)
148 NPN_Prolog(getvalue
);
149 return FIND_FUNCTION_POINTER(NPN_GetValueFP
, qNetscapeFuncs
->getvalue
)(instance
, variable
, ret_value
);
152 NPError
NPN_SetValue(NPP instance
, NPPVariable variable
, void *ret_value
)
154 NPN_Prolog(setvalue
);
155 return FIND_FUNCTION_POINTER(NPN_SetValueFP
, qNetscapeFuncs
->setvalue
)(instance
, variable
, ret_value
);
158 NPIdentifier
NPN_GetStringIdentifier(const char* name
)
160 NPN_Prolog(getstringidentifier
);
161 return FIND_FUNCTION_POINTER(NPN_GetStringIdentifierFP
, qNetscapeFuncs
->getstringidentifier
)(name
);
164 void NPN_GetStringIdentifiers(const char** names
, int32 nameCount
, NPIdentifier
* identifiers
)
166 NPN_Prolog(getstringidentifiers
);
167 FIND_FUNCTION_POINTER(NPN_GetStringIdentifiersFP
, qNetscapeFuncs
->getstringidentifiers
)(names
, nameCount
, identifiers
);
170 NPIdentifier
NPN_GetIntIdentifier(int32 intid
)
172 NPN_Prolog(getintidentifier
);
173 return FIND_FUNCTION_POINTER(NPN_GetIntIdentifierFP
, qNetscapeFuncs
->getintidentifier
)(intid
);
176 bool NPN_IdentifierIsString(NPIdentifier identifier
)
178 NPN_Prolog(identifierisstring
);
179 return FIND_FUNCTION_POINTER(NPN_IdentifierIsStringFP
, qNetscapeFuncs
->identifierisstring
)(identifier
);
182 char* NPN_UTF8FromIdentifier(NPIdentifier identifier
)
184 NPN_Prolog(utf8fromidentifier
);
185 return FIND_FUNCTION_POINTER(NPN_UTF8FromIdentifierFP
, qNetscapeFuncs
->utf8fromidentifier
)(identifier
);
188 int32
NPN_IntFromIdentifier(NPIdentifier identifier
)
190 NPN_Prolog(intfromidentifier
);
191 return FIND_FUNCTION_POINTER(NPN_IntFromIdentifierFP
, qNetscapeFuncs
->intfromidentifier
)(identifier
);
194 NPObject
* NPN_CreateObject(NPP npp
, NPClass
*aClass
)
196 NPN_Prolog(createobject
);
197 return FIND_FUNCTION_POINTER(NPN_CreateObjectFP
, qNetscapeFuncs
->createobject
)(npp
, aClass
);
200 NPObject
* NPN_RetainObject(NPObject
*obj
)
202 NPN_Prolog(retainobject
);
203 return FIND_FUNCTION_POINTER(NPN_RetainObjectFP
, qNetscapeFuncs
->retainobject
)(obj
);
206 void NPN_ReleaseObject(NPObject
*obj
)
208 NPN_Prolog(releaseobject
);
209 FIND_FUNCTION_POINTER(NPN_ReleaseObjectFP
, qNetscapeFuncs
->releaseobject
)(obj
);
212 // Scripting implementation (QObject calling JavaScript in browser) - we don't use those
213 bool NPN_Invoke(NPP npp
, NPObject
* obj
, NPIdentifier methodName
, const NPVariant
*args
, int32 argCount
, NPVariant
*result
)
216 return FIND_FUNCTION_POINTER(NPN_InvokeFP
, qNetscapeFuncs
->invoke
)(npp
, obj
, methodName
, args
, argCount
, result
);
219 bool NPN_InvokeDefault(NPP npp
, NPObject
* obj
, const NPVariant
*args
, int32 argCount
, NPVariant
*result
)
221 NPN_Prolog(invokedefault
);
222 return FIND_FUNCTION_POINTER(NPN_InvokeDefaultFP
, qNetscapeFuncs
->invokedefault
)(npp
, obj
, args
, argCount
, result
);
225 bool NPN_Evaluate(NPP npp
, NPObject
*obj
, NPString
*script
, NPVariant
*result
)
227 NPN_Prolog(evaluate
);
228 return FIND_FUNCTION_POINTER(NPN_EvaluateFP
, qNetscapeFuncs
->evaluate
)(npp
, obj
, script
, result
);
231 bool NPN_GetProperty(NPP npp
, NPObject
*obj
, NPIdentifier propertyName
, NPVariant
*result
)
233 NPN_Prolog(getproperty
);
234 return FIND_FUNCTION_POINTER(NPN_GetPropertyFP
, qNetscapeFuncs
->getproperty
)(npp
, obj
, propertyName
, result
);
237 bool NPN_SetProperty(NPP npp
, NPObject
*obj
, NPIdentifier propertyName
, const NPVariant
*value
)
239 NPN_Prolog(setproperty
);
240 return FIND_FUNCTION_POINTER(NPN_SetPropertyFP
, qNetscapeFuncs
->setproperty
)(npp
, obj
, propertyName
, value
);
243 bool NPN_RemoveProperty(NPP npp
, NPObject
*obj
, NPIdentifier propertyName
)
245 NPN_Prolog(removeproperty
);
246 return FIND_FUNCTION_POINTER(NPN_RemovePropertyFP
, qNetscapeFuncs
->removeproperty
)(npp
, obj
, propertyName
);
249 bool NPN_HasProperty(NPP npp
, NPObject
*obj
, NPIdentifier propertyName
)
251 NPN_Prolog(hasproperty
);
252 return FIND_FUNCTION_POINTER(NPN_HasPropertyFP
, qNetscapeFuncs
->hasproperty
)(npp
, obj
, propertyName
);
255 bool NPN_HasMethod(NPP npp
, NPObject
*obj
, NPIdentifier methodName
)
257 NPN_Prolog(hasmethod
);
258 return FIND_FUNCTION_POINTER(NPN_HasMethodFP
, qNetscapeFuncs
->hasmethod
)(npp
, obj
, methodName
);
261 void NPN_ReleaseVariantValue(NPVariant
*variant
)
263 NPN_Prolog(releasevariantvalue
);
264 FIND_FUNCTION_POINTER(NPN_ReleaseVariantValueFP
, qNetscapeFuncs
->releasevariantvalue
)(variant
);
267 void NPN_SetException(NPObject
*obj
, const char *message
)
269 qDebug("NPN_SetException: %s", message
);
270 NPN_Prolog(setexception
);
271 FIND_FUNCTION_POINTER(NPN_SetExceptionFP
, qNetscapeFuncs
->setexception
)(obj
, message
);
274 // Scripting implementation (JavaScript calling QObject)
275 #define NPClass_Prolog \
276 if (!npobj->_class) return false; \
277 if (!npobj->_class->qtnp) return false; \
278 QtNPInstance *This = npobj->_class->qtnp; \
279 if (!This->qt.object) return false; \
280 QObject *qobject = This->qt.object \
283 static NPObject *NPAllocate(NPP npp, NPClass *aClass)
292 static void NPDeallocate(NPObject
*npobj
)
300 static void NPInvalidate(NPObject
*npobj
)
303 delete npobj
->_class
;
307 enum MetaOffset
{ MetaProperty
, MetaMethod
};
309 static int metaOffset(const QMetaObject
*metaObject
, MetaOffset offsetType
)
311 int classInfoIndex
= metaObject
->indexOfClassInfo("ToSuperClass");
312 if (classInfoIndex
== -1)
314 QByteArray ToSuperClass
= metaObject
->classInfo(classInfoIndex
).value();
315 int offset
= offsetType
== MetaProperty
? metaObject
->propertyOffset()
316 : metaObject
->methodOffset();
318 while (ToSuperClass
!= metaObject
->className()) {
319 metaObject
= metaObject
->superClass();
322 offset
-= offsetType
== MetaProperty
? metaObject
->propertyCount()
323 : metaObject
->methodCount();
328 static int publicMethodIndex(NPObject
*npobj
, const QByteArray
&slotName
, int argCount
= -1)
331 const QMetaObject
*metaObject
= qobject
->metaObject();
332 for (int slotIndex
= metaOffset(metaObject
, MetaMethod
); slotIndex
< metaObject
->methodCount(); ++slotIndex
) {
333 const QMetaMethod slot
= qobject
->metaObject()->method(slotIndex
);
334 if (slot
.access() != QMetaMethod::Public
|| slot
.methodType() == QMetaMethod::Signal
)
336 QByteArray signature
= slot
.signature();
337 if (signature
.left(signature
.indexOf('(')) == slotName
) {
338 if (argCount
== -1 || slot
.parameterTypes().count() == argCount
)
345 static bool NPClass_HasMethod(NPObject
*npobj
, NPIdentifier name
)
349 return publicMethodIndex(npobj
, NPN_UTF8FromIdentifier(name
)) != -1;
352 static bool NPClass_Invoke(NPObject
*npobj
, NPIdentifier name
, const NPVariant
*args
, uint32 argCount
, NPVariant
*result
)
355 const QByteArray slotName
= NPN_UTF8FromIdentifier(name
);
356 int slotIndex
= publicMethodIndex(npobj
, slotName
, static_cast<int>(argCount
));
357 if (slotIndex
== -1) {
358 NPN_SetException(npobj
, QByteArray("No method '" + slotName
+ "' with " + QByteArray::number(argCount
) + " parameters").constData());
362 const QMetaMethod slot
= qobject
->metaObject()->method(slotIndex
);
363 QList
<QByteArray
> parameterTypes
= slot
.parameterTypes();
364 if (parameterTypes
.count() != static_cast<int>(argCount
)) {
365 NPN_SetException(npobj
, QByteArray("Wrong parameter count for method " + slotName
).constData());
369 QVariant
returnVariant(QVariant::nameToType(slot
.typeName()), (void*)0);
370 QVector
<QVariant
> variants(parameterTypes
.count()); // keep data alive
371 QVector
<const void*> metacallArgs(parameterTypes
.count() + 1); // arguments for qt_metacall
372 metacallArgs
[0] = returnVariant
.data(); // args[0] == return value
374 for (int p
= 0; p
< parameterTypes
.count(); ++p
) {
375 QVariant::Type type
= QVariant::nameToType(parameterTypes
.at(p
));
376 if (type
== QVariant::Invalid
&& parameterTypes
.at(p
) != "QVariant") {
377 NPN_SetException(npobj
, QString("Parameter %1 in method '%2' has invalid type")
378 .arg(p
).arg(QString::fromUtf8(slotName
)).toAscii().constData());
381 QVariant qvar
= args
[p
];
382 if (type
!= QVariant::Invalid
&& !qvar
.convert(type
)) {
383 NPN_SetException(npobj
, QString("Parameter %1 to method '%2' needs to be convertable to '%3'")
384 .arg(p
).arg(QString::fromUtf8(slotName
)).arg(QString::fromAscii(parameterTypes
.at(p
))).toAscii().constData());
389 if (type
== QVariant::Invalid
)
390 metacallArgs
[p
+ 1] = &variants
.at(p
);
392 metacallArgs
[p
+ 1] = variants
.at(p
).constData(); // must not detach!
395 qobject
->qt_metacall(QMetaObject::InvokeMetaMethod
, slotIndex
, const_cast<void**>(metacallArgs
.data()));
396 if (returnVariant
.isValid() && result
)
397 *result
= NPVariant::fromQVariant(This
, returnVariant
);
402 static bool NPClass_InvokeDefault(NPObject
* /*npobj*/, const NPVariant
* /*args*/, uint32
/*argCount*/, NPVariant
* /*result*/)
407 static bool NPClass_HasProperty(NPObject
*npobj
, NPIdentifier name
)
410 const QByteArray qname
= NPN_UTF8FromIdentifier(name
);
411 const QMetaObject
*metaObject
= qobject
->metaObject();
412 int propertyIndex
= metaObject
->indexOfProperty(qname
);
413 if (propertyIndex
== -1 || propertyIndex
< metaOffset(metaObject
, MetaProperty
))
415 QMetaProperty property
= qobject
->metaObject()->property(propertyIndex
);
416 if (!property
.isScriptable())
422 static bool NPClass_GetProperty(NPObject
*npobj
, NPIdentifier name
, NPVariant
*result
)
425 const QByteArray qname
= NPN_UTF8FromIdentifier(name
);
426 QVariant qvar
= qobject
->property(qname
);
427 if (!qvar
.isValid()) {
428 NPN_SetException(npobj
, QByteArray("Failed to get value for property " + qname
).constData());
431 *result
= NPVariant::fromQVariant(This
, qvar
);
435 static bool NPClass_SetProperty(NPObject
*npobj
, NPIdentifier name
, const NPVariant
*result
)
438 const QByteArray qname
= NPN_UTF8FromIdentifier(name
);
439 QVariant qvar
= *result
;
440 return qobject
->setProperty(qname
, qvar
);
443 static bool NPClass_RemoveProperty(NPObject
* /*npobj*/, NPIdentifier
/*name*/)
448 NPClass::NPClass(QtNPInstance
*This
)
450 structVersion
= NP_CLASS_STRUCT_VERSION
;
453 invalidate
= NPInvalidate
;
454 hasMethod
= NPClass_HasMethod
;
455 invoke
= NPClass_Invoke
;
456 invokeDefault
= NPClass_InvokeDefault
;
457 hasProperty
= NPClass_HasProperty
;
458 getProperty
= NPClass_GetProperty
;
459 setProperty
= NPClass_SetProperty
;
460 removeProperty
= NPClass_RemoveProperty
;
472 NPString
NPString::fromQString(const QString
&qstr
)
475 const QByteArray qutf8
= qstr
.toUtf8();
477 npstring
.utf8length
= qutf8
.length();
478 npstring
.utf8characters
= (char*)NPN_MemAlloc(npstring
.utf8length
);
479 memcpy((char*)npstring
.utf8characters
, qutf8
.constData(), npstring
.utf8length
);
484 NPString::operator QString() const
486 return QString::fromUtf8(utf8characters
, utf8length
);
489 NPVariant
NPVariant::fromQVariant(QtNPInstance
*This
, const QVariant
&qvariant
)
495 QVariant
qvar(qvariant
);
496 switch(qvariant
.type()) {
498 npvar
.value
.boolValue
= qvar
.toBool();
499 npvar
.type
= Boolean
;
502 npvar
.value
.intValue
= qvar
.toInt();
505 case QVariant::Double
:
506 npvar
.value
.doubleValue
= qvar
.toDouble();
509 case QVariant::UserType
:
511 QByteArray userType
= qvariant
.typeName();
512 if (userType
.endsWith('*')) {
513 QtNPInstance
*that
= new QtNPInstance
;
514 that
->npp
= This
->npp
;
515 that
->qt
.object
= *(QObject
**)qvariant
.constData();
516 NPClass
*npclass
= new NPClass(that
);
517 npclass
->delete_qtnp
= true;
518 npvar
.value
.objectValue
= NPN_CreateObject(This
->npp
, npclass
);
523 default: // including QVariant::String
524 if (!qvar
.convert(QVariant::String
))
527 npvar
.value
.stringValue
= NPString::fromQString(qvar
.toString());
534 NPVariant::operator QVariant() const
542 if (!value
.objectValue
|| !value
.objectValue
->_class
)
544 NPClass
*aClass
= value
.objectValue
->_class
;
546 if (aClass
->invoke
!= NPClass_Invoke
)
548 // or just empty for some reason
549 QObject
*qobject
= aClass
->qtnp
->qt
.object
;
552 QByteArray typeName
= qobject
->metaObject()->className();
553 int userType
= QMetaType::type(typeName
+ "*");
554 if (userType
== QVariant::Invalid
)
556 QVariant
result(userType
, &aClass
->qtnp
->qt
.object
);
558 Q_ASSERT(*(QObject
**)result
.constData() == aClass
->qtnp
->qt
.object
);
562 return value
.boolValue
;
564 return value
.intValue
;
566 return value
.doubleValue
;
568 return QString(value
.stringValue
);
575 // Helper class for handling incoming data
579 QtNPStream(NPP instance
, NPStream
*st
);
580 virtual ~QtNPStream()
585 bool finish(QtNPBindable
*bindable
);
597 qint64
readData(char *, qint64
);
598 qint64
writeData(const char *, qint64
);
601 QtNPStream::QtNPStream(NPP instance
, NPStream
*st
)
602 : reason(NPRES_DONE
), npp(instance
), stream(st
)
607 Returns the URL from which the stream was created, or the empty string
608 for write-only streams.
610 QString
QtNPStream::url() const
614 return QString::fromLocal8Bit(stream
->url
);
617 class ErrorBuffer
: public QBuffer
619 friend class QtNPStream
;
622 bool QtNPStream::finish(QtNPBindable
*bindable
)
631 // no data at all? url is probably local file (Opera)
632 if (buffer
.isEmpty() && file
.fileName().isEmpty()) {
633 QUrl u
= QUrl::fromEncoded(stream
->url
);
634 QString lfn
= u
.toLocalFile();
635 if (lfn
.startsWith("//localhost/"))
637 file
.setFileName(lfn
);
641 file
.setObjectName(url());
642 res
= bindable
->readData(&file
, mime
);
645 io
.setObjectName(url());
646 res
= bindable
->readData(&io
, mime
);
649 case NPRES_USER_BREAK
:
652 empty
.setObjectName(url());
653 empty
.setErrorString("User cancelled operation."),
654 res
= bindable
->readData(&empty
, mime
);
657 case NPRES_NETWORK_ERR
:
660 empty
.setObjectName(url());
661 empty
.setErrorString("Network error during download."),
662 res
= bindable
->readData(&empty
, mime
);
674 // Helper class for forwarding signal emissions to the respective JavaScript
675 class QtSignalForwarder
: public QObject
678 QtSignalForwarder(QtNPInstance
*that
)
679 : This(that
), domNode(0)
686 NPN_ReleaseObject(domNode
);
689 int qt_metacall(QMetaObject::Call call
, int index
, void **args
);
696 int QtSignalForwarder::qt_metacall(QMetaObject::Call call
, int index
, void **args
)
698 // no support for QObject method/properties etc!
699 if (!This
|| !This
->npp
|| call
!= QMetaObject::InvokeMetaMethod
706 QString msg
= *(QString
*)args
[1];
707 NPN_Status(This
->npp
, msg
.toLocal8Bit().constData());
712 QObject
*qobject
= This
->qt
.object
;
714 NPN_GetValue(This
->npp
, NPNVPluginElementNPObject
, &domNode
);
717 const QMetaObject
*metaObject
= qobject
->metaObject();
718 if (index
< metaOffset(metaObject
, MetaMethod
))
721 const QMetaMethod method
= metaObject
->method(index
);
722 Q_ASSERT(method
.methodType() == QMetaMethod::Signal
);
724 QByteArray signalSignature
= method
.signature();
725 QByteArray scriptFunction
= signalSignature
.left(signalSignature
.indexOf('('));
726 NPIdentifier id
= NPN_GetStringIdentifier(scriptFunction
.constData());
727 if (NPN_HasMethod(This
->npp
, domNode
, id
)) {
728 QList
<QByteArray
> parameterTypes
= method
.parameterTypes();
729 QVector
<NPVariant
> parameters
;
732 for (int p
= 0; p
< parameterTypes
.count(); ++p
) {
733 QVariant::Type type
= QVariant::nameToType(parameterTypes
.at(p
));
734 if (type
== QVariant::Invalid
) {
735 NPN_SetException(domNode
, QByteArray("Unsupported parameter type in ") + scriptFunction
);
739 QVariant
qvar(type
, args
[p
+ 1]);
740 NPVariant npvar
= NPVariant::fromQVariant(This
, qvar
);
741 if (npvar
.type
== NPVariant::Null
|| npvar
.type
== NPVariant::Void
) {
742 NPN_SetException(domNode
, QByteArray("Unsupported parameter value in ") + scriptFunction
);
751 NPError nperror
= NPN_Invoke(This
->npp
, domNode
, id
, parameters
.constData(), parameters
.count(), &result
);
752 if (nperror
!= NPERR_NO_ERROR
&& false) { // disabled, as NPN_Invoke seems to always return GENERICERROR
753 NPN_SetException(domNode
, QByteArray("Error invoking event handler ") + scriptFunction
);
755 // ### TODO: update return value (args[0]) (out-parameters not supported anyway)
756 NPN_ReleaseVariantValue(&result
);
768 NPP_GetValue(NPP instance
, NPPVariable variable
, void *value
)
770 if (!instance
|| !instance
->pdata
)
771 return NPERR_INVALID_INSTANCE_ERROR
;
773 QtNPInstance
* This
= (QtNPInstance
*) instance
->pdata
;
776 case NPPVpluginNameString
:
778 static QByteArray name
= qtNPFactory()->pluginName().toLocal8Bit();
779 *(const char**)value
= name
.constData();
782 case NPPVpluginDescriptionString
:
784 static QByteArray description
= qtNPFactory()->pluginDescription().toLocal8Bit();
785 *(const char**)value
= description
.constData();
790 case NPPVpluginNeedsXEmbed
:
791 *(int*)value
= true; // PRBool = int
795 case NPPVpluginScriptableNPObject
:
797 NPObject
*object
= NPN_CreateObject(instance
, new NPClass(This
));
798 *(NPObject
**)value
= object
;
803 QObject
*object
= This
->qt
.object
;
804 const QMetaObject
*metaObject
= object
->metaObject();
805 int defaultIndex
= metaObject
->indexOfClassInfo("DefaultProperty");
806 if (defaultIndex
== -1)
807 return NPERR_GENERIC_ERROR
;
808 QByteArray defaultProperty
= metaObject
->classInfo(defaultIndex
).value();
809 if (defaultProperty
.isEmpty())
810 return NPERR_GENERIC_ERROR
;
811 QVariant defaultValue
= object
->property(defaultProperty
);
812 if (!defaultValue
.isValid())
813 return NPERR_GENERIC_ERROR
;
814 defaultProperty
= defaultValue
.toString().toUtf8();
815 int size
= defaultProperty
.size();
816 char *utf8
= (char*)NPN_MemAlloc(size
+ 1);
817 memcpy(utf8
, defaultProperty
.constData(), size
);
818 utf8
[size
] = 0; // null-terminator
819 *(void**)value
= utf8
;
823 return NPERR_GENERIC_ERROR
;
826 return NPERR_NO_ERROR
;
830 NPP_SetValue(NPP instance
, NPPVariable variable
, void *value
)
835 if (!instance
|| !instance
->pdata
)
836 return NPERR_INVALID_INSTANCE_ERROR
;
841 return NPERR_GENERIC_ERROR;
844 return NPERR_NO_ERROR
;
847 extern "C" int16
NPP_Event(NPP instance
, NPEvent
* event
)
849 if (!instance
|| !instance
->pdata
)
850 return NPERR_INVALID_INSTANCE_ERROR
;
852 QtNPInstance
* This
= (QtNPInstance
*) instance
->pdata
;
853 extern bool qtns_event(QtNPInstance
*, NPEvent
*);
854 return qtns_event(This
, event
) ? 1 : 0;
858 // Instance state information about the plugin.
860 NP_GetMIMEDescription(void)
862 static QByteArray mime
= qtNPFactory()->mimeTypes().join(";").toLocal8Bit();
863 return (char*)mime
.constData();
867 NP_GetValue(void*, NPPVariable aVariable
, void *aValue
)
869 NPError err
= NPERR_NO_ERROR
;
871 static QByteArray name
= qtNPFactory()->pluginName().toLocal8Bit();
872 static QByteArray descr
= qtNPFactory()->pluginDescription().toLocal8Bit();
875 case NPPVpluginNameString
:
876 *static_cast<const char **> (aValue
) = name
.constData();
878 case NPPVpluginDescriptionString
:
879 *static_cast<const char **>(aValue
) = descr
.constData();
881 case NPPVpluginNeedsXEmbed
:
882 *static_cast<int*>(aValue
) = true;
884 case NPPVpluginTimerInterval
:
885 case NPPVpluginKeepLibraryInMemory
:
887 err
= NPERR_INVALID_PARAM
;
895 ** NPP_New is called when your plugin is instantiated (i.e. when an EMBED
896 ** tag appears on a page).
899 NPP_New(NPMIMEType pluginType
,
905 NPSavedData
* /*saved*/)
908 return NPERR_INVALID_INSTANCE_ERROR
;
910 QtNPInstance
* This
= new QtNPInstance
;
912 return NPERR_OUT_OF_MEMORY_ERROR
;
914 instance
->pdata
= This
;
917 This
->npp
= instance
;
918 This
->fMode
= mode
; // NP_EMBED, NP_FULL, or NP_BACKGROUND (see npapi.h)
922 This
->rootWidget
= 0;
924 This
->pendingStream
= 0; // stream might be created before instance
925 This
->mimetype
= QString::fromLatin1(pluginType
);
926 This
->notificationSeqNum
= 0;
928 for (int i
= 0; i
< argc
; i
++) {
929 QByteArray name
= QByteArray(argn
[i
]).toLower();
931 This
->htmlID
= argv
[i
];
932 This
->parameters
[name
] = QVariant(argv
[i
]);
935 return NPERR_NO_ERROR
;
939 NPP_Destroy(NPP instance
, NPSavedData
** /*save*/)
941 if (!instance
|| !instance
->pdata
)
942 return NPERR_INVALID_INSTANCE_ERROR
;
944 QtNPInstance
* This
= (QtNPInstance
*) instance
->pdata
;
947 //This->widget->destroy(false, false); // X has destroyed all windows
949 delete This
->qt
.object
;
953 extern void qtns_destroy(QtNPInstance
*This
);
958 return NPERR_NO_ERROR
;
961 static QtNPInstance
*next_pi
= 0; // helper to connect to QtNPBindable
964 NPP_SetWindow(NPP instance
, NPWindow
* window
)
967 return NPERR_INVALID_INSTANCE_ERROR
;
969 QtNPInstance
* This
= (QtNPInstance
*) instance
->pdata
;
970 extern void qtns_setGeometry(QtNPInstance
*, const QRect
&, const QRect
&);
972 const QRect
clipRect(window
->clipRect
.left
, window
->clipRect
.top
,
973 window
->clipRect
.right
- window
->clipRect
.left
,
974 window
->clipRect
.bottom
- window
->clipRect
.top
);
976 This
->geometry
= QRect(window
->x
, window
->y
, window
->width
, window
->height
);
978 // take a shortcut if all that was changed is the geometry
979 if (qobject_cast
<QWidget
*>(This
->qt
.object
) && window
&& This
->window
== (QtNPInstance::Widget
)window
->window
) {
980 qtns_setGeometry(This
, This
->geometry
, clipRect
);
981 return NPERR_NO_ERROR
;
984 delete This
->qt
.object
;
986 extern void qtns_destroy(QtNPInstance
*This
);
991 return NPERR_NO_ERROR
;
994 This
->window
= (QtNPInstance::Widget
)window
->window
;
996 //This->display = ((NPSetWindowCallbackStruct *)window->ws_info)->display;
999 extern void qtns_initialize(QtNPInstance
*);
1000 qtns_initialize(This
);
1003 This
->qt
.object
= qtNPFactory()->createObject(This
->mimetype
);
1006 if (!This
->qt
.object
)
1007 return NPERR_NO_ERROR
;
1009 if (!This
->htmlID
.isEmpty())
1010 This
->qt
.object
->setObjectName(QLatin1String(This
->htmlID
));
1012 This
->filter
= new QtSignalForwarder(This
);
1013 QStatusBar
*statusbar
= qFindChild
<QStatusBar
*>(This
->qt
.object
);
1015 int statusSignal
= statusbar
->metaObject()->indexOfSignal("messageChanged(QString)");
1016 if (statusSignal
!= -1) {
1017 QMetaObject::connect(statusbar
, statusSignal
, This
->filter
, -1);
1022 const QMetaObject
*mo
= This
->qt
.object
->metaObject();
1023 for (int p
= 0; p
< mo
->propertyCount(); ++p
) {
1024 const QMetaProperty property
= mo
->property(p
);
1025 QByteArray
name(property
.name());
1026 QVariant value
= This
->parameters
.value(name
.toLower());
1027 if (value
.isValid())
1028 property
.write(This
->qt
.object
, value
);
1030 for (int methodIndex
= 0; methodIndex
< mo
->methodCount(); ++methodIndex
) {
1031 const QMetaMethod method
= mo
->method(methodIndex
);
1032 if (method
.methodType() == QMetaMethod::Signal
)
1033 QMetaObject::connect(This
->qt
.object
, methodIndex
, This
->filter
, methodIndex
);
1036 if (This
->pendingStream
) {
1037 This
->pendingStream
->finish(This
->bindable
);
1038 This
->pendingStream
= 0;
1041 if (!qobject_cast
<QWidget
*>(This
->qt
.object
))
1042 return NPERR_NO_ERROR
;
1044 extern void qtns_embed(QtNPInstance
*);
1047 QEvent
e(QEvent::EmbeddingControl
);
1048 KApplication::sendEvent(This
->qt
.widget
, &e
);
1050 if (!This
->qt
.widget
->testAttribute(Qt::WA_PaintOnScreen
))
1051 This
->qt
.widget
->setAutoFillBackground(true);
1052 This
->qt
.widget
->raise();
1053 qtns_setGeometry(This
, This
->geometry
, clipRect
);
1054 This
->qt
.widget
->show();
1056 return NPERR_NO_ERROR
;
1060 NPP_NewStream(NPP instance
,
1063 NPBool
/*seekable*/,
1067 return NPERR_INVALID_INSTANCE_ERROR
;
1069 QtNPInstance
* This
= (QtNPInstance
*) instance
->pdata
;
1071 return NPERR_NO_ERROR
;
1073 QtNPStream
*qstream
= new QtNPStream(instance
, stream
);
1074 qstream
->mime
= QString::fromLocal8Bit(type
);
1075 stream
->pdata
= qstream
;
1077 *stype
= NP_ASFILEONLY
;
1079 return NPERR_NO_ERROR
;
1083 NPP_WriteReady(NPP
, NPStream
*stream
)
1090 // Both Netscape and FireFox call this for OnDemand streams as well...
1092 NPP_Write(NPP instance
, NPStream
*stream
, int32
/*offset*/, int32 len
, void *buffer
)
1094 if (!instance
|| !stream
|| !stream
->pdata
)
1095 return NPERR_INVALID_INSTANCE_ERROR
;
1097 // this should not be called, as we always demand a download
1098 QtNPStream
*qstream
= (QtNPStream
*)stream
->pdata
;
1099 QByteArray
data((const char*)buffer
, len
); // make deep copy
1100 qstream
->buffer
+= data
;
1105 // Opera calls this for OnDemand streams without calling NPP_Write first
1107 NPP_DestroyStream(NPP instance
, NPStream
*stream
, NPError reason
)
1109 if (!instance
|| !instance
->pdata
|| !stream
|| !stream
->pdata
)
1110 return NPERR_INVALID_INSTANCE_ERROR
;
1112 QtNPInstance
*This
= (QtNPInstance
*)instance
->pdata
;
1113 QtNPStream
*qstream
= (QtNPStream
*)stream
->pdata
;
1114 qstream
->reason
= reason
;
1116 if (!This
->qt
.object
) { // not yet initialized
1117 This
->pendingStream
= qstream
;
1118 return NPERR_NO_ERROR
;
1121 This
->pendingStream
= 0;
1122 qstream
->finish(This
->bindable
);
1124 return NPERR_NO_ERROR
;
1128 NPP_StreamAsFile(NPP instance
, NPStream
*stream
, const char* fname
)
1130 if (!instance
|| !stream
|| !stream
->pdata
)
1133 QString path
= QString::fromLocal8Bit(fname
);
1135 path
= "/" + path
.section(':', 1).replace(':', '/');
1138 QtNPStream
*qstream
= (QtNPStream
*)stream
->pdata
;
1139 qstream
->file
.setFileName(path
);
1143 NPP_URLNotify(NPP instance
,
1150 QtNPInstance
* This
= (QtNPInstance
*) instance
->pdata
;
1151 if (!This
->bindable
)
1154 QtNPBindable::Reason r
;
1157 r
= QtNPBindable::ReasonDone
;
1159 case NPRES_USER_BREAK
:
1160 r
= QtNPBindable::ReasonBreak
;
1162 case NPRES_NETWORK_ERR
:
1163 r
= QtNPBindable::ReasonError
;
1166 r
= QtNPBindable::ReasonUnknown
;
1170 qint32 id
= static_cast<qint32
>(reinterpret_cast<size_t>(notifyData
));
1171 if (id
< 0) // Sanity check
1174 This
->bindable
->transferComplete(QString::fromLocal8Bit(url
), id
, r
);
1178 NPP_Print(NPP instance
, NPPrint
* printInfo
)
1180 if(!printInfo
|| !instance
)
1183 QtNPInstance
* This
= (QtNPInstance
*) instance
->pdata
;
1184 if (!This
->bindable
)
1188 if (printInfo->mode == NP_FULL) {
1189 printInfo->print.fullPrint.pluginPrinted = This->bindable->printFullPage();
1190 } else if (printInfo->mode == NP_EMBED) {
1191 extern void qtns_print(QtNPInstance*, NPPrint*);
1192 qtns_print(This, printInfo);
1197 // Plug-in entrypoints - these are called by the browser
1199 // Fills in functiontable used by browser to call entry points in plugin.
1200 extern "C" NPError WINAPI
NP_GetEntryPoints(NPPluginFuncs
* pFuncs
)
1203 return NPERR_INVALID_FUNCTABLE_ERROR
;
1205 pFuncs
->size
= sizeof(NPPluginFuncs
);
1206 else if (pFuncs
->size
< sizeof(NPPluginFuncs
))
1207 return NPERR_INVALID_FUNCTABLE_ERROR
;
1209 pFuncs
->version
= (NP_VERSION_MAJOR
<< 8) | NP_VERSION_MINOR
;
1210 pFuncs
->newp
= MAKE_FUNCTION_POINTER(NPP_New
);
1211 pFuncs
->destroy
= MAKE_FUNCTION_POINTER(NPP_Destroy
);
1212 pFuncs
->setwindow
= MAKE_FUNCTION_POINTER(NPP_SetWindow
);
1213 pFuncs
->newstream
= MAKE_FUNCTION_POINTER(NPP_NewStream
);
1214 pFuncs
->destroystream
= MAKE_FUNCTION_POINTER(NPP_DestroyStream
);
1215 pFuncs
->asfile
= MAKE_FUNCTION_POINTER(NPP_StreamAsFile
);
1216 pFuncs
->writeready
= MAKE_FUNCTION_POINTER(NPP_WriteReady
);
1217 pFuncs
->write
= MAKE_FUNCTION_POINTER(NPP_Write
);
1218 pFuncs
->print
= MAKE_FUNCTION_POINTER(NPP_Print
);
1219 pFuncs
->event
= MAKE_FUNCTION_POINTER(NPP_Event
);
1220 pFuncs
->urlnotify
= MAKE_FUNCTION_POINTER(NPP_URLNotify
);
1221 pFuncs
->javaClass
= 0;
1222 pFuncs
->getvalue
= MAKE_FUNCTION_POINTER(NPP_GetValue
);
1223 pFuncs
->setvalue
= MAKE_FUNCTION_POINTER(NPP_SetValue
);
1224 return NPERR_NO_ERROR
;
1234 extern "C" NPError WINAPI
NP_Initialize(NPNetscapeFuncs
* pFuncs
)
1237 return NPERR_INVALID_FUNCTABLE_ERROR
;
1239 qNetscapeFuncs
= pFuncs
;
1240 int navMajorVers
= qNetscapeFuncs
->version
>> 8;
1242 // if the plugin's major version is lower than the Navigator's,
1243 // then they are incompatible, and should return an error
1244 if(navMajorVers
> NP_VERSION_MAJOR
)
1245 return NPERR_INCOMPATIBLE_VERSION_ERROR
;
1247 return NPERR_NO_ERROR
;
1250 extern "C" NPError WINAPI
NP_Initialize(NPNetscapeFuncs
* nFuncs
, NPPluginFuncs
* pFuncs
)
1253 return NPERR_INVALID_FUNCTABLE_ERROR
;
1255 qNetscapeFuncs
= nFuncs
;
1256 int navMajorVers
= qNetscapeFuncs
->version
>> 8;
1258 // if the plugin's major version is lower than the Navigator's,
1259 // then they are incompatible, and should return an error
1260 if(navMajorVers
> NP_VERSION_MAJOR
)
1261 return NPERR_INCOMPATIBLE_VERSION_ERROR
;
1263 // check if the Browser supports the XEmbed protocol
1264 int supportsXEmbed
= 0;
1265 NPError err
= NPN_GetValue(0, NPNVSupportsXEmbedBool
, (void *)&supportsXEmbed
);
1266 if (err
!= NPERR_NO_ERROR
||!supportsXEmbed
)
1267 return NPERR_INCOMPATIBLE_VERSION_ERROR
;
1269 return NP_GetEntryPoints(pFuncs
);
1273 extern "C" NPError WINAPI
NP_Shutdown()
1278 extern void qtns_shutdown();
1282 return NPERR_NO_ERROR
;
1287 \class QtNPBindable qtnetscape.h
1288 \brief The QtNPBindable class provides an interface between a widget and the web browser.
1290 Inherit your plugin widget class from both QWidget (or QObject) and QtNPBindable
1291 to be able to call the functions of this class, and to reimplement the virtual
1292 functions. The \l{moc}{meta-object compiler} requires you to inherit from the
1293 QObject subclass first.
1296 class PluginWidget : public QWidget, public QtNPBindable
1300 PluginWidget(QWidget *parent = 0)
1310 \enum QtNPBindable::DisplayMode
1312 \brief This enum specifies the different display modes of a plugin
1314 \value Embedded The plugin widget is embedded in a web page, usually
1315 with the <EMBED> or the <OBJECT> tag.
1316 \value Fullpage The plugin widget is the primary content of the web browser, which
1317 is usually the case when the web browser displays a file the plugin supports.
1321 \enum QtNPBindable::Reason
1323 \brief This enum specifies how an URL operation was completed
1328 \value ReasonUnknown
1332 Constructs a QtNPBindable object.
1334 This can only happen when the plugin object is created.
1336 QtNPBindable::QtNPBindable()
1340 pi
->bindable
= this;
1345 Destroys the object.
1347 This can only happen when the plugin object is destroyed.
1349 QtNPBindable::~QtNPBindable()
1354 Returns the parameters passed to the plugin instance.
1356 The framework sets the properties of the plugin to the corresponding
1357 parameters when the plugin object has been created, but you can
1358 use this function to process additional parameters.
1360 Note that the SGML specification does not permit multiple
1361 arguments with the same name.
1363 QMap
<QByteArray
, QVariant
> QtNPBindable::parameters() const
1366 return QMap
<QByteArray
, QVariant
>();
1367 return pi
->parameters
;
1371 Returns the user agent (browser name) containing this plugin.
1373 This is a wrapper around NPN_UserAgent.
1375 \sa getBrowserVersion()
1377 QString
QtNPBindable::userAgent() const
1381 return QString::fromLocal8Bit(NPN_UserAgent(pi
->npp
));
1385 Extracts the version of the plugin API used by this plugin into \a major
1388 See http://devedge-temp.mozilla.org/library/manuals/2002/plugin/1.0/
1389 for an explanation of those values.
1391 \sa getBrowserVersion() userAgent()
1393 void QtNPBindable::getNppVersion(int *major
, int *minor
) const
1397 NPN_Version(major
, minor
, &dummy
, &dummy
);
1401 Extracts the version of the browser into \a major and \a minor.
1403 See http://devedge-temp.mozilla.org/library/manuals/2002/plugin/1.0/
1404 for an explanation of those values.
1406 \sa getNppVersion() userAgent()
1408 void QtNPBindable::getBrowserVersion(int *major
, int *minor
) const
1412 NPN_Version(&dummy
, &dummy
, major
, minor
);
1416 Returns the display mode of the plugin.
1418 QtNPBindable::DisplayMode
QtNPBindable::displayMode() const
1422 return (QtNPBindable::DisplayMode
)pi
->fMode
;
1426 Returns the mime type this plugin has been instantiated for.
1428 QString
QtNPBindable::mimeType() const
1432 return pi
->mimetype
;
1436 Returns the browser's plugin instance associated with this plugin object.
1437 The instance is required to call functions in the Netscape Plugin API,
1438 i.e. NPN_GetJavaPeer().
1440 The instance returned is only valid as long as this object is.
1442 See http://devedge-temp.mozilla.org/library/manuals/2002/plugin/1.0/
1443 for documentation of the \c NPP type.
1445 NPP
QtNPBindable::instance() const
1453 Reimplement this function to read data from \a source provided with
1454 mime type \a format. The data is the one specified in the \c src or
1455 \c data attribute of the \c{<EMBED>} or \c{<OBJECT>} tag of in
1456 HTML page. This function is called once for every stream the browser
1457 creates for the plugin.
1459 Return true to indicate successfull processing of the data, otherwise
1460 return false. The default implementation does nothing and returns false.
1463 bool QtNPBindable::readData(QIODevice
*source
, const QString
&format
)
1471 Requests that the \a url be retrieved and sent to the named \a window (or
1472 a new window if \a window is empty), and returns the ID of the request that is
1473 delivered to transferComplete() when the get-operation has finished. Returns 0 when
1474 the browser or the system doesn't support notification, or -1 when an error occured.
1477 void MyPlugin::aboutTrolltech()
1479 openUrl("http://www.trolltech.com");
1483 See Netscape's JavaScript documentation for an explanation of window names.
1485 \sa transferComplete() uploadData() uploadFile()
1487 int QtNPBindable::openUrl(const QString
&url
, const QString
&window
)
1491 QString wnd
= window
;
1495 qint32 id
= pi
->getNotificationSeqNum();
1496 NPError err
= NPN_GetURLNotify(pi
->npp
, url
.toLocal8Bit().constData(), wnd
.toLocal8Bit().constData(), reinterpret_cast<void*>(id
));
1497 if (err
!= NPERR_NO_ERROR
)
1500 if (err
== NPERR_INCOMPATIBLE_VERSION_ERROR
) {
1501 err
= NPN_GetURL(pi
->npp
, url
.toLocal8Bit().constData(), wnd
.toLocal8Bit().constData());
1502 if (NPERR_NO_ERROR
== err
)
1511 Posts \a data to \a url, and displays the result in \a window. Returns the ID of the request
1512 that is delivered to transferComplete() when the post-operation has finished. Returns 0 when
1513 the browser or the system doesn't support notification, or -1 when an error occured.
1516 void MyPlugin::sendMail()
1518 uploadData("mailto:fred@somewhere.com", QString(), "There is a new file for you!");
1522 See Netscape's JavaScript documentation for an explanation of window names.
1524 \sa transferComplete() openUrl() uploadFile()
1526 int QtNPBindable::uploadData(const QString
&url
, const QString
&window
, const QByteArray
&data
)
1531 int id
= pi
->getNotificationSeqNum();
1532 if (NPERR_NO_ERROR
!= NPN_PostURLNotify(pi
->npp
, url
.toLocal8Bit().constData(), window
.isEmpty() ? 0 : window
.toLocal8Bit().constData(), data
.size(), data
.constData(), false, reinterpret_cast<void*>(id
)))
1539 Posts \a filename to \a url, and displays the result in \a window. Returns the ID of
1540 the request that is delivered to transferComplete() when the post-operation has finished.
1541 Returns 0 when the browser or the system doesn't support notification, or -1 when an
1545 void MyPlugin::uploadFile()
1547 uploadFile("ftp://ftp.somewhere.com/incoming", "response", "c:\\temp\\file.txt");
1551 See Netscape's JavaScript documentation for an explanation of window names.
1553 \sa transferComplete() uploadData() openUrl()
1556 int QtNPBindable::uploadFile(const QString
&url
, const QString
&window
, const QString
&filename
)
1561 QByteArray data
= filename
.toLocal8Bit();
1562 int id
= pi
->getNotificationSeqNum();
1563 if (NPERR_NO_ERROR
!= NPN_PostURLNotify(pi
->npp
, url
.toLocal8Bit().constData(), window
.isEmpty() ? 0 : window
.toLocal8Bit().constData(), data
.size(), data
.constData(), true, reinterpret_cast<void*>(id
)))
1570 Called as a result of a call to openUrl, uploadData or uploadFile.
1571 \a url corresponds to the respective parameter, and \a id to value returned
1572 by the call. \a reason indicates how the transfer was completed.
1574 void QtNPBindable::transferComplete(const QString
&url
, int id
, Reason reason
)
1582 /******************************************************************************
1583 * The plugin itself - only one ever exists, created by QtNPFactory::create()
1584 *****************************************************************************/
1588 \class QtNPFactory qtbrowserplugin.h
1589 \brief The QtNPFactory class provides the factory for plugin objects.
1591 Implement this factory once in your plugin project to provide information
1592 about the plugin and to create the plugin objects. Subclass QtNPFactory and
1593 implement the pure virtual functions, and export the factory using the
1594 \c QTNPFACTORY_EXPORT() macro.
1596 If you use the Q_CLASSINFO macro in your object classes you can use the
1597 \c QTNPFACTORY_BEGIN(), \c QTNPCLASS() and \c QTNPFACTORY_END() macros to
1598 generate a factory implementation:
1601 class Widget : public QWidget
1604 Q_CLASSINFO("MIME", "application/x-graphable:g1n:Graphable data")
1609 QTNPFACTORY_BEGIN("Plugin name", "Plugin description")
1610 QTNPCLASS(WidgetClass)
1614 The classes exposed must provide a constructor.
1616 If Qt is linked to the plugin as a dynamic library, only one instance of
1617 QApplication will exist \e{across all plugins that have been made with Qt}.
1618 So, your plugin should tread lightly on global settings. Do not, for example,
1619 use QApplication::setFont() - that will change the font in every widget of
1620 every Qt-based plugin currently loaded!
1624 Creates a QtNPFactory.
1626 QtNPFactory::QtNPFactory()
1631 Destroys the QtNPFactory.
1633 This is called by the plugin binding code just before the plugin is
1634 about to be unloaded from memory. If createObject() has been called,
1635 a QApplication will still exist at this time, but will be deleted
1636 shortly after, just before the plugin is deleted.
1638 QtNPFactory::~QtNPFactory()
1644 \fn QStringList QtNPFactory::mimeTypes() const
1646 Reimplement this function to return the MIME types of the data formats
1647 supported by your plugin. The format of each string is
1648 mime:extension(s):description:
1651 QStringList mimeTypes() const
1654 list << "image/x-png:png:PNG Image"
1655 << "image/png:png:PNG Image"
1656 << "image/jpeg:jpg,jpeg:JPEG Image";
1663 \fn QObject *QtNPFactory::createObject(const QString &type)
1665 Reimplement this function to return the QObject or QWidget subclass
1666 supporting the mime type \a type, or 0 if the factory doesn't support
1669 \a type will be in the same form as the leftmost (mime) part of
1670 the string(s) returned by mimeTypes(), e.g. "image/png".
1674 \fn QString QtNPFactory::pluginName() const
1676 Reimplement this function to return the name of the plugin.
1680 \fn QString QtNPFactory::pluginDescription() const
1682 Reimplement this function to return the description of the plugin.