extern "C" void _lamexp_global_free_utils(void)
{
	//Delete temporary files
	const QString &tempFolder = lamexp_temp_folder2();
	if(!tempFolder.isEmpty())
	{
		bool success = false;
		for(int i = 0; i < 100; i++)
		{
			if(lamexp_clean_folder(tempFolder))
			{
				success = true;
				break;
			}
			lamexp_sleep(100);
		}
		if(!success)
		{
			lamexp_system_message(L"Sorry, LameXP was unable to clean up all temporary files. Some residual files in your TEMP directory may require manual deletion!", lamexp_beep_warning);
			lamexp_exec_shell(NULL, tempFolder, QString(), QString(), true);
		}
	}

	//Free memory
	LAMEXP_DELETE(g_lamexp_temp_folder.path);
	LAMEXP_DELETE(g_lamexp_app_icon.appIcon);
}
/*
 * Make a window blink (to draw user's attention)
 */
void lamexp_blink_window(QWidget *poWindow, unsigned int count, unsigned int delay)
{
	static QMutex blinkMutex;

	const double maxOpac = 1.0;
	const double minOpac = 0.3;
	const double delOpac = 0.1;

	if(!blinkMutex.tryLock())
	{
		qWarning("Blinking is already in progress, skipping!");
		return;
	}
	
	try
	{
		const int steps = static_cast<int>(ceil(maxOpac - minOpac) / delOpac);
		const int sleep = static_cast<int>(floor(static_cast<double>(delay) / static_cast<double>(steps)));
		const double opacity = poWindow->windowOpacity();
	
		for(unsigned int i = 0; i < count; i++)
		{
			for(double x = maxOpac; x >= minOpac; x -= delOpac)
			{
				poWindow->setWindowOpacity(x);
				QApplication::processEvents();
				lamexp_sleep(sleep);
			}

			for(double x = minOpac; x <= maxOpac; x += delOpac)
			{
				poWindow->setWindowOpacity(x);
				QApplication::processEvents();
				lamexp_sleep(sleep);
			}
		}

		poWindow->setWindowOpacity(opacity);
		QApplication::processEvents();
		blinkMutex.unlock();
	}
	catch(...)
	{
		blinkMutex.unlock();
		qWarning("Exception error while blinking!");
	}
}
/*
 * Initialize and launch process object
 */
bool AbstractTool::startProcess(QProcess &process, const QString &program, const QStringList &args)
{
    QMutexLocker lock(&s_mutex_startProcess);

    if(lamexp_current_file_time() <= s_lastLaunchTime)
    {
        lamexp_sleep(START_DELAY);
    }

    emit messageLogged(commandline2string(program, args) + "\n");
    lamexp_init_process(process, QFileInfo(program).absolutePath());

    process.start(program, args);

    if(process.waitForStarted())
    {
        if(s_jobObject)
        {
            if(!s_jobObject->addProcessToJob(&process))
            {
                qWarning("Failed to assign process to job object!");
            }
        }

        lamexp_change_process_priority(&process, -1);
        lock.unlock();

        if(m_firstLaunch)
        {
            emit statusUpdated(0);
            m_firstLaunch = false;
        }

        s_lastLaunchTime = lamexp_current_file_time() + START_DELAY_NANO;
        return true;
    }

    emit messageLogged("Process creation has failed :-(");
    QString errorMsg= process.errorString().trimmed();
    if(!errorMsg.isEmpty()) emit messageLogged(errorMsg);

    process.kill();
    process.waitForFinished(-1);

    s_lastLaunchTime = lamexp_current_file_time() + START_DELAY_NANO;
    return false;
}
QString SettingsModel::initDirectory(const QString &path) const
{
	if(path.isEmpty())
	{
		return QString();
	}

	if(!QDir(path).exists())
	{
		for(int i = 0; i < 32; i++)
		{
			if(QDir(path).mkpath(".")) break;
			lamexp_sleep(1);
		}
	}

	if(!QDir(path).exists())
	{
		return QString();
	}
	
	return QDir(path).canonicalPath();
}