<commit_before>// HistoryModel.cpp

// Implements the HistoryModel class representing a Qt model for displaying the project history in a view / graph





#include "Globals.h"
#include "HistoryModel.h"
#include <assert.h>
#include <QSize>
#include "CodeLocation.h"
#include "CodeLocationStats.h"
#include "FormatNumber.h"
#include "Project.h"





static QColor getNextColor()
{
	static size_t idx = 0;
	static QColor colors[] =
	{
		// Regular colors:
		QColor(0xff, 0x00, 0x00),
		QColor(0x00, 0xff, 0x00),
		QColor(0x00, 0x00, 0xff),
		QColor(0xff, 0xff, 0x00),
		QColor(0x00, 0xff, 0xff),
		QColor(0xff, 0x00, 0xff),

		// Dark colors:
		QColor(0x7f, 0x00, 0x00),
		QColor(0x00, 0x7f, 0x00),
		QColor(0x7f, 0x7f, 0x00),
		QColor(0x00, 0x7f, 0x7f),
		QColor(0x7f, 0x00, 0x7f),

		// Light colors:
		QColor(0xff, 0x7f, 0x7f),
		QColor(0x7f, 0xff, 0x7f),
		QColor(0x7f, 0x7f, 0xff),
		QColor(0xff, 0xff, 0x7f),
		QColor(0x7f, 0xff, 0xff),
		QColor(0xff, 0x7f, 0xff),
	};
	return colors[(idx++) % ARRAYCOUNT(colors)];
}





////////////////////////////////////////////////////////////////////////////////
// HistoryModel::GraphedAllocationPath:

HistoryModel::GraphedAllocationPath::GraphedAllocationPath(
	const AllocationPath & a_AllocationPath,
	const AllocationStats & a_Stats
):
	m_AllocationPath(a_AllocationPath),
	m_Stats(a_Stats),
	m_Color(getNextColor())
{
}





////////////////////////////////////////////////////////////////////////////////
// HistoryModel:

HistoryModel::HistoryModel(ProjectPtr a_Project):
	m_Project(a_Project)
{
	connect(m_Project.get(), SIGNAL(addedSnapshot(SnapshotPtr)), this, SLOT(resetModel()));
	resetModel();
}





bool HistoryModel::canItemExpand(const QModelIndex & a_Index) const
{
	if (!isValidIndex(a_Index))
	{
		return false;
	}
	auto gap = m_GraphedAllocationPaths[a_Index.row()];
	if (gap == nullptr)
	{
		return false;
	}
	auto path = gap->m_AllocationPath;
	for(;;)
	{
		const auto & children = m_Project->getAllAllocationPathsImmediateChildren(path);
		if (children.empty())
		{
			return false;
		}
		if (children.size() > 1)
		{
			return true;
		}
		path = children[0];
	}
}





bool HistoryModel::canItemCollapse(const QModelIndex & a_Index) const
{
	if (!isValidIndex(a_Index))
	{
		return false;
	}
	auto gap = m_GraphedAllocationPaths[a_Index.row()];
	if (gap == nullptr)
	{
		return false;
	}
	const auto & path = gap->m_AllocationPath;
	return (path.getSegments().size() > 1);  // At least two segments
}





bool HistoryModel::isValidIndex(const QModelIndex & a_Index) const
{
	if ((a_Index.row() < 0) || (a_Index.row() >= static_cast<int>(m_GraphedAllocationPaths.size())))
	{
		return false;
	}
	if ((a_Index.column() < 0) || (a_Index.column() > colMax))
	{
		return false;
	}

	return true;
}





void HistoryModel::resetModel()
{
	beginResetModel();

	// Insert all top-level paths:
	m_GraphedAllocationPaths.clear();
	m_GraphedAllocationPaths.push_back(std::make_shared<GraphedAllocationPath>(AllocationPath(), AllocationStats()));

	endResetModel();

	expandItem(0);
}





void HistoryModel::expandItem(const QModelIndex & a_Item)<commit_msg>Fixed HistoryModel for empty projects.<commit_after>// HistoryModel.cpp

// Implements the HistoryModel class representing a Qt model for displaying the project history in a view / graph





#include "Globals.h"
#include "HistoryModel.h"
#include <assert.h>
#include <QSize>
#include "CodeLocation.h"
#include "CodeLocationStats.h"
#include "FormatNumber.h"
#include "Project.h"





static QColor getNextColor()
{
	static size_t idx = 0;
	static QColor colors[] =
	{
		// Regular colors:
		QColor(0xff, 0x00, 0x00),
		QColor(0x00, 0xff, 0x00),
		QColor(0x00, 0x00, 0xff),
		QColor(0xff, 0xff, 0x00),
		QColor(0x00, 0xff, 0xff),
		QColor(0xff, 0x00, 0xff),

		// Dark colors:
		QColor(0x7f, 0x00, 0x00),
		QColor(0x00, 0x7f, 0x00),
		QColor(0x7f, 0x7f, 0x00),
		QColor(0x00, 0x7f, 0x7f),
		QColor(0x7f, 0x00, 0x7f),

		// Light colors:
		QColor(0xff, 0x7f, 0x7f),
		QColor(0x7f, 0xff, 0x7f),
		QColor(0x7f, 0x7f, 0xff),
		QColor(0xff, 0xff, 0x7f),
		QColor(0x7f, 0xff, 0xff),
		QColor(0xff, 0x7f, 0xff),
	};
	return colors[(idx++) % ARRAYCOUNT(colors)];
}





////////////////////////////////////////////////////////////////////////////////
// HistoryModel::GraphedAllocationPath:

HistoryModel::GraphedAllocationPath::GraphedAllocationPath(
	const AllocationPath & a_AllocationPath,
	const AllocationStats & a_Stats
):
	m_AllocationPath(a_AllocationPath),
	m_Stats(a_Stats),
	m_Color(getNextColor())
{
}





////////////////////////////////////////////////////////////////////////////////
// HistoryModel:

HistoryModel::HistoryModel(ProjectPtr a_Project):
	m_Project(a_Project)
{
	connect(m_Project.get(), SIGNAL(addedSnapshot(SnapshotPtr)), this, SLOT(resetModel()));
	resetModel();
}





bool HistoryModel::canItemExpand(const QModelIndex & a_Index) const
{
	if (!isValidIndex(a_Index))
	{
		return false;
	}
	auto gap = m_GraphedAllocationPaths[a_Index.row()];
	if (gap == nullptr)
	{
		return false;
	}
	auto path = gap->m_AllocationPath;
	for(;;)
	{
		const auto & children = m_Project->getAllAllocationPathsImmediateChildren(path);
		if (children.empty())
		{
			return false;
		}
		if (children.size() > 1)
		{
			return true;
		}
		path = children[0];
	}
}





bool HistoryModel::canItemCollapse(const QModelIndex & a_Index) const
{
	if (!isValidIndex(a_Index))
	{
		return false;
	}
	auto gap = m_GraphedAllocationPaths[a_Index.row()];
	if (gap == nullptr)
	{
		return false;
	}
	const auto & path = gap->m_AllocationPath;
	return (path.getSegments().size() > 1);  // At least two segments
}





bool HistoryModel::isValidIndex(const QModelIndex & a_Index) const
{
	if ((a_Index.row() < 0) || (a_Index.row() >= static_cast<int>(m_GraphedAllocationPaths.size())))
	{
		return false;
	}
	if ((a_Index.column() < 0) || (a_Index.column() > colMax))
	{
		return false;
	}

	return true;
}





void HistoryModel::resetModel()
{
	beginResetModel();

	// Insert the root path, to be then expanded:
	m_GraphedAllocationPaths.clear();
	if (m_Project->getNumSnapshots() > 0)
	{
		m_GraphedAllocationPaths.push_back(std::make_shared<GraphedAllocationPath>(AllocationPath(), AllocationStats()));
	}

	endResetModel();

	// Expand the root path:
	if (!m_GraphedAllocationPaths.empty())
	{
		expandItem(0);
	}
}





void HistoryModel::expandItem(const QModelIndex & a_Item)
{'fraction_non_alphanumeric': 0.18623924941360437, 'fraction_numerical': 0.033620015637216574, 'mean_word_length': 3.591529073941134, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 27, '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': '3550045', 'n_tokens_mistral': 2663, 'n_tokens_neox': 2382, 'n_words': 468}