// This may look like C code, but it's really -*- C++ -*-
/*
 * Copyright (C) 2008 Emweb bvba, Kessel-Lo, Belgium.
 *
 * See the LICENSE file for terms of use.
 */
#ifndef WABSTRACT_PROXY_MODEL_H_
#define WABSTRACT_PROXY_MODEL_H_

#include <Wt/WAbstractItemModel>

namespace Wt {

/*! \class WAbstractProxyModel Wt/WAbstractProxyModel Wt/WAbstractProxyModel
 *  \brief An abstract proxy model for %Wt's item models.
 *
 * A proxy model does not store data, but presents data from a source
 * model in another way. It may provide filtering, sorting, or other
 * computed changes to the source model. A proxy model may be a fully
 * functional model, that also allows modification of the underlying
 * model.
 *
 * This abstract proxy model may be used as a starting point for
 * implementing a custom proxy model, when WSortFilterProxyModel is
 * not adequate. It implements data access and manipulation using the
 * a virtual mapping method (mapToSource()) to access and manipulate
 * the underlying sourceModel().
 *
 * \ingroup modelview
 */
class WT_API WAbstractProxyModel : public WAbstractItemModel
{
public:
  /*! \brief Constructor.
   */
  WAbstractProxyModel(WObject *parent = 0);

  /*! \brief Maps a source model index to the proxy model.
   *
   * This method returns a model index in the proxy model that
   * corresponds to the model index \p sourceIndex in the source
   * model. This method must only be implemented for source model
   * indexes that are mapped and thus are the result of mapToSource().
   *
   * \sa mapToSource()
   */
  virtual WModelIndex mapFromSource(const WModelIndex& sourceIndex) const = 0;

  /*! \brief Maps a proxy model index to the source model.
   *
   * This method returns a model index in the source model that
   * corresponds to the proxy model index \p proxyIndex.
   *
   * \sa mapFromSource()
   */
  virtual WModelIndex mapToSource(const WModelIndex& proxyIndex) const = 0;

  /*! \brief Sets the source model.
   *
   * The source model provides the actual data for the proxy
   * model.
   *
   * Ownership of the source model is <i>not</i> transferred.
   */
  virtual void setSourceModel(WAbstractItemModel *sourceModel);

  /*! \brief Returns the source model.
   *
   * \sa setSourceModel()
   */
  WAbstractItemModel *sourceModel() const { return sourceModel_; }

#ifndef DOXYGEN_ONLY
  using WAbstractItemModel::setData;
  using WAbstractItemModel::data;
  using WAbstractItemModel::setHeaderData;

  virtual boost::any data(const WModelIndex& index, int role = DisplayRole)
    const;
  virtual bool setData(const WModelIndex& index, const boost::any& value,
		       int role = EditRole);

  virtual WFlags<ItemFlag> flags(const WModelIndex& index) const;

  virtual bool insertColumns(int column, int count,
			     const WModelIndex& parent = WModelIndex());
  virtual bool removeColumns(int column, int count,
			     const WModelIndex& parent = WModelIndex());

  virtual std::string mimeType() const;
  virtual std::vector<std::string> acceptDropMimeTypes() const;

  virtual void dropEvent(const WDropEvent& e, DropAction action,
			 int row, int column, const WModelIndex& parent);

  virtual void *toRawIndex(const WModelIndex& index) const;
  virtual WModelIndex fromRawIndex(void *rawIndex) const;
#endif // DOXYGEN_ONLY

protected:
  /*! \brief Create a source model index.
   *
   * This is a utility function that allows you to create indexes in
   * the source model. In this way, you can reuse the internal pointers of
   * the source model in proxy model indexes, and convert a proxy model index
   * back to the source model index using this method.
   */
  WModelIndex createSourceIndex(int row, int column, void *ptr) const;

  /*! \brief A base class for an item modeling a source index parent.
   *
   * Many mplementations of a proxy model will need to maintain a data
   * structure per source model indexes, where they relate source rows or
   * columns to proxy rows or columns, per hierarchical parent.
   *
   * It may be convenient to start from this item class as a base
   * class so that shiftModelIndexes() can be used to update this data
   * structure when the source model adds or removes rows.
   *
   * You will typically use your derived class of this item as the
   * internal pointer for proxy model indexes: a proxy model index
   * will have an item as internal pointer whose sourceIndex_ corresponds
   * to the source equivalent of the proxy model index parent.
   *
   * \sa createIndex()
   */
  struct BaseItem {
    /*! \brief The source model index.
     *
     * The source model index for this item.
     */
    WModelIndex sourceIndex_;

    /*! \brief Create a BaseItem.
     */
    BaseItem(const WModelIndex& sourceIndex) : sourceIndex_(sourceIndex) { }
    virtual ~BaseItem();
  };

  /*! \brief A map for items.
   *
   * \sa BaseItem
   */
#ifndef WT_TARGET_JAVA
  typedef std::map<WModelIndex, BaseItem *> ItemMap;
#else
  typedef std::treemap<WModelIndex, BaseItem *> ItemMap;
#endif // WT_TARGET_JAVA

  /*! \brief Utility methods to shift items in an item map.
   *
   * You can use this method to adjust an item map after the source
   * model has inserted or removed rows. When removing rows (count < 0),
   * items may possibly be removed and deleted.
   */
  void shiftModelIndexes(const WModelIndex& sourceParent, int start, int count,
			 ItemMap& items);
private:
  WAbstractItemModel     *sourceModel_;
};

}

#endif // WSORT_FILTER_PROXY_MODEL_H_
