<commit_before>#include "ccontroller.h"
#include "settings/csettings.h"
#include "settings.h"
#include "shell/cshell.h"
#include "pluginengine/cpluginengine.h"
#include "filesystemhelperfunctions.h"
#include "iconprovider/ciconprovider.h"

DISABLE_COMPILER_WARNINGS
#include <QDesktopServices>
#include <QProcess>
#include <QUrl>
RESTORE_COMPILER_WARNINGS

#include <stdlib.h>

CController* CController::_instance = nullptr;

CController::CController() :
	_fileSearchEngine(*this),
	_leftPanel(LeftPanel),
	_rightPanel(RightPanel),
	_workerThread(32, "CController worker thread")
{
	assert_r(_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());

	// Manual update for the CPanels to get the disk list
	_diskEnumerator.updateSynchronously();

	_leftPanel.restoreFromSettings();
	_rightPanel.restoreFromSettings();
}

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

void CController::setPanelContentsChangedListener(Panel p, PanelContentsChangedListener *listener)
{
	panel(p).addPanelContentsChangedListener(listener);
}

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

	// Force an update
	disksChanged();
}

void CController::uiThreadTimerTick()
{
	_leftPanel.uiThreadTimerTick();
	_rightPanel.uiThreadTimerTick();

	_uiQueue.exec(CExecutionQueue::execAll);
}

// 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(refreshCauseOther);
}

// 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)
{
	const auto item = panel(p).itemByHash(itemHash);
	if (item.isDir())
	{
		// Attempting to enter this dir
		const FileOperationResultCode result = setPath(p, item.fullAbsolutePath(), item.isCdUp() ? refreshCauseCdUp : refreshCauseForwardNavigation);
		return result;
	}
	else if (item.isFile())
	{
		if (item.isExecutable())
			// Attempting to launch this exe from the current directory
			return QProcess::startDetached(toPosixSeparators(item.fullAbsolutePath()), 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.fullAbsolutePath()))) ? rcOk : rcFail;
	}

	return rcFail;
}

// A current disk has been switched
bool CController::switchToDisk(Panel p, size_t index)
{
	assert_r(index < _diskEnumerator.drives().size());
	const QString drivePath = _diskEnumerator.drives().at(index).storageInfo.rootPath();

	const size_t currentIndex = currentDiskIndex(otherPanelPosition(p));
	if (currentIndex < _diskEnumerator.drives().size() && drivePath == _diskEnumerator.drives().at(currentIndex).storageInfo.rootPath())
	{
		return setPath(p, otherPanel(p).currentDirPathNative(), refreshCauseOther) == rcOk;
	}
	else
	{
		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();
		return setPath(p, lastPathForDrive, refreshCauseOther) == rcOk;
	}
}

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

	CIconProvider::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
	saveDirectoryForCurrentDisk(p);
}

// 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, FileListRefreshCause operation)
{
	CPanel& targetPanel = panel(p);
	const QString prevPath = targetPanel.currentDirPathNative();
	const FileOperationResultCode result = targetPanel.setPath(path, operation);

	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))
	{
		if (parentDir.absolutePath() == activePanel().currentDirObject().qDir().absolutePath())
		{
			const int slashPosition = posixName.indexOf('/');
			const QString newFolderPath = parentDir.absolutePath() + "/" + (slashPosition > 0 ? posixName.left(posixName.indexOf('/')) : posixName);
			// This is required for the UI to know to set the cursor at the new folder
			setCursorPositionForCurrentFolder(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;

	const QString newFilePath = parentDir.absolutePath() + "/" + name;
	if (QFile(newFilePath).open(QFile::WriteOnly))
	{
		if (toNativeSeparators(parentDir.absolutePath()) == activePanel().currentDirPathNative())
		{
			// This is required for the UI to know to set the cursor at the new file
			setCursorPositionForCurrentFolder(CFileSystemObject(newFilePath).hash());
		}

		return true;
	}
	else
		return false;
}

void CController::openTerminal(const QString &folder)
{
#ifdef _WIN32
	const bool started = QProcess::startDetached(CShell::shellExecutable(), QStringList(), folder);
	assert_r(started);
#elif defined __APPLE__
	system(QString("osascript -e \"tell application \\\"Terminal\\\" to do script \\\"cd %1\\\"\"").arg(folder).toUtf8().data());
#elif defined __linux__
	const bool started = QProcess::startDetached(CShell::shellExecutable(), QStringList(), folder);
	assert_r(started);
#else
	#error unknown platform
#endif
}

FilesystemObjectsStatistics CController::calculateStatistics(Panel p, const std::vector<qulonglong> & hashes)
{
	return panel(p).calculateStatistics(hashes);
}

// Calculates directory size, stores it in the corresponding CFileSystemObject and sends data change notification
void CController::displayDirSize(Panel p, qulonglong dirHash)
{
	panel(p).displayDirSize(dirHash);
}

void CController::showAllFilesFromCurrentFolderAndBelow(Panel p)
{
	panel(p).showAllFilesFromCurrentFolderAndBelow();
}

// Indicates that we need to move cursor (e. g. a folder is being renamed and we want to keep the cursor on it)
// This method takes the current folder in the currently active panel
void CController::setCursorPositionForCurrentFolder(qulonglong newCurrentItemHash)
{
	activePanel().setCurrentItemForFolder(activePanel().currentDirPathNative(), newCurrentItemHash);
	CPluginEngine::get().currentItemChanged(activePanelPosition(), newCurrentItemHash);
}

const CPanel &CController::panel(Panel p) const
{
	switch (p)
	{
	case LeftPanel:
		return _leftPanel;
	case RightPanel:
		return _rightPanel;
	default:
		assert_unconditional_r("Unknown panel");
		return _rightPanel;
	}
}

CPanel& CController::panel(Panel p)
{
	switch (p)
	{
	case LeftPanel:
		return _leftPanel;
	case RightPanel:
		return _rightPanel;
	default:
		assert_unconditional_r("Unknown panel");
		return _rightPanel;
	}
}

const CPanel &CController::otherPanel(Panel p) const
{
	switch (p)
	{
	case LeftPanel:
		return _rightPanel;
	case RightPanel:
		return _leftPanel;
	default:
		assert_unconditional_r("Uknown panel");
		return _rightPanel;
	}
}

CPanel& CController::otherPanel(Panel p)
{
	switch (p)
	{
	case LeftPanel:
		return _rightPanel;
	case RightPanel:
		return _leftPanel;
	default:
		assert_unconditional_r("Uknown panel");
		return _leftPanel;
	}
}

Panel CController::otherPanelPosition(Panel p)
{
	switch (p)
	{
	case LeftPanel:
		return RightPanel;
	case RightPanel:
		return LeftPanel;
	default:
		assert_unconditional_r("Uknown panel");
		return LeftPanel;
	}
}

Panel CController::activePanelPosition() const
{
	assert_r(_activePanel == RightPanel || _activePanel == LeftPanel);
	return _activePanel;
}

const CPanel& CController::activePanel() const
{
	return panel(activePanelPosition());
}

CPanel& CController::activePanel()
{
	return panel(activePanelPosition());
}

CPluginProxy &CController::pluginProxy()
{
	return _pluginProxy;
}

bool CController::itemHashExists(Panel p, qulonglong hash) const
{
	return panel(p).itemHashExists(hash);
}

CFileSystemObject CController::itemByHash( Panel p, qulonglong hash ) const
{
	return panel(p).itemByHash(hash);
}

std::vector<CFileSystemObject> CController::items(Panel p, const std::vector<qulonglong>& hashes) const
{
	std::vector<CFileSystemObject> objects;
	std::for_each(hashes.begin(), hashes.end(), [&objects, p, this] (qulonglong hash) {objects.push_back(itemByHash(p, hash));});
	return objects;
}

QString CController::itemPath(Panel p, qulonglong hash) const
{
	return panel(p).itemByHash(hash).properties().fullPath;
}

CDiskEnumerator& CController::diskEnumerator()
{
	return _diskEnumerator;
}

QString CController::diskPath(size_t index) const
{
	return index < _diskEnumerator.drives().size() ? _diskEnumerator.drives()[index].fileSystemObject.fullAbsolutePath() : QString();
}

size_t CController::currentDiskIndex(Panel p) const
{
	const auto& drives = _diskEnumerator.drives();
	for (size_t i = 0; i < drives.size(); ++i)
	{
		if (CFileSystemObject(panel(p).currentDirPathNative()).isChildOf(drives[i].fileSystemObject))
			return i;
	}

	return std::numeric_limits<int>::max();
}

CFavoriteLocations& CController::favoriteLocations()
{
	return _favoriteLocations;
}

CFileSearchEngine& CController::fileSearchEngine()
{
	return _fileSearchEngine;
}

// Returns hash of an item that was the last selected in the specified dir
qulonglong CController::currentItemInFolder(Panel p, const QString &dir) const
{
	return panel(p).currentItemForFolder(dir);
}

void CController::disksChanged()
{
	const auto& drives = _diskEnumerator.drives();

	_rightPanel.disksChanged(drives);
	_leftPanel.disksChanged(drives);

	for (auto& listener: _disksChangedListeners)
	{
		listener->disksChanged(drives, RightPanel);
		listener->disksChanged(drives, LeftPanel);
	}
}

void CController::saveDirectoryForCurrentDisk(Panel p)
{
	const QString path = panel(p).currentDirPathNative();
	if (CFileSystemObject(path).isNetworkObject())
		return;

	assert_and_return_r(CFileSystemObject(path).isNetworkObject() || currentDiskIndex(p) < _diskEnumerator.drives().size(), );

	const QString drivePath = _diskEnumerator.drives().at(currentDiskIndex(p)).storageInfo.rootPath();
	CSettings().setValue(p == LeftPanel ? KEY_LAST_PATH_FOR_DRIVE_L.arg(drivePath.toHtmlEscaped()) : KEY_LAST_PATH_FOR_DRIVE_R.arg(drivePath.toHtmlEscaped()), path);
}
<commit_msg>Fixed a bug with launching .exe files on Windows<commit_after>#include "ccontroller.h"
#include "settings/csettings.h"
#include "settings.h"
#include "shell/cshell.h"
#include "pluginengine/cpluginengine.h"
#include "filesystemhelperfunctions.h"
#include "iconprovider/ciconprovider.h"

DISABLE_COMPILER_WARNINGS
#include <QDesktopServices>
#include <QProcess>
#include <QUrl>
RESTORE_COMPILER_WARNINGS

#include <stdlib.h>

CController* CController::_instance = nullptr;

CController::CController() :
	_fileSearchEngine(*this),
	_leftPanel(LeftPanel),
	_rightPanel(RightPanel),
	_workerThread(32, "CController worker thread")
{
	assert_r(_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());

	// Manual update for the CPanels to get the disk list
	_diskEnumerator.updateSynchronously();

	_leftPanel.restoreFromSettings();
	_rightPanel.restoreFromSettings();
}

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

void CController::setPanelContentsChangedListener(Panel p, PanelContentsChangedListener *listener)
{
	panel(p).addPanelContentsChangedListener(listener);
}

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

	// Force an update
	disksChanged();
}

void CController::uiThreadTimerTick()
{
	_leftPanel.uiThreadTimerTick();
	_rightPanel.uiThreadTimerTick();

	_uiQueue.exec(CExecutionQueue::execAll);
}

// 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(refreshCauseOther);
}

// 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)
{
	const auto item = panel(p).itemByHash(itemHash);
	if (item.isDir())
	{
		// Attempting to enter this dir
		const FileOperationResultCode result = setPath(p, item.fullAbsolutePath(), item.isCdUp() ? refreshCauseCdUp : refreshCauseForwardNavigation);
		return result;
	}
	else if (item.isFile())
	{
		return QDesktopServices::openUrl(QUrl::fromLocalFile(toPosixSeparators(item.fullAbsolutePath()))) ? rcOk : rcFail;
	}

	return rcFail;
}

// A current disk has been switched
bool CController::switchToDisk(Panel p, size_t index)
{
	assert_r(index < _diskEnumerator.drives().size());
	const QString drivePath = _diskEnumerator.drives().at(index).storageInfo.rootPath();

	const size_t currentIndex = currentDiskIndex(otherPanelPosition(p));
	if (currentIndex < _diskEnumerator.drives().size() && drivePath == _diskEnumerator.drives().at(currentIndex).storageInfo.rootPath())
	{
		return setPath(p, otherPanel(p).currentDirPathNative(), refreshCauseOther) == rcOk;
	}
	else
	{
		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();
		return setPath(p, lastPathForDrive, refreshCauseOther) == rcOk;
	}
}

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

	CIconProvider::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
	saveDirectoryForCurrentDisk(p);
}

// 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, FileListRefreshCause operation)
{
	CPanel& targetPanel = panel(p);
	const QString prevPath = targetPanel.currentDirPathNative();
	const FileOperationResultCode result = targetPanel.setPath(path, operation);

	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))
	{
		if (parentDir.absolutePath() == activePanel().currentDirObject().qDir().absolutePath())
		{
			const int slashPosition = posixName.indexOf('/');
			const QString newFolderPath = parentDir.absolutePath() + "/" + (slashPosition > 0 ? posixName.left(posixName.indexOf('/')) : posixName);
			// This is required for the UI to know to set the cursor at the new folder
			setCursorPositionForCurrentFolder(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;

	const QString newFilePath = parentDir.absolutePath() + "/" + name;
	if (QFile(newFilePath).open(QFile::WriteOnly))
	{
		if (toNativeSeparators(parentDir.absolutePath()) == activePanel().currentDirPathNative())
		{
			// This is required for the UI to know to set the cursor at the new file
			setCursorPositionForCurrentFolder(CFileSystemObject(newFilePath).hash());
		}

		return true;
	}
	else
		return false;
}

void CController::openTerminal(const QString &folder)
{
#ifdef _WIN32
	const bool started = QProcess::startDetached(CShell::shellExecutable(), QStringList(), folder);
	assert_r(started);
#elif defined __APPLE__
	system(QString("osascript -e \"tell application \\\"Terminal\\\" to do script \\\"cd %1\\\"\"").arg(folder).toUtf8().data());
#elif defined __linux__
	const bool started = QProcess::startDetached(CShell::shellExecutable(), QStringList(), folder);
	assert_r(started);
#else
	#error unknown platform
#endif
}

FilesystemObjectsStatistics CController::calculateStatistics(Panel p, const std::vector<qulonglong> & hashes)
{
	return panel(p).calculateStatistics(hashes);
}

// Calculates directory size, stores it in the corresponding CFileSystemObject and sends data change notification
void CController::displayDirSize(Panel p, qulonglong dirHash)
{
	panel(p).displayDirSize(dirHash);
}

void CController::showAllFilesFromCurrentFolderAndBelow(Panel p)
{
	panel(p).showAllFilesFromCurrentFolderAndBelow();
}

// Indicates that we need to move cursor (e. g. a folder is being renamed and we want to keep the cursor on it)
// This method takes the current folder in the currently active panel
void CController::setCursorPositionForCurrentFolder(qulonglong newCurrentItemHash)
{
	activePanel().setCurrentItemForFolder(activePanel().currentDirPathNative(), newCurrentItemHash);
	CPluginEngine::get().currentItemChanged(activePanelPosition(), newCurrentItemHash);
}

const CPanel &CController::panel(Panel p) const
{
	switch (p)
	{
	case LeftPanel:
		return _leftPanel;
	case RightPanel:
		return _rightPanel;
	default:
		assert_unconditional_r("Unknown panel");
		return _rightPanel;
	}
}

CPanel& CController::panel(Panel p)
{
	switch (p)
	{
	case LeftPanel:
		return _leftPanel;
	case RightPanel:
		return _rightPanel;
	default:
		assert_unconditional_r("Unknown panel");
		return _rightPanel;
	}
}

const CPanel &CController::otherPanel(Panel p) const
{
	switch (p)
	{
	case LeftPanel:
		return _rightPanel;
	case RightPanel:
		return _leftPanel;
	default:
		assert_unconditional_r("Uknown panel");
		return _rightPanel;
	}
}

CPanel& CController::otherPanel(Panel p)
{
	switch (p)
	{
	case LeftPanel:
		return _rightPanel;
	case RightPanel:
		return _leftPanel;
	default:
		assert_unconditional_r("Uknown panel");
		return _leftPanel;
	}
}

Panel CController::otherPanelPosition(Panel p)
{
	switch (p)
	{
	case LeftPanel:
		return RightPanel;
	case RightPanel:
		return LeftPanel;
	default:
		assert_unconditional_r("Uknown panel");
		return LeftPanel;
	}
}

Panel CController::activePanelPosition() const
{
	assert_r(_activePanel == RightPanel || _activePanel == LeftPanel);
	return _activePanel;
}

const CPanel& CController::activePanel() const
{
	return panel(activePanelPosition());
}

CPanel& CController::activePanel()
{
	return panel(activePanelPosition());
}

CPluginProxy &CController::pluginProxy()
{
	return _pluginProxy;
}

bool CController::itemHashExists(Panel p, qulonglong hash) const
{
	return panel(p).itemHashExists(hash);
}

CFileSystemObject CController::itemByHash( Panel p, qulonglong hash ) const
{
	return panel(p).itemByHash(hash);
}

std::vector<CFileSystemObject> CController::items(Panel p, const std::vector<qulonglong>& hashes) const
{
	std::vector<CFileSystemObject> objects;
	std::for_each(hashes.begin(), hashes.end(), [&objects, p, this] (qulonglong hash) {objects.push_back(itemByHash(p, hash));});
	return objects;
}

QString CController::itemPath(Panel p, qulonglong hash) const
{
	return panel(p).itemByHash(hash).properties().fullPath;
}

CDiskEnumerator& CController::diskEnumerator()
{
	return _diskEnumerator;
}

QString CController::diskPath(size_t index) const
{
	return index < _diskEnumerator.drives().size() ? _diskEnumerator.drives()[index].fileSystemObject.fullAbsolutePath() : QString();
}

size_t CController::currentDiskIndex(Panel p) const
{
	const auto& drives = _diskEnumerator.drives();
	for (size_t i = 0; i < drives.size(); ++i)
	{
		if (CFileSystemObject(panel(p).currentDirPathNative()).isChildOf(drives[i].fileSystemObject))
			return i;
	}

	return std::numeric_limits<int>::max();
}

CFavoriteLocations& CController::favoriteLocations()
{
	return _favoriteLocations;
}

CFileSearchEngine& CController::fileSearchEngine()
{
	return _fileSearchEngine;
}

// Returns hash of an item that was the last selected in the specified dir
qulonglong CController::currentItemInFolder(Panel p, const QString &dir) const
{
	return panel(p).currentItemForFolder(dir);
}

void CController::disksChanged()
{
	const auto& drives = _diskEnumerator.drives();

	_rightPanel.disksChanged(drives);
	_leftPanel.disksChanged(drives);

	for (auto& listener: _disksChangedListeners)
	{
		listener->disksChanged(drives, RightPanel);
		listener->disksChanged(drives, LeftPanel);
	}
}

void CController::saveDirectoryForCurrentDisk(Panel p)
{
	const QString path = panel(p).currentDirPathNative();
	if (CFileSystemObject(path).isNetworkObject())
		return;

	assert_and_return_r(CFileSystemObject(path).isNetworkObject() || currentDiskIndex(p) < _diskEnumerator.drives().size(), );

	const QString drivePath = _diskEnumerator.drives().at(currentDiskIndex(p)).storageInfo.rootPath();
	CSettings().setValue(p == LeftPanel ? KEY_LAST_PATH_FOR_DRIVE_L.arg(drivePath.toHtmlEscaped()) : KEY_LAST_PATH_FOR_DRIVE_R.arg(drivePath.toHtmlEscaped()), path);
}
<|endoftext|>


<commit_before>/*
 * Super Entity Game Server Project
 * http://segs.sf.net/
 * Copyright (c) 2006 - 2016 Super Entity Game Server Team (see Authors.txt)
 * This software is licensed! (See License.txt for details)
 *

 */

#include "MapServer.h"

#include "Servers/HandlerLocator.h"
#include "ConfigExtension.h"
#include "MapManager.h"
#include "MapServerData.h"
#include "MapTemplate.h"
#include "MapInstance.h"
#include "SEGSTimer.h"
#include "Settings.h"
#include "Servers/MessageBus.h"

#include <ace/Reactor.h>

#include <QtCore/QSettings>
#include <QtCore/QString>
#include <QtCore/QFile>
#include <QtCore/QDebug>

#include <set>

// global variables
MapServer *g_GlobalMapServer=nullptr;

// anonymous namespace
namespace
{
constexpr int                MAPSERVER_VERSION=1;
} // end of anonymous namespace
///////////////////////////////////////////////////////////////////////////////
/// \brief The MapServer::PrivateData class - PIMPL idiom for internal
/// MapServer data
///
class MapServer::PrivateData
{
public:
        MapServerData   m_runtime_data;
        MapManager      m_manager;
};

MapServer::MapServer(uint8_t id) : d(new PrivateData), m_id(id)
{
    assert(g_GlobalMapServer==nullptr && "Only one GameServer instance per process allowed");
    g_GlobalMapServer = this;
    HandlerLocator::setMap_Handler(id,this);
}
MapServer::~MapServer()
{

}
bool MapServer::Run()
{
    assert(m_owner_game_server_id!=255);
    if(!d->m_runtime_data.read_runtime_data("./data/bin/"))
    {
        return false;
    }
    assert(d->m_manager.num_templates()>0); // we have to have a world to run
    return true;
}
/**
 * @param  inipath Doc at RoamingServer::ReadConfig
 * @return bool (false means an error occurred )
 */
bool MapServer::ReadConfigAndRestart()
{
    qInfo() << "Loading MapServer settings...";
    QSettings config(Settings::getSettingsPath(),QSettings::IniFormat,nullptr);

    // tell all instances to shut down
    d->m_manager.shut_down_all();

    config.beginGroup("MapServer");
    if(!config.contains(QStringLiteral("listen_addr")))
        qDebug() << "Config file is missing 'listen_addr' entry in MapServer group, will try to use default";
    if(!config.contains(QStringLiteral("location_addr")))
        qDebug() << "Config file is missing 'location_addr' entry in MapServer group, will try to use default";

    QString listen_addr = config.value("listen_addr","127.0.0.1:7003").toString();
    QString location_addr = config.value("location_addr","127.0.0.1:7003").toString();

    QString map_templates_dir = config.value("maps",".").toString();
    if(!parseAddress(listen_addr,m_base_listen_point))
    {
        qCritical() << "Badly formed IP address" << listen_addr;
        return false;
    }
    if(!parseAddress(location_addr,m_base_location))
    {
        qCritical() << "Badly formed IP address" << location_addr;
        return false;
    }

    config.endGroup(); // MapServer

    if(!d->m_manager.load_templates(map_templates_dir,m_owner_game_server_id,m_id,{m_base_listen_point,m_base_location}))
    {
        postGlobalEvent(new ServiceStatusMessage({ QString("MapServer: Cannot load map templates from %1").arg(map_templates_dir),-1 }));
        return false;
    }
    return Run();
}
bool MapServer::ShutDown()
{
    qWarning() << "Shutting down map server";
    // tell all instances to shut down too
    d->m_manager.shut_down_all();
    putq(SEGSEvent::s_ev_finish.shallow_copy());
    return true;
}

MapManager &MapServer::map_manager()
{
    return d->m_manager;
}

MapServerData &MapServer::runtimeData()
{
    return d->m_runtime_data;
}

void MapServer::sett_game_server_owner(uint8_t owner_id)
{
    m_owner_game_server_id = owner_id;
}

void MapServer::dispatch(SEGSEvent *ev)
{
    assert(ev);
    switch(ev->type())
    {
        case Internal_EventTypes::evReloadConfig:
            ReadConfigAndRestart();
            break;
        case Internal_EventTypes::evExpectMapClientRequest:
            on_expect_client(static_cast<ExpectMapClientRequest *>(ev));
            break;
        default:
            assert(!"Unknown event encountered in dispatch.");
    }
}

void MapServer::on_expect_client(ExpectMapClientRequest *ev)
{
    // TODO: handle contention while creating 2 characters with the same name from different clients
    // TODO: SELECT account_id from characters where name=ev->m_character_name
    const ExpectMapClientRequestData &request_data(ev->m_data);
    MapTemplate *tpl    = map_manager().get_template(request_data.m_map_name);
    if(nullptr==tpl)
    {
        ev->src()->putq(
            new ExpectMapClientResponse({1, 0, m_base_location}, ev->session_token()));
        return;
    }
    EventProcessor *instance = tpl->get_instance();
    // now we know which instance will handle this client, pass the event to it,
    // remember to shallow_copy to mark the event as still owned.
    instance->putq(ev->shallow_copy());
}
<commit_msg>Fix a crash when a map instance is not located for given map<commit_after>/*
 * Super Entity Game Server Project
 * http://segs.sf.net/
 * Copyright (c) 2006 - 2016 Super Entity Game Server Team (see Authors.txt)
 * This software is licensed! (See License.txt for details)
 *

 */

#include "MapServer.h"

#include "Servers/HandlerLocator.h"
#include "ConfigExtension.h"
#include "MapManager.h"
#include "MapServerData.h"
#include "MapTemplate.h"
#include "MapInstance.h"
#include "SEGSTimer.h"
#include "Settings.h"
#include "Servers/MessageBus.h"

#include <ace/Reactor.h>

#include <QtCore/QSettings>
#include <QtCore/QString>
#include <QtCore/QFile>
#include <QtCore/QDebug>

#include <set>

// global variables
MapServer *g_GlobalMapServer=nullptr;

// anonymous namespace
namespace
{
constexpr int                MAPSERVER_VERSION=1;
} // end of anonymous namespace
///////////////////////////////////////////////////////////////////////////////
/// \brief The MapServer::PrivateData class - PIMPL idiom for internal
/// MapServer data
///
class MapServer::PrivateData
{
public:
        MapServerData   m_runtime_data;
        MapManager      m_manager;
};

MapServer::MapServer(uint8_t id) : d(new PrivateData), m_id(id)
{
    assert(g_GlobalMapServer==nullptr && "Only one GameServer instance per process allowed");
    g_GlobalMapServer = this;
    HandlerLocator::setMap_Handler(id,this);
}
MapServer::~MapServer()
{

}
bool MapServer::Run()
{
    assert(m_owner_game_server_id!=255);
    if(!d->m_runtime_data.read_runtime_data("./data/bin/"))
    {
        return false;
    }
    assert(d->m_manager.num_templates()>0); // we have to have a world to run
    return true;
}
/**
 * @param  inipath Doc at RoamingServer::ReadConfig
 * @return bool (false means an error occurred )
 */
bool MapServer::ReadConfigAndRestart()
{
    qInfo() << "Loading MapServer settings...";
    QSettings config(Settings::getSettingsPath(),QSettings::IniFormat,nullptr);

    // tell all instances to shut down
    d->m_manager.shut_down_all();

    config.beginGroup("MapServer");
    if(!config.contains(QStringLiteral("listen_addr")))
        qDebug() << "Config file is missing 'listen_addr' entry in MapServer group, will try to use default";
    if(!config.contains(QStringLiteral("location_addr")))
        qDebug() << "Config file is missing 'location_addr' entry in MapServer group, will try to use default";

    QString listen_addr = config.value("listen_addr","127.0.0.1:7003").toString();
    QString location_addr = config.value("location_addr","127.0.0.1:7003").toString();

    QString map_templates_dir = config.value("maps",".").toString();
    if(!parseAddress(listen_addr,m_base_listen_point))
    {
        qCritical() << "Badly formed IP address" << listen_addr;
        return false;
    }
    if(!parseAddress(location_addr,m_base_location))
    {
        qCritical() << "Badly formed IP address" << location_addr;
        return false;
    }

    config.endGroup(); // MapServer

    if(!d->m_manager.load_templates(map_templates_dir,m_owner_game_server_id,m_id,{m_base_listen_point,m_base_location}))
    {
        postGlobalEvent(new ServiceStatusMessage({ QString("MapServer: Cannot load map templates from %1").arg(map_templates_dir),-1 }));
        return false;
    }
    return Run();
}
bool MapServer::ShutDown()
{
    qWarning() << "Shutting down map server";
    // tell all instances to shut down too
    d->m_manager.shut_down_all();
    putq(SEGSEvent::s_ev_finish.shallow_copy());
    return true;
}

MapManager &MapServer::map_manager()
{
    return d->m_manager;
}

MapServerData &MapServer::runtimeData()
{
    return d->m_runtime_data;
}

void MapServer::sett_game_server_owner(uint8_t owner_id)
{
    m_owner_game_server_id = owner_id;
}

void MapServer::dispatch(SEGSEvent *ev)
{
    assert(ev);
    switch(ev->type())
    {
        case Internal_EventTypes::evReloadConfig:
            ReadConfigAndRestart();
            break;
        case Internal_EventTypes::evExpectMapClientRequest:
            on_expect_client(static_cast<ExpectMapClientRequest *>(ev));
            break;
        default:
            assert(!"Unknown event encountered in dispatch.");
    }
}

void MapServer::on_expect_client(ExpectMapClientRequest *ev)
{
    // TODO: handle contention while creating 2 characters with the same name from different clients
    // TODO: SELECT account_id from characters where name=ev->m_character_name
    const ExpectMapClientRequestData &request_data(ev->m_data);
    MapTemplate *tpl    = map_manager().get_template(request_data.m_map_name);
    if(nullptr==tpl)
    {

        HandlerLocator::getGame_Handler(m_owner_game_server_id)->putq(
            new ExpectMapClientResponse({1, 0, m_base_location}, ev->session_token()));
        return;
    }
    EventProcessor *instance = tpl->get_instance();
    // now we know which instance will handle this client, pass the event to it,
    // remember to shallow_copy to mark the event as still owned.
    instance->putq(ev->shallow_copy());
}
<|endoftext|>


<commit_before>#include "Button.h"

Button::Button()
{
}

Button::~Button()
{
}
<commit_msg>Delete Button.cpp<commit_after><|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_SPACES_BLOCK_HH
#define DUNE_GDT_SPACES_BLOCK_HH

#include <dune/stuff/common/exceptions.hh>

#include <dune/grid/multiscale/default.hh>

#include <dune/gdt/playground/mapper/block.hh>

#include "../../spaces/interface.hh"

namespace Dune {
namespace GDT {
namespace Spaces {

template <class LocalSpaceImp>
class Block;

namespace internal {

template <class LocalSpaceType>
class BlockTraits
{
  static_assert(std::is_base_of<SpaceInterface<typename LocalSpaceType::Traits>, LocalSpaceType>::value,
                "LocalSpaceType has to be derived from SpaceInterface!");
  typedef grid::Multiscale::Default<typename LocalSpaceType::GridViewType::Grid> MsGridType;

public:
  typedef Block<LocalSpaceType> derived_type;
  static const int polOrder = LocalSpaceType::polOrder;
  typedef typename LocalSpaceType::BackendType BackendType;
  typedef Mapper::Block<LocalSpaceType> MapperType;
  typedef typename LocalSpaceType::BaseFunctionSetType BaseFunctionSetType;
  typedef typename MsGridType::GlobalGridViewType GridViewType;
  typedef typename LocalSpaceType::RangeFieldType RangeFieldType;
  static const unsigned int dimRange     = LocalSpaceType::dimRange;
  static const unsigned int dimRangeCols = LocalSpaceType::dimRangeCols;

  static const Stuff::Grid::ChoosePartView part_view_type = LocalSpaceType::part_view_type;

  static const bool needs_grid_view = LocalSpaceType::needs_grid_view;
}; // class BlockTraits

} // namespace internal

template <class LocalSpaceImp>
class Block : public SpaceInterface<internal::BlockTraits<LocalSpaceImp>>
{
  typedef SpaceInterface<internal::BlockTraits<LocalSpaceImp>> BaseType;

public:
  typedef internal::BlockTraits<LocalSpaceImp> Traits;
  typedef typename Traits::BackendType BackendType;
  typedef typename Traits::MapperType MapperType;
  typedef typename Traits::BaseFunctionSetType BaseFunctionSetType;
  typedef LocalSpaceImp LocalSpaceType;

  typedef typename BaseType::PatternType PatternType;
  typedef typename BaseType::GridViewType GridViewType;
  typedef typename BaseType::EntityType EntityType;

  typedef grid::Multiscale::Default<typename GridViewType::Grid> MsGridType;

  Block(const std::shared_ptr<const MsGridType> ms_grid,
        const std::vector<std::shared_ptr<const LocalSpaceType>> local_spaces)
    : ms_grid_(ms_grid)
    , local_spaces_(local_spaces)
    , mapper_(std::make_shared<MapperType>(ms_grid_, local_spaces_))
  {
    if (local_spaces_.size() != ms_grid_->size())
      DUNE_THROW_COLORFULLY(Stuff::Exceptions::shapes_do_not_match,
                            "You have to provide a local space for each subdomain of the multiscale grid!\n"
                                << "  Size of the given multiscale grid: "
                                << ms_grid_->size()
                                << "\n"
                                << "  Number of local spaces given: "
                                << local_spaces_.size());
  } // Block(...)

  const std::shared_ptr<const GridViewType>& grid_view() const
  {
    return ms_grid_->globalGridView();
  }

  const BackendType& backend() const
  {
    return local_spaces_[0]->backend();
  }

  const MapperType& mapper() const
  {
    return *mapper_;
  }

  BaseFunctionSetType base_function_set(const EntityType& entity) const
  {
    const size_t block = find_block_of_(entity);
    return local_spaces_[block]->base_function_set(entity);
  }

  template <class ConstraintsType>
  void local_constraints(const EntityType& /*entity*/, ConstraintsType& /*ret*/) const
  {
    DUNE_THROW_COLORFULLY(NotImplemented, "I am not sure yet how to implement this!");
  }

  template <class G, class S>
  PatternType compute_pattern(const GridView<G>& /*local_grid_view*/, const SpaceInterface<S>& /*ansatz_space*/) const
  {
    DUNE_THROW_COLORFULLY(NotImplemented, "I am not sure yet how to implement this!");
  }

private:
  template <class EntityType>
  size_t find_block_of_(const EntityType& entity) const
  {
    const auto global_entity_index = ms_grid_->globalGridView()->indexSet().index(entity);
    const auto result              = ms_grid_->entityToSubdomainMap()->find(global_entity_index);
#ifndef NDEBUG
    if (result == ms_grid_->entityToSubdomainMap()->end())
      DUNE_THROW_COLORFULLY(Stuff::Exceptions::internal_error,
                            "Entity " << global_entity_index
                                      << " of the global grid view was not found in the multiscale grid!");
#endif // NDEBUG
    const size_t subdomain = result->second;
#ifndef NDEBUG
    if (subdomain >= ms_grid_->size())
      DUNE_THROW_COLORFULLY(Stuff::Exceptions::internal_error,
                            "The multiscale grid is corrupted!\nIt reports Entity " << global_entity_index
                                                                                << " to be in subdomain "
                                                                                << subdomain
                                                                                << " while only having "
                                                                                << ms_grid_->size()
                                                                                << " subdomains!");
#endif // NDEBUG
    assert(subdomain < local_spaces_.size());
    return subdomain;
  } // ... find_block_of_(...)

  std::shared_ptr<const MsGridType> ms_grid_;
  std::vector<std::shared_ptr<const LocalSpaceType>> local_spaces_;
  std::shared_ptr<const MapperType> mapper_;
}; // class Block

} // namespace Spaces
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_SPACES_BLOCK_HH
<commit_msg>[space.block] expose ms_grid() and local_spaces()<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_SPACES_BLOCK_HH
#define DUNE_GDT_SPACES_BLOCK_HH

#include <dune/stuff/common/exceptions.hh>

#include <dune/grid/multiscale/default.hh>

#include <dune/gdt/playground/mapper/block.hh>

#include "../../spaces/interface.hh"

namespace Dune {
namespace GDT {
namespace Spaces {

template <class LocalSpaceImp>
class Block;

namespace internal {

template <class LocalSpaceType>
class BlockTraits
{
  static_assert(std::is_base_of<SpaceInterface<typename LocalSpaceType::Traits>, LocalSpaceType>::value,
                "LocalSpaceType has to be derived from SpaceInterface!");
  typedef grid::Multiscale::Default<typename LocalSpaceType::GridViewType::Grid> MsGridType;

public:
  typedef Block<LocalSpaceType> derived_type;
  static const int polOrder = LocalSpaceType::polOrder;
  typedef typename LocalSpaceType::BackendType BackendType;
  typedef Mapper::Block<LocalSpaceType> MapperType;
  typedef typename LocalSpaceType::BaseFunctionSetType BaseFunctionSetType;
  typedef typename MsGridType::GlobalGridViewType GridViewType;
  typedef typename LocalSpaceType::RangeFieldType RangeFieldType;
  static const unsigned int dimRange     = LocalSpaceType::dimRange;
  static const unsigned int dimRangeCols = LocalSpaceType::dimRangeCols;

  static const Stuff::Grid::ChoosePartView part_view_type = LocalSpaceType::part_view_type;

  static const bool needs_grid_view = LocalSpaceType::needs_grid_view;
}; // class BlockTraits

} // namespace internal

template <class LocalSpaceImp>
class Block : public SpaceInterface<internal::BlockTraits<LocalSpaceImp>>
{
  typedef SpaceInterface<internal::BlockTraits<LocalSpaceImp>> BaseType;

public:
  typedef internal::BlockTraits<LocalSpaceImp> Traits;
  typedef typename Traits::BackendType BackendType;
  typedef typename Traits::MapperType MapperType;
  typedef typename Traits::BaseFunctionSetType BaseFunctionSetType;
  typedef LocalSpaceImp LocalSpaceType;

  typedef typename BaseType::PatternType PatternType;
  typedef typename BaseType::GridViewType GridViewType;
  typedef typename BaseType::EntityType EntityType;

  typedef grid::Multiscale::Default<typename GridViewType::Grid> MsGridType;

  Block(const std::shared_ptr<const MsGridType> ms_grid,
        const std::vector<std::shared_ptr<const LocalSpaceType>> local_spaces)
    : ms_grid_(ms_grid)
    , local_spaces_(local_spaces)
    , mapper_(std::make_shared<MapperType>(ms_grid_, local_spaces_))
  {
    if (local_spaces_.size() != ms_grid_->size())
      DUNE_THROW_COLORFULLY(Stuff::Exceptions::shapes_do_not_match,
                            "You have to provide a local space for each subdomain of the multiscale grid!\n"
                                << "  Size of the given multiscale grid: "
                                << ms_grid_->size()
                                << "\n"
                                << "  Number of local spaces given: "
                                << local_spaces_.size());
  } // Block(...)

  const std::shared_ptr<const MsGridType>& ms_grid() const
  {
    return ms_grid_;
  }

  const std::vector<std::shared_ptr<const LocalSpaceType>>& local_spaces() const
  {
    return local_spaces_;
  }

  const std::shared_ptr<const GridViewType>& grid_view() const
  {
    return ms_grid_->globalGridView();
  }

  const BackendType& backend() const
  {
    return local_spaces_[0]->backend();
  }

  const MapperType& mapper() const
  {
    return *mapper_;
  }

  BaseFunctionSetType base_function_set(const EntityType& entity) const
  {
    const size_t block = find_block_of_(entity);
    return local_spaces_[block]->base_function_set(entity);
  }

  template <class ConstraintsType>
  void local_constraints(const EntityType& /*entity*/, ConstraintsType& /*ret*/) const
  {
    DUNE_THROW_COLORFULLY(NotImplemented, "I am not sure yet how to implement this!");
  }

  template <class G, class S>
  PatternType compute_pattern(const GridView<G>& /*local_grid_view*/, const SpaceInterface<S>& /*ansatz_space*/) const
  {
    DUNE_THROW_COLORFULLY(NotImplemented, "I am not sure yet how to implement this!");
  }

private:
  template <class EntityType>
  size_t find_block_of_(const EntityType& entity) const
  {
    const auto global_entity_index = ms_grid_->globalGridView()->indexSet().index(entity);
    const auto result              = ms_grid_->entityToSubdomainMap()->find(global_entity_index);
#ifndef NDEBUG
    if (result == ms_grid_->entityToSubdomainMap()->end())
      DUNE_THROW_COLORFULLY(Stuff::Exceptions::internal_error,
                            "Entity " << global_entity_index
                                      << " of the global grid view was not found in the multiscale grid!");
#endif // NDEBUG
    const size_t subdomain = result->second;
#ifndef NDEBUG
    if (subdomain >= ms_grid_->size())
      DUNE_THROW_COLORFULLY(Stuff::Exceptions::internal_error,
                            "The multiscale grid is corrupted!\nIt reports Entity " << global_entity_index
                                                                                << " to be in subdomain "
                                                                                << subdomain
                                                                                << " while only having "
                                                                                << ms_grid_->size()
                                                                                << " subdomains!");
#endif // NDEBUG
    assert(subdomain < local_spaces_.size());
    return subdomain;
  } // ... find_block_of_(...)

  std::shared_ptr<const MsGridType> ms_grid_;
  std::vector<std::shared_ptr<const LocalSpaceType>> local_spaces_;
  std::shared_ptr<const MapperType> mapper_;
}; // class Block

} // namespace Spaces
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_SPACES_BLOCK_HH
<|endoftext|>


<commit_before>#include <config.h>

#include <dune/common/exceptions.hh>
#include <dune/common/timer.hh>
#include <dune/multiscale/msfem/coarse_rhs_functional.hh>
#include <dune/multiscale/common/traits.hh>
#include <dune/multiscale/common/grid_creation.hh>
#include <dune/multiscale/problems/selector.hh>
#include <dune/stuff/common/logging.hh>
#include <dune/stuff/common/profiler.hh>
#include <dune/stuff/common/configuration.hh>

#include <dune/gdt/spaces/continuouslagrange.hh>
#include <dune/gdt/discretefunction/default.hh>
#include <dune/gdt/operators/elliptic-cg.hh>
#include <dune/gdt/functionals/l2.hh>
#include <dune/gdt/spaces/constraints.hh>
#include <dune/gdt/assembler/system.hh>
#include <dune/gdt/operators/projections.hh>

#include <limits>
#include <sstream>
#include <string>

#include "fem_solver.hh"

namespace Dune {
namespace Multiscale {

Elliptic_FEM_Solver::Elliptic_FEM_Solver()
  : grid_(make_fine_grid(nullptr, false))
  , grid_provider_(*grid_)
  , space_(CommonTraits::SpaceChooserType::PartViewType::create(*grid_, CommonTraits::st_gdt_grid_level))
  , solution_(space_, "fem_solution")
{
}

CommonTraits::ConstDiscreteFunctionType &Elliptic_FEM_Solver::solve()
{
  apply(solution_);
  return solution_;
}

void Elliptic_FEM_Solver::apply(CommonTraits::DiscreteFunctionType& solution) const {
  DSC_LOG_DEBUG_0 << "Solving linear problem with standard FEM" << std::endl;

  DSC_PROFILER.startTiming("fem.apply");

  typedef CommonTraits::GridViewType GridViewType;

  const auto& boundary_info = Problem::getModelData()->boundaryInfo();
  const auto& neumann = Problem::getNeumannData();
  const auto& dirichlet = Problem::getDirichletData();
  const auto& space = space_;

  typedef GDT::Operators::EllipticCG<Problem::DiffusionBase, CommonTraits::LinearOperatorType,
                                     CommonTraits::SpaceType> EllipticOperatorType;
  CommonTraits::LinearOperatorType system_matrix(space.mapper().size(), space.mapper().size(),
                                                 EllipticOperatorType::pattern(space));
  CommonTraits::GdtVectorType rhs_vector(space.mapper().size());
  auto& solution_vector = solution.vector();
  // left hand side (elliptic operator)
  EllipticOperatorType elliptic_operator(*Problem::getDiffusion(), system_matrix, space);
  // right hand side
  GDT::Functionals::L2Volume<Problem::SourceType, CommonTraits::GdtVectorType, CommonTraits::SpaceType>
  force_functional(*DMP::getSource(), rhs_vector, space);
  GDT::Functionals::L2Face<Problem::NeumannDataBase, CommonTraits::GdtVectorType, CommonTraits::SpaceType>
  neumann_functional(*neumann, rhs_vector, space);
  // dirichlet boundary values
  CommonTraits::DiscreteFunctionType dirichlet_projection(space);
  GDT::Operators::DirichletProjectionLocalizable<GridViewType, Problem::DirichletDataBase,
                                                 CommonTraits::DiscreteFunctionType>
  dirichlet_projection_operator(space.grid_view(), boundary_info, *dirichlet, dirichlet_projection);
  DSC_PROFILER.startTiming("fem.assemble");
  // now assemble everything in one grid walk
  GDT::SystemAssembler<CommonTraits::SpaceType> system_assembler(space);
  system_assembler.add(elliptic_operator);
  system_assembler.add(force_functional);
  system_assembler.add(neumann_functional, new DSG::ApplyOn::NeumannIntersections<GridViewType>(boundary_info));
  system_assembler.add(dirichlet_projection_operator, new DSG::ApplyOn::BoundaryEntities<GridViewType>());
  system_assembler.tbb_assemble();
  DSC_PROFILER.stopTiming("fem.assemble");

  DSC_PROFILER.startTiming("fem.constraints");
  // substract the operators action on the dirichlet values, since we assemble in H^1 but solve in H^1_0
  CommonTraits::GdtVectorType tmp(space.mapper().size());
  system_matrix.mv(dirichlet_projection.vector(), tmp);
  rhs_vector -= tmp;
  // apply the dirichlet zero constraints to restrict the system to H^1_0
  GDT::Spaces::Constraints::Dirichlet<typename GridViewType::Intersection, CommonTraits::RangeFieldType> dirichlet_constraints(
      boundary_info, space.mapper().maxNumDofs(), space.mapper().maxNumDofs());
  system_assembler.add(dirichlet_constraints, system_matrix /*, new GDT::ApplyOn::BoundaryEntities< GridViewType >()*/);
  system_assembler.add(dirichlet_constraints, rhs_vector /*, new GDT::ApplyOn::BoundaryEntities< GridViewType >()*/);
  system_assembler.assemble();
  DSC_PROFILER.stopTiming("fem.constraints");

  // solve the system
  DSC_PROFILER.startTiming("fem.solve");
  const Stuff::LA::Solver<CommonTraits::LinearOperatorType, typename CommonTraits::SpaceType::CommunicatorType>
  linear_solver(system_matrix, space.communicator());
  auto linear_solver_options = linear_solver.options("bicgstab.amg.ilu0");
  linear_solver_options.set("max_iter", "5000", true);
  linear_solver_options.set("precision", "1e-8", true);
  linear_solver_options.set("post_check_solves_system", "0", true);
  linear_solver_options.set("preconditioner.anisotropy_dim", CommonTraits::world_dim, true);
  linear_solver_options.set("preconditioner.isotropy_dim", CommonTraits::world_dim, true);
  linear_solver_options.set("smoother.iterations", "1", true);
  linear_solver_options.set("smoother.relaxation_factor", "0.5", true);
  linear_solver_options.set("criterion.max_level", "100", true);
  linear_solver_options.set("criterion.coarse_target", "1000", true);
  linear_solver_options.set("criterion.min_coarse_rate", "1.2", true);
  linear_solver_options.set("criterion.prolong_damp", "1.6", true);
  linear_solver_options.set("criterion.anisotropy_dim", CommonTraits::world_dim, true);
  linear_solver_options.set("criterion.verbose", "1", true);
  linear_solver_options.set("smoother.verbose", "1", true);

  linear_solver.apply(rhs_vector, solution_vector, linear_solver_options);
  // add the dirichlet shift to obtain the solution in H^1
  DSC_PROFILER.stopTiming("fem.solve");

  solution_vector += dirichlet_projection.vector();

  DSC_PROFILER.stopTiming("fem.apply");
}

} // namespace Multiscale
}
<commit_msg>fix fem build<commit_after>#include <config.h>

#include <dune/common/exceptions.hh>
#include <dune/common/timer.hh>
#include <dune/multiscale/msfem/coarse_rhs_functional.hh>
#include <dune/multiscale/common/traits.hh>
#include <dune/multiscale/common/grid_creation.hh>
#include <dune/multiscale/problems/selector.hh>
#include <dune/stuff/common/logging.hh>
#include <dune/stuff/common/profiler.hh>
#include <dune/stuff/common/configuration.hh>

#include <dune/gdt/spaces/continuouslagrange.hh>
#include <dune/gdt/discretefunction/default.hh>
#include <dune/gdt/operators/elliptic-cg.hh>
#include <dune/gdt/functionals/l2.hh>
#include <dune/gdt/spaces/constraints.hh>
#include <dune/gdt/assembler/system.hh>
#include <dune/gdt/operators/projections.hh>

#include <limits>
#include <sstream>
#include <string>

#include "fem_solver.hh"

namespace Dune {
namespace Multiscale {

Elliptic_FEM_Solver::Elliptic_FEM_Solver()
  : grid_(make_fine_grid(nullptr, false))
  , space_(CommonTraits::SpaceChooserType::PartViewType::create(*grid_, CommonTraits::st_gdt_grid_level))
  , solution_(space_, "fem_solution")
{
}

CommonTraits::ConstDiscreteFunctionType &Elliptic_FEM_Solver::solve()
{
  apply(solution_);
  return solution_;
}

void Elliptic_FEM_Solver::apply(CommonTraits::DiscreteFunctionType& solution) const {
  DSC_LOG_DEBUG_0 << "Solving linear problem with standard FEM" << std::endl;

  DSC_PROFILER.startTiming("fem.apply");

  typedef CommonTraits::GridViewType GridViewType;

  const auto& boundary_info = Problem::getModelData()->boundaryInfo();
  const auto& neumann = Problem::getNeumannData();
  const auto& dirichlet = Problem::getDirichletData();
  const auto& space = space_;

  typedef GDT::Operators::EllipticCG<Problem::DiffusionBase, CommonTraits::LinearOperatorType,
                                     CommonTraits::SpaceType> EllipticOperatorType;
  CommonTraits::LinearOperatorType system_matrix(space.mapper().size(), space.mapper().size(),
                                                 EllipticOperatorType::pattern(space));
  CommonTraits::GdtVectorType rhs_vector(space.mapper().size());
  auto& solution_vector = solution.vector();
  // left hand side (elliptic operator)
  EllipticOperatorType elliptic_operator(*Problem::getDiffusion(), system_matrix, space);
  // right hand side
  GDT::Functionals::L2Volume<Problem::SourceType, CommonTraits::GdtVectorType, CommonTraits::SpaceType>
  force_functional(*DMP::getSource(), rhs_vector, space);
  GDT::Functionals::L2Face<Problem::NeumannDataBase, CommonTraits::GdtVectorType, CommonTraits::SpaceType>
  neumann_functional(*neumann, rhs_vector, space);
  // dirichlet boundary values
  CommonTraits::DiscreteFunctionType dirichlet_projection(space);
  GDT::Operators::DirichletProjectionLocalizable<GridViewType, Problem::DirichletDataBase,
                                                 CommonTraits::DiscreteFunctionType>
  dirichlet_projection_operator(space.grid_view(), boundary_info, *dirichlet, dirichlet_projection);
  DSC_PROFILER.startTiming("fem.assemble");
  // now assemble everything in one grid walk
  GDT::SystemAssembler<CommonTraits::SpaceType> system_assembler(space);
  system_assembler.add(elliptic_operator);
  system_assembler.add(force_functional);
  system_assembler.add(neumann_functional, new DSG::ApplyOn::NeumannIntersections<GridViewType>(boundary_info));
  system_assembler.add(dirichlet_projection_operator, new DSG::ApplyOn::BoundaryEntities<GridViewType>());
  system_assembler.tbb_assemble();
  DSC_PROFILER.stopTiming("fem.assemble");

  DSC_PROFILER.startTiming("fem.constraints");
  // substract the operators action on the dirichlet values, since we assemble in H^1 but solve in H^1_0
  CommonTraits::GdtVectorType tmp(space.mapper().size());
  system_matrix.mv(dirichlet_projection.vector(), tmp);
  rhs_vector -= tmp;
  // apply the dirichlet zero constraints to restrict the system to H^1_0
  GDT::Spaces::Constraints::Dirichlet<typename GridViewType::Intersection, CommonTraits::RangeFieldType> dirichlet_constraints(
      boundary_info, space.mapper().maxNumDofs(), space.mapper().maxNumDofs());
  system_assembler.add(dirichlet_constraints, system_matrix /*, new GDT::ApplyOn::BoundaryEntities< GridViewType >()*/);
  system_assembler.add(dirichlet_constraints, rhs_vector /*, new GDT::ApplyOn::BoundaryEntities< GridViewType >()*/);
  system_assembler.assemble();
  DSC_PROFILER.stopTiming("fem.constraints");

  // solve the system
  DSC_PROFILER.startTiming("fem.solve");
  const Stuff::LA::Solver<CommonTraits::LinearOperatorType, typename CommonTraits::SpaceType::CommunicatorType>
  linear_solver(system_matrix, space.communicator());
  auto linear_solver_options = linear_solver.options("bicgstab.amg.ilu0");
  linear_solver_options.set("max_iter", "5000", true);
  linear_solver_options.set("precision", "1e-8", true);
  linear_solver_options.set("post_check_solves_system", "0", true);
  linear_solver_options.set("preconditioner.anisotropy_dim", CommonTraits::world_dim, true);
  linear_solver_options.set("preconditioner.isotropy_dim", CommonTraits::world_dim, true);
  linear_solver_options.set("smoother.iterations", "1", true);
  linear_solver_options.set("smoother.relaxation_factor", "0.5", true);
  linear_solver_options.set("criterion.max_level", "100", true);
  linear_solver_options.set("criterion.coarse_target", "1000", true);
  linear_solver_options.set("criterion.min_coarse_rate", "1.2", true);
  linear_solver_options.set("criterion.prolong_damp", "1.6", true);
  linear_solver_options.set("criterion.anisotropy_dim", CommonTraits::world_dim, true);
  linear_solver_options.set("criterion.verbose", "1", true);
  linear_solver_options.set("smoother.verbose", "1", true);

  linear_solver.apply(rhs_vector, solution_vector, linear_solver_options);
  // add the dirichlet shift to obtain the solution in H^1
  DSC_PROFILER.stopTiming("fem.solve");

  solution_vector += dirichlet_projection.vector();

  DSC_PROFILER.stopTiming("fem.apply");
}

} // namespace Multiscale
}
<|endoftext|>


<commit_before>#ifndef DUNE_STUFF_COMMON_PARAMETER_TREE_HH
#define DUNE_STUFF_COMMON_PARAMETER_TREE_HH

#ifdef HAVE_CMAKE_CONFIG
  #include "cmake_config.h"
#else
  #include "config.h"
#endif // ifdef HAVE_CMAKE_CONFIG

#include <cstring>
#include <sstream>
#include <vector>

#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/format.hpp>

#include <dune/common/exceptions.hh>
#include <dune/common/parametertreeparser.hh>

#include <dune/stuff/common/string.hh>

namespace Dune {
namespace Stuff {
namespace Common {

//! ParameterTree extension for nicer output
//! \todo This should go into dune-common.
class ExtendedParameterTree
  : public Dune::ParameterTree {
public:
  typedef Dune::ParameterTree BaseType;

  ExtendedParameterTree()
  {}

  ExtendedParameterTree(int argc, char** argv, std::string filename)
    : BaseType(init(argc, argv, filename))
  {}

  ExtendedParameterTree(const Dune::ParameterTree& other)
    : BaseType(other)
  {}

  ExtendedParameterTree& operator=(const Dune::ParameterTree& other)
  {
    if (this != &other) {
      Dune::ParameterTree::operator=(other);
    }
    return *this;
  } // ExtendedParameterTree& operator=(const Dune::ParameterTree& other)

  void report(std::ostream& stream = std::cout, const std::string& prefix = "") const
  {
    reportAsSub(stream, prefix, "");
  } // void report(std::ostream& stream = std::cout, const std::string& prefix = "") const

  std::string reportString(const std::string& prefix = "") const
  {
    std::stringstream stream;
    report(stream, prefix);
    return stream.str();
  } // std::stringstream reportString(const std::string& prefix = "") const

  bool hasVector(const std::string& vector) const
  {
    if (hasKey(vector)) {
      const std::string str = get< std::string >(vector, "default_value");
      if (Dune::Stuff::Common::String::equal(str.substr(0, 1), "[")
          && Dune::Stuff::Common::String::equal(str.substr(str.size() - 1, 1), "]"))
        return true;
    }
    return false;
  } // bool hasVector(const std::string& vector) const

  template< class T >
  std::vector< T > getVector(const std::string& key, const T def, const unsigned int minSize = 1) const
  {
    std::vector< T > ret;
    if (!hasKey(key))
      ret = std::vector< T >(minSize, def);
    else {
      const std::string str = BaseType::get< std::string >(key, "default_value");
      // the dune parametertree strips any leading and trailing whitespace
      // so we can be sure that the first and last have to be the brackets [] if this is a vector
      if (Dune::Stuff::Common::String::equal(str.substr(0, 1), "[")
          && Dune::Stuff::Common::String::equal(str.substr(str.size() - 1, 1), "]")) {
        const std::vector< std::string > tokens = Dune::Stuff::Common::tokenize< std::string >(str.substr(1, str.size() - 2), ";");
        for (unsigned int i = 0; i < tokens.size(); ++i)
          ret.push_back(Dune::Stuff::Common::fromString< T >(boost::algorithm::trim_copy(tokens[i])));
        for (unsigned int i = ret.size(); i < minSize; ++i)
          ret.push_back(def);
      } else if (Dune::Stuff::Common::String::equal(str.substr(0, 1), "[")
                 || Dune::Stuff::Common::String::equal(str.substr(str.size() - 1, 1), "]")) {
          DUNE_THROW(Dune::InvalidStateException, "Vectors have to be of the form '[entry_0; entry_1; ... ]'!");
      } else {
        ret = std::vector< T >(minSize, Dune::Stuff::Common::fromString< T >(boost::algorithm::trim_copy(str)));
      }
    }
    return ret;
  } // std::vector< T > getVector(const std::string& key, const T def) const

  /**
    \brief      Fills a Dune::ParameterTree given a parameter file or command line arguments.
    \param[in]  argc
                From \c main()
    \param[in]  argv
                From \c main()
    \param[out] paramTree
                The Dune::ParameterTree that is to be filled.
    **/
  static ParameterTree init(int argc, char** argv, std::string filename)
  {
    Dune::ParameterTree paramTree;
    if (argc == 1) {
      Dune::ParameterTreeParser::readINITree(filename, paramTree);
    } else if (argc == 2) {
      Dune::ParameterTreeParser::readINITree(argv[1], paramTree);
    } else {
      Dune::ParameterTreeParser::readOptions(argc, argv, paramTree);
    }
    if (paramTree.hasKey("paramfile")) {
      Dune::ParameterTreeParser::readINITree(paramTree.get< std::string >("paramfile"), paramTree, false);
    }
    return paramTree;
  } // static ExtendedParameterTree init(...)

private:
  void reportAsSub(std::ostream& stream, const std::string& prefix, const std::string& subPath) const
  {
    for (auto pair : values)
      stream << prefix << pair.first << " = " << pair.second << std::endl;
//      stream << prefix << pair.first << " = \"" << pair.second << "\"" << std::endl;
    for (auto pair : subs) {
      ExtendedParameterTree subTree(pair.second);
      if (subTree.getValueKeys().size())
        stream << prefix << "[ " << subPath << pair.first << " ]" << std::endl;
      subTree.reportAsSub(stream, prefix, subPath + pair.first + ".");
    }
  } // void report(std::ostream& stream = std::cout, const std::string& prefix = "") const
}; // class ExtendedParameterTree

} // namespace Common
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_COMMON_PARAMETER_TREE_HH
<commit_msg>[common.parameter.tree] added sub()<commit_after>#ifndef DUNE_STUFF_COMMON_PARAMETER_TREE_HH
#define DUNE_STUFF_COMMON_PARAMETER_TREE_HH

#ifdef HAVE_CMAKE_CONFIG
  #include "cmake_config.h"
#else
  #include "config.h"
#endif // ifdef HAVE_CMAKE_CONFIG

#include <cstring>
#include <sstream>
#include <vector>

#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/format.hpp>

#include <dune/common/exceptions.hh>
#include <dune/common/parametertreeparser.hh>

#include <dune/stuff/common/string.hh>

namespace Dune {
namespace Stuff {
namespace Common {

//! ParameterTree extension for nicer output
//! \todo This should go into dune-common.
class ExtendedParameterTree
  : public Dune::ParameterTree {
public:
  typedef Dune::ParameterTree BaseType;

  ExtendedParameterTree()
  {}

  ExtendedParameterTree(int argc, char** argv, std::string filename)
    : BaseType(init(argc, argv, filename))
  {}

  ExtendedParameterTree(const Dune::ParameterTree& other)
    : BaseType(other)
  {}

  ExtendedParameterTree& operator=(const Dune::ParameterTree& other)
  {
    if (this != &other) {
      Dune::ParameterTree::operator=(other);
    }
    return *this;
  } // ExtendedParameterTree& operator=(const Dune::ParameterTree& other)

  ExtendedParameterTree sub(const std::string& sub) const
  {
    return ExtendedParameterTree(BaseType::sub(sub));
  }

  void report(std::ostream& stream = std::cout, const std::string& prefix = "") const
  {
    reportAsSub(stream, prefix, "");
  } // void report(std::ostream& stream = std::cout, const std::string& prefix = "") const

  std::string reportString(const std::string& prefix = "") const
  {
    std::stringstream stream;
    report(stream, prefix);
    return stream.str();
  } // std::stringstream reportString(const std::string& prefix = "") const

  bool hasVector(const std::string& vector) const
  {
    if (hasKey(vector)) {
      const std::string str = get< std::string >(vector, "default_value");
      if (Dune::Stuff::Common::String::equal(str.substr(0, 1), "[")
          && Dune::Stuff::Common::String::equal(str.substr(str.size() - 1, 1), "]"))
        return true;
    }
    return false;
  } // bool hasVector(const std::string& vector) const

  template< class T >
  std::vector< T > getVector(const std::string& key, const T def, const unsigned int minSize = 1) const
  {
    std::vector< T > ret;
    if (!hasKey(key))
      ret = std::vector< T >(minSize, def);
    else {
      const std::string str = BaseType::get< std::string >(key, "default_value");
      // the dune parametertree strips any leading and trailing whitespace
      // so we can be sure that the first and last have to be the brackets [] if this is a vector
      if (Dune::Stuff::Common::String::equal(str.substr(0, 1), "[")
          && Dune::Stuff::Common::String::equal(str.substr(str.size() - 1, 1), "]")) {
        const std::vector< std::string > tokens = Dune::Stuff::Common::tokenize< std::string >(str.substr(1, str.size() - 2), ";");
        for (unsigned int i = 0; i < tokens.size(); ++i)
          ret.push_back(Dune::Stuff::Common::fromString< T >(boost::algorithm::trim_copy(tokens[i])));
        for (unsigned int i = ret.size(); i < minSize; ++i)
          ret.push_back(def);
      } else if (Dune::Stuff::Common::String::equal(str.substr(0, 1), "[")
                 || Dune::Stuff::Common::String::equal(str.substr(str.size() - 1, 1), "]")) {
          DUNE_THROW(Dune::InvalidStateException, "Vectors have to be of the form '[entry_0; entry_1; ... ]'!");
      } else {
        ret = std::vector< T >(minSize, Dune::Stuff::Common::fromString< T >(boost::algorithm::trim_copy(str)));
      }
    }
    return ret;
  } // std::vector< T > getVector(const std::string& key, const T def) const

  /**
    \brief      Fills a Dune::ParameterTree given a parameter file or command line arguments.
    \param[in]  argc
                From \c main()
    \param[in]  argv
                From \c main()
    \param[out] paramTree
                The Dune::ParameterTree that is to be filled.
    **/
  static ParameterTree init(int argc, char** argv, std::string filename)
  {
    Dune::ParameterTree paramTree;
    if (argc == 1) {
      Dune::ParameterTreeParser::readINITree(filename, paramTree);
    } else if (argc == 2) {
      Dune::ParameterTreeParser::readINITree(argv[1], paramTree);
    } else {
      Dune::ParameterTreeParser::readOptions(argc, argv, paramTree);
    }
    if (paramTree.hasKey("paramfile")) {
      Dune::ParameterTreeParser::readINITree(paramTree.get< std::string >("paramfile"), paramTree, false);
    }
    return paramTree;
  } // static ExtendedParameterTree init(...)

private:
  void reportAsSub(std::ostream& stream, const std::string& prefix, const std::string& subPath) const
  {
    for (auto pair : values)
      stream << prefix << pair.first << " = " << pair.second << std::endl;
//      stream << prefix << pair.first << " = \"" << pair.second << "\"" << std::endl;
    for (auto pair : subs) {
      ExtendedParameterTree subTree(pair.second);
      if (subTree.getValueKeys().size())
        stream << prefix << "[ " << subPath << pair.first << " ]" << std::endl;
      subTree.reportAsSub(stream, prefix, subPath + pair.first + ".");
    }
  } // void report(std::ostream& stream = std::cout, const std::string& prefix = "") const
}; // class ExtendedParameterTree

} // namespace Common
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_COMMON_PARAMETER_TREE_HH
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: pathsettings.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: vg $ $Date: 2006-09-26 14:08:38 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef __FRAMEWORK_SERVICES_PATHSETTINGS_HXX_
#define __FRAMEWORK_SERVICES_PATHSETTINGS_HXX_

//_________________________________________________________________________________________________________________
//  my own includes
//_________________________________________________________________________________________________________________

#ifndef __FRAMEWORK_THREADHELP_THREADHELPBASE_HXX_
#include <threadhelp/threadhelpbase.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_GENERIC_HXX_
#include <macros/generic.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_XINTERFACE_HXX_
#include <macros/xinterface.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_XTYPEPROVIDER_HXX_
#include <macros/xtypeprovider.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_XSERVICEINFO_HXX_
#include <macros/xserviceinfo.hxx>
#endif

#ifndef __FRAMEWORK_STDTYPES_H_
#include <stdtypes.h>
#endif

#ifndef __FRAMEWORK_PROPERTIES_H_
#include <properties.h>
#endif

#ifndef __FRAMEWORK_STDTYPES_H_
#include <stdtypes.h>
#endif

//_________________________________________________________________________________________________________________
//  interface includes
//_________________________________________________________________________________________________________________

#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XTYPEPROVIDER_HPP_
#include <com/sun/star/lang/XTypeProvider.hpp>
#endif

#ifndef _COM_SUN_STAR_UTIL_XSTRINGSUBSTITUTION_HPP_
#include <com/sun/star/util/XStringSubstitution.hpp>
#endif

#ifndef _COM_SUN_STAR_UTIL_XCHANGESLISTENER_HPP_
#include <com/sun/star/util/XChangesListener.hpp>
#endif

#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif

//_________________________________________________________________________________________________________________
//  other includes
//_________________________________________________________________________________________________________________

#ifndef _CPPUHELPER_PROPSHLP_HXX
#include <cppuhelper/propshlp.hxx>
#endif

#ifndef _CPPUHELPER_INTERFACECONTAINER_HXX_
#include <cppuhelper/interfacecontainer.hxx>
#endif

#ifndef _CPPUHELPER_WEAK_HXX_
#include <cppuhelper/weak.hxx>
#endif

#ifndef _UTL_CONFIGITEM_HXX_
#include <unotools/configitem.hxx>
#endif

#ifndef _COMPHELPER_SEQUENCEASVECTOR_HXX_
#include <comphelper/sequenceasvector.hxx>
#endif

/* enable it if you whish to migrate old user settings (using the old cfg schema) on demand ....
   disable it in case only the new schema must be used.
 */
#define MIGRATE_OLD_USER_PATHES

namespace framework
{

class PathSettings : public  css::lang::XTypeProvider             ,
                     public  css::lang::XServiceInfo              ,
                     public  css::util::XChangesListener          , // => XEventListener
                     // base classes
                     // Order is neccessary for right initialization!
                     private ThreadHelpBase                       ,
                     public  ::cppu::OBroadcastHelper             ,
                     public  ::cppu::OPropertySetHelper           , // => XPropertySet / XFastPropertySet / XMultiPropertySet
                     public  ::cppu::OWeakObject                    // => XWeak, XInterface
{
    struct PathInfo
    {
        public:

            PathInfo()
                : sPathName     ()
                , lInternalPaths()
                , lUserPaths    ()
                , sWritePath    ()
                , bIsSinglePath (sal_False)
                , bIsReadonly   (sal_False)
            {}

            PathInfo(const PathInfo& rCopy)
            {
                takeOver(rCopy);
            }

            void takeOver(const PathInfo& rCopy)
            {
                sPathName      = rCopy.sPathName;
                lInternalPaths = rCopy.lInternalPaths;
                lUserPaths     = rCopy.lUserPaths;
                sWritePath     = rCopy.sWritePath;
                bIsSinglePath  = rCopy.bIsSinglePath;
                bIsReadonly    = rCopy.bIsReadonly;
            }

            /// an internal name describing this path
            ::rtl::OUString sPathName;

            /// contains all paths, which are used internaly - but are not visible for the user.
            OUStringList lInternalPaths;

            /// contains all paths configured by the user
            OUStringList lUserPaths;

            /// this special path is used to generate feature depending content there
            ::rtl::OUString sWritePath;

            /// indicates real single pathes, which uses WritePath property only
            sal_Bool bIsSinglePath;

            /// simple handling of finalized/mandatory states ... => we know one state READONLY only .-)
            sal_Bool bIsReadonly;
    };

    typedef BaseHash< PathSettings::PathInfo > PathHash;

    enum EChangeOp
    {
        E_UNDEFINED,
        E_ADDED,
        E_CHANGED,
        E_REMOVED
    };

    // ______________________________________
    // member

    private:

        /** reference to factory, which has create this instance. */
        css::uno::Reference< css::lang::XMultiServiceFactory > m_xSMGR;

        /** list of all path variables and her corresponding values. */
        PathSettings::PathHash m_lPaths;

        /** describes all properties available on our interface.
            Will be generated on demand based on our path list m_lPaths. */
        css::uno::Sequence< css::beans::Property > m_lPropDesc;

        /** helper needed to (re-)substitute all internal save path values. */
        css::uno::Reference< css::util::XStringSubstitution > m_xSubstitution;

        /** provides access to the old configuration schema (which will be migrated on demand). */
        css::uno::Reference< css::container::XNameAccess > m_xCfgOld;

        /** provides access to the new configuration schema. */
        css::uno::Reference< css::container::XNameAccess > m_xCfgNew;

        ::cppu::OPropertyArrayHelper* m_pPropHelp;

    // ___________________________________________
    // interface

    public:

        /** initialize a new instance of this class.
            Attention: It's neccessary for right function of this class, that the order of base
            classes is the right one. Because we transfer information from one base to another
            during this ctor runs! */
        PathSettings(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR);

        /** free all used ressources ... if it was not already done. */
        virtual ~PathSettings();

        /** declaration of XInterface, XTypeProvider, XServiceInfo */
        FWK_DECLARE_XINTERFACE
        FWK_DECLARE_XTYPEPROVIDER
        DECLARE_XSERVICEINFO

        // css::util::XChangesListener
        virtual void SAL_CALL changesOccurred(const css::util::ChangesEvent& aEvent) throw (css::uno::RuntimeException);

        // css::lang::XEventListener
        virtual void SAL_CALL disposing(const css::lang::EventObject& aSource)
            throw(css::uno::RuntimeException);

        using ::cppu::OPropertySetHelper::disposing;

    // ___________________________________________
    // helper

    private:

        /** read all configured paths and create all needed internal structures. */
        void impl_readAll();

        /** read a path info using the old cfg schema.
            This is needed for "migration on demand" reasons only.
            Can be removed for next major release .-) */
        OUStringList impl_readOldFormat(const ::rtl::OUString& sPath);

        /** read a path info using the new cfg schema. */
        PathSettings::PathInfo impl_readNewFormat(const ::rtl::OUString& sPath);

        /** filter "real user defined paths" from the old configuration schema
            and set it as UserPaths on the new schema.
            Can be removed with new major release ... */
        #ifdef MIGRATE_OLD_USER_PATHES
        void impl_mergeOldUserPaths(      PathSettings::PathInfo& rPath,
                                     const OUStringList&           lOld );
        #endif

        /** reload one path directly from the new configuration schema (because
            it was updated by any external code) */
        PathSettings::EChangeOp impl_updatePath(const ::rtl::OUString& sPath          ,
                                                      sal_Bool         bNotifyListener);

        /** replace all might existing placeholder variables inside the given path ...
            or check if the given path value uses paths, which can be replaced with predefined
            placeholder variables ...
         */
        void impl_subst(      OUStringList&                                          lVals   ,
                        const css::uno::Reference< css::util::XStringSubstitution >& xSubst  ,
                              sal_Bool                                               bReSubst);

        void impl_subst(PathSettings::PathInfo& aPath   ,
                        sal_Bool                bReSubst);

        /** converts our new string list schema to the old ";" seperated schema ... */
        ::rtl::OUString impl_convertPath2OldStyle(const PathSettings::PathInfo& rPath        ) const;
        OUStringList    impl_convertOldStyle2Path(const ::rtl::OUString&        sOldStylePath) const;

        /** remove still known paths from the given lList argument.
            So real user defined paths can be extracted from the list of
            fix internal paths !
         */
        void impl_purgeKnownPaths(const PathSettings::PathInfo& rPath,
                                         OUStringList&           lList);

        /** rebuild the member m_lPropDesc using the path list m_lPaths. */
        void impl_rebuildPropertyDescriptor();

        /** provides direct access to the list of path values
            using it's internal property id.
         */
        css::uno::Any impl_getPathValue(      sal_Int32      nID ) const;
        void          impl_setPathValue(      sal_Int32      nID ,
                                        const css::uno::Any& aVal);

        /** check the given handle and return the corresponding PathInfo reference.
            These reference can be used then directly to manipulate these path. */
              PathSettings::PathInfo* impl_getPathAccess     (sal_Int32 nHandle);
        const PathSettings::PathInfo* impl_getPathAccessConst(sal_Int32 nHandle) const;

        /** it checks, if the given path value seams to be a valid URL or system path. */
        sal_Bool impl_isValidPath(const ::rtl::OUString& sPath) const;
        sal_Bool impl_isValidPath(const OUStringList&    lPath) const;

        void impl_storePath(const PathSettings::PathInfo& aPath);

        css::uno::Sequence< sal_Int32 > impl_mapPathName2IDList(const ::rtl::OUString& sPath);

        void impl_notifyPropListener(      PathSettings::EChangeOp eOp     ,
                                           const ::rtl::OUString&        sPath   ,
                                           const PathSettings::PathInfo* pPathOld,
                                           const PathSettings::PathInfo* pPathNew);

        //  OPropertySetHelper
        virtual sal_Bool                                            SAL_CALL convertFastPropertyValue        (       css::uno::Any&  aConvertedValue ,
                                                                                css::uno::Any&  aOldValue       ,
                                                                                sal_Int32       nHandle         ,
                                                                                const css::uno::Any&  aValue          ) throw(css::lang::IllegalArgumentException);
        virtual void                                                SAL_CALL setFastPropertyValue_NoBroadcast(       sal_Int32       nHandle         ,
                                                                                const css::uno::Any&  aValue          ) throw(css::uno::Exception);
        using cppu::OPropertySetHelper::getFastPropertyValue;
        virtual void                                                SAL_CALL getFastPropertyValue            (       css::uno::Any&  aValue          ,
                                                                                sal_Int32       nHandle         ) const;
        virtual ::cppu::IPropertyArrayHelper&                       SAL_CALL getInfoHelper                   (                                       );
        virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo              (                                       ) throw(::com::sun::star::uno::RuntimeException);

        /** factory methods to guarantee right (but on demand) initialized members ... */
        css::uno::Reference< css::util::XStringSubstitution > fa_getSubstitution();
        css::uno::Reference< css::container::XNameAccess >    fa_getCfgOld();
        css::uno::Reference< css::container::XNameAccess >    fa_getCfgNew();
};

} // namespace framework

#endif // __FRAMEWORK_SERVICES_PATHSETTINGS_HXX_
<commit_msg>INTEGRATION: CWS fwk70 (1.7.144); FILE MERGED 2007/07/27 14:01:37 as 1.7.144.1: #i80116# repair old-path-style handling<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: pathsettings.hxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: hr $ $Date: 2007-08-02 13:30:13 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef __FRAMEWORK_SERVICES_PATHSETTINGS_HXX_
#define __FRAMEWORK_SERVICES_PATHSETTINGS_HXX_

//_________________________________________________________________________________________________________________
//  my own includes
//_________________________________________________________________________________________________________________

#ifndef __FRAMEWORK_THREADHELP_THREADHELPBASE_HXX_
#include <threadhelp/threadhelpbase.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_GENERIC_HXX_
#include <macros/generic.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_XINTERFACE_HXX_
#include <macros/xinterface.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_XTYPEPROVIDER_HXX_
#include <macros/xtypeprovider.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_XSERVICEINFO_HXX_
#include <macros/xserviceinfo.hxx>
#endif

#ifndef __FRAMEWORK_STDTYPES_H_
#include <stdtypes.h>
#endif

#ifndef __FRAMEWORK_PROPERTIES_H_
#include <properties.h>
#endif

#ifndef __FRAMEWORK_STDTYPES_H_
#include <stdtypes.h>
#endif

//_________________________________________________________________________________________________________________
//  interface includes
//_________________________________________________________________________________________________________________

#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XTYPEPROVIDER_HPP_
#include <com/sun/star/lang/XTypeProvider.hpp>
#endif

#ifndef _COM_SUN_STAR_UTIL_XSTRINGSUBSTITUTION_HPP_
#include <com/sun/star/util/XStringSubstitution.hpp>
#endif

#ifndef _COM_SUN_STAR_UTIL_XCHANGESLISTENER_HPP_
#include <com/sun/star/util/XChangesListener.hpp>
#endif

#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif

//_________________________________________________________________________________________________________________
//  other includes
//_________________________________________________________________________________________________________________

#ifndef _CPPUHELPER_PROPSHLP_HXX
#include <cppuhelper/propshlp.hxx>
#endif

#ifndef _CPPUHELPER_INTERFACECONTAINER_HXX_
#include <cppuhelper/interfacecontainer.hxx>
#endif

#ifndef _CPPUHELPER_WEAK_HXX_
#include <cppuhelper/weak.hxx>
#endif

#ifndef _UTL_CONFIGITEM_HXX_
#include <unotools/configitem.hxx>
#endif

#ifndef _COMPHELPER_SEQUENCEASVECTOR_HXX_
#include <comphelper/sequenceasvector.hxx>
#endif

/* enable it if you whish to migrate old user settings (using the old cfg schema) on demand ....
   disable it in case only the new schema must be used.
 */
#define MIGRATE_OLD_USER_PATHES

namespace framework
{

class PathSettings : public  css::lang::XTypeProvider             ,
                     public  css::lang::XServiceInfo              ,
                     public  css::util::XChangesListener          , // => XEventListener
                     // base classes
                     // Order is neccessary for right initialization!
                     private ThreadHelpBase                       ,
                     public  ::cppu::OBroadcastHelper             ,
                     public  ::cppu::OPropertySetHelper           , // => XPropertySet / XFastPropertySet / XMultiPropertySet
                     public  ::cppu::OWeakObject                    // => XWeak, XInterface
{
    struct PathInfo
    {
        public:

            PathInfo()
                : sPathName     ()
                , lInternalPaths()
                , lUserPaths    ()
                , sWritePath    ()
                , bIsSinglePath (sal_False)
                , bIsReadonly   (sal_False)
            {}

            PathInfo(const PathInfo& rCopy)
            {
                takeOver(rCopy);
            }

            void takeOver(const PathInfo& rCopy)
            {
                sPathName      = rCopy.sPathName;
                lInternalPaths = rCopy.lInternalPaths;
                lUserPaths     = rCopy.lUserPaths;
                sWritePath     = rCopy.sWritePath;
                bIsSinglePath  = rCopy.bIsSinglePath;
                bIsReadonly    = rCopy.bIsReadonly;
            }

            /// an internal name describing this path
            ::rtl::OUString sPathName;

            /// contains all paths, which are used internaly - but are not visible for the user.
            OUStringList lInternalPaths;

            /// contains all paths configured by the user
            OUStringList lUserPaths;

            /// this special path is used to generate feature depending content there
            ::rtl::OUString sWritePath;

            /// indicates real single pathes, which uses WritePath property only
            sal_Bool bIsSinglePath;

            /// simple handling of finalized/mandatory states ... => we know one state READONLY only .-)
            sal_Bool bIsReadonly;
    };

    typedef BaseHash< PathSettings::PathInfo > PathHash;

    enum EChangeOp
    {
        E_UNDEFINED,
        E_ADDED,
        E_CHANGED,
        E_REMOVED
    };

    // ______________________________________
    // member

    private:

        /** reference to factory, which has create this instance. */
        css::uno::Reference< css::lang::XMultiServiceFactory > m_xSMGR;

        /** list of all path variables and her corresponding values. */
        PathSettings::PathHash m_lPaths;

        /** describes all properties available on our interface.
            Will be generated on demand based on our path list m_lPaths. */
        css::uno::Sequence< css::beans::Property > m_lPropDesc;

        /** helper needed to (re-)substitute all internal save path values. */
        css::uno::Reference< css::util::XStringSubstitution > m_xSubstitution;

        /** provides access to the old configuration schema (which will be migrated on demand). */
        css::uno::Reference< css::container::XNameAccess > m_xCfgOld;

        /** provides access to the new configuration schema. */
        css::uno::Reference< css::container::XNameAccess > m_xCfgNew;

        ::cppu::OPropertyArrayHelper* m_pPropHelp;

        ::sal_Bool m_bIgnoreEvents;

    // ___________________________________________
    // interface

    public:

        /** initialize a new instance of this class.
            Attention: It's neccessary for right function of this class, that the order of base
            classes is the right one. Because we transfer information from one base to another
            during this ctor runs! */
        PathSettings(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR);

        /** free all used ressources ... if it was not already done. */
        virtual ~PathSettings();

        /** declaration of XInterface, XTypeProvider, XServiceInfo */
        FWK_DECLARE_XINTERFACE
        FWK_DECLARE_XTYPEPROVIDER
        DECLARE_XSERVICEINFO

        // css::util::XChangesListener
        virtual void SAL_CALL changesOccurred(const css::util::ChangesEvent& aEvent) throw (css::uno::RuntimeException);

        // css::lang::XEventListener
        virtual void SAL_CALL disposing(const css::lang::EventObject& aSource)
            throw(css::uno::RuntimeException);

        using ::cppu::OPropertySetHelper::disposing;

    // ___________________________________________
    // helper

    private:

        /** read all configured paths and create all needed internal structures. */
        void impl_readAll();

        /** read a path info using the old cfg schema.
            This is needed for "migration on demand" reasons only.
            Can be removed for next major release .-) */
        OUStringList impl_readOldFormat(const ::rtl::OUString& sPath);

        /** read a path info using the new cfg schema. */
        PathSettings::PathInfo impl_readNewFormat(const ::rtl::OUString& sPath);

        /** filter "real user defined paths" from the old configuration schema
            and set it as UserPaths on the new schema.
            Can be removed with new major release ... */
        #ifdef MIGRATE_OLD_USER_PATHES
        void impl_mergeOldUserPaths(      PathSettings::PathInfo& rPath,
                                     const OUStringList&           lOld );
        #endif

        /** reload one path directly from the new configuration schema (because
            it was updated by any external code) */
        PathSettings::EChangeOp impl_updatePath(const ::rtl::OUString& sPath          ,
                                                      sal_Bool         bNotifyListener);

        /** replace all might existing placeholder variables inside the given path ...
            or check if the given path value uses paths, which can be replaced with predefined
            placeholder variables ...
         */
        void impl_subst(      OUStringList&                                          lVals   ,
                        const css::uno::Reference< css::util::XStringSubstitution >& xSubst  ,
                              sal_Bool                                               bReSubst);

        void impl_subst(PathSettings::PathInfo& aPath   ,
                        sal_Bool                bReSubst);

        /** converts our new string list schema to the old ";" seperated schema ... */
        ::rtl::OUString impl_convertPath2OldStyle(const PathSettings::PathInfo& rPath        ) const;
        OUStringList    impl_convertOldStyle2Path(const ::rtl::OUString&        sOldStylePath) const;

        /** remove still known paths from the given lList argument.
            So real user defined paths can be extracted from the list of
            fix internal paths !
         */
        void impl_purgeKnownPaths(const PathSettings::PathInfo& rPath,
                                         OUStringList&           lList);

        /** rebuild the member m_lPropDesc using the path list m_lPaths. */
        void impl_rebuildPropertyDescriptor();

        /** provides direct access to the list of path values
            using it's internal property id.
         */
        css::uno::Any impl_getPathValue(      sal_Int32      nID ) const;
        void          impl_setPathValue(      sal_Int32      nID ,
                                        const css::uno::Any& aVal);

        /** check the given handle and return the corresponding PathInfo reference.
            These reference can be used then directly to manipulate these path. */
              PathSettings::PathInfo* impl_getPathAccess     (sal_Int32 nHandle);
        const PathSettings::PathInfo* impl_getPathAccessConst(sal_Int32 nHandle) const;

        /** it checks, if the given path value seams to be a valid URL or system path. */
        sal_Bool impl_isValidPath(const ::rtl::OUString& sPath) const;
        sal_Bool impl_isValidPath(const OUStringList&    lPath) const;

        void impl_storePath(const PathSettings::PathInfo& aPath);

        css::uno::Sequence< sal_Int32 > impl_mapPathName2IDList(const ::rtl::OUString& sPath);

        void impl_notifyPropListener(      PathSettings::EChangeOp eOp     ,
                                           const ::rtl::OUString&        sPath   ,
                                           const PathSettings::PathInfo* pPathOld,
                                           const PathSettings::PathInfo* pPathNew);

        //  OPropertySetHelper
        virtual sal_Bool                                            SAL_CALL convertFastPropertyValue        (       css::uno::Any&  aConvertedValue ,
                                                                                css::uno::Any&  aOldValue       ,
                                                                                sal_Int32       nHandle         ,
                                                                                const css::uno::Any&  aValue          ) throw(css::lang::IllegalArgumentException);
        virtual void                                                SAL_CALL setFastPropertyValue_NoBroadcast(       sal_Int32       nHandle         ,
                                                                                const css::uno::Any&  aValue          ) throw(css::uno::Exception);
        using cppu::OPropertySetHelper::getFastPropertyValue;
        virtual void                                                SAL_CALL getFastPropertyValue            (       css::uno::Any&  aValue          ,
                                                                                sal_Int32       nHandle         ) const;
        virtual ::cppu::IPropertyArrayHelper&                       SAL_CALL getInfoHelper                   (                                       );
        virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo              (                                       ) throw(::com::sun::star::uno::RuntimeException);

        /** factory methods to guarantee right (but on demand) initialized members ... */
        css::uno::Reference< css::util::XStringSubstitution > fa_getSubstitution();
        css::uno::Reference< css::container::XNameAccess >    fa_getCfgOld();
        css::uno::Reference< css::container::XNameAccess >    fa_getCfgNew();
};

} // namespace framework

#endif // __FRAMEWORK_SERVICES_PATHSETTINGS_HXX_
<|endoftext|>