#ifndef MODEL_FLATPROXYMODEL_H
#define MODEL_FLATPROXYMODEL_H

#include <QMap>
#include <QList>
#include <QPair>
#include <QAbstractItemModel>

namespace Model {
    /**
     * This is a proxy model, useful for combo boxes.
     *
     * You can give a format string for it to use. This is QString::arg()
     * based, so you do something like this: "%1: %2". And then you need
     * to give a list of column numbers in the model for this format. In
     * the above example, you could give {0, 3} as the columns to use.
     * The column 0 would be inserted on %1 and column 3 would be inserted
     * on %2.
     *
     * This class can only handle strings, so all data from the model will
     * be converted to a string representation.
     *
     * The default format is a space separated list of all columns. If
     * this is not good, or your model has columns that are not representable
     * as strings (numbers and such will be automatically converted), you
     * must set a format string.
     */
    class FlatProxyModel : public QAbstractItemModel {
        Q_OBJECT

    public:
        explicit FlatProxyModel(QObject* parent=0);
        explicit FlatProxyModel(QAbstractItemModel* model, QObject* parent=0);
        FlatProxyModel(const QPair<QList<int>, QString>& format,
                        QAbstractItemModel* model, QObject* parent=0);
        ~FlatProxyModel();

        // Set the format. In the string, you can use %1, %2, etc. to get
        // column contents. You must give the list of column numbers to
        // insert in the list
        void setFormat(const QPair<QList<int>, QString>& format);

        virtual int columnCount(const QModelIndex& parent) const;

        virtual QVariant data(const QModelIndex& index,
                               int role=Qt::DisplayRole) const;

        virtual Qt::ItemFlags flags(const QModelIndex& index) const;

        virtual bool hasChildren(const QModelIndex&) const;

        virtual QModelIndex index(int row, int column,
                                   const QModelIndex& parent=QModelIndex()) const;

        virtual QModelIndex parent(const QModelIndex& child) const;

        virtual int rowCount(const QModelIndex& parent = QModelIndex()) const;

        void setModel(QAbstractItemModel* model);
        QAbstractItemModel* model() { return mModel; }

        // Return the index in the real model
        QModelIndex modelIndex(const QModelIndex& proxyIndex) const;

        // Return the index in the real model
        QModelIndex modelIndex(int row) const;

    Q_SIGNALS:
        // This is emitted when a new model is set
        void modelChanged();

    protected Q_SLOTS:
        virtual void slotDataChanged(QModelIndex, QModelIndex);
        virtual void slotLayoutChanged();

    protected:
        // Redo the model mapping
        void remap();

        // Map all members of this parent
        void mapModel(int& position, const QModelIndex& parent) const;

        QAbstractItemModel* mModel;
        QPair<QList<int>, QString> mFormat;
        mutable QMap<int, QModelIndex> mModelIndexMap;
    };
}

#endif // MODEL_FLATPROXYMODEL_H

