<commit_before>/***********************************************************************************************************************
 * VExtendable.cpp
 *
 *  Created on: Dec 14, 2010
 *      Author: <NAME>
 **********************************************************************************************************************/

#include "items/VExtendable.h"

#include "items/Text.h"

#include <QtCore/QString>
#include <QtCore/QPair>
#include <QtCore/QList>

namespace Visualization {

ITEM_COMMON_DEFINITIONS(VExtendable)

VExtendable::VExtendable(Item* parent, Model::ExtendableNode* node, const VExtendableStyle* style) :
	ModelItem(parent, node, style), header( new SequentialLayout(this, &style->smallHeaderStyle())), layout(NULL), attributes(NULL), expanded_(style->expanded())
{
	header->append(new Text(header, node->typeName()));
	if (!expanded_) removeShape();
}

VExtendable::~VExtendable()
{
	if ( expanded_ )
	{
		SAFE_DELETE_ITEM(layout);

		// These were automatically deleted by layout's destructor
		header = NULL ;
		attributes = NULL;
	}
	else SAFE_DELETE_ITEM(header);
}

void VExtendable::determineChildren()
{
	Model::ExtendableNode* node = static_cast<Model::ExtendableNode*> (getNode());

	// Set the name if any
	if ( node->hasAttribute("name") )
	{
		Model::Node* name = node->get("name");
		if ( header->length() == 1 ) header->prepend(renderer()->render(header, name));
		if ( header->length() == 2 && header->at<ModelItem> (0)->getNode() != name )
		{
			header->remove(0);
			header->prepend(renderer()->render(header, name));
		}
	}
	else
	{
		if ( header->length() > 1 ) header->remove(0);
	}

	// Clean up when switching styles
	if ( expandedSwtiched() )
	{
		if ( expanded_ )
		{
			useShape();
			layout = new PanelBorderLayout(this, &style()->borderStyle());
			attributes = new SequentialLayout(NULL, &style()->attributesStyle());

			layout->setTop(true);
			layout->top()->setMiddle(header);
			layout->setContent(attributes);
		}
		else
		{
			removeShape();
			// This is the header. We do not want this to be removed by layout's destructor
			layout->top()->setMiddle(NULL, false);
			header->setParentItem(this);

			SAFE_DELETE_ITEM(layout);

			attributes = NULL; // This was automatically deleted by layout's destructor
		}
	}

	// TODO: find a better way and place to determine the style of children. Is doing this causing too many updates?
	// TODO: consider the performance of this. Possibly introduce a style updated boolean for all items so that they know
	//			what's the reason they are being updated.
	// The style needs to be updated every time since if our own style changes, so will that of the children.
	if (expanded_)
	{
		header->setStyle(&style()->headerStyle());
		layout->setStyle(&style()->borderStyle());
		attributes->setStyle(&style()->attributesStyle());
	}
	else header->setStyle(&style()->smallHeaderStyle());

	if ( expanded_ )
	{
		// Set the attributes
		// TODO this can be done smarter
		QList<QPair<QString, Model::Node*> > attr = node->getAllAttributes();

		// Remove extra elements
		while (attr.size() < attributes->length()) attributes->remove(attributes->length()-1);

		bool changed = false;
		int nameFound = 0; // This will become 1 if the name attribute was already encountered

		for (int i = 0; i < attr.size(); ++i)
		{
			if ( attr[i].first == "name" )
			{
				nameFound = 1;
				while (attr.size() < attributes->length() + 1) attributes->remove(attributes->length()-1); // TODO is this OK here, it's a mess.
				continue;
			}

			if ( !changed )
			{
				changed = attributes->length() + nameFound <= i;
				if ( !changed ) changed = attributes->at<SequentialLayout> (i - nameFound)->at<ModelItem> (1)->getNode() != attr[i].second;

				if ( changed ) while ( attributes->length() + nameFound > i )
					attributes->remove(attributes->length() - 1);
			}

			if ( changed )
			{
				SequentialLayout* s = new SequentialLayout(attributes);
				s->append(new Text(s, attr[i].first));
				s->append(renderer()->render(s, attr[i].second));
				attributes->append(s);
			}
		}
	}

}

void VExtendable::updateGeometry(int, int)
{
	if ( expanded_ )<commit_msg>Improved the determineChildren procedure of VExtendable.<commit_after>/***********************************************************************************************************************
 * VExtendable.cpp
 *
 *  Created on: Dec 14, 2010
 *      Author: <NAME>
 **********************************************************************************************************************/

#include "items/VExtendable.h"

#include "items/Text.h"

#include <QtCore/QString>
#include <QtCore/QPair>
#include <QtCore/QList>

namespace Visualization {

ITEM_COMMON_DEFINITIONS(VExtendable)

VExtendable::VExtendable(Item* parent, Model::ExtendableNode* node, const VExtendableStyle* style) :
	ModelItem(parent, node, style), header( new SequentialLayout(this, &style->smallHeaderStyle())), layout(NULL), attributes(NULL), expanded_(style->expanded())
{
	header->append(new Text(header, node->typeName()));
	if (!expanded_) removeShape();
}

VExtendable::~VExtendable()
{
	if ( expanded_ )
	{
		SAFE_DELETE_ITEM(layout);

		// These were automatically deleted by layout's destructor
		header = NULL ;
		attributes = NULL;
	}
	else SAFE_DELETE_ITEM(header);
}

void VExtendable::determineChildren()
{
	Model::ExtendableNode* node = static_cast<Model::ExtendableNode*> (getNode());

	// Set the name if any
	if ( node->hasAttribute("name") )
	{
		Model::Node* name = node->get("name");
		if ( header->length() == 1 ) header->prepend(renderer()->render(header, name));
		if ( header->length() == 2 && header->at<ModelItem> (0)->getNode() != name )
		{
			header->remove(0);
			header->prepend(renderer()->render(header, name));
		}
	}
	else
	{
		if ( header->length() > 1 ) header->remove(0);
	}

	// Clean up when switching styles
	if ( expandedSwtiched() )
	{
		if ( expanded_ )
		{
			useShape();
			layout = new PanelBorderLayout(this, &style()->borderStyle());
			attributes = new SequentialLayout(NULL, &style()->attributesStyle());

			layout->setTop(true);
			layout->top()->setMiddle(header);
			layout->setContent(attributes);
		}
		else
		{
			removeShape();
			// This is the header. We do not want this to be removed by layout's destructor
			layout->top()->setMiddle(NULL, false);
			header->setParentItem(this);

			SAFE_DELETE_ITEM(layout);

			attributes = NULL; // This was automatically deleted by layout's destructor
		}
	}

	// TODO: find a better way and place to determine the style of children. Is doing this causing too many updates?
	// TODO: consider the performance of this. Possibly introduce a style updated boolean for all items so that they know
	//			what's the reason they are being updated.
	// The style needs to be updated every time since if our own style changes, so will that of the children.
	if (expanded_)
	{
		header->setStyle(&style()->headerStyle());
		layout->setStyle(&style()->borderStyle());
		attributes->setStyle(&style()->attributesStyle());
	}
	else header->setStyle(&style()->smallHeaderStyle());

	if ( expanded_ )
	{
		// Set the attributes
		// NOTE: This procedure assumes that the order of the named attributes will never change. Attributes might be
		// deleted or added but their ordering should be kept constant.
		// TODO: document this somewhere more visible.
		QList<QPair<QString, Model::Node*> > attr = node->getAllAttributes();

		// Remove elements from attributes which are outdated
		for(int i = attributes->length() - 1; i>=0; --i)
		{
			bool found = false;
			for (int k = 0; k<attr.size(); ++k)
			{
				if (attr[k].second == attributes->at<ModelItem>(i)->getNode())
				{
					found = true;
					break;
				}
			}

			if (!found) attributes->remove(i);
		}

		int attributeIndex = 0;
		for (int i = 0; i < attr.size(); ++i)
		{
			if ( attr[i].first == "name" ) continue;

			if (attributes->length() <= i || attributes->at<ModelItem>(attributeIndex)->getNode() != attr[i].second)
			{
				SequentialLayout* s = new SequentialLayout(attributes);
				s->append(new Text(s, attr[i].first));
				s->append(renderer()->render(s, attr[i].second));
				attributes->insert(s, attributeIndex);
			}

			++attributeIndex;
		}
	}

}

void VExtendable::updateGeometry(int, int)
{
	if ( expanded_ )
{'fraction_non_alphanumeric': 0.20267341040462428, 'fraction_numerical': 0.004576107899807322, 'mean_word_length': 4.27972027972028, 'pattern_counts': {'":': 0, '<': 30, '<?xml version=': 0, '>': 125, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3389472', 'n_tokens_mistral': 2778, 'n_tokens_neox': 2485, 'n_words': 660}