/****************************************************************************
** $Id: quickextensions.cpp  beta1   edited Dec 13 10:09 $
**
** Copyright (C) 2001-2002 Trolltech AS.  All rights reserved.
**
** This file is part of the Qt Script for Applications framework (QSA).
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** Licensees holding a valid QSA Beta Evaluation Version license may use
** this file in accordance with the QSA Beta Evaluation Version License
** Agreement provided with the Software.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
**   information about QSA Commercial License Agreements.
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
*****************************************************************************/

#include "quickextensions.h"

#include "quickqtwidgets.h"
#include "quicksystem.h"
#include "quickqtdom.h"
#include "quickqtdialogs.h"
#include "quickqtkernel.h"
#include "quickqtnamespace.h"
#if defined(QT_MODULE_SQL) && !defined(QSA_NO_SQL)
#include "quickqtsql.h"
#endif
#if defined(QT_MODULE_NETWORK) && !defined(QSA_NO_NETWORK)
#include "quickqtnetwork.h"
#endif

#include <qptrlist.h>
#include <qsocket.h>
#include <qwidgetfactory.h>
#include <qlayout.h>
#include <qvariant.h>

QuickExtensions::QuickExtensions()
{
}

QStringList QuickExtensions::featureList() const
{
    static QStringList *features = 0;
    if ( features )
	return *features;
    QStringList lst;

    // widgets
    lst << "QWidget" << "QDateEdit" << "QTable" << "QListViewItem" << "QListView"
	<< "ToolTip" << "WhatsThis" << "WidgetFactory"
	<< "QPopupMenu" << "QWidgetStack" << "QHBoxLayout" << "QVBoxLayout"
	<< "QListBox" << "QListBoxItem" << "QComboBox" << "QTextEdit";

#if defined(QT_MODULE_SQL) && !defined(QSA_NO_SQL)
    // sql
    lst << "Database" << "QSqlRecord" << "QSqlField" << "QSqlQuery" << "QSqlCursor" << "QSqlIndex";
    lst << "QDataTable";
#endif

#if defined(QT_MODULE_NETWORK) && !defined(QSA_NO_NETWORK)
    // network
    lst << "Network" << "QSocket";
#endif

    // system
    lst << "System";

    // dom
    lst << "DomNode" << "DomElement" << "DomText" << "DomDocument";
    lst << "QDomNode" << "QDomElement" << "QDomText" << "QDomDocument";

    // dialogs
    lst << "FileDialog" << "MessageBox" << "InputDialog" << "ColorDialog";

    // kernel
    lst << "QProcess" << "QFontDatabase" << "FontDatabase" << "File" << "QFile" << "Dir" << "QDir";

    // namespace
    lst << "Qt" << "QuickNamespace";

    // other
    lst << "QObjectList";

    QStringList widgets = QWidgetFactory::widgets();
    for ( QStringList::Iterator it = widgets.begin(); it != widgets.end(); ++it ) {
	if ( lst.find( *it ) == lst.end() )
	    lst << *it;
    }

    features = new QStringList( lst );
    return *features;
}

bool QuickExtensions::createInterface( const QCString &className,
				       void *ptr, QPtrVector<QObject> &result )
{
    if ( className == "QWidget" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickWidgetInterface( (QWidget*)ptr ) );
	return TRUE;
    } else if ( className == "ToolTip" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickToolTip );
	return TRUE;
    } else if ( className == "WhatsThis" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickWhatsThis );
	return TRUE;
    } else if ( className == "QDateEdit" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickDateEditInterface( (QDateEdit*)ptr ) );
	return TRUE;
    } else if ( className == "QTable" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickTableInterface( (QTable*)ptr ) );
	return TRUE;
    } else if ( className == "QListView" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickListViewInterface( (QListView*)ptr ) );
	return TRUE;
    } else if ( className == "QListBox" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickListBoxInterface( (QListBox*)ptr ) );
	return TRUE;
    } else if ( className == "QTextEdit" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickTextEditInterface( (QTextEdit*)ptr ) );
	return TRUE;
    } else if ( className == "QComboBox" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickComboBoxInterface( (QComboBox*)ptr ) );
	return TRUE;
    } else if ( className == "QPopupMenu" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickPopupMenuInterface( (QPopupMenu*)ptr ) );
	return TRUE;
    } else if ( className == "QWidgetStack" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickWidgetStackInterface( (QWidgetStack*)ptr ) );
	return TRUE;
    } else if ( className == "QHBoxLayout" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickHBoxLayoutInterface( (QHBoxLayout*)ptr ) );
	return TRUE;
    } else if ( className == "QVBoxLayout" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickVBoxLayoutInterface( (QVBoxLayout*)ptr ) );
	return TRUE;
    } else if ( className == "QListViewItem" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QListViewItemPtr( (QListViewItem*)ptr ) );
	return TRUE;
    } else if ( className == "QListBoxItem" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QListBoxItemPtr( (QListBoxItem*)ptr ) );
	return TRUE;
    } else if ( className == "WidgetFactory" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickWidgetFactory );
	return TRUE;
#if defined(QT_MODULE_SQL) && !defined(QSA_NO_SQL)
    } else if ( className == "Database" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickDatabase );
	return TRUE;
    } else if ( className == "QSqlQuery" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickDatabaseQueryPtr( (QSqlQuery*)ptr ) );
	return TRUE;
    } else if ( className == "QSqlField" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickDatabaseFieldPtr( (QSqlField*)ptr ) );
	return TRUE;
    } else if ( className == "QSqlRecord" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickDatabaseRecordPtr( (QSqlRecord*)ptr ) );
	return TRUE;
    } else if ( className == "QSqlCursor" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickDatabaseCursorPtr( (QSqlCursor*)ptr ) );
	return TRUE;
    } else if ( className == "QSqlIndex" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickDatabaseIndexPtr( (QSqlIndex*)ptr ) );
	return TRUE;
    } else if ( className == "QDataTable" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickDataTableInterface( (QDataTable*)ptr ) );
	return TRUE;
#endif
#if defined(QT_MODULE_NETWORK) && !defined(QSA_NO_NETWORK)
    } else if ( className == "Network" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickNetwork );
	return TRUE;
    } else if ( className == "QSocket" ) {
	result.resize( 2 );
	result.insert( 0, (QSocket*)ptr );
	result.insert( 1, new QuickSocket( (QSocket*)ptr ) );
	return TRUE;
#endif
    } else if ( className == "System" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new System );
	return TRUE;

    } else if ( className == "QDomNode" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new DomNode( (QDomNode*)ptr ) );
	return TRUE;
    } else if ( className == "QDomElement" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new DomElement( (QDomElement*)ptr ) );
	return TRUE;
    } else if ( className == "QDomText" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new DomText( (QDomText*)ptr ) );
	return TRUE;
    } else if ( className == "QDomDocument" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new DomDocument( (QDomDocument*)ptr ) );
	return TRUE;

    } else if ( className == "FileDialog" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickFileDialogInterface );
	return TRUE;
    } else if ( className == "MessageBox" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickMessageBoxInterface );
	return TRUE;
    } else if ( className == "ColorDialog" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickColorDialogInterface );
	return TRUE;
    } else if ( className == "InputDialog" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickInputDialogInterface );
	return TRUE;

    } else if ( className == "Qt" || className == "QuickNamespace" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickNamespace );
	return TRUE;

    } else if ( className == "QObjectList" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QObjectListPtr( (QObjectList*)ptr ) );
	return TRUE;
    }

    return FALSE;
}

bool QuickExtensions::isGlobal( const QCString &className ) const
{
    if ( className == "Database" || className == "MessageBox" ||
	 className == "Network" || className == "ToolTip" || className == "WhatsThis" ||
	 className == "WidgetFactory" || className == "System" ||
	 className == "FileDialog" || className == "ColorDialog" || className == "InputDialog" ||
	 className == "Qt" || className == "QuickNamespace" )
	return TRUE;
    return FALSE;
}

bool QuickExtensions::isConstructor( const QString &className ) const
{
    if ( /*className == "DomNode" ||
	 className == "DomElement" ||
	 className == "DomText" || */
	 className == "DomDocument" )
	return TRUE;
    if ( className == "QListViewItem" )
	return TRUE;
    if ( className == "QObjectList" )
	return TRUE;
    if ( className == "QProcess" )
	return TRUE;
    if ( className == "QFontDatabase" || className == "FontDatabase" )
	return TRUE;
    if ( className == "QFile" || className == "File" )
	return TRUE;
    if ( className == "QDir" || className == "Dir" )
	return TRUE;
    if ( className == "QVBoxLayout" || className == "QHBoxLayout" )
	return TRUE;
    if ( QWidgetFactory::supportsWidget( className ) )
	return TRUE;

    return FALSE;
}

bool QuickExtensions::construct( const QString & className,
				 const QValueList<QVariant> &args,
				 QPtrVector<QObject> &result ) const
{
    int oldIdx = result.size();
    if ( className == "DomDocument" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new DomDocument( args[0].toString() ) );
	return TRUE;
    } else if ( className == "QListViewItem" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	if ( args.count() == 1 ) {
	    ObjAttr oa = extractObject( args[0] );
	    if ( oa.num ) {
		if( !oa.isQObject ) {
		    QListViewItem *i = (QListViewItem*)oa.num;
		    if ( i ) {
			result.insert( idx, new QListViewItemPtr( new QListViewItem( i ) ) );
			return TRUE;
		    }
		}
		if ( ( (QObject*)oa.num )->inherits( "QListView" ) ) {
		    QListView *lv = (QListView*)oa.num;
		    result.insert( idx, new QListViewItemPtr( new QListViewItem( lv ) ) );
		    return TRUE;
		}
	    }
	}
    } else if ( className == "QProcess" ) {
	QString s = args[0].toString();
	QuickProcess *p;
	if ( s.find( ' ' ) == -1 ) {
	    p = new QuickProcess( s );
	} else {
	    QStringList lst = QStringList::split( ' ', s );
	    p = new QuickProcess( lst );
	}
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, p );
	return TRUE;
    } else if ( className == "QFontDatabase" || className == "FontDatabase" ) {
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, new QuickFontDatabase );
	return TRUE;
    } else if ( className == "QFile" || className == "File" ) {
	QString s = args[0].toString();
	QuickFile *f = new QuickFile( s );
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, f );
	return TRUE;
    } else if ( className == "QDir" || className == "Dir" ) {
	QString s = args[0].toString();
	QuickDir *d = new QuickDir( s );
	int idx = result.size();
	result.resize( idx + 1 );
	result.insert( idx, d );
	return TRUE;
    } else if ( QWidgetFactory::supportsWidget( className ) ||
		className == "QVBoxLayout" || className == "QHBoxLayout" ) {
	QObject *parent = 0;
	QWidget *parentWidget = 0;
	const char *name = 0;

	ObjAttr oa = extractObject( args[0] );
	if ( oa.num && oa.isQObject ) {
	    parent = (QObject*)oa.num;
	    if ( parent->isWidgetType() )
	        parentWidget = (QWidget*)parent;
	}
	if ( args[1].type() == QVariant::String || args[1].type() == QVariant::CString )
	    name = qstrdup( args[1].toString().latin1() );

	QObject *w = 0;
	if ( className == "QVBoxLayout" ) {
	    if ( parentWidget )
		w = new QVBoxLayout( parentWidget, 6, 6, name );
	    else
		w = new QVBoxLayout( (QLayout*)parent, 6, name );
	    int idx = result.size();
	    result.resize( idx + 2 );
	    result.insert( idx, w );
	    result.insert( idx + 1, new QuickVBoxLayoutInterface( (QVBoxLayout*)w ) );
	} else if ( className == "QHBoxLayout" ) {
	    if ( parentWidget )
		w = new QHBoxLayout( parentWidget, 6, 6, name );
	    else
		w = new QHBoxLayout( (QLayout*)parent, 6, name );
	    int idx = result.size();
	    result.resize( idx + 2 );
	    result.insert( idx, w );
	    result.insert( idx + 1, new QuickHBoxLayoutInterface( (QHBoxLayout*)w ) );
	} else {
	    QWidgetFactory f;
	    w = f.createWidget( className, parentWidget, name );
	    int idx = result.size();
	    result.resize( idx + 1 );
	    result.insert( idx, w );
	}
	return TRUE;
    }
    for ( uint i = oldIdx; i < result.size(); ++i )
	result.insert( i, 0 );

    throwError( "Qt Script Extensions::construct: " + className +
		": constructor argument does not match any constructor overload of " +
		className  );
    return FALSE;
}

ObjAttr QuickExtensions::extractObject( const QVariant &arg ) const
{
    ObjAttr oa( 0, FALSE );
    if ( arg.type() == QVariant::String || arg.type() == QVariant::CString ) {
	static int length_of_Pointer = 7;
	static QString pointer_header = "Pointer";
	QString s = arg.toString();
	if ( s.left( length_of_Pointer ) == pointer_header ) {
	    QStringList l = QStringList::split( ':', s );
	    if ( l.count() == 3 ) {
		oa.num = l[1].toULong();
		if ( l[2] == "QObject" )
		    oa.isQObject = TRUE;
		return oa;
	    }
	}
    }
    return oa;
}
