// 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

%ModuleHeaderCode
#include <tqapplication.h>
%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

	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

	~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,PyBytes_FromString(sipCpp -> argv()[a])) < 0)
				{
					Py_DECREF(sipRes);
					sipIsErr = 1;
					break;
				}
%End

	Type type() const;
	static TQStyle &style();
	static void setStyle(TQStyle * /Transfer/);
	static TQStyle *setStyle(const TQString &);

	enum ColorSpec
	{
		NormalColor = 0,
		CustomColor = 1,
		ManyColor = 2
	};

	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);
	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);
	static TQFontMetrics fontMetrics();
	TQWidget *mainWidget() const;
	virtual void setMainWidget(TQWidget *);
	virtual void polish(TQWidget *);
	static TQWidgetList *allWidgets();
	static TQWidgetList *topLevelWidgets();
	static TQDesktopWidget *desktop();
	static TQWidget *activePopupWidget();
	static TQWidget *activeModalWidget();
	static TQClipboard *clipboard();
	TQWidget *focusWidget() const;
	TQWidget *activeWindow() const;
	static TQWidget *widgetAt(int,int,bool = 0);
	static TQWidget *widgetAt(const TQPoint &,bool = 0);

	static TQEventLoop *eventLoop();

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

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


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

signals:
	void lastWindowClosed();
	void aboutToQuit();
	void guiThreadAwake();

public slots:
	void quit();
	void closeAllWindows();
	void aboutTQt();

protected:
	bool event(TQEvent *);

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)
	{
		PyObject *argObject = PyList_GET_ITEM(argvlist, a);
		char *arg;

		if (PyUnicode_Check(argObject))
		{
			arg = tqstrdup(sipString_AsUTF8String(&argObject));
		}
		else if (PyBytes_Check(argObject))
		{
			arg = tqstrdup(PyBytes_AS_STRING(argObject));
		}
		else
		{
			return NULL;
		}

		argv[a] = argv[a + argc + 1] = arg;
	}

	argv[argc] = argv[argc + argc + 1] = 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) ? pytqtMsgHandler : 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 == pytqtMsgHandler) ? pytqtPyMsgHandler : Py_None;
	Py_INCREF(sipRes);

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

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

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

	SIP_BLOCK_THREADS

	res = sipCallMethod(0, pytqtPyMsgHandler, "Es", type, sipEnum_TQtMsgType, msg);

	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
