/*
   KD Tools - a set of useful widgets for TQt
   $Id: KDStream.h 387954 2005-02-10 07:49:40Z blackie $
*/

/****************************************************************************
** Copyright (C) 2001-2005 Klar�lvdalens Datakonsult AB.  All rights reserved.
**
** This file is part of the KD Tools library.
**
** 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 valid commercial KD Tools licenses may use this file in
** accordance with the KD Tools Commercial 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.
**
** Contact info@klaralvdalens-datakonsult.se if any conditions of this
** licensing are not clear to you.
**
**********************************************************************/

#ifndef KIPI_KDSTREAM
#define KIPI_KDSTREAM

// Forward declarations.
class TQImage;
class TQPixmap;
class TQColor;
class TQColorGroup;
class TQPalette;
class TQCursor;
class TQDate;
class TQDateTime;
class TQTime;
class TQFont;
class TQPen;
class TQPoint;
class TQSize;
class TQRect;
class TQObject;
class TQVariant;
class TQBrush;
class TQSizePolicy;
class TQKeySequence;

#include <tqstring.h>
#include <tqvaluelist.h>
#include <tqstrlist.h>
#include <tqasciidict.h>
#include <tqintdict.h>
#include <tqptrdict.h>
#include <tqdict.h>
#include <tqvaluestack.h>
#include <tqasciicache.h>
#include <tqintcache.h>
#include <tqcache.h>

#include <tqptrlist.h>
#include <tqptrstack.h>
#include <tqptrqueue.h>
#include <tqpair.h>
#include <tqptrvector.h>
#include <tqvaluevector.h>

// utility functions.
class KDStream;
typedef KDStream & (*KDSTREAMFUNC)(KDStream &);
KDStream& endl( KDStream& stream);
KDStream& flush( KDStream& stream);

class KDStream
{
public:
  KDStream( TQString* outputString = 0);
  ~KDStream();
  void flush();

  // Standard C++ types
  KDStream& operator<<( bool );
  KDStream& operator<<( char );
  KDStream& operator<<( float );
  KDStream& operator<<( double );
  KDStream& operator<<( short );
  KDStream& operator<<( unsigned short );
  KDStream& operator<<( int );
  KDStream& operator<<( unsigned int );
  KDStream& operator<<( long );
  KDStream& operator<<( unsigned long );
  KDStream& operator<<( const char* );
  KDStream& operator<<( const void* );

  // Data holding classes.
  KDStream& operator<<( const TQString& );
  KDStream& operator<<( const TQCString& );
  KDStream& operator<<( const TQChar& );

  KDStream& operator<<( const TQColor& );
  KDStream& operator<<( const TQColorGroup& );
  KDStream& operator<<( const TQPalette& );
  KDStream& operator<<( const TQCursor& );

  KDStream& operator<<( const TQDate& );
  KDStream& operator<<( const TQDateTime& );
  KDStream& operator<<( const TQTime& );

  KDStream& operator<<( const TQFont& );
  KDStream& operator<<( const TQPen& );
  KDStream& operator<<( const TQPoint& );
  KDStream& operator<<( const TQSize& );
  KDStream& operator<<( const TQRect& );
  KDStream& operator<<( const TQBrush& );
  KDStream& operator<<( const TQSizePolicy& );
  KDStream& operator<<( const TQKeySequence& );
  KDStream& operator<<( const TQPixmap& );
  KDStream& operator<<( const TQImage& );

  // misc
  KDStream& operator<<( KDSTREAMFUNC );
  KDStream& operator<<( const TQVariant& );
  KDStream& operator<<( const TQObject& );
  KDStream& operator<<( const TQStrList& list );

protected:
  TQString TQColor2Str( const TQColor& col );

private:
  TQString _output;
  TQString* _out;
};


// Helper functions for KDStream.
// Defined as global functions to support
// compilers without support for member templates
// You should not need to call those yourself
template <class Iterator> void KDStream_valueListStream( KDStream& st, Iterator begin, Iterator end )
{
  st << "[";
  bool first = true;
  for ( Iterator it = begin; it != end; ++it ){
    if ( first )
      first = false;
    else
      st << ", ";
    st << *it;
  }
  st << "]";
}

template<class Iterator> void KDStream_ptrListStream( KDStream& st, Iterator it, bool doubleDeref )
{
  st << "[";
  bool first = true;
  for ( ; *it; ++ it) {
    if ( first )
      first = false;
    else
      st << ", ";

    if ( doubleDeref )
      st << *(*it);
    else {
      // TQStrList ought to be a value list rather than a ptr list, one less dereference is
      // necesary here, otherwise we will only stream out a char, rather than a char *
      st << *it;
    }
  }
  st << "]";
}

template<class Iterator> void KDStream_ptrDictStream( KDStream& st, Iterator it )
{
  st << "{";
  bool first = true;
  for ( ; it; ++ it) {
    if ( first )
      first = false;
    else
      st << ", ";

    st << (it.currentKey()) << ": " << *(it.current()) ;
  }
  st << "}";
}

// Stream operators for containers
// Defined as global functions to support
// compilers without member templates

template<class T> KDStream& operator<<( KDStream& st, const TQValueList<T>& list )
{
  KDStream_valueListStream( st, list.begin(), list.end() );
  return st;
}

template<class T> KDStream& operator<<( KDStream& st, const TQMemArray<T>& array )
{
  KDStream_valueListStream( st, array.begin(), array.end() );
  return st;
}

template<class T> KDStream& operator<<( KDStream& st, const TQPtrList<T>& list )
{
  KDStream_ptrListStream ( st, TQPtrListIterator<T>( list ), true );
  return st;
}

template<class T1, class T2> KDStream& operator<<( KDStream& st, const TQPair<T1,T2>& pair )
{
  st << "(" << pair.first << "," << pair.second << ")";
  return st;
}

template<class T> KDStream& operator<<( KDStream& st, const TQPtrVector<T>& vector )
{
  TQPtrList<T> list;
  vector.toList( &list );

  KDStream_ptrListStream( st, TQPtrListIterator<T>( list ), true );
  return st;
}

template<class T> KDStream& operator<<( KDStream& st, const TQValueVector<T>& vector )
{
  KDStream_valueListStream( st, vector.begin(), vector.end() );
  return st;
}

template<class T> KDStream& operator<<( KDStream& st, const TQPtrStack<T>& stack )
{

  // I need a copy to look at the individual elements.
  TQPtrStack<T> copy(stack);
  /*}*/

  st << "[";
  if ( stack.count() > 1 )
    st << "top| ";
  st << " ";

  bool first = true;
  while ( !copy.isEmpty() ) {
    if (first)
      first = false;
    else
      st << ", ";
    st << *(copy.pop());
  }

  st << " ";
  if (  stack.count() > 1 )
    st << " |bottom";
  st << "]";
  return st;
}

// This function can unfortunately not be merged with the function for
// Q(Ptr)Stack, as the Q(Ptr)Stack dereferences what it pops of the stack,
// before streaming it:
// Q(Ptr)Stack: *this << *(copy.pop());
// TQValueStack: *this <<   copy.pop() ;
template<class T> KDStream& operator<<( KDStream& st, const TQValueStack<T>& stack )
{
  // I need a copy to look at the individual elements.
  TQValueStack<T> copy(stack);
  st << "[";
  if ( stack.count() > 1 )
    st << "top| ";
  st << " ";

  bool first = true;
  while ( !copy.isEmpty() ) {
    if (first)
      first = false;
    else
      st << ", ";
    st << copy.pop();
  }

  st << " ";
  if (  stack.count() > 1 )
    st << " |bottom";
  st << "]";
  return st;
}


template<class T> KDStream& operator<<( KDStream& st, const TQAsciiDict<T>& dict )
{
  KDStream_ptrDictStream( st, TQAsciiDictIterator<T>( dict ) );
  return st;
}

template<class T> KDStream& operator<<( KDStream& st, const TQIntDict<T>& dict )
{
  KDStream_ptrDictStream( st, TQIntDictIterator<T>( dict ) );
  return st;
}

template<class T> KDStream& operator<<( KDStream& st, const TQPtrDict<T>& dict )
{
  KDStream_ptrDictStream( st, TQPtrDictIterator<T>( dict ) );
  return st;
}

template<class T> KDStream& operator<<( KDStream& st, const TQDict<T>& dict )
{
  KDStream_ptrDictStream( st, TQDictIterator<T>( dict ) );
  return st;
}

template<class T> KDStream& operator<<( KDStream& st, const TQAsciiCache<T>& cache )
{
  KDStream_ptrDictStream( st, TQAsciiCacheIterator<T>( cache ) );
  return st;
}

template<class T> KDStream& operator<<( KDStream& st, const TQIntCache<T>& cache )
{
  KDStream_ptrDictStream( st, TQIntCacheIterator<T>( cache ) );
  return st;
}

template<class T> KDStream& operator<<( KDStream& st, const TQCache<T>& cache )
{
  KDStream_ptrDictStream( st, TQCacheIterator<T>( cache ) );
  return st;
}

#endif /* KDStream */
