// -*- C++ -*- //

/* set.h
 *
 * Copyright 2006 libgdamm Development Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or(at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <libgdamm/holder.h>
#include <libgdamm/value.h>

_DEFS(libgdamm,libgda)
_PINCLUDE(glibmm/private/object_p.h)

namespace Gnome
{

namespace Gda
{


/** Container for several values.
 *
 * The Gda::Set object is a container for several values (as Gda::Holder objects), 
 * which also offers different classifications of the group of GdaHolder values 
 * (see get_node(), get_source() or get_group()).
 *
 * It is possible to control the values a Gda::Holder can have in the Gda::Set by 
 * connecting to the signal_before_holder_change() signal.
 * 
 * @ingroup DataHandlers
 */
class Set : public Glib::Object
{
  _CLASS_GOBJECT(Set, GdaSet, GDA_SET, Glib::Object, GObject)
protected:
  typedef std::vector< Glib::RefPtr<Holder> > HolderVector;

  #m4 _CONVERSION(`const HolderVector&', `GSList*', `Glib::SListHandler<  Glib::RefPtr<Holder> >::vector_to_slist($3).data()')
  _WRAP_CTOR(Set(const HolderVector& holders), gda_set_new)

public:
  _WRAP_CREATE(const HolderVector& holders = HolderVector())
  
  _WRAP_METHOD(Glib::RefPtr<Set> copy(), gda_set_copy)

  _WRAP_METHOD(Value get_holder_value(const Glib::ustring& holder_id) const, gda_set_get_holder_value)

  _WRAP_METHOD_DOCS_ONLY(gda_set_set_holder_value)
  template<class T>
  bool set_holder_value(const Glib::ustring& holder_id, T value);
  
  _WRAP_METHOD(Glib::RefPtr<Holder> get_holder(const Glib::ustring& holder_id), gda_set_get_holder, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const Holder> get_holder(const Glib::ustring& holder_id) const, gda_set_get_holder, refreturn)

  _WRAP_METHOD(void add_holder(const Glib::RefPtr<Holder>& holder), gda_set_add_holder)
  
  /** Add a holder
   * 
   * Convenience method to add a holder with value
   * @param id Name of the holder
   * @param value Value of the holder
   */
#ifdef GLIBMM_EXCEPTIONS_ENABLED
  void add_holder_as_value(const Glib::ustring& id, const Gda::Value& value);
#else
  void add_holder_as_value(const Glib::ustring& id, const Gda::Value& value, std::auto_ptr<Glib::Error>& error);
#endif
  /** Add a holder
   * 
   * Convenience method to add a holder with value
   * @param id Name of the holder
   * @param value Value of the holder
   */
  template <class ValueType>
  void add_holder(const Glib::ustring& id, const ValueType& value);
  
  _WRAP_METHOD(void remove_holder(const Glib::RefPtr<Holder>& holder), gda_set_remove_holder)

  _WRAP_METHOD(void merge_with_set(const Glib::RefPtr<Set>& set_to_merge), gda_set_merge_with_set)
  
  _WRAP_METHOD(bool is_valid() const, gda_set_is_valid, errthrow)
  
  /* TODO: These don't seem to be very useful */
  //See http://bugzilla.gnome.org/show_bug.cgi?id=574742
  _IGNORE(gda_set_get_source_model, gda_set_get_source, gda_source_get_group, gda_source_get_node)
/*
  _WRAP_METHOD(SetSource* get_source_for_model (const Glib::RefPtr<DataModel>& model), gda_set_get_source_for_model)
  _WRAP_METHOD(SetSource* get_source (const Glib::RefPtr<Holder>& holder), gda_set_get_source)
  _WRAP_METHOD(SetGroup* get_group (const Glib::RefPtr<Holder>& holder), gda_set_get_group)
  _WRAP_METHOD(SetNode* get_node (const Glib::RefPtr<Holder>& holder), gda_set_get_node)
*/		

//The m4 conversion is here because it is only for signals:
#m4 _CONVERSION(`GdaHolder*',`const Glib::RefPtr<Holder>&',`Glib::wrap($3, true /* take_copy */)')

  _WRAP_SIGNAL(void holder_changed(const Glib::RefPtr<Holder>& holder), "holder-changed")
  _WRAP_SIGNAL(void public_data_changed(), "public-data-changed")
  
#m4 _CONVERSION(`GError*', `Glib::Error*', `Glib::wrap($3)')
#m4 _CONVERSION(`Glib::Error', `GError*', `($3).gobj()')
  _WRAP_SIGNAL(Glib::Error validate_set(), "validate-set", no_default_handler)
  
#m4 _CONVERSION(`GValue*',`const Value&',`Value($3)')
  _WRAP_SIGNAL(Glib::Error validate_holder_change(const Glib::RefPtr<Holder>& holder, const Value& value), "validate-holder-change", no_default_handler)
  
#m4 _CONVERSION(`const char*',`const Glib::ustring&',__GCHARP_TO_USTRING)
  _WRAP_SIGNAL(void holder_attr_changed(const Glib::RefPtr<Holder>& holder, const Glib::ustring& attr_name, Value value), "holder-attr-changed", no_default_handler)
     
  _WRAP_PROPERTY("description", Glib::ustring)
  _WRAP_PROPERTY("id", Glib::ustring)
  _WRAP_PROPERTY("name", Glib::ustring)
};

#ifndef DOXYGEN_SHOULD_SKIP_THIS
template <class ValueType> inline
void Set::add_holder(const Glib::ustring& id, const ValueType& value)
{
  Gnome::Gda::Value gdavalue(value);
  Glib::RefPtr<Holder> holder = Holder::create(gdavalue.get_value_type(), id);
#ifdef GLIBMM_EXCEPTIONS_ENABLED
  holder->set_value(value);
#else
  std::auto_ptr<Glib::Error> error;
  holder->set_value(value, error);
#endif
  this->add_holder(holder);
}
#endif //DOXYGEN_SHOULD_SKIP_THIS

} // namespace Gda
} // namespace Gnome

