QQuickItem * DataSetView::createRowNumber(int row)
{
	//std::cout << "createRowNumber("<<row<<") called!\n" << std::flush;


	if(_rowNumberDelegate == NULL)
	{
		_rowNumberDelegate = new QQmlComponent(qmlEngine(this));
		_rowNumberDelegate->setData("import QtQuick 2.10\nItem {\n"
			"property alias text: tekst.text\n"
			"Rectangle	{ color: \"lightGrey\";	anchors.fill: parent }\n"
			"Text		{ id: tekst; anchors.centerIn: parent }\n"
		"}", QUrl());
	}

	QQuickItem * rowNumber = NULL;

	if(_rowNumberItems.count(row) == 0  || _rowNumberItems[row] == NULL)
	{

		if(_rowNumberStorage.size() > 0)
		{
#ifdef DEBUG_VIEWPORT
			std::cout << "createRowNumber("<<row<<") from storage!\n" << std::flush;
#endif
			rowNumber = _rowNumberStorage.top();
			_rowNumberStorage.pop();
		}
		else
		{
#ifdef DEBUG_VIEWPORT
			std::cout << "createRowNumber("<<row<<") ex nihilo!\n" << std::flush;
#endif
			rowNumber = qobject_cast<QQuickItem*>(_rowNumberDelegate->create());
			rowNumber->setParent(this);
			rowNumber->setParentItem(this);
		}

		rowNumber->setProperty("z", 10);
		rowNumber->setProperty("text", QString::fromStdString(std::to_string(row + 1))); //Nobody wants zero-based rows...

		rowNumber->setY(_dataRowsMaxHeight * (1 + row));
		rowNumber->setZ(-3);
		rowNumber->setHeight(_dataRowsMaxHeight);
		rowNumber->setWidth(_rowNumberMaxWidth);

		rowNumber->setVisible(true);

		_rowNumberItems[row] = rowNumber;
	}
	else
		rowNumber = _rowNumberItems[row];

	rowNumber->setX(_viewportX);

	return _rowNumberItems[row];
}
QQuickItem * DataSetView::createColumnHeader(int col)
{
	//std::cout << "createColumnHeader("<<col<<") called!\n" << std::flush;


	if(_columnHeaderDelegate == NULL)
	{
		_columnHeaderDelegate = new QQmlComponent(qmlEngine(this));
		_columnHeaderDelegate->setData("import QtQuick 2.10\nItem {\n"
			"property alias text: tekst.text\n"
		   "Rectangle	{ color: \"lightGrey\";	anchors.fill: parent }\n"
		   "Text		{ id: tekst; anchors.centerIn: parent }\n"
		"}", QUrl());
	}

	QQuickItem * columnHeader = NULL;

	if(_columnHeaderItems.count(col) == 0  || _columnHeaderItems[col] == NULL)
	{

		if(_columnHeaderStorage.size() > 0)
		{
#ifdef DEBUG_VIEWPORT
			std::cout << "createColumnHeader("<<col<<") from storage!\n" << std::flush;
#endif
			columnHeader = _columnHeaderStorage.top();
			_columnHeaderStorage.pop();
		}
		else
		{
#ifdef DEBUG_VIEWPORT
			std::cout << "createColumnHeader("<<col<<") ex nihilo!\n" << std::flush;
#endif
			columnHeader = qobject_cast<QQuickItem*>(_columnHeaderDelegate->create());
			columnHeader->setParent(this);
			columnHeader->setParentItem(this);
		}

		columnHeader->setProperty("z", 10);
		columnHeader->setProperty("text", _model->headerData(col, Qt::Orientation::Horizontal).toString());

		columnHeader->setZ(-3);
		columnHeader->setHeight(_dataRowsMaxHeight);
		columnHeader->setWidth(_dataColsMaxWidth[col]);

		columnHeader->setVisible(true);

		_columnHeaderItems[col] = columnHeader;
	}
	else
		columnHeader = _columnHeaderItems[col];

	columnHeader->setX(_colXPositions[col]);
	columnHeader->setY(_viewportY);

	return columnHeader;
}
QQuickItem * DataSetView::createTextItem(int row, int col)
{
	//std::cout << "createTextItem("<<row<<", "<<col<<") called!\n" << std::flush;

	if((_cellTextItems.count(col) == 0 && _cellTextItems[col].count(row) == 0) || _cellTextItems[col][row] == NULL)
	{

		if(_itemDelegate == NULL)
		{
			_itemDelegate = new QQmlComponent(qmlEngine(this));
			_itemDelegate->setData("import QtQuick 2.10\nText { property bool active: true; text: \"???\"; color: active ? 'black' : 'grey' }", QUrl());
		}

		QQuickItem * textItem = NULL;

		if(_textItemStorage.size() > 0)
		{
#ifdef DEBUG_VIEWPORT
			std::cout << "createTextItem("<<row<<", "<<col<<") from storage!\n" << std::flush;
#endif
			textItem = _textItemStorage.top();
			_textItemStorage.pop();
		}
		else
		{
#ifdef DEBUG_VIEWPORT
			std::cout << "createTextItem("<<row<<", "<<col<<") ex nihilo!\n" << std::flush;
#endif
			textItem = qobject_cast<QQuickItem*>(_itemDelegate->create());
			textItem->setParent(this);
			textItem->setParentItem(this);
		}

		QModelIndex ind(_model->index(row, col));
		bool active = _model->data(ind, _roleNameToRole["active"]).toBool();
		textItem->setProperty("color", active ? "black" : "grey");
		textItem->setProperty("text", _model->data(ind));
		textItem->setX(_colXPositions[col] + _itemHorizontalPadding);
		textItem->setY(-2 + _dataRowsMaxHeight + _itemVerticalPadding + row * _dataRowsMaxHeight);
		textItem->setZ(-4);
		textItem->setVisible(true);

		_cellTextItems[col][row] = textItem;
	}

	return _cellTextItems[col][row];
}
void TelegramImageElement::initImage()
{
    if(p->image)
        return;

    QQmlEngine *engine = qmlEngine(this);
    QQmlContext *context = qmlContext(this);
    if(!engine || !context)
        return;

    QQmlComponent component(engine);

    QString qmlImageCreationCode = p->qmlImageCreationCode;
    if(qmlImageCreationCode.isEmpty())
        qmlImageCreationCode = QString("import QtQuick %1\n"
                                       "Image { anchors.fill: parent; }").arg(p->qtQuickVersion);

    component.setData(qmlImageCreationCode.toUtf8(), QUrl());
    QQuickItem *item = qobject_cast<QQuickItem *>(component.create(context));
    if(!item)
        return;

    item->setParent(this);
    item->setParentItem(this);

    QHashIterator<QString, QVariant> i(p->properties);
    while(i.hasNext())
    {
        i.next();
        item->setProperty(i.key().toUtf8(), i.value());
    }

    connect(item, SIGNAL(asynchronousChanged()), this, SIGNAL(asynchronousChanged()));

    #if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
        connect(item, SIGNAL(autoTransformChanged()), this, SIGNAL(autoTransformChanged()));
    #endif

    connect(item, SIGNAL(cacheChanged()), this, SIGNAL(cacheChanged()));
    connect(item, SIGNAL(fillModeChanged()), this, SIGNAL(fillModeChanged()));
    connect(item, SIGNAL(mirrorChanged()), this, SIGNAL(mirrorChanged()));
    connect(item, SIGNAL(sourceSizeChanged()), this, SIGNAL(sourceSizeChanged()));

    p->image = item;
}