/* This file is part of the KDE project
   Copyright (C) 2003-2007 Jaroslaw Staniek <js@iidea.pl>

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

   This program is distributed 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this program; see the file COPYING.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
*/

#ifndef KEXIUTILS_UTILS_H
#define KEXIUTILS_UTILS_H

#include "kexiutils_export.h"

#include <tqguardedptr.h>
#include <tqobjectlist.h>
#include <kmimetype.h>
class TQColor;

//! @short General Utils
namespace KexiUtils
{
	//! \return true if \a o has parent \a par.
	inline bool hasParent(TQObject* par, TQObject* o)
	{
		if (!o || !par)
			return false;
		while (o && o!=par)
			o = o->parent();
		return o==par;
	}

	//! \return parent object of \a o that inherits \a className or NULL if no such parent
	template<class type>
	inline type* findParent(TQObject* o, const char* className)
	{
		if (!o || !className || className[0]=='\0')
			return 0;
		while ( ((o=o->parent())) && !o->inherits(className) )
			;
		return static_cast<type*>(o);
	}

	//! Const version of findParent()
	template<class type>
	inline const type* findParentConst(const TQObject* const o, const char* className)
	{
		const TQObject * obj = o;
		if (!obj || !className || className[0]=='\0')
			return 0;
		while ( ((obj=obj->parent())) && !obj->inherits(className) )
			;
		return static_cast<const type*>(obj);
	}

	/*! \return first found child of \a o, inheriting \a className.
	 If objName is 0 (the default), all object names match. 
	 Returned pointer type is casted. */
	template<class type>
	type* findFirstChild(TQObject *o, const char* className, const char* objName = 0)
	{
		if (!o || !className || className[0]=='\0')
			return 0;
		TQObjectList *l = o->queryList( className, objName );
		TQObject *result = l->first();
		delete l;
		return static_cast<type*>(result);
	}

	//! TQDateTime - a hack needed because TQVariant(TQTime) has broken isNull()
	inline TQDateTime stringToHackedTQTime(const TQString& s)
	{
		if (s.isEmpty())
			return TQDateTime();
	//		kdDebug() << TQDateTime( TQDate(0,1,2), TQTime::fromString( s, TQt::ISODate ) ).toString(TQt::ISODate) << endl;;
		return TQDateTime( TQDate(0,1,2), TQTime::fromString( s, TQt::ISODate ) );
	}

	/*! Sets "wait" cursor with 1 second delay (or 0 seconds if noDelay is true).
	 Does nothing if the application has no GUI enabled. (see TDEApplication::guiEnabled()) */
	KEXIUTILS_EXPORT void setWaitCursor(bool noDelay = false);

	/*! Remove "wait" cursor previously set with \a setWaitCursor(), 
	 even if it's not yet visible.
	 Does nothing if the application has no GUI enabled. (see TDEApplication::guiEnabled()) */
	KEXIUTILS_EXPORT void removeWaitCursor();

	/*! Helper class. Allocate it in your code block as follows:
	 <code>
	 KexiUtils::WaitCursor wait;
	 </code>
	 .. and wait cursor will be visible (with one second delay) until you're in this block, without 
	 a need to call removeWaitCursor() before exiting the block.
	 Does nothing if the application has no GUI enabled. (see TDEApplication::guiEnabled()) */
	class KEXIUTILS_EXPORT WaitCursor
	{
		public:
			WaitCursor(bool noDelay = false);
			~WaitCursor();
	};

	/*! Helper class. Allocate it in your code block as follows:
	 <code>
	 KexiUtils::WaitCursorRemover remover;
	 </code>
	 .. and the wait cursor will be hidden unless you leave this block, without 
	 a need to call setWaitCursor() before exiting the block. After leaving the codee block,
	 the cursor will be visible again, if it was visible before creating the WaitCursorRemover object.
	 Does nothing if the application has no GUI enabled. (see TDEApplication::guiEnabled()) */
	class KEXIUTILS_EXPORT WaitCursorRemover
	{
		public:
			WaitCursorRemover();
			~WaitCursorRemover();
		private:
			bool m_reactivateCursor : 1;
	};

	/*! \return filter string in TQFileDialog format for a mime type pointed by \a mime
	 If \a kdeFormat is true, TQFileDialog-compatible filter string is generated, 
	 eg. "Image files (*.png *.xpm *.jpg)", otherwise KFileDialog -compatible 
	 filter string is generated, eg. "*.png *.xpm *.jpg|Image files (*.png *.xpm *.jpg)".
	 "\\n" is appended if \a kdeFormat is true, otherwise ";;" is appended. */
	KEXIUTILS_EXPORT TQString fileDialogFilterString(const KMimeType::Ptr& mime, bool kdeFormat = true);

	/*! @overload TQString fileDialogFilterString(const KMimeType::Ptr& mime, bool kdeFormat = true) */
	KEXIUTILS_EXPORT TQString fileDialogFilterString(const TQString& mimeString, bool kdeFormat = true);

	/*! Like TQString fileDialogFilterString(const KMimeType::Ptr& mime, bool kdeFormat = true)
	 but returns a list of filter strings. */
	KEXIUTILS_EXPORT TQString fileDialogFilterStrings(const TQStringList& mimeStrings, bool kdeFormat);

	/*! \return a color being a result of blending \a c1 with \a c2 with \a factor1 
	 and \a factor1 factors: (c1*factor1+c2*factor2)/(factor1+factor2). */
	KEXIUTILS_EXPORT TQColor blendedColors(const TQColor& c1, const TQColor& c2, int factor1 = 1, int factor2 = 1);

	/*! \return a contrast color for a color \a c: 
	 If \a c is light color, darker color created using c.dark(200) is returned; 
	 otherwise lighter color created using c.light(200) is returned. */
	KEXIUTILS_EXPORT TQColor contrastColor(const TQColor& c);

	/*! \return a lighter color for a color \a c and a factor \a factor.
	 For colors like TQt::red or TQt::green where hue and saturation are near to 255,
	 hue is decreased so the result will be more bleached. 
	 For black color the result is dark gray rather than black. */
	KEXIUTILS_EXPORT TQColor bleachedColor(const TQColor& c, int factor);

	/*! \return icon set computed as a result of colorizing \a icon pixmap with "buttonText" 
	 color of \a palette palette. This function is useful for displaying monochromed icons 
	 on the list view or table view header, to avoid bloat, but still have the color compatible 
	 with accessibility settings. */
	KEXIUTILS_EXPORT TQIconSet colorizeIconToTextColor(const TQPixmap& icon, const TQPalette& palette);

	/*! \return empty (fully transparent) pixmap that can be used as a place for icon of size \a iconGroup */
	KEXIUTILS_EXPORT TQPixmap emptyIcon(TDEIcon::Group iconGroup);

	/*! Serializes \a map to \a array.
	 KexiUtils::deserializeMap() can be used to deserialize this array back to map. */
	KEXIUTILS_EXPORT void serializeMap(const TQMap<TQString,TQString>& map, const TQByteArray& array);
	KEXIUTILS_EXPORT void serializeMap(const TQMap<TQString,TQString>& map, TQString& string);

	/*! \return a map deserialized from a byte array \a array.
	 \a array need to contain data previously serialized using KexiUtils::serializeMap(). */
	KEXIUTILS_EXPORT TQMap<TQString,TQString> deserializeMap(const TQByteArray& array);

	/*! \return a map deserialized from \a string.
	 \a string need to contain data previously serialized using KexiUtils::serializeMap(). */
	KEXIUTILS_EXPORT TQMap<TQString,TQString> deserializeMap(const TQString& string);

	/*! \return a valid filename converted from \a string by:
	 - replacing \\, /, :, *, ?, ", <, >, |, \n \\t characters with a space
	 - simplifing whitespace by removing redundant space characters using TQString::simplifyWhiteSpace()
	 Do not pass full paths here, but only filename strings. */
	KEXIUTILS_EXPORT TQString stringToFileName(const TQString& string);

	/*! Performs a simple \a string  encryption using rot47-like algorithm. 
	 Each character's unicode value is increased by 47 + i (where i is index of the character). 
	 The resulting string still contains redable characters.
	 Do not use this for data that can be accessed by attackers! */
	KEXIUTILS_EXPORT void simpleCrypt(TQString& string);

	/*! Performs a simple \a string decryption using rot47-like algorithm, 
	 using opposite operations to KexiUtils::simpleCrypt(). */
	KEXIUTILS_EXPORT void simpleDecrypt(TQString& string);

#ifdef KEXI_DEBUG_GUI
	//! Creates debug window for convenient debugging output
	KEXIUTILS_EXPORT TQWidget *createDebugWindow(TQWidget *parent);

	//! Adds debug line for for KexiDB database
	KEXIUTILS_EXPORT void addKexiDBDebug(const TQString& text);

	//! Adds debug line for for Table Designer (Alter Table actions)
	KEXIUTILS_EXPORT void addAlterTableActionDebug(const TQString& text, int nestingLevel = 0);

	//! Connects push button action to \a receiver and its \a slot. This allows to execute debug-related actions
	//! using buttons displayed in the debug window.
	KEXIUTILS_EXPORT void connectPushButtonActionForDebugWindow(const char* actionName, 
		const TQObject *receiver, const char* slot);
#endif

	//! Draws pixmap on painter \a p using predefined parameters.
	//! Used in KexiDBImageBox and KexiBlobTableEdit.
	KEXIUTILS_EXPORT void drawPixmap( TQPainter& p, int lineWidth, const TQRect& rect,
		const TQPixmap& pixmap, int alignment, bool scaledContents, bool keepAspectRatio);

	//! @internal
	KEXIUTILS_EXPORT TQString ptrToStringInternal(void* ptr, uint size);
	//! @internal
	KEXIUTILS_EXPORT void* stringToPtrInternal(const TQString& str, uint size);

	//! \return a pointer \a ptr safely serialized to string
	template<class type>
	TQString ptrToString(type *ptr)
	{
		return ptrToStringInternal(ptr, sizeof(type*));
	}
	
	//! \return a pointer of type \a type safely deserialized from \a str
	template<class type>
	type* stringToPtr(const TQString& str)
	{
		return static_cast<type*>( stringToPtrInternal(str, sizeof(type*)) );
	}

	//! Sets focus for widget \a widget with reason \a reason.
	KEXIUTILS_EXPORT void setFocusWithReason(TQWidget* widget, TQFocusEvent::Reason reason);

	//! Unsets focus for widget \a widget with reason \a reason.
	KEXIUTILS_EXPORT void unsetFocusWithReason(TQWidget* widget, TQFocusEvent::Reason reason);

	//! Used by copyFile()
	enum CopyFileResult {
		CopySuccess = 0,
		CopyReadError = 1,
		CopyWriteError = 2
	};
	
	/*!
	 Copies @p src file to @p dest file.
	 @return CopySuccess on success, CopyReadError on source file error,
	 CopyWriteError on destination file error.
	*/
	KEXIUTILS_EXPORT CopyFileResult copyFile(const TQString& src, const TQString& dest);
}


//! sometimes we leave a space in the form of empty TQFrame and want to insert here
//! a widget that must be instantiated by hand.
//! This macro inserts a widget \a what into a frame \a where.
#define GLUE_WIDGET(what, where) \
	{ TQVBoxLayout *lyr = new TQVBoxLayout(where); \
	  lyr->addWidget(what); }


#endif //KEXIUTILS_UTILS_H
