// This is the SIP interface definition for TQApplication.
//
// Copyright (c) 2007
// 	Riverbank Computing Limited <info@riverbankcomputing.co.uk>
// 
// This file is part of PyTQt.
// 
// This copy of PyTQt 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, or (at your option) any later
// version.
// 
// PyTQt is supplied in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
// details.
// 
// You should have received a copy of the GNU General Public License along with
// PyTQt; see the file LICENSE.  If not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.


%ExportedDoc
<Sect2><Title>TQApplication</Title>
<FuncSynopsis>
        <FuncDef><Function>TQApplication</Function></FuncDef>
        <ParamDef>int &amp;<Parameter>argc</Parameter></ParamDef>
        <ParamDef>char **<Parameter>argv</Parameter></ParamDef>
</FuncSynopsis>
<Para>
This takes one parameter which is a list of argument strings.  Arguments
used by TQt are removed from the list.
</Para>

<FuncSynopsis>
        <FuncDef><Function>TQApplication</Function></FuncDef>
        <ParamDef>int &amp;<Parameter>argc</Parameter></ParamDef>
        <ParamDef>char **<Parameter>argv</Parameter></ParamDef>
        <ParamDef>bool <Parameter>GUIenabled</Parameter></ParamDef>
</FuncSynopsis>
<Para>
This takes two parameters, the first of which is a list of argument strings.
Arguments used by TQt are removed from the list.
</Para>

<FuncSynopsis>
        <FuncDef><Function>TQApplication</Function></FuncDef>
        <ParamDef>int &amp;<Parameter>argc</Parameter></ParamDef>
        <ParamDef>char **<Parameter>argv</Parameter></ParamDef>
        <ParamDef>Type <Parameter>type</Parameter></ParamDef>
</FuncSynopsis>
<Para>
This takes two parameters, the first of which is a list of argument strings.
Arguments used by TQt are removed from the list. (TQt v2.2+)
</Para>

<FuncSynopsis>
        <FuncDef>int <Function>exec</Function></FuncDef>
        <ParamDef></ParamDef>
</FuncSynopsis>
<Para>
This has been renamed to <Literal>exec_loop</Literal> in Python.
</Para>
</Sect2>
%End


TQApplication *tqApp;


class TQApplication : TQObject
{
%TypeHeaderCode
#include <tqapplication.h>
#include <tqwidgetlist.h>
%End

public:
	TQApplication(SIP_PYLIST) /PostHook=__pyTQtTQAppHook__/ [(int &,char **)];
%MethodCode
		// The Python interface is a list of argument strings that is
		// modified.

		int argc;
		char **argv;

		// Convert the list.
		if ((argv = pyArgvToC(a0,argc)) == NULL)
			sipIsErr = 1;
		else
		{
			// Create it now the arguments are right.
			static int nargc;
			nargc = argc;

			Py_BEGIN_ALLOW_THREADS
			sipCpp = new sipTQApplication(nargc,argv);
			Py_END_ALLOW_THREADS

			// Now modify the original list.
			updatePyArgv(a0,argc,argv);
		}
%End

	TQApplication(SIP_PYLIST,bool) /PostHook=__pyTQtTQAppHook__/ [(int &,char **,bool)];
%MethodCode
		// The Python interface is a list of argument strings that is
		// modified.

		int argc;
		char **argv;

		// Convert the list.
		if ((argv = pyArgvToC(a0,argc)) == NULL)
			sipIsErr = 1;
		else
		{
			// Create it now the arguments are right.
			static int nargc;
			nargc = argc;

			Py_BEGIN_ALLOW_THREADS
			sipCpp = new sipTQApplication(nargc,argv,a1);
			Py_END_ALLOW_THREADS

			// Now modify the original list.
			updatePyArgv(a0,argc,argv);
		}
%End

%If (TQt_2_2_0 -)
	enum Type {
		Tty,
		GuiClient,
		GuiServer
	};

	TQApplication(SIP_PYLIST,Type /Constrained/) /PostHook=__pyTQtTQAppHook__/ [(int &,char **,Type)];
%MethodCode
		// The Python interface is a list of argument strings that is
		// modified.

		int argc;
		char **argv;

		// Convert the list.
		if ((argv = pyArgvToC(a0,argc)) == NULL)
			sipIsErr = 1;
		else
		{
			// Create it now the arguments are right.
			static int nargc;
			nargc = argc;

			Py_BEGIN_ALLOW_THREADS
			sipCpp = new sipTQApplication(nargc,argv,(TQApplication::Type)a1);
			Py_END_ALLOW_THREADS

			// Now modify the original list.
			updatePyArgv(a0,argc,argv);
		}
%End
%End

	~TQApplication();
%MethodCode
		// Make sure all remaining top level widgets are not owned by
		// Python.  When a PyTQt script terminates we have no control
		// over the order in which the TQApplication instance and the
		// top level widgets are destroyed.  If the former happens
		// first then we get a seg. fault.  We could take the approach
		// of only pretending to delete the TQApplication instance, but
		// TQt seems to allow an application to delete the TQApplication
		// instance and then create another one.  The approach we take
		// is to transfer ownership of all top level widgets away from
		// Python so that the C++ dtor is not called if they are
		// destroyed after the TQApplication instance.  This might be
		// seen as a memory leak - but if we really are terminating
		// then it doesn't matter, and if we are just deleting the
		// TQApplication instance then (I think) we should have already
		// deleted the top level widgets manually.  In any event, the X
		// server resources will be freed.

		TQWidgetList *tlw = TQApplication::topLevelWidgets();
		TQWidgetListIt it(*tlw);
		TQWidget *w;

		while ((w = it.current()) != 0)
		{
			PyObject *sw;

			if ((sw = sipGetWrapper(w,sipClass_TQWidget)) != NULL)
				sipTransferTo(sw,NULL);

			++it;
		}

		delete tlw;
%End

	int argc() const;
	SIP_PYLIST argv() const;
%MethodCode
		// The Python interface returns a list of strings.

		int argc = sipCpp -> argc();

		if ((sipRes = PyList_New(argc)) == NULL)
			sipIsErr = 1;
		else
			for (int a = 0; a < argc; ++a)
				if (PyList_SetItem(sipRes,a,PyString_FromString(sipCpp -> argv()[a])) < 0)
				{
					Py_DECREF(sipRes);
					sipIsErr = 1;
					break;
				}
%End

%If (TQt_2_3_0 -)
	Type type() const;
%End
%If (- TQt_2_00)
	static GUIStyle style();
	static void setStyle(GUIStyle);
%End
%If (TQt_2_00 -)
	static TQStyle &style();
	static void setStyle(TQStyle * /Transfer/);
%End
%If (TQt_3_0_0 -)
	static TQStyle *setStyle(const TQString &);
%End

%If (- TQt_2_00)
	enum ColorSpec
	{
		NormalColor = 0,
		CustomColor = 1,
		PrivateColor = 4,
		ManyColor = 4,
		TrueColor = 4
	};
%End
%If (TQt_2_00 -)
	enum ColorSpec
	{
		NormalColor = 0,
		CustomColor = 1,
		ManyColor = 2
	};
%End

	static int colorSpec();
	static void setColorSpec(int);
	static TQCursor *overrideCursor();
	static void setOverrideCursor(TQCursor &,bool = 0);
	static void restoreOverrideCursor();
	static bool hasGlobalMouseTracking();
	static void setGlobalMouseTracking(bool);
%If (- TQt_2_00)
	static TQPalette *palette();
	static void setPalette(TQPalette &,bool = 0);
	static TQFont *font();
	static void setFont(const TQFont &,bool = 0);
%End
%If (TQt_2_00 -)
	static TQPalette palette(const TQWidget * = 0);
	static void setPalette(TQPalette &,bool = 0,const char * = 0);
	static TQFont font(const TQWidget * = 0);
	static void setFont(const TQFont &,bool = 0,const char * = 0);
%End
	static TQFontMetrics fontMetrics();
	TQWidget *mainWidget() const;
%If (- TQt_2_00)
	// We may not need the /Transfer/ now that the TQApplication dtor is
	// instrumented, but we'll leave it in so as not to break old programs
	// needlessly.
	void setMainWidget(TQWidget * /Transfer/);
%End
%If (TQt_2_00 -)
	virtual void setMainWidget(TQWidget *);
	virtual void polish(TQWidget *);
%End
	static TQWidgetList *allWidgets();
	static TQWidgetList *topLevelWidgets();
%If (- TQt_3_0_0)
	static TQWidget *desktop();
%End
%If (TQt_3_0_0 -)
	static TQDesktopWidget *desktop();
%End
	static TQWidget *activePopupWidget();
	static TQWidget *activeModalWidget();
	static TQClipboard *clipboard();
	TQWidget *focusWidget() const;
%If (TQt_2_00 -)
	TQWidget *activeWindow() const;
%End
	static TQWidget *widgetAt(int,int,bool = 0);
	static TQWidget *widgetAt(const TQPoint &,bool = 0);

%If (TQt_3_1_0 -)
	static TQEventLoop *eventLoop();
%End

	int exec() /PyName=exec_loop, ReleaseGIL,
		    PreHook=__pyTQtPreEventLoopHook__,
		    PostHook=__pyTQtPostEventLoopHook__/;
	void processEvents() /ReleaseGIL/;
	void processEvents(int) /ReleaseGIL/;
	void processOneEvent() /ReleaseGIL/;
%If (TQt_3_0_0 -)
	bool hasPendingEvents();
%End
	int enter_loop() /ReleaseGIL/;
	void exit_loop();
%If (TQt_2_00 -)
	int loopLevel() const;
%End
	static void exit(int = 0);
	static bool sendEvent(TQObject *,TQEvent *) /ReleaseGIL/;
	static void postEvent(TQObject *,TQEvent * /Transfer/) /ReleaseGIL/;
	static void sendPostedEvents(TQObject *,int) /ReleaseGIL/;
%If (TQt_2_00 -)
	static void sendPostedEvents() /ReleaseGIL/;
	static void removePostedEvents(TQObject *);
%End
	virtual bool notify(TQObject *,TQEvent *) /ReleaseGIL/;
	static bool startingUp();
	static bool closingDown();
	static void flushX();
%If (TQt_3_0_0 -)
	static void flush();
%End
	static void syncX();
	static void beep();
%If (TQt_2_00 -)
	void setDefaultCodec(TQTextCodec *);
	TQTextCodec *defaultCodec() const;
	void installTranslator(TQTranslator *);
	void removeTranslator(TQTranslator *);
%End
%If (TQt_2_00 - TQt_3_0_0)
	TQString translate(const char *,const char *) const;
%End
%If (TQt_2_2_0 - TQt_3_0_0)
	TQString translate(const char *,const char *,const char *) const;
%End
%If (TQt_3_0_0 -)
	enum Encoding {
		DefaultCodec,
		UnicodeUTF8
	};

	TQString translate(const char *,const char *,const char * = 0,
			  Encoding = DefaultCodec) const;
%End
%If (TQt_3_2_0 -)
	TQString applicationDirPath();
	TQString applicationFilePath();
%End
%If (- TQt_3_0_0)
	static void setWinStyleHighlightColor(const TQColor &);
	static const TQColor &winStyleHighlightColor();
%End
%If (TQt_2_00 -)
	static void setDesktopSettingsAware(bool);
	static bool desktopSettingsAware();
	static void setCursorFlashTime(int);
	static int cursorFlashTime();
%End
	static void setDoubleClickInterval(int);
	static int doubleClickInterval();
%If (TQt_2_1_0 -)
	static void setWheelScrollLines(int);
	static int wheelScrollLines();
%If (TQt_2_2_0 -)
	static void setGlobalStrut(const TQSize &);
	static TQSize globalStrut();
%End
%If (TQt_3_0_0 -)
	static void setLibraryPaths(const TQStringList &);
	static TQStringList libraryPaths();
	static void addLibraryPath(const TQString &);
	static void removeLibraryPath(const TQString &);
%End
	static void setStartDragTime(int);
	static int startDragTime();
	static void setStartDragDistance(int);
	static int startDragDistance();
%If (TQt_3_0_0 -)
	static void setReverseLayout(bool);
	static bool reverseLayout();
 
	static int horizontalAlignment(int);
%End
%If (TQt_2_2_0 -)
	static bool isEffectEnabled(TQt::UIEffect);
	static void setEffectEnabled(TQt::UIEffect,bool = 1);
%End
%End


%If (TQt_2_00 -)
	bool isSessionRestored() const;
	TQString sessionId() const;
%If (TQt_3_1_0 -)
	TQString sessionKey() const;
%End
	virtual void commitData(TQSessionManager &);
	virtual void saveState(TQSessionManager &);
%End
%If (TQt_2_1_0 -)
	void wakeUpGuiThread();
%End
%If (TQt_THREAD_SUPPORT)
%If (TQt_2_2_0 -)
	void lock() /ReleaseGIL/;
	void unlock(bool = 1);
	bool locked();
%End
%If (TQt_3_0_0 -)
	bool tryLock();
%End
%End

signals:
	void lastWindowClosed();
%If (TQt_2_00 -)
	void aboutToQuit();
%End
%If (TQt_2_1_0 -)
	void guiThreadAwake();
%End

public slots:
	void quit();
%If (TQt_2_00 -)
	void closeAllWindows();
%End
%If (TQt_3_2_0 -)
	void aboutTQt();
%End

protected:
%If (TQt_3_1_0 -)
	bool event(TQEvent *);
%End

private:
	TQApplication(const TQApplication &);


%TypeCode
#include <string.h>


// Convert a Python argv list to a conventional C argc count and argv array.
static char **pyArgvToC(PyObject *argvlist,int &argc)
{
	char **argv;

	argc = PyList_Size(argvlist);

	// Allocate space for two copies of the argument pointers, plus the
	// terminating NULL.
	if ((argv = (char **)sipMalloc(2 * (argc + 1) * sizeof (char *))) == NULL)
		return NULL;

	// Convert the list.
	for (int a = 0; a < argc; ++a)
	{
		char *arg;

		// Get the argument and allocate memory for it.
		if ((arg = PyString_AsString(PyList_GetItem(argvlist,a))) == NULL ||
		    (argv[a] = (char *)sipMalloc(strlen(arg) + 1)) == NULL)
			return NULL;

		// Copy the argument and save a pointer to it.
		strcpy(argv[a],arg);
		argv[a + argc + 1] = argv[a];
	}

	argv[argc + argc + 1] = argv[argc] = NULL;

	return argv;
}


// Remove arguments from the Python argv list that have been removed from the
// C argv array.
static void updatePyArgv(PyObject *argvlist,int argc,char **argv)
{
	for (int a = 0, na = 0; a < argc; ++a)
	{
		// See if it was removed.
		if (argv[na] == argv[a + argc + 1])
			++na;
		else
			PyList_SetSlice(argvlist,na,na + 1,NULL);
	}
}
%End

};


enum TQtMsgType {
	TQtDebugMsg,
	TQtWarningMsg,
	TQtFatalMsg
};


SIP_PYCALLABLE qInstallMsgHandler(SIP_PYCALLABLE /AllowNone/);
%MethodCode
	void (*old)(TQtMsgType, const char *);

	// Treat None as the default handler.
	old = qInstallMsgHandler((a0 != Py_None) ? pyqtMsgHandler : 0);

	// If we recognise the old handler, then return it.  Otherwise return
	// the default handler.  This doesn't exactly mimic the TQt behaviour
	// but it is probably close enough for the way it will be used.
	sipRes = (old == pyqtMsgHandler) ? pyqtPyMsgHandler : Py_None;
	Py_INCREF(sipRes);

	// Save the new Python handler.
	Py_XDECREF(pyqtPyMsgHandler);
	pyqtPyMsgHandler = a0;
	Py_INCREF(pyqtPyMsgHandler);
%End

%ModuleCode
// The user supplied Python handler.
static PyObject *pyqtPyMsgHandler = 0;

// The C++ wrapper around the Python handler.
static void pyqtMsgHandler(TQtMsgType type, const char *msg)
{
	PyObject *res;

	SIP_BLOCK_THREADS

#if SIP_VERSION >= 0x040200
	res = sipCallMethod(0, pyqtPyMsgHandler, "Es", type, sipEnum_TQtMsgType, msg);
#elif SIP_VERSION >= 0x040000
	res = sipCallMethod(0, pyqtPyMsgHandler, "es", type, msg);
#else
	PyObject *args = Py_BuildValue("is", type, msg);

	if (args != NULL)
	{
		res = PyEval_CallObject(pyqtPyMsgHandler, args);
		Py_DECREF(args);
	}
#endif

	Py_XDECREF(res);

	if (res != NULL && res != Py_None)
	{
		PyErr_SetString(PyExc_TypeError, "invalid result type from PyTQt message handler");
		res = NULL;
	}

	if (res == NULL)
		PyErr_Print();

	SIP_UNBLOCK_THREADS
}
%End
