<commit_before>#include "ccontroller.h"
#include "settings/csettings.h"
#include "settings.h"
#include "pluginengine/cpluginengine.h"

#include <stdlib.h>
#include <assert.h>

CController* CController::_instance = nullptr;

CController::CController() : _leftPanel(LeftPanel), _rightPanel(RightPanel), _diskEnumerator(CDiskEnumerator::instance())
{
	assert(_instance == nullptr); // Only makes sense to create one controller
	_instance = this;

	_diskEnumerator.addObserver(this);
	CPluginEngine::get().loadPlugins();

	_leftPanel.addPanelContentsChangedListener(&CPluginEngine::get());
	_rightPanel.addPanelContentsChangedListener(&CPluginEngine::get());
}

CController& CController::get()
{
	assert(_instance);
	return *_instance;
}

void CController::setPanelContentsChangedListener(PanelContentsChangedListener *listener)
{
	_leftPanel.addPanelContentsChangedListener(listener);
	_rightPanel.addPanelContentsChangedListener(listener);
}

void CController::setDisksChangedListener(CController::IDiskListObserver *listener)
{
	assert(std::find(_disksChangedListeners.begin(), _disksChangedListeners.end(), listener) == _disksChangedListeners.end());
	_disksChangedListeners.push_back(listener);
}

// Updates the list of files in the current directory this panel is viewing, and send the new state to UI
void CController::refreshPanelContents (Panel p)
{
	panel(p).refreshFileList();
}

// Creates a new tab for the specified panel, returns tab ID
int CController::tabCreated (Panel /*p*/)
{
	return -1;
}

// Removes a tab for the specified panel and tab ID
void CController::tabRemoved (Panel /*panel*/, int /*tabId*/)
{

}

// Indicates that an item was activated and appropriate action should be taken. Returns error message, if any
FileOperationResultCode CController::itemActivated(qulonglong itemHash, Panel p)
{
	auto& item = panel(p).itemByHash(itemHash);
	if (item.isDir())
	{
		// Attempting to enter this dir
		const FileOperationResultCode result = setPath(p, item.absoluteFilePath());
		return result;
	}
	else if (item.isFile())
	{
		if (item.isExecutable())
			// Attempting to launch this exe from the current directory
			return QProcess::startDetached(toPosixSeparators(item.absoluteFilePath()), QStringList(), toPosixSeparators(item.parentDirPath())) ? rcOk : rcFail;
		else
			// It's probably not a binary file, try opening with openUrl
			return QDesktopServices::openUrl(QUrl::fromLocalFile(toPosixSeparators(item.absoluteFilePath()))) ? rcOk : rcFail;
	}

	return rcFail;
}

// A current disk has been switched
void CController::diskSelected(Panel p, size_t index)
{
	assert(index < _diskEnumerator.drives().size());
	const QString drivePath = _diskEnumerator.drives()[index].fileSystemObject.absoluteFilePath();
	const QString lastPathForDrive = CSettings().value(p == LeftPanel ? KEY_LAST_PATH_FOR_DRIVE_L.arg(drivePath.toHtmlEscaped()) : KEY_LAST_PATH_FOR_DRIVE_R.arg(drivePath.toHtmlEscaped()), drivePath).toString();
	setPath(p, lastPathForDrive);
}

// Porgram settings have changed
void CController::settingsChanged()
{
	_rightPanel.settingsChanged();
	_leftPanel.settingsChanged();
}

void CController::activePanelChanged(Panel p)
{
	_activePanel = p;
}

// Navigates specified panel up the directory tree
void CController::navigateUp(Panel p)
{
	panel(p).navigateUp();
	disksChanged(); // To select a proper drive button
}

// Go to the previous location from history, if any
void CController::navigateBack(Panel p)
{
	panel(p).navigateBack();
	saveDirectoryForCurrentDisk(p);
	disksChanged(); // To select a proper drive button
}

// Go to the next location from history, if any
void CController::navigateForward(Panel p)
{
	panel(p).navigateForward();
	saveDirectoryForCurrentDisk(p);
	disksChanged(); // To select a proper drive button
}

// Sets the specified path, if possible. Otherwise reverts to the previously set path
FileOperationResultCode CController::setPath(Panel p, const QString &path)
{
	CPanel& targetPanel = panel(p);
	const QString prevPath = targetPanel.currentDirPath();
	const FileOperationResultCode result = targetPanel.setPath(path);
	if (result != rcOk)
		targetPanel.setPath(prevPath);

	saveDirectoryForCurrentDisk(p);
	disksChanged(); // To select a proper drive button
	return result;
}

bool CController::createFolder(const QString &parentFolder, const QString &name)
{
	QDir parentDir(parentFolder);
	if (!parentDir.exists())
		return false;

	const QString posixName = toPosixSeparators(name);
	if (parentDir.mkpath(posixName))
	{
		const QString newFolderPath = parentDir.absolutePath() + "/" + posixName.left(posixName.indexOf('/'));
		activePanel().setCurrentItemInFolder(activePanel().currentDirPath(), CFileSystemObject(newFolderPath).hash());
		return true;
	}
	else
		return false;
}

bool CController::createFile(const QString &parentFolder, const QString &name)
{
	QDir parentDir(parentFolder);
	if (!parentDir.exists())
		return false;
	return QFile(parentDir.absolutePath() + "/" + name).open(QFile::WriteOnly);
}

void CController::openTerminal(const QString &folder)
{
#ifdef _WIN32
	const bool started = QProcess::startDetached(shellExecutable(), QStringList(), folder);
	assert(started);
	Q_UNUSED(started);<commit_msg>Cursor handling when creating a new folder fixed<commit_after>#include "ccontroller.h"
#include "settings/csettings.h"
#include "settings.h"
#include "pluginengine/cpluginengine.h"

#include <stdlib.h>
#include <assert.h>

CController* CController::_instance = nullptr;

CController::CController() : _leftPanel(LeftPanel), _rightPanel(RightPanel), _diskEnumerator(CDiskEnumerator::instance())
{
	assert(_instance == nullptr); // Only makes sense to create one controller
	_instance = this;

	_diskEnumerator.addObserver(this);
	CPluginEngine::get().loadPlugins();

	_leftPanel.addPanelContentsChangedListener(&CPluginEngine::get());
	_rightPanel.addPanelContentsChangedListener(&CPluginEngine::get());
}

CController& CController::get()
{
	assert(_instance);
	return *_instance;
}

void CController::setPanelContentsChangedListener(PanelContentsChangedListener *listener)
{
	_leftPanel.addPanelContentsChangedListener(listener);
	_rightPanel.addPanelContentsChangedListener(listener);
}

void CController::setDisksChangedListener(CController::IDiskListObserver *listener)
{
	assert(std::find(_disksChangedListeners.begin(), _disksChangedListeners.end(), listener) == _disksChangedListeners.end());
	_disksChangedListeners.push_back(listener);
}

// Updates the list of files in the current directory this panel is viewing, and send the new state to UI
void CController::refreshPanelContents (Panel p)
{
	panel(p).refreshFileList();
}

// Creates a new tab for the specified panel, returns tab ID
int CController::tabCreated (Panel /*p*/)
{
	return -1;
}

// Removes a tab for the specified panel and tab ID
void CController::tabRemoved (Panel /*panel*/, int /*tabId*/)
{

}

// Indicates that an item was activated and appropriate action should be taken. Returns error message, if any
FileOperationResultCode CController::itemActivated(qulonglong itemHash, Panel p)
{
	auto& item = panel(p).itemByHash(itemHash);
	if (item.isDir())
	{
		// Attempting to enter this dir
		const FileOperationResultCode result = setPath(p, item.absoluteFilePath());
		return result;
	}
	else if (item.isFile())
	{
		if (item.isExecutable())
			// Attempting to launch this exe from the current directory
			return QProcess::startDetached(toPosixSeparators(item.absoluteFilePath()), QStringList(), toPosixSeparators(item.parentDirPath())) ? rcOk : rcFail;
		else
			// It's probably not a binary file, try opening with openUrl
			return QDesktopServices::openUrl(QUrl::fromLocalFile(toPosixSeparators(item.absoluteFilePath()))) ? rcOk : rcFail;
	}

	return rcFail;
}

// A current disk has been switched
void CController::diskSelected(Panel p, size_t index)
{
	assert(index < _diskEnumerator.drives().size());
	const QString drivePath = _diskEnumerator.drives()[index].fileSystemObject.absoluteFilePath();
	const QString lastPathForDrive = CSettings().value(p == LeftPanel ? KEY_LAST_PATH_FOR_DRIVE_L.arg(drivePath.toHtmlEscaped()) : KEY_LAST_PATH_FOR_DRIVE_R.arg(drivePath.toHtmlEscaped()), drivePath).toString();
	setPath(p, lastPathForDrive);
}

// Porgram settings have changed
void CController::settingsChanged()
{
	_rightPanel.settingsChanged();
	_leftPanel.settingsChanged();
}

void CController::activePanelChanged(Panel p)
{
	_activePanel = p;
}

// Navigates specified panel up the directory tree
void CController::navigateUp(Panel p)
{
	panel(p).navigateUp();
	disksChanged(); // To select a proper drive button
}

// Go to the previous location from history, if any
void CController::navigateBack(Panel p)
{
	panel(p).navigateBack();
	saveDirectoryForCurrentDisk(p);
	disksChanged(); // To select a proper drive button
}

// Go to the next location from history, if any
void CController::navigateForward(Panel p)
{
	panel(p).navigateForward();
	saveDirectoryForCurrentDisk(p);
	disksChanged(); // To select a proper drive button
}

// Sets the specified path, if possible. Otherwise reverts to the previously set path
FileOperationResultCode CController::setPath(Panel p, const QString &path)
{
	CPanel& targetPanel = panel(p);
	const QString prevPath = targetPanel.currentDirPath();
	const FileOperationResultCode result = targetPanel.setPath(path);
	if (result != rcOk)
		targetPanel.setPath(prevPath);

	saveDirectoryForCurrentDisk(p);
	disksChanged(); // To select a proper drive button
	return result;
}

bool CController::createFolder(const QString &parentFolder, const QString &name)
{
	QDir parentDir(parentFolder);
	if (!parentDir.exists())
		return false;

	const QString posixName = toPosixSeparators(name);
	if (parentDir.mkpath(posixName))
	{
		const int slashPosition = posixName.indexOf('/');
		const QString newFolderPath = parentDir.absolutePath() + "/" + (slashPosition > 0 ? posixName.left(posixName.indexOf('/')) : posixName);
		activePanel().setCurrentItemInFolder(activePanel().currentDirPath(), CFileSystemObject(newFolderPath).hash());
		return true;
	}
	else
		return false;
}

bool CController::createFile(const QString &parentFolder, const QString &name)
{
	QDir parentDir(parentFolder);
	if (!parentDir.exists())
		return false;
	return QFile(parentDir.absolutePath() + "/" + name).open(QFile::WriteOnly);
}

void CController::openTerminal(const QString &folder)
{
#ifdef _WIN32
	const bool started = QProcess::startDetached(shellExecutable(), QStringList(), folder);
	assert(started);
	Q_UNUSED(started);
{'fraction_non_alphanumeric': 0.117864944439168, 'fraction_numerical': 0.0006648304682306011, 'mean_word_length': 6.3584905660377355, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 8, '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': '4027677', 'n_tokens_mistral': 3222, 'n_tokens_neox': 3166, 'n_words': 795}