/*
    QGL PropertyEditor
    Ivan Pelipenko peri4ko@yandex.ru

    This program 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 3 of the License, or
    (at your option) any later version.

    This program 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 program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "propertyeditor.h"

#include "clineedit.h"
#include "colorbutton.h"
#include "qpointedit.h"
#include "qrectedit.h"

#include <QApplication>
#include <QCheckBox>
#include <QPainter>


QWidget * Delegate::widgetForProperty(QWidget * parent, const QModelIndex & index) const {
	QWidget * w    = nullptr;
	int type       = 0;
	QVariant value = index.data(Qt::UserRole);
	if (index.data(Qt::UserRole + 2).toString() == "__flags") return nullptr;
	if (index.data(Qt::UserRole + 1).toString() == "__flag") {
		qulonglong key = index.data(Qt::UserRole).toULongLong();
		value          = index.parent().data(Qt::UserRole);
		// QMetaProperty prop = index.parent().data(Qt::UserRole + 1).value<QMetaProperty>();
		w              = new QCheckBox(parent);
		type           = 14;
		((QCheckBox *)w)->setChecked(((value.toULongLong() & key) == key && key != 0) || (value.toULongLong() == 0 && key == 0));
		((QCheckBox *)w)->setText("0x" + QString::number(key, 16).toUpper());
		connect((QCheckBox *)w, SIGNAL(clicked(bool)), this, SLOT(changedFlag()));
		// qDebug() << prop.enumerator().name();
	} else {
		if (value.canConvert<PropertyValuePair>()) {
			PropertyValuePair prop = value.value<PropertyValuePair>();
			if (prop.first.isEnumType()) {
				w    = new QComboBox(parent);
				type = 13;
				((QComboBox *)w)->setCurrentIndex(value.toInt());
				w->setProperty("__prop", QVariant::fromValue<QMetaProperty>(prop.first));
				QMetaEnum menum = prop.first.enumerator();
				for (int i = 0; i < menum.keyCount(); ++i) {
					((QComboBox *)w)
						->addItem(QString(menum.key(i)) + " (0x" + QString::number(menum.value(i), 16).toUpper() + ")", menum.value(i));
					if (menum.value(i) == prop.second.toInt()) ((QComboBox *)w)->setCurrentIndex(i);
				}
				connect((QComboBox *)w, SIGNAL(currentIndexChanged(int)), this, SLOT(changed()));
			}
		} else {
#if QT_VERSION_MAJOR <= 5
			switch (value.type()) {
#else
			switch (value.metaType().id()) {
#endif
#if QT_VERSION_MAJOR <= 5
			case QVariant::Int:
#else
			case QMetaType::Int:
#endif
				w    = new QSpinBox(parent);
				type = 2;
				((QSpinBox *)w)->setRange(-0x7FFFFFFF, 0x7FFFFFFF);
				connect((QSpinBox *)w, SIGNAL(valueChanged(int)), this, SLOT(changed()));
				break;
#if QT_VERSION_MAJOR <= 5
			case QVariant::UInt:
#else
			case QMetaType::UInt:
#endif
				w    = new QSpinBox(parent);
				type = 3;
				((QSpinBox *)w)->setRange(0, 0xFFFFFFFF);
				connect((QSpinBox *)w, SIGNAL(valueChanged(int)), this, SLOT(changed()));
				break;
#if QT_VERSION_MAJOR <= 5
			case QVariant::LongLong:
#else
			case QMetaType::LongLong:
#endif
				w    = new QSpinBox(parent);
				type = 4;
				((QSpinBox *)w)->setRange(-0x7FFFFFFF, 0x7FFFFFFF);
				connect((QSpinBox *)w, SIGNAL(valueChanged(int)), this, SLOT(changed()));
				break;
#if QT_VERSION_MAJOR <= 5
			case QVariant::ULongLong:
#else
			case QMetaType::ULongLong:
#endif
				w    = new QSpinBox(parent);
				type = 5;
				((QSpinBox *)w)->setRange(0, 0xFFFFFFFF);
				connect((QSpinBox *)w, SIGNAL(valueChanged(int)), this, SLOT(changed()));
				break;
#if QT_VERSION_MAJOR <= 5
			case QVariant::Double:
#else
			case QMetaType::Double:
#endif
				w    = new QDoubleSpinBox(parent);
				type = 6;
				((QDoubleSpinBox *)w)->setRange(-999999999, 999999999);
				((QDoubleSpinBox *)w)->setDecimals(3);
				connect((QDoubleSpinBox *)w, SIGNAL(valueChanged(double)), this, SLOT(changed()));
				break;
#if QT_VERSION_MAJOR <= 5
			case QVariant::Bool:
#else
			case QMetaType::Bool:
#endif
				w    = new QCheckBox(parent);
				type = 7;
				((QCheckBox *)w)->setChecked(value.toBool());
				connect((QCheckBox *)w, SIGNAL(toggled(bool)), this, SLOT(changed()));
				break;
#if QT_VERSION_MAJOR <= 5
			case QVariant::Color:
#else
			case QMetaType::QColor:
#endif
				w    = new ColorButton(parent);
				type = 8;
				((ColorButton *)w)->setUseAlphaChannel(true);
				((ColorButton *)w)->setColor(value.value<QColor>());
				connect((ColorButton *)w, SIGNAL(colorChanged(QColor)), this, SLOT(changed()));
				break;
#if QT_VERSION_MAJOR <= 5
			case QVariant::Point:
#else
			case QMetaType::QPoint:
#endif
				w    = new QPointEdit(parent);
				type = 9;
				((QPointEdit *)w)->setDecimals(0);
				((QPointEdit *)w)->setValue(QPointF(value.toPoint()));
				connect((QPointEdit *)w, SIGNAL(valueChanged(QPointF)), this, SLOT(changed()));
				break;
#if QT_VERSION_MAJOR <= 5
			case QVariant::PointF:
#else
			case QMetaType::QPointF:
#endif
				w    = new QPointEdit(parent);
				type = 10;
				((QPointEdit *)w)->setDecimals(3);
				((QPointEdit *)w)->setValue(value.toPointF());
				connect((QPointEdit *)w, SIGNAL(valueChanged(QPointF)), this, SLOT(changed()));
				break;
#if QT_VERSION_MAJOR <= 5
			case QVariant::Rect:
#else
			case QMetaType::QRect:
#endif
				w    = new QRectEdit(parent);
				type = 11;
				((QRectEdit *)w)->setDecimals(0);
				((QRectEdit *)w)->setValue(QRectF(value.toRect()));
				connect((QRectEdit *)w, SIGNAL(valueChanged(QRectF)), this, SLOT(changed()));
				break;
#if QT_VERSION_MAJOR <= 5
			case QVariant::RectF:
#else
			case QMetaType::QRectF:
#endif
				w    = new QRectEdit(parent);
				type = 12;
				((QRectEdit *)w)->setDecimals(3);
				((QRectEdit *)w)->setValue(value.toRectF());
				connect((QRectEdit *)w, SIGNAL(valueChanged(QRectF)), this, SLOT(changed()));
				break;
#if QT_VERSION_MAJOR <= 5
			case QVariant::String:
			default:
#else
			case QMetaType::QString:
			default:
#endif
				w    = new CLineEdit(parent);
				type = 1;
				((CLineEdit *)w)->setDefaultText(value.toString());
				connect((CLineEdit *)w, SIGNAL(textChanged(QString)), this, SLOT(changed()));
				break;
			}
		}
	}
	if (w == 0) return 0;
	/*QPalette pal = w->palette();
	pal.setColor(QPalette::Window, Qt::white);
	w->setPalette(pal);*/
	w->setAutoFillBackground(true);
	w->setProperty("__type", type);
	return w;
}


void Delegate::setWidgetProperty(QWidget * w, const QVariant & value) const {
	if (w == 0) return;
	switch (w->property("__type").toInt()) {
	case 1: ((CLineEdit *)w)->setText(value.toString()); break;
	case 2:
	case 3:
	case 4:
	case 5: ((QSpinBox *)w)->setValue(value.toInt()); break;
	case 6: ((QDoubleSpinBox *)w)->setValue(value.toDouble()); break;
	case 7: ((QCheckBox *)w)->setChecked(value.toBool()); break;
	case 8: ((ColorButton *)w)->setColor(value.value<QColor>()); break;
	case 9: ((QPointEdit *)w)->setValue(value.value<QPoint>()); break;
	case 10: ((QPointEdit *)w)->setValue(value.value<QPointF>()); break;
	case 11: ((QRectEdit *)w)->setValue(value.value<QRect>()); break;
	case 12: ((QRectEdit *)w)->setValue(value.value<QRectF>()); break;
	}
}


const QVariant Delegate::widgetProperty(QWidget * w) const {
	if (w == 0) return QVariant();
	switch (w->property("__type").toInt()) {
	case 1: return QVariant::fromValue<QString>(((CLineEdit *)w)->text()); break;
	case 2: return QVariant::fromValue<int>(((QSpinBox *)w)->value()); break;
	case 3: return QVariant::fromValue<uint>(((QSpinBox *)w)->value()); break;
	case 4: return QVariant::fromValue<qlonglong>(((QSpinBox *)w)->value()); break;
	case 5: return QVariant::fromValue<qulonglong>(((QSpinBox *)w)->value()); break;
	case 6: return QVariant::fromValue<double>(((QDoubleSpinBox *)w)->value()); break;
	case 7: return QVariant::fromValue<bool>(((QCheckBox *)w)->isChecked()); break;
	case 8: return QVariant::fromValue<QColor>(((ColorButton *)w)->color()); break;
	case 9: return QVariant::fromValue<QPoint>(((QPointEdit *)w)->value().toPoint()); break;
	case 10: return QVariant::fromValue<QPointF>(((QPointEdit *)w)->value()); break;
	case 11: return QVariant::fromValue<QRect>(((QRectEdit *)w)->value().toRect()); break;
	case 12: return QVariant::fromValue<QRectF>(((QRectEdit *)w)->value()); break;
	case 13:
		return QVariant::fromValue<PropertyValuePair>(
			PropertyValuePair(w->property("__prop").value<QMetaProperty>(), ((QComboBox *)w)->itemData(((QComboBox *)w)->currentIndex())));
		break;
	default: return QVariant(); break;
	}
	return QVariant();
}


void Delegate::setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const {
	if (index.data(Qt::UserRole + 1).toString() != "__flag") model->setData(index, widgetProperty(editor), Qt::UserRole);
}


void Delegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const {
	QStyledItemDelegate::paint(painter, option, index);
	QVariant value            = index.data(Qt::UserRole);
	QStyle * style            = QApplication::style();
	QStyleOption * so         = 0;
	QStyleOptionComplex * soc = 0;
	QString text;
	QRect rect;
	QPalette::ColorRole role =
		(option.state.testFlag(QStyle::State_Selected) && option.state.testFlag(QStyle::State_Active) ? QPalette::HighlightedText
	                                                                                                  : QPalette::WindowText);
	if (index.data(Qt::UserRole + 2).toString() == "__flags") {
		text = "0x" + QString::number(value.toInt(), 16).toUpper();
		style->drawItemText(painter,
		                    style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text),
		                    Qt::AlignLeft | Qt::AlignVCenter,
		                    option.palette,
		                    true,
		                    text,
		                    role);
		return;
	}
	if (index.data(Qt::UserRole + 1) == "__flag") {
		qulonglong key  = index.data(Qt::UserRole).toULongLong();
		value           = index.parent().data(Qt::UserRole);
		so              = new QStyleOptionButton();
		so->rect        = option.rect;
		so->palette     = option.palette;
		so->fontMetrics = option.fontMetrics;
		((QStyleOptionButton *)so)->state =
			(((value.toULongLong() & key) == key && key != 0) || (value.toULongLong() == 0 && key == 0) ? QStyle::State_On
		                                                                                                : QStyle::State_Off) |
			option.state;
		((QStyleOptionButton *)so)->text = "0x" + QString::number(key, 16).toUpper();
		if (option.state.testFlag(QStyle::State_Selected))
			so->palette.setColor(QPalette::WindowText, so->palette.color(QPalette::HighlightedText));
		style->drawControl(QStyle::CE_CheckBox, so, painter);
	} else {
		if (value.canConvert<PropertyValuePair>()) {
			PropertyValuePair prop = value.value<PropertyValuePair>();
			if (prop.first.isEnumType()) {
				QMetaEnum menum = prop.first.enumerator();
				for (int i = 0; i < menum.keyCount(); ++i) {
					if (menum.value(i) == prop.second.toInt()) {
						text = QString(menum.key(i)) + " (0x" + QString::number(menum.value(i), 16).toUpper() + ")";
						break;
					}
				}
				style->drawItemText(painter,
				                    style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text),
				                    Qt::AlignLeft | Qt::AlignVCenter,
				                    option.palette,
				                    true,
				                    text,
				                    role);
			}
		} else {
#if QT_VERSION_MAJOR <= 5
			switch (value.type()) {
#else
			switch (value.metaType().id()) {
#endif
#if QT_VERSION_MAJOR <= 5
			case QVariant::Int:
#else
			case QMetaType::Int:
#endif
				text.setNum(value.toInt());
				style->drawItemText(painter,
				                    style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text),
				                    Qt::AlignLeft | Qt::AlignVCenter,
				                    option.palette,
				                    true,
				                    text,
				                    role);
				break;
#if QT_VERSION_MAJOR <= 5
			case QVariant::UInt:
#else
			case QMetaType::UInt:
#endif
				text.setNum(value.toUInt());
				style->drawItemText(painter,
				                    style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text),
				                    Qt::AlignLeft | Qt::AlignVCenter,
				                    option.palette,
				                    true,
				                    text,
				                    role);
				break;
#if QT_VERSION_MAJOR <= 5
			case QVariant::LongLong:
#else
			case QMetaType::LongLong:
#endif
				text.setNum(value.toLongLong());
				style->drawItemText(painter,
				                    style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text),
				                    Qt::AlignLeft | Qt::AlignVCenter,
				                    option.palette,
				                    true,
				                    text,
				                    role);
				break;
#if QT_VERSION_MAJOR <= 5
			case QVariant::ULongLong:
#else
			case QMetaType::ULongLong:
#endif
				text.setNum(value.toULongLong());
				style->drawItemText(painter,
				                    style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text),
				                    Qt::AlignLeft | Qt::AlignVCenter,
				                    option.palette,
				                    true,
				                    text,
				                    role);
				break;
#if QT_VERSION_MAJOR <= 5
			case QVariant::Double:
#else
			case QMetaType::Double:
#endif
				text.setNum(value.toDouble(), 'f', 3);
				style->drawItemText(painter,
				                    style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text),
				                    Qt::AlignLeft | Qt::AlignVCenter,
				                    option.palette,
				                    true,
				                    text,
				                    role);
				break;
#if QT_VERSION_MAJOR <= 5
			case QVariant::Bool:
#else
			case QMetaType::Bool:
#endif
				so                                = new QStyleOptionButton();
				so->rect                          = option.rect;
				so->state                         = option.state;
				so->palette                       = option.palette;
				so->fontMetrics                   = option.fontMetrics;
				((QStyleOptionButton *)so)->state = (value.toBool() ? QStyle::State_On : QStyle::State_Off) | option.state;
				style->drawControl(QStyle::CE_CheckBox, so, painter);
				break;
#if QT_VERSION_MAJOR <= 5
			case QVariant::Color:
#else
			case QMetaType::QColor:
#endif
				rect = option.rect; // style->subElementRect(QStyle::QStyle::SE_FrameContents, so);
				rect.setRect(rect.x() + 3, rect.y() + 3, rect.width() - 6, rect.height() - 6);
				painter->fillRect(rect, ab);
				painter->fillRect(rect, value.value<QColor>());
				break;
#if QT_VERSION_MAJOR <= 5
			case QVariant::Point:
#else
			case QMetaType::QPoint:
#endif
				text = pointString(value.toPoint());
				style->drawItemText(painter,
				                    style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text),
				                    Qt::AlignLeft | Qt::AlignVCenter,
				                    option.palette,
				                    true,
				                    text,
				                    role);
				break;
#if QT_VERSION_MAJOR <= 5
			case QVariant::PointF:
#else
			case QMetaType::QPointF:
#endif
				text = pointString(value.toPointF());
				style->drawItemText(painter,
				                    style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text),
				                    Qt::AlignLeft | Qt::AlignVCenter,
				                    option.palette,
				                    true,
				                    text,
				                    role);
				break;
#if QT_VERSION_MAJOR <= 5
			case QVariant::Rect:
#else
			case QMetaType::QRect:
#endif
				text = rectString(value.toRect());
				style->drawItemText(painter,
				                    style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text),
				                    Qt::AlignLeft | Qt::AlignVCenter,
				                    option.palette,
				                    true,
				                    text,
				                    role);
				break;
#if QT_VERSION_MAJOR <= 5
			case QVariant::RectF:
#else
			case QMetaType::QRectF:
#endif
				text = rectString(value.toRectF());
				style->drawItemText(painter,
				                    style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text),
				                    Qt::AlignLeft | Qt::AlignVCenter,
				                    option.palette,
				                    true,
				                    text,
				                    role);
				break;
#if QT_VERSION_MAJOR <= 5
			case QVariant::String:
			default:
#else
			case QMetaType::QString:
			default:
#endif
				style->drawItemText(
					painter,
					style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, value.toString()),
					Qt::AlignLeft | Qt::AlignVCenter,
					option.palette,
					true,
					value.toString(),
					role);
				break;
			}
		}
	}
	/*so = new QStyleOptionFrame();
	so->rect = option.rect;
	so->state = option.state;
	so->palette = option.palette;
	so->fontMetrics = option.fontMetrics;
	((QStyleOptionFrame*)so)->state = (value.toBool() ? QStyle::State_On : QStyle::State_Off);
	style->drawPrimitive(QStyle::PE_PanelLineEdit, so, painter);
	style->drawPrimitive(QStyle::PE_FrameLineEdit, so, painter);
	break;*/
	if (so != 0) delete so;
	if (soc != 0) delete soc;
}


void Delegate::changedFlag() {
	QAbstractItemModel * model = const_cast<QAbstractItemModel *>(cmi.model());
	model->setData(cmi, qobject_cast<QCheckBox *>(sender())->isChecked(), Qt::UserRole + 3);
	QModelIndex p  = cmi.parent(), mi;
	int row        = 0;
	qulonglong val = 0;
	QList<QModelIndex> chldr;
	mi = model->index(row, 1, p);
	while (mi.isValid()) {
		chldr << mi;
		model->setData(mi, !mi.data(Qt::UserRole + 4).toBool(), Qt::UserRole + 4);
		mi = model->index(++row, 1, p);
	}
	bool cc       = cmi.data(Qt::UserRole + 3).toBool();
	qulonglong cv = cmi.data(Qt::UserRole).toULongLong();
	// qDebug() << "*****";
	if (cc && cv == 0) {
		val = 0;
		// qDebug() << "null" << cv;
	} else {
		if (!cc && cv != 0) {
			// qDebug() << "uncheck" << cv;
			for (int i = 0; i < chldr.size(); ++i) {
				if (chldr[i] == cmi) continue;
				// qDebug() << (chldr[i].data(Qt::UserRole).toULongLong() & cv);
				if (chldr[i].data(Qt::UserRole).toULongLong() & cv) model->setData(chldr[i], false, Qt::UserRole + 3);
			}
		}
		for (int i = 0; i < chldr.size(); ++i) {
			// qDebug() << chldr[i].data(Qt::UserRole + 3).toBool();
			if (chldr[i].data(Qt::UserRole + 3).toBool()) val |= chldr[i].data(Qt::UserRole).toULongLong();
		}
	}
	for (int i = 0; i < chldr.size(); ++i) {
		if (chldr[i] == cmi) continue;
		cv = chldr[i].data(Qt::UserRole).toULongLong();
		model->setData(chldr[i], ((val & cv) == cv && cv != 0) || (val == 0 && cv == 0), Qt::UserRole + 3);
	}
	// qDebug() << val;
	model->setData(p, val, Qt::UserRole);
	model->setData(p.sibling(p.row(), 1), val, Qt::UserRole);
}


PropertyEditor::PropertyEditor(QWidget * parent): QTreeWidget(parent) {
	object  = 0;
	active_ = false;
	configTree();
	connect(this, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(itemClicked(QTreeWidgetItem *, int)));
	connect(this, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(itemChanged(QTreeWidgetItem *, int)));
}


PropertyEditor::~PropertyEditor() {}


void PropertyEditor::changeEvent(QEvent * e) {
	QTreeWidget::changeEvent(e);
	if (e->type() == QEvent::LanguageChange) {
		configTree();
		return;
	}
}


void PropertyEditor::configTree() {
	setColumnCount(2);
	setRootIsDecorated(false);
	setColumnWidth(0, 170);
	setColumnWidth(1, 10);
	header()->setStretchLastSection(true);
	QStringList lbls;
	lbls << tr("Property") << tr("Value");
	setHeaderLabels(lbls);
	setAlternatingRowColors(true);
	setItemDelegateForColumn(1, new Delegate());
}


void PropertyEditor::itemClicked(QTreeWidgetItem * item, int column) {
	if (column == 0)
		item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
	else {
		item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable);
		editItem(item, 1);
	}
}


void PropertyEditor::itemChanged(QTreeWidgetItem * item, int column) {
	if (!active_) return;
	if (column != 1) return;
	QVariant value = item->data(1, Qt::UserRole);
	if (value.canConvert<PropertyValuePair>()) {
		value = value.value<PropertyValuePair>().second;
	}
	object->setProperty(item->text(0).toLatin1(), value);
}


void PropertyEditor::rebuild() {
	clear();
	configTree();
	if (object == 0) return;
	active_                = false;
	const QMetaObject * mo = object->metaObject();
	QList<const QMetaObject *> mol;
	while (mo != 0) {
		mol.push_front(mo);
		mo = mo->superClass();
	}
	int ps, pe;
	QTreeWidgetItem *ti, *tli, *tfi;
	QVariant value;
	//	QWidget * pw = 0;
	int chue = 0;
	QColor bc;
	font_b = font();
	font_b.setBold(true);
	foreach(const QMetaObject * o, mol) {
		ps  = o->propertyOffset();
		pe  = o->propertyCount(); // - ps;
		// qDebug() << i->className() << ps << pe;
		tli = new QTreeWidgetItem();
		tli->setText(0, o->className());
		tli->setFont(0, font_b);
		setItemBackColor(tli, Qt::darkGray);
		setItemForeColor(tli, Qt::white);
		addTopLevelItem(tli);
		tli->setFirstColumnSpanned(true);
		tli->setExpanded(true);
		for (int i = ps; i < pe; ++i) {
			props << o->property(i);
			value = o->property(i).read(object);
			ti    = new QTreeWidgetItem();
			ti->setSizeHint(1, QSize(20, 20));
			bc.setHsv(chue, 60, 245 + (i % 2) * 20 - 10);
			setItemBackColor(ti, bc);
			ti->setText(0, o->property(i).name());
			if (props.back().isFlagType()) {
				QMetaEnum menum = props.back().enumerator();
				for (int j = 0; j < menum.keyCount(); ++j) {
					tfi = new QTreeWidgetItem();
					tfi->setText(0, menum.key(j));
					tfi->setData(1, Qt::UserRole, menum.value(j));
					tfi->setData(1, Qt::UserRole + 1, "__flag");
					tfi->setData(1, Qt::UserRole + 2, value.toULongLong());
					tfi->setData(1, Qt::UserRole + 3, (value.toULongLong() & menum.value(j)) > 0);
					tfi->setSizeHint(1, QSize(20, 20));
					bc.setHsv(chue, 60, 245 + ((i + j + 1) % 2) * 20 - 10);
					setItemBackColor(tfi, bc);
					ti->addChild(tfi);
				}
				ti->setData(0, Qt::UserRole, value);
				ti->setData(1, Qt::UserRole, value);
				ti->setData(1, Qt::UserRole + 2, "__flags");
				ti->setData(0, Qt::UserRole + 1, QVariant::fromValue<QMetaProperty>(props.back()));
			} else if (props.back().isEnumType())
				value.setValue<PropertyValuePair>(PropertyValuePair(props.back(), value));
			// ti->setText(1, value.toString());
			ti->setData(1, Qt::UserRole, value);
			tli->addChild(ti);
			// const_cast<QModelIndex & >(indexFromItem(ti, 1)).;
			// if (pw != 0) setItemWidget(ti, 1, pw);
		}
		chue += 60;
		chue %= 360;
	}
	active_ = true;
}


void PropertyEditor::refresh() {}
