/***************************************************************************
                            QtSupport.cpp -  description
                             -------------------
    begin                : Fri Oct 20 13:46:55 2000
    copyright            : (C) 2000 Lost Highway Ltd
    email                : Richard_Dale@tipitina.demon.co.uk
    generated by         : duke@tipitina on Fri Oct 20 13:46:55 2000, using kdoc $.
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include <stdlib.h>
#include <stdio.h>

#include <qmetaobject.h>

#include <qtjava/QtSupport.h>
#include <qtjava/QObject.h>
#include <qtjava/JavaSlot.h>

static JavaVM *	_jvm;


jmethodID	QtSupport::MID_String_init;
jmethodID	QtSupport::MID_String_getBytes;
bool		QtSupport::_bigEndianUnicode;

void
QtSupport::registerJVM(JNIEnv * env)
{
	jstring	testString;
	const jchar * _jchar_str;

	env->GetJavaVM((JavaVM **) &_jvm);

	// Cache commonly used method id's and classes.
	MID_String_init = env->GetMethodID(env->FindClass("java/lang/String"), "<init>", "([B)V");
	MID_String_getBytes = env->GetMethodID(env->FindClass("java/lang/String"), "getBytes", "()[B");

	// Test for the endianess of the unicode string returned by GetStringChars()
	testString = env->NewStringUTF("A");
	_jchar_str = env->GetStringChars(testString, 0);
	QString temp((QChar*)_jchar_str, env->GetStringLength(testString));
	env->ReleaseStringChars(testString, _jchar_str);
	_bigEndianUnicode = strcmp((const char *) temp, "A") == 0;
	env->DeleteLocalRef(testString);

	return;
}

JNIEnv *
QtSupport::GetEnv()
{
	JNIEnv *	env;

	_jvm->GetEnv((void **) &env, JNI_VERSION_1_2);
	return env;
}

const char *
QtSupport::eventTypeToEventClassName(QEvent::Type eventType)
{
	switch (eventType) {
	case QEvent::ChildInserted:
	case QEvent::ChildRemoved:
		 return "org.kde.qt.QChildEvent";
	case QEvent::Close:
		 return "org.kde.qt.QCloseEvent";
	case QEvent::ContextMenu:
		 return "org.kde.qt.QContextMenuEvent";
	case QEvent::User:
		 return "org.kde.qt.QCustomEvent";
	case QEvent::DragEnter:
		 return "org.kde.qt.QDragEnterEvent";
	case QEvent::DragLeave:
		 return "org.kde.qt.QDragLeaveEvent";
	case QEvent::DragMove:
		 return "org.kde.qt.QDragMoveEvent";
	case QEvent::DragResponse:
		 return "org.kde.qt.QDragResponseEvent";
	case QEvent::Drop:
		 return "org.kde.qt.QDropEvent";
	case QEvent::FocusIn:
	case QEvent::FocusOut:
		 return "org.kde.qt.QFocusEvent";
	case QEvent::Hide:
		 return "org.kde.qt.QHideEvent";
	case QEvent::KeyPress:
	case QEvent::KeyRelease:
		 return "org.kde.qt.QKeyEvent";
	case QEvent::IMStart:
	case QEvent::IMCompose:
	case QEvent::IMEnd:
		 return "org.kde.qt.QIMEvent";
	case QEvent::MouseButtonPress:
	case QEvent::MouseButtonRelease:
	case QEvent::MouseButtonDblClick:
	case QEvent::MouseMove:
		 return "org.kde.qt.QMouseEvent";
	case QEvent::Move:
		 return "org.kde.qt.QMoveEvent";
	case QEvent::Paint:
		 return "org.kde.qt.QPaintEvent";
	case QEvent::Resize:
		 return "org.kde.qt.QResizeEvent";
	case QEvent::Show:
		 return "org.kde.qt.QShowEvent";
//	case QEvent::Tablet:
//		 return "org.kde.qt.QTabletEvent";
	case QEvent::Timer:
		 return "org.kde.qt.QTimerEvent";
	case QEvent::Wheel:
		 return "org.kde.qt.QWheelEvent";
	default:
		 return "org.kde.qt.QEvent";
	}
}

bool
QtSupport::eventFilterDelegate(QObject * object, const char * objectType, QObject * filteredObject, QEvent * event)
{
	JNIEnv *	env;
	jclass		cls;
	jstring		objectTypeString;
	jstring		eventNameString;
	jstring		eventMethodString;
	jmethodID	mid;

    (void) objectType; // Not used at present, the event's Qt rtti is used instead
    
	env = QtSupport::GetEnv();
	if (env == 0) {
		return FALSE;
	}
	
	cls = env->FindClass("org/kde/qt/Invocation");
	if (cls == 0) {
		return FALSE;
	}

	mid = env->GetStaticMethodID(cls, "invoke", "(JJLjava/lang/String;JLjava/lang/String;Ljava/lang/String;)Z");
	if (mid == 0) {
		return FALSE;
	}

	objectTypeString = env->NewStringUTF("org.kde.qt.QObject");
	eventNameString = env->NewStringUTF(QtSupport::eventTypeToEventClassName(event->type()));
	eventMethodString = env->NewStringUTF("eventFilter");
	
	bool result = (bool) env->CallStaticBooleanMethod(	cls, mid,
														(jlong) object,
														(jlong) filteredObject,
														objectTypeString,
														(jlong) event,
														eventNameString,
														eventMethodString );
												
	env->DeleteLocalRef(cls);
	env->DeleteLocalRef(objectTypeString);
	env->DeleteLocalRef(eventNameString);
	env->DeleteLocalRef(eventMethodString);
	return result;
}

bool
QtSupport::eventDelegate(QObject * object, const char * eventType, void * event, const char * eventName)
{
	JNIEnv *	env;
	jclass		cls;
	jstring		eventNameString;
	jstring		eventTypeString;
	jmethodID	mid;
	
	env = QtSupport::GetEnv();
	if (env == 0) {
		return FALSE;
	}
	
	cls = env->FindClass("org/kde/qt/Invocation");
	if (cls == 0) {
		return FALSE;
	}

	mid = env->GetStaticMethodID(cls, "invoke", "(JJLjava/lang/String;Ljava/lang/String;)Z");
	if (mid == 0) {
		return FALSE;
	}

	eventNameString = env->NewStringUTF(eventName);
	eventTypeString = env->NewStringUTF(eventType);
	
	bool result = (bool) env->CallStaticBooleanMethod(	cls, mid,
												(jlong) object,
												(jlong) event,
												eventNameString,
												eventTypeString );
	env->DeleteLocalRef(cls);
	env->DeleteLocalRef(eventNameString);
	env->DeleteLocalRef(eventTypeString);
	return result;
}

bool
QtSupport::voidDelegate(void * object, const char * className, const char * methodName)
{
	JNIEnv *	env;
	jclass		cls;
	jstring		classNameString;
	jstring		methodNameString;
	jmethodID	mid;
	env = QtSupport::GetEnv();
	if (env == 0) {
		return FALSE;
	}
	
	cls = env->FindClass("org/kde/qt/Invocation");
	if (cls == 0) {
		return FALSE;
	}

	mid = env->GetStaticMethodID(cls, "invoke", "(JLjava/lang/String;Ljava/lang/String;)Z");
	if (mid == 0) {
		return FALSE;
	}
	
	classNameString = env->NewStringUTF(className);
	methodNameString = env->NewStringUTF(methodName);
	bool result = (bool) env->CallStaticBooleanMethod(	cls, mid,
														(jlong) object,
														classNameString,
														methodNameString );
	env->DeleteLocalRef(cls);
	env->DeleteLocalRef(methodNameString);
	env->DeleteLocalRef(classNameString);
	return result;
}

bool
QtSupport::booleanDelegate(QObject * object, const char * methodName)
{
	JNIEnv *	env;
	jclass		cls;
	jstring		methodNameString;
	jmethodID	mid;

	env = QtSupport::GetEnv();
	if (env == 0) {
		return FALSE;
	}
	
	cls = env->FindClass("org/kde/qt/Invocation");
	if (cls == 0) {
		return FALSE;
	}

	mid = env->GetStaticMethodID(cls, "booleanInvoke", "(JLjava/lang/String;)Z");
	if (mid == 0) {
		return FALSE;
	}

	methodNameString = env->NewStringUTF(methodName);
	bool result = (bool) env->CallStaticBooleanMethod(	cls, mid,
														(jlong) object,
														methodNameString );
	env->DeleteLocalRef(cls);
	env->DeleteLocalRef(methodNameString);
	return result;
}

int
QtSupport::validateDelegate(QValidator * object, QString & input, int & pos)
{
	JNIEnv *	env;
	jclass		cls;
	jmethodID	mid;
	jobject		validator;
	jstring		inputString;
	QString *	inputPtr;
	jstring		resultString;
	jobject		buffer;
	jmethodID	bufferConstructor;
	jclass		bufferClass;
	jintArray	positionArray;
	int			result;
	jmethodID	bufferToString;

	env = QtSupport::GetEnv();
	env->PushLocalFrame(10);
	
	// Allocate a java StringBuffer to hold the input string
	inputString = QtSupport::fromQString(env, (QString *) &input);
	bufferClass = env->FindClass("java/lang/StringBuffer");
	bufferConstructor = env->GetMethodID(bufferClass, "<init>", "(Ljava/lang/String;)V");
	if (bufferConstructor == 0) {
		return 0;
	}
	buffer = env->NewObject(bufferClass, bufferConstructor, inputString);

	// Get the cursor position and convert to type 'int[]'
	positionArray = QtSupport::fromIntPtr(env, &pos);

	// Obtain the validate() method id, and call the method
	validator = (jobject) QtSupport::objectForQtKey(env, object, "org.kde.qt.QValidator");
    cls = env->GetObjectClass(validator);
    if (cls == 0) {
    	return 0;
    }

	mid = env->GetMethodID(cls, "validate", "(Ljava/lang/StringBuffer;[I)I");
	if (mid == 0) {
		return 0;
	}
	result = (int) env->CallIntMethod(validator, mid, buffer, positionArray);

	// Copy the java result string back into the 'input' QString
	bufferToString = env->GetMethodID(bufferClass, "toString", "()Ljava/lang/String;");
	if (bufferToString == 0) {
		env->PopLocalFrame(0);
		return 0;
	}
	resultString = (jstring) env->CallObjectMethod(buffer, bufferToString);
	inputPtr = &input;
	QtSupport::toQString(env, resultString, &inputPtr);

	pos = *(QtSupport::toIntPtr(env, positionArray));
	env->PopLocalFrame(0);

	return result;
}

void
QtSupport::fixupDelegate(QValidator * object, QString & input)
{
	JNIEnv *	env;
	jclass		cls;
	jmethodID	mid;
	jobject		fixer;
	jstring		inputString;
	QString *	inputPtr;
	jstring		resultString;
	jobject		buffer;
	jmethodID	bufferConstructor;
	jclass		bufferClass;
	jmethodID	bufferToString;

	env = QtSupport::GetEnv();
	env->PushLocalFrame(10);

	// Allocate a java StringBuffer to hold the input string
	inputString = QtSupport::fromQString(env, (QString *) &input);
	bufferClass = env->FindClass("java/lang/StringBuffer");
	bufferConstructor = env->GetMethodID(bufferClass, "<init>", "(Ljava/lang/String;)V");
	if (bufferConstructor == 0) {
		return;
	}
	buffer = env->NewObject(bufferClass, bufferConstructor, inputString);

	// Obtain the fixup() method id and call the method
	fixer = (jobject) QtSupport::objectForQtKey(env, object, "org.kde.qt.QValidator");
    cls = env->GetObjectClass(fixer);
    if (cls == 0) {
    	return;
    }
	mid = env->GetMethodID(cls, "fixup", "(Ljava/lang/StringBuffer;)V");
	if (mid == 0) {
		return;
	}
	env->CallVoidMethod(fixer, mid, buffer);

	// Copy the java result string back into the 'input' QString
	bufferToString = env->GetMethodID(bufferClass, "toString", "()Ljava/lang/String;");
	if (bufferToString == 0) {
		env->PopLocalFrame(0);
		return;
	}
	resultString = (jstring) env->CallObjectMethod(buffer, bufferToString);
	inputPtr = &input;
	QtSupport::toQString(env, resultString, &inputPtr);
	env->PopLocalFrame(0);

	return;
}

bool
QtSupport::allocatedInJavaWorld(JNIEnv * env, jobject obj)
{
	if (obj == 0) {
		return FALSE;
	}

	jclass cls = env->GetObjectClass(obj);
	bool result = (bool) env->GetBooleanField(obj, env->GetFieldID(cls, "_allocatedInJavaWorld", "Z"));
	env->DeleteLocalRef(cls);
	return result;
}

void
QtSupport::setAllocatedInJavaWorld(JNIEnv * env, jobject obj, bool yn)
{
	jclass cls = env->GetObjectClass(obj);
	env->SetBooleanField(obj, env->GetFieldID(cls, "_allocatedInJavaWorld", "Z"), (jboolean) yn);
	env->DeleteLocalRef(cls);
	return;
}

void *
QtSupport::getQt(JNIEnv * env, jobject obj)
{
	if (obj == 0) {
		return 0;
	}

	jclass cls = env->GetObjectClass(obj);
	void * result = (void *) env->GetLongField(obj, env->GetFieldID(cls, "_qt", "J"));
	env->DeleteLocalRef(cls);
	return result;
}

void
QtSupport::setQt(JNIEnv * env, jobject obj, void * qt)
{
	jclass cls = env->GetObjectClass(obj);
	env->SetLongField(obj, env->GetFieldID(cls, "_qt", "J"), (jlong) qt);
	env->DeleteLocalRef(cls);
	return;
}

void
QtSupport::setObjectForQtKey(JNIEnv * env, jobject obj, void * qt)
{
	jclass		cls;
	jmethodID	mid;

	cls = env->FindClass("org/kde/qt/qtjava");
	if (cls == 0) {
		return;
	}

	mid = env->GetStaticMethodID(cls, "setObjectForQtKey", "(Ljava/lang/Object;J)V");
	if (mid == 0) {
		return;
	}

	env->CallStaticVoidMethod(cls, mid, obj, (jlong) qt);
	env->DeleteLocalRef(cls);
	return;
}

jobject
QtSupport::objectForQtKey(JNIEnv * env, void * qt, const char * className, const bool allocatedInJavaWorld)
{
	jclass		cls;
	jmethodID	mid;
	jstring		javaClassName;

	if (qt == 0) {
		return 0;
	}
	
	javaClassName = env->NewStringUTF(className);

	cls = env->FindClass("org/kde/qt/qtjava");
	if (cls == 0) {
		return 0;
	}

	mid = env->GetStaticMethodID(cls, "objectForQtKey", "(JLjava/lang/String;Z)Ljava/lang/Object;");
	if (mid == 0) {
		return 0;
	}

	jobject result = env->CallStaticObjectMethod(cls, mid, (jlong) qt, javaClassName, (jboolean) allocatedInJavaWorld);
	env->DeleteLocalRef(cls);
	env->DeleteLocalRef(javaClassName);
	return result;
}
	
void
QtSupport::qtKeyDeleted(void * qt)
{
	JNIEnv *	env;
	jclass		cls;
	jmethodID	mid;

	env = QtSupport::GetEnv();
	if (env == 0) {
		return;
	}

	cls = env->FindClass("org/kde/qt/qtjava");
	if (cls == 0) {
		return;
	}

	mid = env->GetStaticMethodID(cls, "qtKeyDeleted", "(J)V");
	if (mid == 0) {
		return;
	}

	env->CallStaticVoidMethod(cls, mid, (jlong) qt);
	env->DeleteLocalRef(cls);
	return;
}

jboolean
QtSupport::connect(JNIEnv * env, jobject sender, jstring signal, jobject receiver, jstring slot)
{
	JavaSlot *		javaSlot = QtSupport::slotForReceiver(env, receiver, slot);
	QMetaObject *	smeta = ((QObject *) QtSupport::getQt(env, sender))->metaObject();
	QString			qtSignalName(javaSlot->javaToQtSignalName(env, signal, smeta));

	// Attempt to connect from the signal on the underlying C++ object first,
	// otherwise assume that the connection is for a Java signal.
	if (!qtSignalName.isEmpty()) {
		QMetaObject *	smetaTarget = ((QObject *) QtSupport::getQt(env, receiver))->metaObject();
		QString	qtTargetSignalName(javaSlot->javaToQtSignalName(env, slot, smetaTarget));

		if (!qtTargetSignalName.isEmpty()) {
			// The sender is a C++ signal, and the target is also a C++ signal
			return (jboolean) QObject::connect(	(QObject*) QtSupport::getQt(env, sender),
												(const char *) qtSignalName,
												(QObject*) QtSupport::getQt(env, receiver),
												(const char *) qtTargetSignalName );
		} else {
			// The sender is a C++ signal, and the target is a java slot
			return (jboolean) QObject::connect(	(QObject*) QtSupport::getQt(env, sender),
												(const char *) qtSignalName,
												javaSlot,
												javaSlot->javaToQtSlotName(env, slot, qtSignalName) );
		}
	} else {
		// The sender is a java signal, and the target is either a java slot or a java signal
		// Java signals are always of type jobjectArray
		return (jboolean) QObject::connect(	QtSupport::signalForSender(env, QtSupport::getQt(env, sender), signal),
											"2signalJava(jobjectArray)",
											javaSlot,
											"1invoke(jobjectArray)" );
	}
}

jboolean
QtSupport::disconnect(JNIEnv * env, jobject sender, jstring signal, jobject receiver, jstring slot)
{
	JavaSlot *		javaSlot = QtSupport::slotForReceiver(env, receiver, slot);
	QMetaObject *	smeta = ((QObject *) QtSupport::getQt(env, sender))->metaObject();
	QString			qtSignalName(javaSlot->javaToQtSignalName(env, signal, smeta));

	// Attempt to disconnect from the signal on the underlying C++ object first,
	// otherwise assume that the connection is for a Java signal.
	if (!qtSignalName.isEmpty()) {
		QMetaObject *	smetaTarget = ((QObject *) QtSupport::getQt(env, receiver))->metaObject();
		QString	qtTargetSignalName(javaSlot->javaToQtSignalName(env, slot, smetaTarget));

		if (!qtTargetSignalName.isEmpty()) {
			// The sender is a C++ signal, and the target is also a C++ signal
			return (jboolean) QObject::disconnect(	(QObject*) QtSupport::getQt(env, sender),
													(const char *) qtSignalName,
													(QObject*) QtSupport::getQt(env, receiver),
													(const char *) qtTargetSignalName );
		} else {
			// The sender is a C++ signal, and the target is a java slot
			return (jboolean) QObject::disconnect(	(QObject*) QtSupport::getQt(env, sender),
													(const char *) qtSignalName,
													javaSlot,
													javaSlot->javaToQtSlotName(env, slot, qtSignalName) );
		}
	} else {
		// The sender is a java signal, and the target is either a java slot or a java signal
		// Java signals are always of type jobjectArray
		return (jboolean) QObject::disconnect(	QtSupport::signalForSender(env, QtSupport::getQt(env, sender), signal),
												"2signalJava(jobjectArray)",
												javaSlot,
												"1invoke(jobjectArray)" );
	}
}

void
QtSupport::emitJavaSignal(JNIEnv * env, jobject sender, jstring signal, jobjectArray args)
{
	JavaSignal * javaSignal = QtSupport::signalForSender(env, QtSupport::getQt(env, sender), signal);
	javaSignal->emitArgs(args);
}

JavaSignal *
QtSupport::signalForSender(JNIEnv * env, void * qt, jstring signal)
{
	jclass		cls;
	jmethodID	mid;

	cls = env->FindClass("org/kde/qt/qtjava");
	mid = env->GetStaticMethodID(cls, "signalForSender", "(JLjava/lang/String;)J");
	if (mid == 0) {
		return 0;
	}

	JavaSignal * result = (JavaSignal *) env->CallStaticLongMethod(cls, mid, (jlong) qt, signal);
	env->DeleteLocalRef(cls);
	return result;
}

JavaSlot *
QtSupport::slotForReceiver(JNIEnv * env, jobject receiver, jstring slot)
{
	jclass		cls;
	jmethodID	mid;

	cls = env->FindClass("org/kde/qt/qtjava");
	mid = env->GetStaticMethodID(cls, "slotForReceiver", "(JLorg/kde/qt/QObject;Ljava/lang/String;)J");
	if (mid == 0) {
		return 0;
	}

	JavaSlot * result = (JavaSlot *) env->CallStaticLongMethod(cls, mid, (jlong) QtSupport::getQt(env, receiver), receiver, slot);
	env->DeleteLocalRef(cls);
	return result;
}

QPaintDevice *
QtSupport::paintDevice(JNIEnv * env, jobject obj)
{
	jclass		cls;
	jmethodID	mid;

	cls = env->GetObjectClass(obj);
	mid = env->GetMethodID(cls, "paintDevice", "()J");
	if (mid == 0) {
		return 0;
	}

	env->DeleteLocalRef(cls);
	return (QPaintDevice *) env->CallLongMethod(obj, mid);
}

QMimeSource *
QtSupport::mimeSource(JNIEnv * env, jobject obj)
{
	jclass		cls;
	jmethodID	mid;

	cls = env->GetObjectClass(obj);
	mid = env->GetMethodID(cls, "mimeSource", "()J");
	if (mid == 0) {
		return 0;
	}

	env->DeleteLocalRef(cls);
	return (QMimeSource *) env->CallLongMethod(obj, mid);
}

bool
QtSupport::bigEndianUnicode()
{
	return _bigEndianUnicode;
}

bool *
QtSupport::toBooleanPtr(JNIEnv * env, jbooleanArray obj)
{
	bool *	result;
	int		length;

	length = env->GetArrayLength(obj);
	result = (bool *) calloc(length, sizeof(bool));
	env->GetBooleanArrayRegion(obj, 0, length, (jboolean *) result);
	return result;
}

int *
QtSupport::toIntPtr(JNIEnv * env, jintArray obj)
{
	int *	result;
	int		length;

	length = env->GetArrayLength(obj);
	result = (int *) calloc(length, sizeof(int));
	env->GetIntArrayRegion(obj, 0, length, (jint *) result);
	return result;
}

double *
QtSupport::toDoublePtr(JNIEnv * env, jdoubleArray obj)
{
	double *	result;
	int			length;

	length = env->GetArrayLength(obj);
	result = (double *) calloc(length, sizeof(double));
	env->GetDoubleArrayRegion(obj, 0, length, (jdouble *) result);
	return result;
}

short *
QtSupport::toShortPtr(JNIEnv * env, jshortArray obj)
{
	short *	result;
	int		length;

	length = env->GetArrayLength(obj);
	result = (short *) calloc(length, sizeof(short));
	env->GetShortArrayRegion(obj, 0, length, (jshort *) result);
	return result;
}

jbooleanArray
QtSupport::fromBooleanPtr(JNIEnv * env, bool * arg)
{
	jbooleanArray	result;

	result = env->NewBooleanArray(1);
	env->SetBooleanArrayRegion(result, 0, 1, (jboolean *) arg);
	return (jbooleanArray) result;
}

jintArray
QtSupport::fromIntPtr(JNIEnv * env, int * arg)
{
	jintArray	result;

	result = env->NewIntArray(1);
	env->SetIntArrayRegion(result, 0, 1, (jint *) arg);
	return (jintArray) result;
}

jdoubleArray
QtSupport::fromDoublePtr(JNIEnv * env, double * arg)
{
	jdoubleArray	result;

	result = env->NewDoubleArray(1);
	env->SetDoubleArrayRegion(result, 0, 1, (jdouble *) arg);
	return (jdoubleArray) result;
}

jshortArray
QtSupport::fromShortPtr(JNIEnv * env, short * arg)
{
	jshortArray	result;

	result = env->NewShortArray(1);
	env->SetShortArrayRegion(result, 0, 1, (jshort *) arg);
	return (jshortArray) result;
}


jobject QtSupport::fromQDateTime(JNIEnv * env, QDateTime* qdate)
{
	jclass 		cls;
	jmethodID	cid;
	jobject		date;

	cls = env->FindClass("java/util/GregorianCalendar");
	if (cls == 0) {
		return 0;
	}

	cid = env->GetMethodID(cls, "<init>", "(IIIIII)V");
	if (cid == 0) {
		return 0;
	}

	date = env->NewObject(	cls, cid,
							(jint) qdate->date().year(), (jint) qdate->date().month() - 1, (jint) qdate->date().day(),
							(jint) qdate->time().hour(), (jint) qdate->time().minute(), (jint) qdate->time().second() );
	QtSupport::setObjectForQtKey(env, date, qdate);

	env->DeleteLocalRef(cls);
	return (jobject) date;
}

jobject
QtSupport::fromQDate(JNIEnv * env, QDate* qdate)
{
	jclass 		cls;
	jmethodID	cid;
	jobject		date;

	cls = env->FindClass("java/util/GregorianCalendar");
	if (cls == 0) {
		return 0;
	}

	cid = env->GetMethodID(cls, "<init>", "(III)V");
	if (cid == 0) {
		return 0;
	}

	date = env->NewObject(cls, cid, (jint) qdate->year(), (jint) qdate->month() - 1, (jint) qdate->day());
	QtSupport::setObjectForQtKey(env, date, qdate);

	env->DeleteLocalRef(cls);
	return (jobject) date;
}

jobject
QtSupport::fromQTime(JNIEnv * env, QTime* qtime)
{
	jclass 		cls;
	jmethodID	cid;
	jobject		time;
	jmethodID	mid;

	cls = env->FindClass("java/util/Date");
	if (cls == 0) {
		return 0;
	}

	cid = env->GetMethodID(cls, "<init>", "()V");
	if (cid == 0) {
		return 0;
	}

	time = env->NewObject(cls, cid);
	QtSupport::setObjectForQtKey(env, time, qtime);

	mid = env->GetMethodID(cls, "setHours", "(I)V");
	if (mid == 0) {
		return 0;
	}

	env->CallVoidMethod(time, mid, qtime->hour());

	mid = env->GetMethodID(cls, "setMinutes", "(I)V");
	if (mid == 0) {
		return 0;
	}

	env->CallVoidMethod(time, mid, qtime->minute());

	mid = env->GetMethodID(cls, "setSeconds", "(I)V");
	if (mid == 0) {
		return 0;
	}

	env->CallVoidMethod(time, mid, qtime->second());

	env->DeleteLocalRef(cls);
	return (jobject) time;
}


QDateTime *
QtSupport::toQDateTime(JNIEnv * env, jobject jdate, QDateTime** qdatetime)
{
static QDate * qdate = 0;
static QTime * qtime = 0;

	if (*qdatetime == 0) {
		*qdatetime = new QDateTime();
		qdate = new QDate();
		qtime = new QTime();
	}

	QtSupport::toQDate(env, jdate, &qdate);
	QtSupport::toQTime(env, jdate, &qtime);
	(*qdatetime)->setDate(*qdate);
	(*qdatetime)->setTime(*qtime);

	return *qdatetime;
}


#define JAVA_YEAR 1
#define JAVA_MONTH 2
#define JAVA_DAY_OF_MONTH 5
QDate *
QtSupport::toQDate(JNIEnv * env, jobject jdate, QDate** qdate)
{
	jclass 		cls;
	jmethodID	mid;
	jint		year;
	jint		month;
	jint		day;

	if (*qdate == 0) {
		*qdate = new QDate();
	}

	cls = env->FindClass("java/util/Calendar");

	mid = env->GetMethodID(cls, "get", "(I)I");
	if (mid == 0) {
		return 0;
	}

	year = env->CallIntMethod(jdate, mid, JAVA_YEAR);
	month = env->CallIntMethod(jdate, mid, JAVA_MONTH);
	day = env->CallIntMethod(jdate, mid, JAVA_DAY_OF_MONTH);

	(*qdate)->setYMD((int) year, (int) month + 1, (int) day);

	env->DeleteLocalRef(cls);
	return *qdate;
}

QTime *
QtSupport::toQTime(JNIEnv * env, jobject jtime, QTime** qtime)
{
	jclass 		cls;
	jmethodID	mid;
	jint		hour;
	jint		minute;
	jint		second;

	if (*qtime == 0) {
		*qtime = new QTime();
	}

	cls = env->FindClass("java/util/Date");

	mid = env->GetMethodID(cls, "getHours", "()I");
	if (mid == 0) {
		return 0;
	}

	hour = env->CallIntMethod(jtime, mid);

	mid = env->GetMethodID(cls, "getMinutes", "()I");
	if (mid == 0) {
		return 0;
	}

	minute = env->CallIntMethod(jtime, mid);

	mid = env->GetMethodID(cls, "getSeconds", "()I");
	if (mid == 0) {
		return 0;
	}

	second = env->CallIntMethod(jtime, mid);

	(*qtime)->setHMS((int) hour, (int) minute, (int) second);

	env->DeleteLocalRef(cls);
	return *qtime;
}

jstring
QtSupport::fromQString(JNIEnv * env, QString * qstring)
{
	if (qstring == 0) {
		return 0;
	}
	
	if (_bigEndianUnicode) {
		return env->NewString((const jchar *) qstring->unicode(), (long) qstring->length());
	} else {
static QString *	temp = 0L;

		if (temp == 0L) {
			temp = new QString();
		}

		// Hack to change the big endian unicode in 'qstring' to little endian in 'temp'.
		temp->setUnicodeCodes((const ushort *) qstring->unicode(), (long) qstring->length());
		return env->NewString((const jchar *) temp->unicode(), (long) temp->length());
	}
}

jstring
QtSupport::fromQCString(JNIEnv * env, QCString * qcstring)
{
	jstring result = 0;
	jbyteArray bytes = 0;
	int len;
	jclass cls;

	if (qcstring == 0) {
		return 0;
	}
	
	len = qcstring->length();
	bytes = env->NewByteArray(len);
	env->SetByteArrayRegion(bytes, 0, len, (jbyte *) (const char *) *qcstring);
	cls = env->FindClass("java/lang/String");
	result = (jstring) env->NewObject(cls, QtSupport::MID_String_init, bytes);
	env->DeleteLocalRef(cls);
	env->DeleteLocalRef(bytes);
	return result;
}

jstring
QtSupport::fromCharString(JNIEnv * env, char * qcstring)
{
	jstring result = 0;
	jbyteArray bytes = 0;
	int len;

	if (qcstring == 0) {
		return 0;
	}
	
	len = strlen(qcstring);
	bytes = env->NewByteArray(len);
	env->SetByteArrayRegion(bytes, 0, len, (jbyte *) (const char *) qcstring);
	jclass stringClass = env->FindClass("java/lang/String");
	result = (jstring) env->NewObject(stringClass, QtSupport::MID_String_init, bytes);
	env->DeleteLocalRef(stringClass);
	env->DeleteLocalRef(bytes);
	return result;
}

QString *
QtSupport::toQString(JNIEnv * env, jstring str, QString ** qstring)
{
	const jchar *	_jchar_str;

	if (str == 0L) {
		return (QString*) &QString::null;
	}

	if (*qstring == 0L) {
		*qstring = new QString();
	}

	_jchar_str = env->GetStringChars(str, 0);

	if (_bigEndianUnicode) {
		(*qstring)->setUnicode((QChar *) _jchar_str, env->GetStringLength(str));
	} else {
		(*qstring)->setUnicodeCodes((const ushort *) _jchar_str, env->GetStringLength(str));
	}

	env->ReleaseStringChars(str, _jchar_str);
	return *qstring;
}

QCString *
QtSupport::toQCString(JNIEnv * env, jstring str, QCString ** qcstring)
{
	jbyteArray	bytes = 0;
	jthrowable	exc;
	jint		len = 0;
	char *		data;

	if (str == 0) {
		return 0;
	}

	bytes = (jbyteArray) env->CallObjectMethod(str, QtSupport::MID_String_getBytes);
	exc = env->ExceptionOccurred();

	if (exc) {
		env->DeleteLocalRef(exc);
		return 0;
	}

	len = env->GetArrayLength(bytes);

	if (*qcstring == 0) {
		*qcstring = new QCString(len + 1);
	} else {
		(*qcstring)->resize(len + 1);
	}

	data = (*qcstring)->data();
	env->GetByteArrayRegion(bytes, 0, len, (jbyte *) data);
	data[len] = 0;
	env->DeleteLocalRef(bytes);
	return *qcstring;
}

char *
QtSupport::toCharString(JNIEnv * env, jstring str, QCString ** qcstring)
{
	if (str == 0) {
		return 0;
	}

	(void) QtSupport::toQCString(env, str, qcstring);
	return (*qcstring)->data();
}


void
QtSupport::fromQStringToStringBuffer(JNIEnv * env, QString * qstring, jobject buffer)
{
	jclass 		cls;
	jmethodID	mid;
	jmethodID	appendMid;

	if (buffer == 0) {
		return;
	}

	cls = env->FindClass("java/lang/StringBuffer");
	if (cls == 0) {
		return;
	}

	mid = env->GetMethodID(cls, "setLength", "(I)V");
	if (mid == 0) {
		return;
	}

	env->CallVoidMethod(buffer, mid, 0);

	appendMid = env->GetMethodID(cls, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
	if (appendMid == 0) {
		return;
	}
	
	(void) env->CallObjectMethod(buffer, appendMid, QtSupport::fromQString(env, qstring));
	env->DeleteLocalRef(cls);
	return;
}

QString *
QtSupport::toQStringFromStringBuffer(JNIEnv * env, jobject buffer, QString ** qstring)
{
	jclass 		cls;
	jmethodID	mid;
	jstring		str;
	
	if (buffer == 0) {
		return 0;
  	}

	cls = env->FindClass("java/lang/StringBuffer");
	if (cls == 0) {
		return 0;
	}

	mid = env->GetMethodID(cls, "toString", "()Ljava/lang/String;");
	if (mid == 0) {
		return 0;
	}

	str = (jstring) env->CallObjectMethod(buffer, mid);
	env->DeleteLocalRef(cls);
	return QtSupport::toQString(env, str, qstring);
}
void
QtSupport::fromQCStringToStringBuffer(JNIEnv * env, QCString * qcstring, jobject buffer)
{
	jclass 		cls;
	jmethodID	mid;
	jmethodID	appendMid;

	if (buffer == 0) {
		return;
	}

	cls = env->FindClass("java/lang/StringBuffer");
	if (cls == 0) {
		return;
	}

	mid = env->GetMethodID(cls, "setLength", "(I)V");
	if (mid == 0) {
		return;
	}

	env->CallVoidMethod(buffer, mid, 0);

	appendMid = env->GetMethodID(cls, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
	if (appendMid == 0) {
		return;
	}
	
	(void) env->CallObjectMethod(buffer, appendMid, QtSupport::fromQCString(env, qcstring));
	env->DeleteLocalRef(cls);
	return;
}

jchar
QtSupport::fromQChar(JNIEnv * env, QChar * qchar)
{
	(void) env;
	return (jchar) qchar->unicode();
}

QChar *
QtSupport::toQChar(JNIEnv * env, jchar unichar, QChar ** qchar)
{
	(void) env;
	
	if (*qchar != 0L) {
		delete *qchar;
	}

	*qchar = new QChar((ushort) unichar);
	return *qchar;
}

jbyteArray
QtSupport::fromQByteArray(JNIEnv * env, QByteArray * qbyteArray)
{
	jbyteArray result = 0;
	int len;

	len = qbyteArray->size();
	result = env->NewByteArray(len);
	env->SetByteArrayRegion(result, 0, len, (jbyte *) (const char *) qbyteArray->data());
	return result;
}

QByteArray *
QtSupport::toQByteArray(JNIEnv * env, jbyteArray bytes, QByteArray ** qbyteArray)
{
	if (bytes == 0) {
		return 0;
	}

	jsize len = env->GetArrayLength(bytes);
	if (*qbyteArray == 0) {
		*qbyteArray = new QByteArray(len);
	} else {
		(*qbyteArray)->resize(len);
	}

	jboolean isCopy;
	(*qbyteArray)->duplicate((const char *)env->GetByteArrayElements(bytes, &isCopy), len);
	return *qbyteArray;
}
	
uchar *
QtSupport::toUcharArray(JNIEnv * env, jcharArray bytes, QByteArray ** qbyteArray)
{
	uchar *				data;
	unsigned short *	ptr;
	
	if (bytes == 0) {
		return 0;
	}

	jsize len = env->GetArrayLength(bytes);
	if (*qbyteArray == 0) {
		*qbyteArray = new QByteArray(len*2);
	} else {
		(*qbyteArray)->resize(len*2);
	}

	jboolean isCopy;
	(*qbyteArray)->duplicate((const char *)env->GetCharArrayElements(bytes, &isCopy), len*2);
	data = (uchar *) (*qbyteArray)->data();
	ptr = (unsigned short *) data;
	
	/* Convert the array from 16 bit Java 'char[]' to 8 bit C++ 'char *' array */
	for (int index = 0; index < len; index++) {
		data[index] = (uchar) ptr[index];
	}
	
	(*qbyteArray)->resize(len);
	return (uchar*) (*qbyteArray)->data();
}

QValueList<int>
QtSupport::toQIntValueList(JNIEnv * env, jintArray ints, QValueList<int> ** qintArray)
{
	int		len;
	jint *	carr;
	int		index;
	
	(*qintArray)->clear();
	len = env->GetArrayLength(ints);
	carr = env->GetIntArrayElements(ints, 0);
	
	for (index = 0; index < len; index++) {
		(*qintArray)->append((int) carr[index]);
	}
	
	env->ReleaseIntArrayElements(ints, carr, 0);
	return **qintArray;
}
	
jintArray
QtSupport::fromQIntValueList(JNIEnv * env, QValueList<int> * qintArray)
{
	jintArray result = 0;
	int len;
	int	index;

	len = qintArray->size();
	result = env->NewIntArray(len);
	for (index = 0; index < len; index++) {
		env->SetIntArrayRegion(result, index, 1, (jint *) &(*qintArray)[index]);
	}
	
	return result;
}

char **
QtSupport::toArgv(JNIEnv * env, jobjectArray stringList)
{
	char ** 		argv;
	int				length;
	int				index;
	jstring			jstr;
	const char *	str;

	if (stringList == NULL) {
		return NULL;
	}

	length = env->GetArrayLength(stringList);
	argv = (char **) calloc(length + 1, sizeof(char*));
	/* Add a dummy first argument of 'java [interpreter-options] <main class>' to appear
	   in usage messages, in place of the usual executable name from argv[0]. */
	argv[0] = strdup("java [interpreter-options] <main class>");

	for (index = 0; index < length; index++) {
		jstr = (jstring) env->GetObjectArrayElement(stringList, index);
		str = env->GetStringUTFChars(jstr, NULL);
		argv[index + 1] = strdup(str);
		env->ReleaseStringUTFChars(jstr, str);
		env->DeleteLocalRef(jstr);
	}

	return argv;
}

char **
QtSupport::toStringArray(JNIEnv * env, jobjectArray stringList)
{
	char ** 		argv;
	int				length;
	int				index;
	jstring			jstr;
	const char *	str;

	if (stringList == 0) {
		return 0;
	}

	length = env->GetArrayLength(stringList);
	argv = (char **) calloc(length, sizeof(char*));

	for (index = 0; index < length; index++) {
		jstr = (jstring) env->GetObjectArrayElement(stringList, index);
		str = env->GetStringUTFChars(jstr, 0);
		argv[index] = strdup(str);
		env->ReleaseStringUTFChars(jstr, str);
		env->DeleteLocalRef(jstr);
	}

	return argv;
}

QStrList *
QtSupport::toQStrList(JNIEnv * env, jobjectArray stringList, QStrList ** qstringList)
{
	int				length;
	int				index;
	jstring			jstr;
static QString * _qstring_temp = 0;

	if (*qstringList == 0) {
		*qstringList = new QStrList();
	}

	(*qstringList)->clear();
	
	if (stringList == 0) {
		return *qstringList;
	}

	length = env->GetArrayLength(stringList);

	for (index = 0; index < length; index++) {
		jstr = (jstring) env->GetObjectArrayElement(stringList, index);
		(*qstringList)->append((QString &) * (QString *) QtSupport::toQString(env, jstr, &_qstring_temp));		
		env->DeleteLocalRef(jstr);
	}

	return *qstringList;
}

QStringList *
QtSupport::toQStringList(JNIEnv * env, jobjectArray stringList, QStringList ** qstringList)
{
	int				length;
	int				index;
	jstring			jstr;
static QString * _qstring_temp = 0;

	if (*qstringList == 0) {
		*qstringList = new QStringList();
	}
	
	(*qstringList)->clear();
	
	if (stringList == 0) {
		return *qstringList;
	}

	length = env->GetArrayLength(stringList);

	for (index = 0; index < length; index++) {
		jstr = (jstring) env->GetObjectArrayElement(stringList, index);
		(*qstringList)->append((QString &) * (QString *) QtSupport::toQString(env, jstr, &_qstring_temp));
		env->DeleteLocalRef(jstr);
	}

	return *qstringList;
}


jobject
QtSupport::arrayWithQStrList(JNIEnv * env, QStrList * qstrList, jobject stringArray)
{
	jclass			cls;
	jmethodID		clearMid;
	jmethodID		addMid;
	
	if (stringArray == 0) {
		stringArray = (jobject) QtSupport::objectForQtKey(env, qstrList, "java.util.ArrayList");
	}

	cls = env->GetObjectClass(stringArray);
	clearMid = env->GetMethodID(cls, "clear", "()V");
	if (clearMid == 0) {
		return 0;
	}

	env->CallVoidMethod(stringArray, clearMid);

	addMid = env->GetMethodID(cls, "add", "(Ljava/lang/Object;)Z");
	if (addMid == 0) {
		return 0;
	}

	for (unsigned int index = 0; index < qstrList->count(); index++) {
		char * currentItem = (char *) qstrList->at(index);
		jstring currentString = env->NewStringUTF(currentItem);
		
		if (! env->CallBooleanMethod(stringArray, addMid, currentString)) {
			return 0;
		}
		env->DeleteLocalRef(currentString);
	}

	env->DeleteLocalRef(cls);
	return (jobject) stringArray;
}

jobject
QtSupport::arrayWithQStringList(JNIEnv * env, QStringList * qstringList, jobject stringArray)
{
	jclass			cls;
	jmethodID		clearMid;
	jmethodID		addMid;

	if (stringArray == 0) {
		stringArray = (jobject) QtSupport::objectForQtKey(env, qstringList, "java.util.ArrayList");
	}

	cls = env->GetObjectClass(stringArray);
	clearMid = env->GetMethodID(cls, "clear", "()V");
	if (clearMid == 0) {
		return 0;
	}

	env->CallVoidMethod(stringArray, clearMid);

	addMid = env->GetMethodID(cls, "add", "(Ljava/lang/Object;)Z");
	if (addMid == 0) {
		return 0;
	}

	for (QStringList::Iterator it = qstringList->begin(); it != qstringList->end(); ++it) {
		if (! env->CallBooleanMethod(	stringArray,
										addMid,
										QtSupport::fromQString(env, (QString *) &(*it)) ) )
		{
			return 0;
		}
	}

	env->DeleteLocalRef(cls);
	return (jobject) stringArray;
}

jobject
QtSupport::arrayWithQWidgetList(JNIEnv * env, QWidgetList * widgetList, jobject widgetArray)
{
	jclass			cls;
	jmethodID		clearMid;
	jmethodID		addMid;

	if (widgetArray == 0) {
		widgetArray = (jobject) QtSupport::objectForQtKey(env, widgetList, "java.util.ArrayList");
	}

	cls = env->GetObjectClass(widgetArray);
	clearMid = env->GetMethodID(cls, "clear", "()V");
	if (clearMid == 0) {
		return 0;
	}

	env->CallVoidMethod(widgetArray, clearMid);

	addMid = env->GetMethodID(cls, "add", "(Ljava/lang/Object;)Z");
	if (addMid == 0) {
		return 0;
	}

	for (unsigned int index = 0; index < widgetList->count(); index++) {
		QWidget * currentWidget = (QWidget *) widgetList->at(index);
		if (! env->CallBooleanMethod(	widgetArray,
										addMid,
										QtSupport::objectForQtKey(env, currentWidget, "org.kde.qt.QWidget") ) )
		{
			return 0;
		}
	}

	env->DeleteLocalRef(cls);
	return (jobject) widgetArray;
}

jobject
QtSupport::arrayWithQDomNodeList(JNIEnv * env, QDomNodeList * domNodeList, jobject domNodeArray)
{
	jclass			cls;
	jmethodID		clearMid;
	jmethodID		addMid;

	if (domNodeArray == 0) {
		domNodeArray = (jobject) QtSupport::objectForQtKey(env, domNodeList, "java.util.ArrayList");
	}

	cls = env->GetObjectClass(domNodeArray);
	clearMid = env->GetMethodID(cls, "clear", "()V");
	if (clearMid == 0) {
		return 0;
	}

	env->CallVoidMethod(domNodeArray, clearMid);

	addMid = env->GetMethodID(cls, "add", "(Ljava/lang/Object;)Z");
	if (addMid == 0) {
		return 0;
	}

	for (unsigned int index = 0; index < domNodeList->count(); index++) {
		QDomNode currentDomNode = (QDomNode) domNodeList->item(index);

		if (! env->CallBooleanMethod(	domNodeArray,
										addMid,
										QtSupport::objectForQtKey(env, &currentDomNode, "org.kde.qt.QDomNode") ) )
		{
			return 0;
		}
	}

	env->DeleteLocalRef(cls);
	return (jobject) domNodeArray;
}

jobject
QtSupport::arrayWithQObjectList(JNIEnv * env, QObjectList * objectList, jobject objectArray)
{
	jclass			cls;
	jmethodID		clearMid;
	jmethodID		addMid;

	if (objectArray == 0) {
		objectArray = (jobject) QtSupport::objectForQtKey(env, objectList, "java.util.ArrayList");
	}

	cls = env->GetObjectClass(objectArray);
	clearMid = env->GetMethodID(cls, "clear", "()V");
	if (clearMid == 0) {
		return 0;
	}

	env->CallVoidMethod(objectArray, clearMid);

	addMid = env->GetMethodID(cls, "add", "(Ljava/lang/Object;)Z");
	if (addMid == 0) {
		return 0;
	}

	for (unsigned int index = 0; index < objectList->count(); index++) {
		QObject * currentObject = (QObject *) objectList->at(index);

		if (! env->CallBooleanMethod(	objectArray,
										addMid,
										QtSupport::objectForQtKey(env, currentObject, "org.kde.qt.QObject") ) )
		{
			return 0;
		}
	}

	env->DeleteLocalRef(cls);
	return (jobject) objectArray;
}

jobject
QtSupport::arrayWithQCanvasItemList(JNIEnv * env, QCanvasItemList * itemList, jobject objectArray)
{
	jclass			cls;
	jmethodID		clearMid;
	jmethodID		addMid;

	if (objectArray == 0) {
		objectArray = (jobject) QtSupport::objectForQtKey(env, itemList, "java.util.ArrayList");
	}

	cls = env->GetObjectClass(objectArray);
	clearMid = env->GetMethodID(cls, "clear", "()V");
	if (clearMid == 0) {
		return 0;
	}

	env->CallVoidMethod(objectArray, clearMid);

	addMid = env->GetMethodID(cls, "add", "(Ljava/lang/Object;)Z");
	if (addMid == 0) {
		return 0;
	}
	
	for (QCanvasItemList::Iterator it = itemList->begin(); it != itemList->end(); ++it) {
		const char * classString;

		switch ((*it)->rtti()) {
		case QCanvasItem::Rtti_Item:
			classString = "org.kde.qt.QCanvasItem";
			break;
		case QCanvasItem::Rtti_Ellipse:
			classString = "org.kde.qt.QCanvasEllipse";
			break;
		case QCanvasItem::Rtti_Line:
			classString = "org.kde.qt.QCanvasLine";
			break;
		case QCanvasItem::Rtti_Polygon:
			classString = "org.kde.qt.QCanvasPolygon";
			break;
		case QCanvasItem::Rtti_PolygonalItem:
			classString = "org.kde.qt.QCanvasPolygonalItem";
			break;
		case QCanvasItem::Rtti_Rectangle:
			classString = "org.kde.qt.QCanvasRectangle";
			break;
		case QCanvasItem::Rtti_Spline:
			classString = "org.kde.qt.QCanvasSpline";
			break;
		case QCanvasItem::Rtti_Sprite:
			classString = "org.kde.qt.QCanvasSprite";
			break;
		case QCanvasItem::Rtti_Text:
			classString = "org.kde.qt.QCanvasText";
			break;
		default:
			classString = "org.kde.qt.QCanvasItem";
			break;
		}

		if (! env->CallBooleanMethod(	objectArray,
										addMid,
										QtSupport::objectForQtKey(env, *it, classString) ) )
		{
			return 0;
		}
	}

	env->DeleteLocalRef(cls);
	return (jobject) objectArray;
}

jobject
QtSupport::arrayWithQListViewItemList(JNIEnv * env, QListViewItemIterator * iterator, jobject arrayList)
{
	jclass			cls;
	jmethodID		clearMid;
	jmethodID		addMid;
    const char *			className;

	if (arrayList == 0) {
		arrayList = (jobject) QtSupport::objectForQtKey(env, iterator, "java.util.ArrayList");
	}

	cls = env->GetObjectClass(arrayList);
	clearMid = env->GetMethodID(cls, "clear", "()V");
	if (clearMid == 0) {
		return 0;
	}

	env->CallVoidMethod(arrayList, clearMid);

	addMid = env->GetMethodID(cls, "add", "(Ljava/lang/Object;)Z");
	if (addMid == 0) {
		return 0;
	}
	
	for (	; iterator->current(); ++(*iterator)) {
		QListViewItem * currentItem =  iterator->current();
		
		/* rtti() is: 0 = QListViewItem, 1 = QCheckListItem */
		className = (currentItem->rtti() == 1 ? "org.kde.qt.QCheckListItem" : "org.kde.qt.QListViewItem");
		if (! env->CallBooleanMethod(	arrayList,
										addMid,
										QtSupport::objectForQtKey(env, currentItem, className) ) )
		{
			return 0;
		}
	}

	env->DeleteLocalRef(cls);
	return (jobject) arrayList;
}

jobject
QtSupport::arrayWithQRectList(JNIEnv * env, QMemArray<QRect> * rectList, jobject arrayList)
{
	jclass			cls;
	jmethodID		clearMid;
	jmethodID		addMid;

	if (arrayList == 0) {
		arrayList = (jobject) QtSupport::objectForQtKey(env, rectList, "java.util.ArrayList");
	}

	cls = env->GetObjectClass(arrayList);
	clearMid = env->GetMethodID(cls, "clear", "()V");
	if (clearMid == 0) {
		return 0;
	}

	env->CallVoidMethod(arrayList, clearMid);

	addMid = env->GetMethodID(cls, "add", "(Ljava/lang/Object;)Z");
	if (addMid == 0) {
		return 0;
	}

	for (unsigned int index = 0; index < rectList->count(); index++) {
		QRect currentRect = (QRect) rectList->at(index);
		if (! env->CallBooleanMethod(	arrayList,
										addMid,
										QtSupport::objectForQtKey(	env,
																	new QRect(currentRect.topLeft(), currentRect.bottomRight()),
																	"org.kde.qt.QRect",
																	TRUE ) ) )
		{
			return 0;
		}
	}

	env->DeleteLocalRef(cls);
	return (jobject) arrayList;
}

jobject
QtSupport::arrayWithQIconDragItemList(JNIEnv * env, QValueList<QIconDragItem> * dragItemList, jobject arrayList)
{
	jclass			cls;
	jmethodID		clearMid;
	jmethodID		addMid;

	if (arrayList == 0) {
		arrayList = (jobject) QtSupport::objectForQtKey(env, dragItemList, "java.util.ArrayList");
	}

	cls = env->GetObjectClass(arrayList);
	clearMid = env->GetMethodID(cls, "clear", "()V");
	if (clearMid == 0) {
		return 0;
	}

	env->CallVoidMethod(arrayList, clearMid);

	addMid = env->GetMethodID(cls, "add", "(Ljava/lang/Object;)Z");
	if (addMid == 0) {
		return 0;
	}

	for (QValueList<QIconDragItem>::Iterator it = dragItemList->begin(); it != dragItemList->end(); ++it) {
		QIconDragItem currentItem = (QIconDragItem) *it;
		if (! env->CallBooleanMethod(	arrayList,
										addMid,
										QtSupport::objectForQtKey(env, &currentItem, "org.kde.qt.QIconDragItem") ) )
		{
			return 0;
		}
	}

	env->DeleteLocalRef(cls);
	return (jobject) arrayList;
}

jobject
QtSupport::arrayWithQUrlInfoList(JNIEnv * env, QValueList<QUrlInfo> * infoList, jobject arrayList)
{
	jclass			cls;
	jmethodID		clearMid;
	jmethodID		addMid;

	if (arrayList == 0) {
		arrayList = (jobject) QtSupport::objectForQtKey(env, infoList, "java.util.ArrayList");
	}

	cls = env->GetObjectClass(arrayList);
	clearMid = env->GetMethodID(cls, "clear", "()V");
	if (clearMid == 0) {
		return 0;
	}

	env->CallVoidMethod(arrayList, clearMid);

	addMid = env->GetMethodID(cls, "add", "(Ljava/lang/Object;)Z");
	if (addMid == 0) {
		return 0;
	}

	for (QValueList<QUrlInfo>::Iterator it = infoList->begin(); it != infoList->end(); ++it) {
		QUrlInfo currentItem = (QUrlInfo) *it;
		if (! env->CallBooleanMethod(	arrayList,
										addMid,
										QtSupport::objectForQtKey(env, &currentItem, "org.kde.qt.QUrlInfo") ) )
		{
			return 0;
		}
	}

	env->DeleteLocalRef(cls);
	return (jobject) arrayList;
}
