// -*- Mode: C++; c-basic-offset: 4  -*-
/* $Id: changeset.hg,v 1.4 2006/06/05 17:54:23 murrayc Exp $ */

/* changeset.hg 
 * 
 * Copyright (C) 2002 GConfmm 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 <glibmm/ustring.h>
#include <gconfmm/value.h>
#include <gconfmm/setinterface.h>
#include <sigc++/slot.h>

_DEFS(gconfmm,gconf)

extern "C" {
    typedef struct _GConfChangeSet GConfChangeSet;
}

namespace Gnome
{
namespace Conf
{


/** A ChangeSet is a set of changes to the GConf database that can be commited
 * and reversed easily. The changes can be both set and unset operations.
 * Currently the ChangeSet operations are not atomic, and not specially optimized
 * for. However, it is suitable for use, for instance, preferences dialogs.
 * 
 * The set*() methods do not throw errors, they simply store the keys and the values.
 * 
 * @see Client::change_set_from_current(), Client::change_set_commit(), 
 *      Client::change_set_reverse().
 */
class ChangeSet : public SetInterface
{
    _CLASS_GENERIC(ChangeSet,GConfChangeSet)
    _IGNORE(gconf_change_set_new, gconf_change_set_ref, gconf_change_set_unref)
    _IGNORE(gconf_change_set_set_user_data, gconf_change_set_get_user_data)
public:
    ChangeSet();
    explicit ChangeSet(GConfChangeSet* castitem, bool make_a_copy = false);

    ChangeSet(const ChangeSet& src);
    ChangeSet& operator=(const ChangeSet& src);
    virtual ~ChangeSet();

    GConfChangeSet*       gobj()       { return gobject_; }
    const GConfChangeSet* gobj() const { return gobject_; }
    GConfChangeSet* gobj_copy() const;

protected:
    GConfChangeSet* gobject_;

public:
    /** Clear all entries.
     * After this method, commiting the changeset is a no-op. */
    _WRAP_METHOD(void clear(), gconf_change_set_clear)

    /** Returns the number of keys in the changeset. */
    _WRAP_METHOD(unsigned int size() const, gconf_change_set_size)

    /** Remove the specified key from the changeset.
     * This means that the given key will not be modified by a commit. */
    _WRAP_METHOD(void remove(const Glib::ustring& key), gconf_change_set_remove)

    /** Check whether the given key will be modified by a commit operation.
     * @return 0 if the key will not be modified, else the modified value.
     * Remember to delete the Value. */
    Value* exists(const Glib::ustring& key) const;
    _IGNORE(gconf_change_set_check_value)

    /** Unset the given key. 
     * Mark the key, so that it will be removed from the configuration database during a commit. */
    _WRAP_METHOD(void unset(const Glib::ustring& key), gconf_change_set_unset)

    //Hand-code these, because we need to ignore the Glib::Error argument when using --enable-api-exceptions=no:
    //We must match the virtual method signatures in SetInterface, even though these implementations of that 
    //interface do not actually throw exceptions.
    //_WRAP_METHOD(void set(const Glib::ustring& key, bool what), gconf_change_set_set_bool)
    //_WRAP_METHOD(void set(const Glib::ustring& key, int what), gconf_change_set_set_int)
    //_WRAP_METHOD(void set(const Glib::ustring& key, double what), gconf_change_set_set_float)
    //_WRAP_METHOD(void set(const Glib::ustring& key, const Glib::ustring& what), gconf_change_set_set_string)
    //_WRAP_METHOD(void set(const Glib::ustring& key, const Schema& val), gconf_change_set_set_schema)
    //_WRAP_METHOD(void set(const Glib::ustring& key, const Value& what), gconf_change_set_set)
    _IGNORE(gconf_change_set_set_list, gconf_change_set_set_pair)
    _IGNORE(gconf_change_set_set_nocopy)

    #ifdef GLIBMM_EXCEPTIONS_ENABLED
    virtual void set(const Glib::ustring& key, const Value& value);
    virtual void set(const Glib::ustring& key, bool what);
    virtual void set(const Glib::ustring& key, int what);
    virtual void set(const Glib::ustring& key, double what);
    virtual void set(const Glib::ustring& key, const Glib::ustring& what);
    virtual void set(const Glib::ustring& key, const Schema& what);
    #else
    virtual void set(const Glib::ustring& key, const Value& value, std::auto_ptr<Glib::Error>& error);
    virtual void set(const Glib::ustring& key, bool what, std::auto_ptr<Glib::Error>& error);
    virtual void set(const Glib::ustring& key, int what, std::auto_ptr<Glib::Error>& error);
    virtual void set(const Glib::ustring& key, double what, std::auto_ptr<Glib::Error>& error);
    virtual void set(const Glib::ustring& key, const Glib::ustring& what, std::auto_ptr<Glib::Error>& error);
    virtual void set(const Glib::ustring& key, const Schema& what, std::auto_ptr<Glib::Error>& error);    
    #endif //GLIBMM_EXCEPTIONS_ENABLED

    _IGNORE(gconf_change_set_set_bool, gconf_change_set_set_int, gconf_change_set_set_float, 
    gconf_change_set_set_string, gconf_change_set_set_schema, gconf_change_set_set)

    typedef sigc::slot<void, const Glib::ustring&, const Value&> ForeachSlot;
    /** Iterate over the keys marked in this ChangeSet.
     * Calls @p slot for each key-value pair that is marked in the ChangeSet.
     * Keys marked unset will have a Value with type VALUE_INVALID.
     */
    void for_each(const ForeachSlot& slot);
    _IGNORE(gconf_change_set_foreach)
private:
    static GConfChangeSet* do_ref(GConfChangeSet*);
};


} // namespace Conf
} // namespace Gnome
