<commit_before>#include "cfilelistview.h"
#include "../columns.h"
#include "model/cfilelistsortfilterproxymodel.h"
#include "delegate/cfilelistitemdelegate.h"

#include <assert.h>
#include <time.h>
#include <set>

#if defined __linux__ || defined __APPLE__
#include "cfocusframestyle.h"
#endif

CFileListView::CFileListView(QWidget *parent) :
	QTreeView(parent),
	_controller(CController::get()),
	_panelPosition(UnknownPanel),
	_bHeaderAdjustmentRequired(true),
	_singleMouseClickValid(false),
	_shiftPressedItemSelected(false)
{
	setMouseTracking(true);
	setItemDelegate(new CFileListItemDelegate);
	connect(this, &QTreeView::doubleClicked, [this](const QModelIndex &idx) {

		_itemUnderCursorBeforeMouseClick = QModelIndex();
		_singleMouseClickValid = false;

		for(FileListViewEventObserver* observer: _eventObservers)
		{
			if (observer->fileListReturnPressOrDoubleClickPerformed(idx))
				break;
		}
	});

#if defined __linux__ || defined __APPLE__
	setStyle(new CFocusFrameStyle);
#endif
}

void CFileListView::addEventObserver(FileListViewEventObserver* observer)
{
	_eventObservers.push_back(observer);
}

// Sets the position (left or right) of a panel that this model represents
void CFileListView::setPanelPosition(enum Panel p)
{
	assert(_panelPosition == UnknownPanel); // Doesn't make sense to call this method more than once
	_panelPosition = p;
}

// Preserves item's selection state
void CFileListView::moveCursorToItem(const QModelIndex& index, bool invertSelection)
{
	if (index.isValid() && selectionModel()->model()->hasIndex(index.row(), index.column()))
	{
		const QModelIndex fixedIndex = model()->index(index.row(), index.column());
		const QModelIndex currentIdx = currentIndex();
		if (invertSelection && currentIdx.isValid())
		{
			for (int row = currentIdx.row(); row < fixedIndex.row(); ++row)
				selectionModel()->setCurrentIndex(fixedIndex, (!_shiftPressedItemSelected ? QItemSelectionModel::Select : QItemSelectionModel::Deselect) | QItemSelectionModel::Rows);
		}
		selectionModel()->setCurrentIndex(fixedIndex, QItemSelectionModel::Current | QItemSelectionModel::Rows);
		scrollTo(fixedIndex);
	}
}

// Header management
void CFileListView::saveHeaderState()
{
	if (header())
	{
		_headerGeometry = header()->saveGeometry();
		_headerState    = header()->saveState();
	}
}

void CFileListView::restoreHeaderState()
{
	if (header())
	{
		if (!_headerGeometry.isEmpty())
			header()->restoreGeometry(_headerGeometry);
		if (!_headerState.isEmpty())
			header()->restoreState(_headerState);
	}
}

void CFileListView::invertSelection()
{
	for (int i = 0; i < model()->rowCount(); ++i)
		selectionModel()->select(model()->index(i, 0), QItemSelectionModel::Toggle | QItemSelectionModel::Rows);
}

// For managing selection and cursor
void CFileListView::mousePressEvent(QMouseEvent *e)
{
	_singleMouseClickValid = !_singleMouseClickValid;

	_itemUnderCursorBeforeMouseClick = currentIndex();
	const QModelIndex itemClicked = indexAt(e->pos());

	// Always let Qt process this event
	QTreeView::mousePressEvent(e);

	// TODO: sometimes a double-clicked item remains selected. Find out why it happens.
	if (e->button() == Qt::LeftButton && itemClicked.isValid())
	{
		if (e->modifiers() == Qt::NoModifier)
		{
			selectionModel()->clearSelection();
		}
		else if (e->modifiers() == Qt::ControlModifier)
		{
			if (_itemUnderCursorBeforeMouseClick.isValid() && _itemUnderCursorBeforeMouseClick != itemClicked)
				selectionModel()->select(_itemUnderCursorBeforeMouseClick, QItemSelectionModel::Select | QItemSelectionModel::Rows);
		}
	}<commit_msg>CFileListView::invertSelection: drastic performance increase for large number of items<commit_after>#include "cfilelistview.h"
#include "../columns.h"
#include "model/cfilelistsortfilterproxymodel.h"
#include "delegate/cfilelistitemdelegate.h"

#include <assert.h>
#include <time.h>
#include <set>

#if defined __linux__ || defined __APPLE__
#include "cfocusframestyle.h"
#endif

CFileListView::CFileListView(QWidget *parent) :
	QTreeView(parent),
	_controller(CController::get()),
	_panelPosition(UnknownPanel),
	_bHeaderAdjustmentRequired(true),
	_singleMouseClickValid(false),
	_shiftPressedItemSelected(false)
{
	setMouseTracking(true);
	setItemDelegate(new CFileListItemDelegate);
	connect(this, &QTreeView::doubleClicked, [this](const QModelIndex &idx) {

		_itemUnderCursorBeforeMouseClick = QModelIndex();
		_singleMouseClickValid = false;

		for(FileListViewEventObserver* observer: _eventObservers)
		{
			if (observer->fileListReturnPressOrDoubleClickPerformed(idx))
				break;
		}
	});

#if defined __linux__ || defined __APPLE__
	setStyle(new CFocusFrameStyle);
#endif
}

void CFileListView::addEventObserver(FileListViewEventObserver* observer)
{
	_eventObservers.push_back(observer);
}

// Sets the position (left or right) of a panel that this model represents
void CFileListView::setPanelPosition(enum Panel p)
{
	assert(_panelPosition == UnknownPanel); // Doesn't make sense to call this method more than once
	_panelPosition = p;
}

// Preserves item's selection state
void CFileListView::moveCursorToItem(const QModelIndex& index, bool invertSelection)
{
	if (index.isValid() && selectionModel()->model()->hasIndex(index.row(), index.column()))
	{
		const QModelIndex fixedIndex = model()->index(index.row(), index.column());
		const QModelIndex currentIdx = currentIndex();
		if (invertSelection && currentIdx.isValid())
		{
			for (int row = currentIdx.row(); row < fixedIndex.row(); ++row)
				selectionModel()->setCurrentIndex(fixedIndex, (!_shiftPressedItemSelected ? QItemSelectionModel::Select : QItemSelectionModel::Deselect) | QItemSelectionModel::Rows);
		}
		selectionModel()->setCurrentIndex(fixedIndex, QItemSelectionModel::Current | QItemSelectionModel::Rows);
		scrollTo(fixedIndex);
	}
}

// Header management
void CFileListView::saveHeaderState()
{
	if (header())
	{
		_headerGeometry = header()->saveGeometry();
		_headerState    = header()->saveState();
	}
}

void CFileListView::restoreHeaderState()
{
	if (header())
	{
		if (!_headerGeometry.isEmpty())
			header()->restoreGeometry(_headerGeometry);
		if (!_headerState.isEmpty())
			header()->restoreState(_headerState);
	}
}

void CFileListView::invertSelection()
{
	QItemSelection allItems(model()->index(0, 0), model()->index(model()->rowCount() - 1, 0));
	selectionModel()->select(allItems, QItemSelectionModel::Toggle | QItemSelectionModel::Rows);
}

// For managing selection and cursor
void CFileListView::mousePressEvent(QMouseEvent *e)
{
	_singleMouseClickValid = !_singleMouseClickValid;

	_itemUnderCursorBeforeMouseClick = currentIndex();
	const QModelIndex itemClicked = indexAt(e->pos());

	// Always let Qt process this event
	QTreeView::mousePressEvent(e);

	// TODO: sometimes a double-clicked item remains selected. Find out why it happens.
	if (e->button() == Qt::LeftButton && itemClicked.isValid())
	{
		if (e->modifiers() == Qt::NoModifier)
		{
			selectionModel()->clearSelection();
		}
		else if (e->modifiers() == Qt::ControlModifier)
		{
			if (_itemUnderCursorBeforeMouseClick.isValid() && _itemUnderCursorBeforeMouseClick != itemClicked)
				selectionModel()->select(_itemUnderCursorBeforeMouseClick, QItemSelectionModel::Select | QItemSelectionModel::Rows);
		}
	}
{'fraction_non_alphanumeric': 0.13282863041982107, 'fraction_numerical': 0.0008258774948382657, 'mean_word_length': 6.513960703205791, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 48, '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': '4817025', 'n_tokens_mistral': 2328, 'n_tokens_neox': 2202, 'n_words': 446}