#ifndef QVARIANTEDIT_H
#define QVARIANTEDIT_H

#include "clineedit.h"
#include "ecombobox.h"
#include "colorbutton.h"
#include "qrectedit.h"
#include "qpointedit.h"
#include <QCheckBox>
#include <QDoubleSpinBox>


class StringListEdit: public QWidget
{
	Q_OBJECT
public:
	StringListEdit(QWidget * parent = 0);
	~StringListEdit();
	
	QStringList value() const;
	
private:
	virtual void changeEvent(QEvent * e);
	
	QBoxLayout lay;
	EComboBox * combo;
	QPushButton * butt_add, * butt_del, * butt_clear;
	
public slots:
	void setValue(const QStringList & v);
	
private slots:
	void editItem();
	void addItem();
	void delItem();
	void clear();
	
signals:
	void valueChanged();
	
};




class PathEdit: public QWidget
{
	Q_OBJECT
public:
	PathEdit(QWidget * parent = 0);
	~PathEdit() {delete line; delete butt_select;}
	
	QString value() const {return line->text();}
	
	bool is_dir, is_abs;
	QString filter;
	
private:
	virtual void changeEvent(QEvent * e);
	
	QBoxLayout lay;
	CLineEdit * line;
	QPushButton * butt_select;
	
public slots:
	void setValue(const QString & v) {line->setText(v);}
	
private slots:
	void select();
	
signals:
	void valueChanged();
	
};




class QVariantEdit: public QWidget
{
	Q_OBJECT
	Q_PROPERTY(QVariant value READ value WRITE setValue)
	
public:
	explicit QVariantEdit(QWidget * parent = 0);
	~QVariantEdit();
	
	QVariant value() const;
	QSize sizeHint() const {if (_cur_edit) return _cur_edit->sizeHint(); return QWidget::sizeHint();}
	
	struct EnumType {
		QString toString() const {return value;}
		QString value;
		QStringList enum_list;
	};
	
	struct FileType {
		FileType(const QString & p = QString(), const QString & f = QString(), bool abs = false): file(p), filter(f), is_abs(abs) {}
		QString toString() const {return file;}
		QString file;
		QString filter;
		bool is_abs;
	};
	
	struct DirType {
		DirType(const QString & d = QString(), bool abs = false): dir(d), is_abs(abs) {}
		QString toString() const {return dir;}
		QString dir;
		bool is_abs;
	};
	
protected:
	void resizeEvent(QResizeEvent * );
	void _recreate(const QVariant & new_value);
	void _delete();
	void _resize() {if (_cur_edit) _cur_edit->resize(size());}
	void _newPath();
	void _setEnum(const EnumType & v);
	void _setFile(const FileType & v);
	void _setDir(const DirType & v);
	
	
	QLabel * _empty;
	CLineEdit * _line;
	QCheckBox * _check;
	ColorButton * _color;
	StringListEdit * _list;
	QDateTimeEdit * _date;
	QDoubleSpinBox * _spin;
	QRectEdit * _rect;
	QPointEdit * _point;
	PathEdit * _path;
	QComboBox * _enum;
	QWidget * _cur_edit;
	QVariant _value;
	
private slots:
	void _changed() {emit valueChanged(value());}
	
public slots:
	void setValue(const QVariant & v);
	
signals:
	void valueChanged(QVariant);
	
};

Q_DECLARE_METATYPE(QVariantEdit::EnumType)
inline QDataStream & operator <<(QDataStream & s, const QVariantEdit::EnumType & v) {s << v.value << v.enum_list; return s;}
inline QDataStream & operator >>(QDataStream & s, QVariantEdit::EnumType & v) {s >> v.value >> v.enum_list; return s;}
inline QDebug operator <<(QDebug s, const QVariantEdit::EnumType & v) {s.nospace() << v.value; return s.space();}

Q_DECLARE_METATYPE(QVariantEdit::FileType)
inline QDataStream & operator <<(QDataStream & s, const QVariantEdit::FileType & v) {s << v.file << v.filter << v.is_abs; return s;}
inline QDataStream & operator >>(QDataStream & s, QVariantEdit::FileType & v) {s >> v.file >> v.filter >> v.is_abs; return s;}
inline QDebug operator <<(QDebug s, const QVariantEdit::FileType & v) {s.nospace() << v.file; return s.space();}

Q_DECLARE_METATYPE(QVariantEdit::DirType)
inline QDataStream & operator <<(QDataStream & s, const QVariantEdit::DirType & v) {s << v.dir << v.is_abs; return s;}
inline QDataStream & operator >>(QDataStream & s, QVariantEdit::DirType & v) {s >> v.dir >> v.is_abs; return s;}
inline QDebug operator <<(QDebug s, const QVariantEdit::DirType & v) {s.nospace() << v.dir; return s.space();}

class __QVariantEditRegistrator__ {
public:
	__QVariantEditRegistrator__() {
		qRegisterMetaType<QVariantEdit::EnumType>("QVariantEdit::EnumType");
		qRegisterMetaTypeStreamOperators<QVariantEdit::EnumType>("QVariantEdit::EnumType");
		
		qRegisterMetaType<QVariantEdit::FileType>("QVariantEdit::FileType");
		qRegisterMetaTypeStreamOperators<QVariantEdit::FileType>("QVariantEdit::FileType");
		
		qRegisterMetaType<QVariantEdit::DirType>("QVariantEdit::DirType");
		qRegisterMetaTypeStreamOperators<QVariantEdit::DirType>("QVariantEdit::DirType");
	}
};

#endif // QVARIANTEDIT_H
