<commit_before>#include "Task.h"
#include <ESP8266WiFi.h>
#include "ThingSpeak.h"
#include "Setting.h"

#define LED_FIELD           1
#define FAN_FIELD           2
#define WATER_PUMP_FIELD    3
#define COOLER_FIELD        4
#define HEATER_FIELD        5

#define VALUE_CONTROL_FOR_DEVICE(device, controlVal, maxValOfDevice )  analogWrite( device, map(controlVal, 0, maxValOfDevice, 0, 255) )

void performTasks(int channel_ID){

  Serial.println("Reading brightness, fanSpeed, heaterValue , coolerValue, waterPumpVal from ThingSpeak......\n");

  int ledBrightness = ThingSpeak.readFloatField(channel_ID, LED_FIELD);
  int fanSpeed      = ThingSpeak.readFloatField(channel_ID, FAN_FIELD);
  int waterPumpVal  = ThingSpeak.readFloatField(channel_ID, WATER_PUMP_FIELD);
  int coolerVal     = ThingSpeak.readFloatField(channel_ID, HEATER_FIELD);
  int heaterVal     = ThingSpeak.readFloatField(channel_ID, COOLER_FIELD);

  Serial.printf("ledBrightness : %d Lux\n", ledBrightness);
  Serial.printf("fanSpeed      : %d \n", fanSpeed);
  Serial.printf("waterPumpVal  : %d \n", waterPumpVal);
  Serial.printf("coolerVal     : %d \n", coolerVal);
  Serial.printf("heaterVal     : %d \n", heaterVal);

  VALUE_CONTROL_FOR_DEVICE( LED       , ledBrightness , 35000); //Set 35000 Lux as the max Brightness of LED
  VALUE_CONTROL_FOR_DEVICE( FAN       , fanSpeed      , 1);     //Use 1 and 0 as On/Off, doesn't has value skecthing
  VALUE_CONTROL_FOR_DEVICE( WATER_PUMP, waterPumpVal  , 1);     //Use 1 and 0 as On/Off, doesn't has value skecthing
  VALUE_CONTROL_FOR_DEVICE( COOLER    , coolerVal     , 1);     //Use 1 and 0 as On/Off, doesn't has value skecthing
  VALUE_CONTROL_FOR_DEVICE( HEATER    , heaterVal     , 1);     //Use 1 and 0 as On/Off, doesn't has value skecthing
}

<commit_msg>corrected wrong assigns of cooler and heater<commit_after>#include "Task.h"
#include <ESP8266WiFi.h>
#include "ThingSpeak.h"
#include "Setting.h"

#define LED_FIELD           1
#define FAN_FIELD           2
#define WATER_PUMP_FIELD    3
#define COOLER_FIELD        4
#define HEATER_FIELD        5

#define VALUE_CONTROL_FOR_DEVICE(device, controlVal, maxValOfDevice )  analogWrite( device, map(controlVal, 0, maxValOfDevice, 0, 255) )

void performTasks(int channel_ID){

  Serial.println("Reading brightness, fanSpeed, heaterValue , coolerValue, waterPumpVal from ThingSpeak......\n");

  int ledBrightness = ThingSpeak.readFloatField(channel_ID, LED_FIELD);
  int fanSpeed      = ThingSpeak.readFloatField(channel_ID, FAN_FIELD);
  int waterPumpVal  = ThingSpeak.readFloatField(channel_ID, WATER_PUMP_FIELD);
  int heaterVal     = ThingSpeak.readFloatField(channel_ID, HEATER_FIELD);
  int coolerVal     = ThingSpeak.readFloatField(channel_ID, COOLER_FIELD);

  Serial.printf("ledBrightness : %d Lux\n", ledBrightness);
  Serial.printf("fanSpeed      : %d \n", fanSpeed);
  Serial.printf("waterPumpVal  : %d \n", waterPumpVal);
  Serial.printf("coolerVal     : %d \n", coolerVal);
  Serial.printf("heaterVal     : %d \n", heaterVal);

  VALUE_CONTROL_FOR_DEVICE( LED       , ledBrightness , 35000); //Set 35000 Lux as the max Brightness of LED
  VALUE_CONTROL_FOR_DEVICE( FAN       , fanSpeed      , 1);     //Use 1 and 0 as On/Off, doesn't has value skecthing
  VALUE_CONTROL_FOR_DEVICE( WATER_PUMP, waterPumpVal  , 1);     //Use 1 and 0 as On/Off, doesn't has value skecthing
  VALUE_CONTROL_FOR_DEVICE( COOLER    , coolerVal     , 1);     //Use 1 and 0 as On/Off, doesn't has value skecthing
  VALUE_CONTROL_FOR_DEVICE( HEATER    , heaterVal     , 1);     //Use 1 and 0 as On/Off, doesn't has value skecthing
}

<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993-2011 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

// BZFlag common header
#include "common.h"

#include <sys/types.h>
#include <sys/stat.h>

#if defined(_WIN32)
#  include <shlobj.h>
#  include <direct.h>
#else
#  include <pwd.h>
#  include <dirent.h>
#endif /* defined(_WIN32) */

#include "clientConfig.h"

#include "version.h"
#include "StateDatabase.h"
#include "KeyManager.h"
#include "TextUtils.h"
#include "DirectoryNames.h"
#include "ErrorHandler.h"

std::vector<std::string> configQualityValues;
std::vector<std::string> configViewValues;

void initConfigData ( void )
{
	configQualityValues.push_back(std::string("low"));
	configQualityValues.push_back(std::string("medium"));
	configQualityValues.push_back(std::string("high"));
	configQualityValues.push_back(std::string("experimental"));

	configViewValues.push_back(std::string("normal"));
	configViewValues.push_back(std::string("stereo"));
	configViewValues.push_back(std::string("stacked"));
	configViewValues.push_back(std::string("three"));
	configViewValues.push_back(std::string("anaglyph"));
	configViewValues.push_back(std::string("interlaced"));
}

std::string	getOldConfigFileName(void)
{
#if !defined(_WIN32)

	std::string name = getConfigDirName();
	name += "config";

	// add in hostname on UNIX
	if (getenv("HOST")) {
		name += ".";
		name += getenv("HOST");
	}

	return name;

#elif defined(_WIN32) /* !defined(_WIN32) */

	std::string name("C:");
	char dir[MAX_PATH];
	ITEMIDLIST* idl;
	if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_PERSONAL , &idl))) {
		if (SHGetPathFromIDList(idl, dir)) {
			struct stat statbuf;
			if (stat(dir, &statbuf) == 0 && (statbuf.st_mode & _S_IFDIR) != 0)
				name = dir;
		}

		IMalloc* shalloc;
		if (SUCCEEDED(SHGetMalloc(&shalloc))) {
			shalloc->Free(idl);
			shalloc->Release();
		}
	}

	name += "\\My BZFlag Files\\2.0\\config.cfg";
	return name;

#endif /* !defined(_WIN32) */
}

#if !defined(_WIN32)		// who uses this sucker any more?
static std::string	getReallyOldConfigFileName()
{
	std::string name = getConfigDirName();
	name += "config";
	return name;
}
#endif

std::string getCurrentConfigFileName(void)
{
	std::string configFile = BZ_CONFIG_FILE_NAME;

	std::string name = getConfigDirName(BZ_CONFIG_DIR_VERSION);
	name += configFile;

#if !defined(_WIN32)
	// add in hostname on UNIX
	if (getenv("HOST")) {
		name += ".";
		name += getenv("HOST");
	}
#endif
	return name;
}

// this function will look for the config, if it's not there,
// it will TRY and find an old one and copy it
// so that the update function can upgrade it to the current version
// the assumption is that there is a unique config per version
void findConfigFile(void)
{
	// look for the current file
	std::string configName = getCurrentConfigFileName();
	FILE *fp = fopen(configName.c_str(), "rb");
	if (fp) {
		// we found the current file, nothing to do, just return
		fclose(fp);
		return;
	}

	// try and find the old file
	std::string oldConfigName = getOldConfigFileName();
	fp = fopen(oldConfigName.c_str(), "rb");
	if (fp) {
		// there is an old config so lets copy it to the new dir and let the update take care of it.
#if defined(_WIN32)
		fclose(fp);
		// make the dir if we need to
		std::string configDir = getConfigDirName(BZ_CONFIG_DIR_VERSION);
		mkdir(configDir.c_str());
		// copy the old config to the new dir location with the new name
		CopyFile(oldConfigName.c_str(), configName.c_str(),true);

#else	// the other OSs should do what they need to do
		mkdir(getConfigDirName(BZ_CONFIG_DIR_VERSION).c_str(), 0755);

		FILE *newFile = fopen(configName.c_str(),"wb");
		if (newFile) {
			fseek(fp, 0, SEEK_END);
			int len = ftell(fp);
			fseek(fp, 0, SEEK_SET);

			unsigned char* temp = (unsigned char*) malloc(len);

			fread(temp, len, 1, fp);
			fwrite(temp, len, 1, newFile);

			free(temp);

			fclose(newFile);
			fclose(fp);
		}
#endif
	}

	// try and find the REALLY old file
	// who uses this sucker any more?
#if !defined(_WIN32)
	std::string realyOldConfigName = getReallyOldConfigFileName();
	fp = fopen(realyOldConfigName.c_str(), "rb");
	if (fp) {
		// there is an old config so lets copy it to the new dir and let the update take care of it.
		// apparently only linux needs this so do the magic
		mkdir(getConfigDirName(BZ_CONFIG_DIR_VERSION).c_str(), 0755);

		FILE *newFile = fopen(configName.c_str(),"wb");
		if (newFile) {
			fseek(fp, 0, SEEK_END);
			int len = ftell(fp);
			fseek(fp, 0, SEEK_SET);

			unsigned char* temp = (unsigned char*) malloc(len);

			fread(temp, len, 1, fp);
			fwrite(temp, len, 1, newFile);

			free(temp);
			fclose(newFile);
			fclose(fp);
		}
	}
#endif
}

void updateConfigFile(void)
{
	int		configVersion = 0;
	if (BZDB.isSet("config_version"))
		configVersion = (int)BZDB.eval("config_version");

	switch (configVersion) {
  case 0: // 1.10-1.12
	  // update from old unversioned config
	  // roaming fixes - remove keys bound to "roam translate *" and "roam rotate *"
	  KEYMGR.unbindCommand("roam translate left");
	  KEYMGR.unbindCommand("roam translate right");
	  KEYMGR.unbindCommand("roam translate up");
	  KEYMGR.unbindCommand("roam translate down");
	  KEYMGR.unbindCommand("roam translate forward");
	  KEYMGR.unbindCommand("roam translate backward");
	  KEYMGR.unbindCommand("roam rotate left");
	  KEYMGR.unbindCommand("roam rotate right");
	  KEYMGR.unbindCommand("roam rotate up");
	  KEYMGR.unbindCommand("roam rotate down");
	  KEYMGR.unbindCommand("roam rotate stop");

	  // add new default keybindings if there's no conflict

	  // iconify
	  BzfKeyEvent key;
	  if (KEYMGR.stringToKeyEvent("F4", key)
		  && (KEYMGR.get(key, true) == ""))
		  KEYMGR.bind(key, true, "iconify");
	  // toggle console & radar
	  if (KEYMGR.stringToKeyEvent("Q", key)
		  && (KEYMGR.get(key, true) == ""))
		  KEYMGR.bind(key, true, "toggleRadar");
	  if (KEYMGR.stringToKeyEvent("W", key)
		  && (KEYMGR.get(key, true) == ""))
		  KEYMGR.bind(key, true, "toggleConsole");
	  // controlpanel tabs - all or nothing
	  if (KEYMGR.stringToKeyEvent("Shift+F1", key)
		  && (KEYMGR.get(key, true) == "")
		  && KEYMGR.stringToKeyEvent("Shift+F2", key)
		  && (KEYMGR.get(key, true) == "")
		  && KEYMGR.stringToKeyEvent("Shift+F3", key)
		  && (KEYMGR.get(key, true) == "")
		  && KEYMGR.stringToKeyEvent("Shift+F4", key)
		  && (KEYMGR.get(key, true) == "")) {
			  KEYMGR.stringToKeyEvent("Shift+F1", key);
			  KEYMGR.bind(key, true, "messagepanel all");
			  KEYMGR.stringToKeyEvent("Shift+F2", key);
			  KEYMGR.bind(key, true, "messagepanel chat");
			  KEYMGR.stringToKeyEvent("Shift+F3", key);
			  KEYMGR.bind(key, true, "messagepanel server");
			  KEYMGR.stringToKeyEvent("Shift+F4", key);
			  KEYMGR.bind(key, true, "messagepanel misc");
		  }

		  // TODO - any other breaking changes from 1.10 to 2.0

  case 1: // 1.11.20
	  if (KEYMGR.stringToKeyEvent("Tab", key)
		  && (KEYMGR.get(key, false) == ""))
		  KEYMGR.bind(key, false, "jump");

  case 2: // 2.0
	  if (KEYMGR.stringToKeyEvent("7", key)
		  && (KEYMGR.get(key, true) == ""))
		  KEYMGR.bind(key, true, "addhunt");

  case 3: // Upgrade from 2.0.x to 2.4.x

    // Convert from email to motto

    // If the email is set, see if we should convert it
    if (BZDB.isSet("email")) {
      std::string email = BZDB.get("email");
      // If the email is set and does not contain an @ sign, move it to motto
      if (!email.empty() && email.find('@') == std::string::npos) {
	BZDB.set("motto", email);
      }
      BZDB.unset("email");	// discard email string from before version 2.4
    }

    if (BZDB.isSet("emailDispLen")) {
      BZDB.set("mottoDispLen", BZDB.get("emailDispLen"));
      BZDB.unset("emailDispLen");	// discard setting from before version 2.4
    }

    if (BZDB.isSet("hideEmails")) {
      BZDB.setBool("hideMottos", BZDB.isTrue("hideEmails"));
      BZDB.unset("hideEmails");	// discard setting from before version 2.4
    }

    // Get rid of geometry setting
    BZDB.unset("geometry");

    // Turn off dithering (since none of our automatic performance checks turn it on anymore)
    BZDB.setBool("dither", false);

    break;

  case 4: // Upgrade 2.4.x to .... (Do nothing right now as this is the current version)
	  break;

  default: // hm, we don't know about this one...
	  printError(TextUtils::format("Config file is tagged version \"%d\", "
		  "which was not expected (too new perhaps). "
		  "Trying to load anyhow.", configVersion));
	  break;
	}

	// set us as the updated version
	configVersion = BZ_CONFIG_FILE_VERSION;
	BZDB.setInt("config_version", configVersion);
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>Properly locate the old 2.0.x configuration file on non-Windows platforms so it can be upgraded.<commit_after>/* bzflag
 * Copyright (c) 1993-2011 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

// BZFlag common header
#include "common.h"

#include <sys/types.h>
#include <sys/stat.h>

#if defined(_WIN32)
#  include <shlobj.h>
#  include <direct.h>
#else
#  include <pwd.h>
#  include <dirent.h>
#endif /* defined(_WIN32) */

#include "clientConfig.h"

#include "version.h"
#include "StateDatabase.h"
#include "KeyManager.h"
#include "TextUtils.h"
#include "DirectoryNames.h"
#include "ErrorHandler.h"

std::vector<std::string> configQualityValues;
std::vector<std::string> configViewValues;

void initConfigData ( void )
{
	configQualityValues.push_back(std::string("low"));
	configQualityValues.push_back(std::string("medium"));
	configQualityValues.push_back(std::string("high"));
	configQualityValues.push_back(std::string("experimental"));

	configViewValues.push_back(std::string("normal"));
	configViewValues.push_back(std::string("stereo"));
	configViewValues.push_back(std::string("stacked"));
	configViewValues.push_back(std::string("three"));
	configViewValues.push_back(std::string("anaglyph"));
	configViewValues.push_back(std::string("interlaced"));
}

std::string	getOldConfigFileName(void)
{
#if !defined(_WIN32)

	std::string name = getConfigDirName("2.0");
	name += "config.cfg";

	// add in hostname on UNIX
	if (getenv("HOST")) {
		name += ".";
		name += getenv("HOST");
	}

	return name;

#elif defined(_WIN32) /* !defined(_WIN32) */

	std::string name("C:");
	char dir[MAX_PATH];
	ITEMIDLIST* idl;
	if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_PERSONAL , &idl))) {
		if (SHGetPathFromIDList(idl, dir)) {
			struct stat statbuf;
			if (stat(dir, &statbuf) == 0 && (statbuf.st_mode & _S_IFDIR) != 0)
				name = dir;
		}

		IMalloc* shalloc;
		if (SUCCEEDED(SHGetMalloc(&shalloc))) {
			shalloc->Free(idl);
			shalloc->Release();
		}
	}

	name += "\\My BZFlag Files\\2.0\\config.cfg";
	return name;

#endif /* !defined(_WIN32) */
}

#if !defined(_WIN32)		// who uses this sucker any more?
static std::string	getReallyOldConfigFileName()
{
	std::string name = getConfigDirName();
	name += "config";
	return name;
}
#endif

std::string getCurrentConfigFileName(void)
{
	std::string configFile = BZ_CONFIG_FILE_NAME;

	std::string name = getConfigDirName(BZ_CONFIG_DIR_VERSION);
	name += configFile;

#if !defined(_WIN32)
	// add in hostname on UNIX
	if (getenv("HOST")) {
		name += ".";
		name += getenv("HOST");
	}
#endif
	return name;
}

// this function will look for the config, if it's not there,
// it will TRY and find an old one and copy it
// so that the update function can upgrade it to the current version
// the assumption is that there is a unique config per version
void findConfigFile(void)
{
	// look for the current file
	std::string configName = getCurrentConfigFileName();
	FILE *fp = fopen(configName.c_str(), "rb");
	if (fp) {
		// we found the current file, nothing to do, just return
		fclose(fp);
		return;
	}

	// try and find the old file
	std::string oldConfigName = getOldConfigFileName();
	fp = fopen(oldConfigName.c_str(), "rb");
	if (fp) {
		// there is an old config so lets copy it to the new dir and let the update take care of it.
#if defined(_WIN32)
		fclose(fp);
		// make the dir if we need to
		std::string configDir = getConfigDirName(BZ_CONFIG_DIR_VERSION);
		mkdir(configDir.c_str());
		// copy the old config to the new dir location with the new name
		CopyFile(oldConfigName.c_str(), configName.c_str(),true);

#else	// the other OSs should do what they need to do
		mkdir(getConfigDirName(BZ_CONFIG_DIR_VERSION).c_str(), 0755);

		FILE *newFile = fopen(configName.c_str(),"wb");
		if (newFile) {
			fseek(fp, 0, SEEK_END);
			int len = ftell(fp);
			fseek(fp, 0, SEEK_SET);

			unsigned char* temp = (unsigned char*) malloc(len);

			fread(temp, len, 1, fp);
			fwrite(temp, len, 1, newFile);

			free(temp);

			fclose(newFile);
			fclose(fp);
		}
#endif
	}

	// try and find the REALLY old file
	// who uses this sucker any more?
#if !defined(_WIN32)
	std::string realyOldConfigName = getReallyOldConfigFileName();
	fp = fopen(realyOldConfigName.c_str(), "rb");
	if (fp) {
		// there is an old config so lets copy it to the new dir and let the update take care of it.
		// apparently only linux needs this so do the magic
		mkdir(getConfigDirName(BZ_CONFIG_DIR_VERSION).c_str(), 0755);

		FILE *newFile = fopen(configName.c_str(),"wb");
		if (newFile) {
			fseek(fp, 0, SEEK_END);
			int len = ftell(fp);
			fseek(fp, 0, SEEK_SET);

			unsigned char* temp = (unsigned char*) malloc(len);

			fread(temp, len, 1, fp);
			fwrite(temp, len, 1, newFile);

			free(temp);
			fclose(newFile);
			fclose(fp);
		}
	}
#endif
}

void updateConfigFile(void)
{
	int		configVersion = 0;
	if (BZDB.isSet("config_version"))
		configVersion = (int)BZDB.eval("config_version");

	switch (configVersion) {
  case 0: // 1.10-1.12
	  // update from old unversioned config
	  // roaming fixes - remove keys bound to "roam translate *" and "roam rotate *"
	  KEYMGR.unbindCommand("roam translate left");
	  KEYMGR.unbindCommand("roam translate right");
	  KEYMGR.unbindCommand("roam translate up");
	  KEYMGR.unbindCommand("roam translate down");
	  KEYMGR.unbindCommand("roam translate forward");
	  KEYMGR.unbindCommand("roam translate backward");
	  KEYMGR.unbindCommand("roam rotate left");
	  KEYMGR.unbindCommand("roam rotate right");
	  KEYMGR.unbindCommand("roam rotate up");
	  KEYMGR.unbindCommand("roam rotate down");
	  KEYMGR.unbindCommand("roam rotate stop");

	  // add new default keybindings if there's no conflict

	  // iconify
	  BzfKeyEvent key;
	  if (KEYMGR.stringToKeyEvent("F4", key)
		  && (KEYMGR.get(key, true) == ""))
		  KEYMGR.bind(key, true, "iconify");
	  // toggle console & radar
	  if (KEYMGR.stringToKeyEvent("Q", key)
		  && (KEYMGR.get(key, true) == ""))
		  KEYMGR.bind(key, true, "toggleRadar");
	  if (KEYMGR.stringToKeyEvent("W", key)
		  && (KEYMGR.get(key, true) == ""))
		  KEYMGR.bind(key, true, "toggleConsole");
	  // controlpanel tabs - all or nothing
	  if (KEYMGR.stringToKeyEvent("Shift+F1", key)
		  && (KEYMGR.get(key, true) == "")
		  && KEYMGR.stringToKeyEvent("Shift+F2", key)
		  && (KEYMGR.get(key, true) == "")
		  && KEYMGR.stringToKeyEvent("Shift+F3", key)
		  && (KEYMGR.get(key, true) == "")
		  && KEYMGR.stringToKeyEvent("Shift+F4", key)
		  && (KEYMGR.get(key, true) == "")) {
			  KEYMGR.stringToKeyEvent("Shift+F1", key);
			  KEYMGR.bind(key, true, "messagepanel all");
			  KEYMGR.stringToKeyEvent("Shift+F2", key);
			  KEYMGR.bind(key, true, "messagepanel chat");
			  KEYMGR.stringToKeyEvent("Shift+F3", key);
			  KEYMGR.bind(key, true, "messagepanel server");
			  KEYMGR.stringToKeyEvent("Shift+F4", key);
			  KEYMGR.bind(key, true, "messagepanel misc");
		  }

		  // TODO - any other breaking changes from 1.10 to 2.0

  case 1: // 1.11.20
	  if (KEYMGR.stringToKeyEvent("Tab", key)
		  && (KEYMGR.get(key, false) == ""))
		  KEYMGR.bind(key, false, "jump");

  case 2: // 2.0
	  if (KEYMGR.stringToKeyEvent("7", key)
		  && (KEYMGR.get(key, true) == ""))
		  KEYMGR.bind(key, true, "addhunt");

  case 3: // Upgrade from 2.0.x to 2.4.x

    // Convert from email to motto

    // If the email is set, see if we should convert it
    if (BZDB.isSet("email")) {
      std::string email = BZDB.get("email");
      // If the email is set and does not contain an @ sign, move it to motto
      if (!email.empty() && email.find('@') == std::string::npos) {
	BZDB.set("motto", email);
      }
      BZDB.unset("email");	// discard email string from before version 2.4
    }

    if (BZDB.isSet("emailDispLen")) {
      BZDB.set("mottoDispLen", BZDB.get("emailDispLen"));
      BZDB.unset("emailDispLen");	// discard setting from before version 2.4
    }

    if (BZDB.isSet("hideEmails")) {
      BZDB.setBool("hideMottos", BZDB.isTrue("hideEmails"));
      BZDB.unset("hideEmails");	// discard setting from before version 2.4
    }

    // Get rid of geometry setting
    BZDB.unset("geometry");

    // Turn off dithering (since none of our automatic performance checks turn it on anymore)
    BZDB.setBool("dither", false);

    break;

  case 4: // Upgrade 2.4.x to .... (Do nothing right now as this is the current version)
	  break;

  default: // hm, we don't know about this one...
	  printError(TextUtils::format("Config file is tagged version \"%d\", "
		  "which was not expected (too new perhaps). "
		  "Trying to load anyhow.", configVersion));
	  break;
	}

	// set us as the updated version
	configVersion = BZ_CONFIG_FILE_VERSION;
	BZDB.setInt("config_version", configVersion);
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>/** ==========================================================================
 * 2011 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
 * with no warranties. This code is yours to share, use and modify with no
 * strings attached and no restrictions or obligations.
 *
 * For more information see g3log/LICENSE or refer refer to http://unlicense.org
 * ============================================================================
 *
 * Filename:g3log.hpp  Framework for Logging and Design By Contract
 * Created: 2011 by Kjell Hedström
 *
 * PUBLIC DOMAIN and Not copywrited since it was built on public-domain software and influenced
 * at least in "spirit" from the following sources
 * 1. kjellkod.cc ;)
 * 2. Dr.Dobbs, Petru Marginean:  http://drdobbs.com/article/printableArticle.jhtml?articleId=201804215&dept_url=/caddpp/
 * 3. Dr.Dobbs, Michael Schulze: http://drdobbs.com/article/printableArticle.jhtml?articleId=225700666&dept_url=/cpp/
 * 4. Google 'glog': http://google-glog.googlecode.com/svn/trunk/doc/glog.html
 * 5. Various Q&A at StackOverflow
 * ********************************************* */

#pragma once

#include "g3log/loglevels.hpp"
#include "g3log/logcapture.hpp"
#include "g3log/logmessage.hpp"
#include "g3log/generated_definitions.hpp"

#include <string>
#include <functional>

#if !(defined(__PRETTY_FUNCTION__))
#define __PRETTY_FUNCTION__   __FUNCTION__
#endif

// thread_local doesn't exist before VS2013
// it exists on VS2015
#if !(defined(thread_local)) && defined(_MSC_VER) && _MSC_VER < 1900
#define thread_local __declspec(thread)
#endif

/** namespace for LOG() and CHECK() frameworks
 * History lesson:   Why the names 'g3' and 'g3log'?:
 * The framework was made in my own free time as PUBLIC DOMAIN but the
 * first commercial project to use it used 'g3' as an internal denominator for
 * the current project. g3 as in 'generation 2'. I decided to keep the g3 and g3log names
 * to give credit to the people in that project (you know who you are :) and I guess also
 * for 'sentimental' reasons. That a big influence was Google's glog is just a happy
 * coincidence or subconscious choice. Either way g3log became the name for this logger.
 *
 * --- Thanks for a great 2011 and good luck with 'g3' --- KjellKod
 */
namespace g3 {
   class LogWorker;
   struct LogMessage;
   struct FatalMessage;

   /** Should be called at very first startup of the software with \ref g3LogWorker
    *  pointer. Ownership of the \ref g3LogWorker is the responsibility of the caller */
   void initializeLogging(LogWorker *logger);

   /** setFatalPreLoggingHook() provides an optional extra step before the fatalExitHandler is called
    *
    * Set a function-hook before a fatal message will be sent to the logger
    * i.e. this is a great place to put a break point, either in your debugger
    * or programatically to catch LOG(FATAL), CHECK(...) or an OS fatal event (exception or signal)
    * This will be reset to default (does nothing) at initializeLogging(...);
    *
    * Example usage:
    * Windows: g3::setFatalPreLoggingHook([]{__debugbreak();}); // remember #include <intrin.h>
    *         WARNING: '__debugbreak()' when not running in Debug in your Visual Studio IDE will likely
    *                   trigger a recursive crash if used here. It should only be used when debugging
    *                   in your Visual Studio IDE. Recursive crashes are handled but are unnecessary.
    *
    * Linux:   g3::setFatalPreLoggingHook([]{ raise(SIGTRAP); });
    */
   void setFatalPreLoggingHook(std::function<void(void)>  pre_fatal_hook);

   /** If the @ref setFatalPreLoggingHook is not enough and full fatal exit handling is needed then
    * use "setFatalExithandler".  Please see g3log.cpp and crashhandler_windows.cpp or crashhandler_unix for
    * example of restoring signal and exception handlers, flushing the log and shutting down.
    */
   void setFatalExitHandler(std::function<void(FatalMessagePtr)> fatal_call);

#ifdef G3_DYNAMIC_MAX_MESSAGE_SIZE
  // only_change_at_initialization namespace is for changes to be done only during initialization. More specifically
  // items here would be called prior to calling other parts of g3log
  namespace only_change_at_initialization {
    // Sets the MaxMessageSize to be used when capturing log messages. Currently this value is set to 2KB. Messages
    // Longer than this are bound to 2KB with the string "[...truncated...]" at the end. This function allows
    // this limit to be changed.
    void setMaxMessageSize(size_t max_size);
  }
#endif /* G3_DYNAMIC_MAX_MESSAGE_SIZE */

   // internal namespace is for completely internal or semi-hidden from the g3 namespace due to that it is unlikely
   // that you will use these
   namespace internal {
      /// @returns true if logger is initialized
      bool isLoggingInitialized();

      // Save the created LogMessage to any existing sinks
      void saveMessage(const char *message, const char *file, int line, const char *function, const LEVELS &level,
                       const char *boolean_expression, int fatal_signal, const char *stack_trace);

      // forwards the message to all sinks
      void pushMessageToLogger(LogMessagePtr log_entry);

      // forwards a FATAL message to all sinks,. after which the g3logworker
      // will trigger crashhandler / g3::internal::exitWithDefaultSignalHandler
      //
      // By default the "fatalCall" will forward a FatalMessageptr to this function
      // this behavior can be changed if you set a different fatal handler through
      // "setFatalExitHandler"
      void pushFatalMessageToLogger(FatalMessagePtr message);

      // Saves the created FatalMessage to any existing sinks and exits with
      // the originating fatal signal,. or SIGABRT if it originated from a broken contract.
      // By default forwards to: pushFatalMessageToLogger, see "setFatalExitHandler" to override
      //
      // If you override it then you probably want to call "pushFatalMessageToLogger" after your
      // custom fatal handler is done. This will make sure that the fatal message the pushed
      // to sinks as well as shutting down the process
      void fatalCall(FatalMessagePtr message);

      // Shuts down logging. No object cleanup but further LOG(...) calls will be ignored.
      void shutDownLogging();

      // Shutdown logging, but ONLY if the active logger corresponds to the one currently initialized
      bool shutDownLoggingForActiveOnly(LogWorker *active);

   } // internal
} // g3

#define INTERNAL_LOG_MESSAGE(level) LogCapture(__FILE__, __LINE__, static_cast<const char*>(__PRETTY_FUNCTION__), level)

#define INTERNAL_CONTRACT_MESSAGE(boolean_expression)  \
   LogCapture(__FILE__, __LINE__, __PRETTY_FUNCTION__, g3::internal::CONTRACT, boolean_expression)

// LOG(level) is the API for the stream log
#define LOG(level) if(!g3::logLevel(level)) {} else INTERNAL_LOG_MESSAGE(level).stream()

// 'Conditional' stream log
#define LOG_IF(level, boolean_expression)  \
   if (false == (boolean_expression) || !g3::logLevel(level)) {} else INTERNAL_LOG_MESSAGE(level).stream()

// 'Design By Contract' stream API. For Broken Contracts:
//         unit testing: it will throw std::runtime_error when a contract breaks
//         I.R.L : it will exit the application by using fatal signal SIGABRT
#define CHECK(boolean_expression)        \
   if (true == (boolean_expression)) {} else INTERNAL_CONTRACT_MESSAGE(#boolean_expression).stream()

/** For details please see this
 * REFERENCE: http://www.cppreference.com/wiki/io/c/printf_format
 * \verbatim
 *
  There are different %-codes for different variable types, as well as options to
    limit the length of the variables and whatnot.
    Code Format
    %[flags][width][.precision][length]specifier
 SPECIFIERS
 ----------
 %c character
 %d signed integers
 %i signed integers
 %e scientific notation, with a lowercase “e”
 %E scientific notation, with a uppercase “E”
 %f floating point
 %g use %e or %f, whichever is shorter
 %G use %E or %f, whichever is shorter
 %o octal
 %s a string of characters
 %u unsigned integer
 %x unsigned hexadecimal, with lowercase letters
 %X unsigned hexadecimal, with uppercase letters
 %p a pointer
 %n the argument shall be a pointer to an integer into which is placed the number of characters written so far

For flags, width, precision etc please see the above references.
EXAMPLES:
{
   LOGF(INFO, "Characters: %c %c \n", 'a', 65);
   LOGF(INFO, "Decimals: %d %ld\n", 1977, 650000L);      // printing long
   LOGF(INFO, "Preceding with blanks: %10d \n", 1977);
   LOGF(INFO, "Preceding with zeros: %010d \n", 1977);
   LOGF(INFO, "Some different radixes: %d %x %o %#x %#o \n", 100, 100, 100, 100, 100);
   LOGF(INFO, "floats: %4.2f %+.0e %E \n", 3.1416, 3.1416, 3.1416);
   LOGF(INFO, "Width trick: %*d \n", 5, 10);
   LOGF(INFO, "%s \n", "A string");
   return 0;
}
And here is possible output
:      Characters: a A
:      Decimals: 1977 650000
:      Preceding with blanks:       1977
:      Preceding with zeros: 0000001977
:      Some different radixes: 100 64 144 0x64 0144
:      floats: 3.14 +3e+000 3.141600E+000
:      Width trick:    10
:      A string  \endverbatim */
#define LOGF(level, printf_like_message, ...)                 \
   if (!g3::logLevel(level)) {} else INTERNAL_LOG_MESSAGE(level).capturef(printf_like_message, ##__VA_ARGS__)

// Conditional log printf syntax
#define LOGF_IF(level,boolean_expression, printf_like_message, ...) \
   if (false == (boolean_expression) || !g3::logLevel(level)) {} else INTERNAL_LOG_MESSAGE(level).capturef(printf_like_message, ##__VA_ARGS__)

// Design By Contract, printf-like API syntax with variadic input parameters.
// Throws std::runtime_eror if contract breaks
#define CHECKF(boolean_expression, printf_like_message, ...)    \
   if (true == (boolean_expression)) {} else INTERNAL_CONTRACT_MESSAGE(#boolean_expression).capturef(printf_like_message, ##__VA_ARGS__)

// Backwards compatible. The same as CHECKF.
// Design By Contract, printf-like API syntax with variadic input parameters.
// Throws std::runtime_eror if contract breaks
#define CHECK_F(boolean_expression, printf_like_message, ...)    \
   if (true == (boolean_expression)) {} else INTERNAL_CONTRACT_MESSAGE(#boolean_expression).capturef(printf_like_message, ##__VA_ARGS__)
<commit_msg>updated code comments since SIGABRT is used with default fatal handler instead of a throw<commit_after>/** ==========================================================================
 * 2011 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
 * with no warranties. This code is yours to share, use and modify with no
 * strings attached and no restrictions or obligations.
 *
 * For more information see g3log/LICENSE or refer refer to http://unlicense.org
 * ============================================================================
 *
 * Filename:g3log.hpp  Framework for Logging and Design By Contract
 * Created: 2011 by Kjell Hedström
 *
 * PUBLIC DOMAIN and Not copywrited since it was built on public-domain software and influenced
 * at least in "spirit" from the following sources
 * 1. kjellkod.cc ;)
 * 2. Dr.Dobbs, Petru Marginean:  http://drdobbs.com/article/printableArticle.jhtml?articleId=201804215&dept_url=/caddpp/
 * 3. Dr.Dobbs, Michael Schulze: http://drdobbs.com/article/printableArticle.jhtml?articleId=225700666&dept_url=/cpp/
 * 4. Google 'glog': http://google-glog.googlecode.com/svn/trunk/doc/glog.html
 * 5. Various Q&A at StackOverflow
 * ********************************************* */

#pragma once

#include "g3log/loglevels.hpp"
#include "g3log/logcapture.hpp"
#include "g3log/logmessage.hpp"
#include "g3log/generated_definitions.hpp"

#include <string>
#include <functional>

#if !(defined(__PRETTY_FUNCTION__))
#define __PRETTY_FUNCTION__   __FUNCTION__
#endif

// thread_local doesn't exist before VS2013
// it exists on VS2015
#if !(defined(thread_local)) && defined(_MSC_VER) && _MSC_VER < 1900
#define thread_local __declspec(thread)
#endif

/** namespace for LOG() and CHECK() frameworks
 * History lesson:   Why the names 'g3' and 'g3log'?:
 * The framework was made in my own free time as PUBLIC DOMAIN but the
 * first commercial project to use it used 'g3' as an internal denominator for
 * the current project. g3 as in 'generation 2'. I decided to keep the g3 and g3log names
 * to give credit to the people in that project (you know who you are :) and I guess also
 * for 'sentimental' reasons. That a big influence was Google's glog is just a happy
 * coincidence or subconscious choice. Either way g3log became the name for this logger.
 *
 * --- Thanks for a great 2011 and good luck with 'g3' --- KjellKod
 */
namespace g3 {
   class LogWorker;
   struct LogMessage;
   struct FatalMessage;

   /** Should be called at very first startup of the software with \ref g3LogWorker
    *  pointer. Ownership of the \ref g3LogWorker is the responsibility of the caller */
   void initializeLogging(LogWorker *logger);

   /** setFatalPreLoggingHook() provides an optional extra step before the fatalExitHandler is called
    *
    * Set a function-hook before a fatal message will be sent to the logger
    * i.e. this is a great place to put a break point, either in your debugger
    * or programatically to catch LOG(FATAL), CHECK(...) or an OS fatal event (exception or signal)
    * This will be reset to default (does nothing) at initializeLogging(...);
    *
    * Example usage:
    * Windows: g3::setFatalPreLoggingHook([]{__debugbreak();}); // remember #include <intrin.h>
    *         WARNING: '__debugbreak()' when not running in Debug in your Visual Studio IDE will likely
    *                   trigger a recursive crash if used here. It should only be used when debugging
    *                   in your Visual Studio IDE. Recursive crashes are handled but are unnecessary.
    *
    * Linux:   g3::setFatalPreLoggingHook([]{ raise(SIGTRAP); });
    */
   void setFatalPreLoggingHook(std::function<void(void)>  pre_fatal_hook);

   /** If the @ref setFatalPreLoggingHook is not enough and full fatal exit handling is needed then
    * use "setFatalExithandler".  Please see g3log.cpp and crashhandler_windows.cpp or crashhandler_unix for
    * example of restoring signal and exception handlers, flushing the log and shutting down.
    */
   void setFatalExitHandler(std::function<void(FatalMessagePtr)> fatal_call);

#ifdef G3_DYNAMIC_MAX_MESSAGE_SIZE
  // only_change_at_initialization namespace is for changes to be done only during initialization. More specifically
  // items here would be called prior to calling other parts of g3log
  namespace only_change_at_initialization {
    // Sets the MaxMessageSize to be used when capturing log messages. Currently this value is set to 2KB. Messages
    // Longer than this are bound to 2KB with the string "[...truncated...]" at the end. This function allows
    // this limit to be changed.
    void setMaxMessageSize(size_t max_size);
  }
#endif /* G3_DYNAMIC_MAX_MESSAGE_SIZE */

   // internal namespace is for completely internal or semi-hidden from the g3 namespace due to that it is unlikely
   // that you will use these
   namespace internal {
      /// @returns true if logger is initialized
      bool isLoggingInitialized();

      // Save the created LogMessage to any existing sinks
      void saveMessage(const char *message, const char *file, int line, const char *function, const LEVELS &level,
                       const char *boolean_expression, int fatal_signal, const char *stack_trace);

      // forwards the message to all sinks
      void pushMessageToLogger(LogMessagePtr log_entry);

      // forwards a FATAL message to all sinks,. after which the g3logworker
      // will trigger crashhandler / g3::internal::exitWithDefaultSignalHandler
      //
      // By default the "fatalCall" will forward a FatalMessageptr to this function
      // this behavior can be changed if you set a different fatal handler through
      // "setFatalExitHandler"
      void pushFatalMessageToLogger(FatalMessagePtr message);

      // Saves the created FatalMessage to any existing sinks and exits with
      // the originating fatal signal,. or SIGABRT if it originated from a broken contract.
      // By default forwards to: pushFatalMessageToLogger, see "setFatalExitHandler" to override
      //
      // If you override it then you probably want to call "pushFatalMessageToLogger" after your
      // custom fatal handler is done. This will make sure that the fatal message the pushed
      // to sinks as well as shutting down the process
      void fatalCall(FatalMessagePtr message);

      // Shuts down logging. No object cleanup but further LOG(...) calls will be ignored.
      void shutDownLogging();

      // Shutdown logging, but ONLY if the active logger corresponds to the one currently initialized
      bool shutDownLoggingForActiveOnly(LogWorker *active);

   } // internal
} // g3

#define INTERNAL_LOG_MESSAGE(level) LogCapture(__FILE__, __LINE__, static_cast<const char*>(__PRETTY_FUNCTION__), level)

#define INTERNAL_CONTRACT_MESSAGE(boolean_expression)  \
   LogCapture(__FILE__, __LINE__, __PRETTY_FUNCTION__, g3::internal::CONTRACT, boolean_expression)

// LOG(level) is the API for the stream log
#define LOG(level) if(!g3::logLevel(level)) {} else INTERNAL_LOG_MESSAGE(level).stream()

// 'Conditional' stream log
#define LOG_IF(level, boolean_expression)  \
   if (false == (boolean_expression) || !g3::logLevel(level)) {} else INTERNAL_LOG_MESSAGE(level).stream()

// 'Design By Contract' stream API. For Broken Contracts:
//         unit testing: it will throw std::runtime_error when a contract breaks
//         I.R.L : it will exit the application by using fatal signal SIGABRT
#define CHECK(boolean_expression)        \
   if (true == (boolean_expression)) {} else INTERNAL_CONTRACT_MESSAGE(#boolean_expression).stream()

/** For details please see this
 * REFERENCE: http://www.cppreference.com/wiki/io/c/printf_format
 * \verbatim
 *
  There are different %-codes for different variable types, as well as options to
    limit the length of the variables and whatnot.
    Code Format
    %[flags][width][.precision][length]specifier
 SPECIFIERS
 ----------
 %c character
 %d signed integers
 %i signed integers
 %e scientific notation, with a lowercase “e”
 %E scientific notation, with a uppercase “E”
 %f floating point
 %g use %e or %f, whichever is shorter
 %G use %E or %f, whichever is shorter
 %o octal
 %s a string of characters
 %u unsigned integer
 %x unsigned hexadecimal, with lowercase letters
 %X unsigned hexadecimal, with uppercase letters
 %p a pointer
 %n the argument shall be a pointer to an integer into which is placed the number of characters written so far

For flags, width, precision etc please see the above references.
EXAMPLES:
{
   LOGF(INFO, "Characters: %c %c \n", 'a', 65);
   LOGF(INFO, "Decimals: %d %ld\n", 1977, 650000L);      // printing long
   LOGF(INFO, "Preceding with blanks: %10d \n", 1977);
   LOGF(INFO, "Preceding with zeros: %010d \n", 1977);
   LOGF(INFO, "Some different radixes: %d %x %o %#x %#o \n", 100, 100, 100, 100, 100);
   LOGF(INFO, "floats: %4.2f %+.0e %E \n", 3.1416, 3.1416, 3.1416);
   LOGF(INFO, "Width trick: %*d \n", 5, 10);
   LOGF(INFO, "%s \n", "A string");
   return 0;
}
And here is possible output
:      Characters: a A
:      Decimals: 1977 650000
:      Preceding with blanks:       1977
:      Preceding with zeros: 0000001977
:      Some different radixes: 100 64 144 0x64 0144
:      floats: 3.14 +3e+000 3.141600E+000
:      Width trick:    10
:      A string  \endverbatim */
#define LOGF(level, printf_like_message, ...)                 \
   if (!g3::logLevel(level)) {} else INTERNAL_LOG_MESSAGE(level).capturef(printf_like_message, ##__VA_ARGS__)

// Conditional log printf syntax
#define LOGF_IF(level,boolean_expression, printf_like_message, ...) \
   if (false == (boolean_expression) || !g3::logLevel(level)) {} else INTERNAL_LOG_MESSAGE(level).capturef(printf_like_message, ##__VA_ARGS__)

// Design By Contract, printf-like API syntax with variadic input parameters.
// Calls the signal handler if the contract failed with the default exit for a failed contract. This is typically SIGABRT
// See g3log, setFatalExitHandler(...) which can be overriden for unit tests (ref test_io.cpp)
#define CHECKF(boolean_expression, printf_like_message, ...)    \
   if (true == (boolean_expression)) {} else INTERNAL_CONTRACT_MESSAGE(#boolean_expression).capturef(printf_like_message, ##__VA_ARGS__)

// Backwards compatible. The same as CHECKF.
// Design By Contract, printf-like API syntax with variadic input parameters.
// Calls the signal handler if the contract failed. See g3log, setFatalExitHandler(...) which can be overriden for unit tests
// (ref test_io.cpp)
#define CHECK_F(boolean_expression, printf_like_message, ...)    \
   if (true == (boolean_expression)) {} else INTERNAL_CONTRACT_MESSAGE(#boolean_expression).capturef(printf_like_message, ##__VA_ARGS__)
<|endoftext|>


<commit_before>#include "convergence/final_flux_or_n.h"

#include <memory>
#include <optional>

#include "convergence/status.h"
#include "convergence/flux/tests/multi_checker_mock.h"
#include "data/system_fluxes.h"
#include "test_helpers/test_helper_functions.h"
#include "test_helpers/gmock_wrapper.h"

using ::testing::_;
using ::testing::NiceMock;

class ConvergenceFinalFluxOrNTest : public ::testing::Test {
 protected:
  std::unique_ptr<bart::convergence::flux::MultiCheckerMock>
      mock_multi_checker_ptr;
  std::unique_ptr<NiceMock<bart::convergence::flux::MultiCheckerMock>>
      nice_mock_multi_checker_ptr;
  std::shared_ptr<bart::data::SystemFluxes> system_fluxes;
  void SetUp();
};

void ConvergenceFinalFluxOrNTest::SetUp() {
  mock_multi_checker_ptr =
      std::make_unique<bart::convergence::flux::MultiCheckerMock>();
  nice_mock_multi_checker_ptr =
      std::make_unique<NiceMock<bart::convergence::flux::MultiCheckerMock>>();
  system_fluxes = std::make_shared<bart::data::SystemFluxes>();
}

TEST_F(ConvergenceFinalFluxOrNTest, DefaultStatus) {
  bart::convergence::FinalFluxOrN flux_tester(std::move(mock_multi_checker_ptr),
                                              system_fluxes);
  bart::convergence::Status status;
  status = flux_tester.convergence_status();
  ASSERT_EQ(status.iteration_number, 0);
  ASSERT_EQ(status.max_iterations, 1);
  ASSERT_FALSE(status.is_complete);
  ASSERT_FALSE(status.failed_index.has_value());
  ASSERT_FALSE(status.delta.has_value());
}

TEST_F(ConvergenceFinalFluxOrNTest, BadMaxIterations) {
  bart::convergence::FinalFluxOrN flux_tester(std::move(mock_multi_checker_ptr),
                                              system_fluxes);
  EXPECT_ANY_THROW(flux_tester.SetMaxIterations(0));
  EXPECT_ANY_THROW(flux_tester.SetMaxIterations(-1));
}

TEST_F(ConvergenceFinalFluxOrNTest, BadIterations) {
  bart::convergence::FinalFluxOrN flux_tester(std::move(mock_multi_checker_ptr),
                                              system_fluxes);
  EXPECT_ANY_THROW(flux_tester.SetIteration(0));
  EXPECT_ANY_THROW(flux_tester.SetIteration(-1));
}

/* Checks for proper handling of the MultiChecker returning a status of
 * complete, without reaching max iterations */
TEST_F(ConvergenceFinalFluxOrNTest, Convergence) {
  EXPECT_CALL(*mock_multi_checker_ptr, CheckIfConverged(_,_)).
      WillOnce(::testing::Return(true));

  bart::convergence::FinalFluxOrN flux_tester(std::move(mock_multi_checker_ptr),
                                              system_fluxes);
  flux_tester.SetMaxIterations(5).SetIteration(0);
  auto status = flux_tester.CheckFinalConvergence();
  EXPECT_TRUE(status.is_complete);
  EXPECT_EQ(status.iteration_number, 1);
  EXPECT_FALSE(status.failed_index.has_value());
  EXPECT_FALSE(status.delta.has_value());
}

/* Checks for proper handling of the Multichecker returning a status of
 * not complete, without reaching max iterations */
TEST_F(ConvergenceFinalFluxOrNTest, NoConvergence) {
  EXPECT_CALL(*mock_multi_checker_ptr, CheckIfConverged(_,_)).
      WillOnce(::testing::Return(false));
  EXPECT_CALL(*mock_multi_checker_ptr, failed_index()).
      WillOnce(::testing::Return(std::make_optional(2)));
  EXPECT_CALL(*mock_multi_checker_ptr, failed_delta()).
      WillOnce(::testing::Return(std::make_optional(1.3)));

  bart::convergence::FinalFluxOrN flux_tester(std::move(mock_multi_checker_ptr),
                                              system_fluxes);
  flux_tester.SetMaxIterations(5).SetIteration(0);
  auto status = flux_tester.CheckFinalConvergence();
  EXPECT_FALSE(status.is_complete);
  EXPECT_EQ(status.iteration_number, 1);
  EXPECT_EQ(status.failed_index.value(), 2);
  EXPECT_DOUBLE_EQ(status.delta.value(), 1.3);
}

/* Checks for proper handling of the Multichecker returning a status of
 * complete when max iterations is reached, even if not converged. */
TEST_F(ConvergenceFinalFluxOrNTest, MaxIterNoConvergence) {
  EXPECT_CALL(*nice_mock_multi_checker_ptr, CheckIfConverged(_,_)).
      WillOnce(::testing::Return(false));
  ON_CALL(*nice_mock_multi_checker_ptr, failed_index()).
      WillByDefault(::testing::Return(std::make_optional(2)));
  ON_CALL(*nice_mock_multi_checker_ptr, failed_delta()).
      WillByDefault(::testing::Return(std::make_optional(1.3)));

  bart::convergence::FinalFluxOrN flux_tester(
      std::move(nice_mock_multi_checker_ptr),
      system_fluxes);

  flux_tester.SetMaxIterations(5).SetIteration(4);
  auto status = flux_tester.CheckFinalConvergence();
  EXPECT_TRUE(status.is_complete);
}

/* Checks for proper handling of the Multichecker returning a status of
 * complete when max iterations is reached, if converged. */
TEST_F(ConvergenceFinalFluxOrNTest, MaxIterConvergence) {
  EXPECT_CALL(*mock_multi_checker_ptr, CheckIfConverged(_,_)).
      WillOnce(::testing::Return(true));

  bart::convergence::FinalFluxOrN flux_tester(std::move(mock_multi_checker_ptr),
                                              system_fluxes);

  flux_tester.SetMaxIterations(5).SetIteration(4);
  auto status = flux_tester.CheckFinalConvergence();
  EXPECT_TRUE(status.is_complete);
}

<commit_msg>corrected tests for FinalFluxOrN convergence handling<commit_after>#include "convergence/final_flux_or_n.h"

#include <memory>
#include <optional>

#include "convergence/status.h"
#include "convergence/flux/tests/multi_checker_mock.h"
#include "data/system_fluxes.h"
#include "test_helpers/test_helper_functions.h"
#include "test_helpers/gmock_wrapper.h"

using ::testing::_;
using ::testing::NiceMock;

class ConvergenceFinalFluxOrNTest : public ::testing::Test {
 protected:
  std::unique_ptr<bart::convergence::flux::MultiCheckerMock>
      mock_multi_checker_ptr;
  std::unique_ptr<NiceMock<bart::convergence::flux::MultiCheckerMock>>
      nice_mock_multi_checker_ptr;
  std::shared_ptr<bart::data::SystemFluxes> system_fluxes;
  void SetUp();
};

void ConvergenceFinalFluxOrNTest::SetUp() {
  mock_multi_checker_ptr =
      std::make_unique<bart::convergence::flux::MultiCheckerMock>();
  nice_mock_multi_checker_ptr =
      std::make_unique<NiceMock<bart::convergence::flux::MultiCheckerMock>>();
  system_fluxes = std::make_shared<bart::data::SystemFluxes>();
}

TEST_F(ConvergenceFinalFluxOrNTest, DefaultStatus) {
  bart::convergence::FinalFluxOrN flux_tester(std::move(mock_multi_checker_ptr),
                                              system_fluxes);
  bart::convergence::Status status;
  status = flux_tester.convergence_status();
  ASSERT_EQ(status.iteration_number, 0);
  ASSERT_EQ(status.max_iterations, 1);
  ASSERT_FALSE(status.is_complete);
  ASSERT_FALSE(status.failed_index.has_value());
  ASSERT_FALSE(status.delta.has_value());
}

TEST_F(ConvergenceFinalFluxOrNTest, BadMaxIterations) {
  bart::convergence::FinalFluxOrN flux_tester(std::move(mock_multi_checker_ptr),
                                              system_fluxes);
  EXPECT_ANY_THROW(flux_tester.SetMaxIterations(0));
  EXPECT_ANY_THROW(flux_tester.SetMaxIterations(-1));
}

TEST_F(ConvergenceFinalFluxOrNTest, BadIterations) {
  bart::convergence::FinalFluxOrN flux_tester(std::move(mock_multi_checker_ptr),
                                              system_fluxes);
  EXPECT_ANY_THROW(flux_tester.SetIteration(-1));
}

/* Checks for proper handling of the MultiChecker returning a status of
 * complete, without reaching max iterations */
TEST_F(ConvergenceFinalFluxOrNTest, Convergence) {
  EXPECT_CALL(*mock_multi_checker_ptr, CheckIfConverged(_,_)).
      WillOnce(::testing::Return(true));
  EXPECT_CALL(*mock_multi_checker_ptr, failed_delta()).
      WillOnce(::testing::Return(std::nullopt));
  EXPECT_CALL(*mock_multi_checker_ptr, failed_index()).
      WillOnce(::testing::Return(std::nullopt));

  bart::convergence::FinalFluxOrN flux_tester(std::move(mock_multi_checker_ptr),
                                              system_fluxes);

  flux_tester.SetMaxIterations(5).SetIteration(0);
  auto status = flux_tester.CheckFinalConvergence();
  EXPECT_TRUE(status.is_complete);
  EXPECT_EQ(status.iteration_number, 1);
  EXPECT_FALSE(status.failed_index.has_value());
  EXPECT_FALSE(status.delta.has_value());
}

/* Checks for proper handling of the Multichecker returning a status of
 * not complete, without reaching max iterations */
TEST_F(ConvergenceFinalFluxOrNTest, NoConvergence) {
  EXPECT_CALL(*mock_multi_checker_ptr, CheckIfConverged(_,_)).
      WillOnce(::testing::Return(false));
  EXPECT_CALL(*mock_multi_checker_ptr, failed_index()).
      WillOnce(::testing::Return(std::make_optional(2)));
  EXPECT_CALL(*mock_multi_checker_ptr, failed_delta()).
      WillOnce(::testing::Return(std::make_optional(1.3)));

  bart::convergence::FinalFluxOrN flux_tester(std::move(mock_multi_checker_ptr),
                                              system_fluxes);
  flux_tester.SetMaxIterations(5).SetIteration(0);
  auto status = flux_tester.CheckFinalConvergence();
  EXPECT_FALSE(status.is_complete);
  EXPECT_EQ(status.iteration_number, 1);
  EXPECT_EQ(status.failed_index.value(), 2);
  EXPECT_DOUBLE_EQ(status.delta.value(), 1.3);
}

/* Checks for proper handling of the Multichecker returning a status of
 * complete when max iterations is reached, even if not converged. */
TEST_F(ConvergenceFinalFluxOrNTest, MaxIterNoConvergence) {
  EXPECT_CALL(*nice_mock_multi_checker_ptr, CheckIfConverged(_,_)).
      WillOnce(::testing::Return(false));
  ON_CALL(*nice_mock_multi_checker_ptr, failed_index()).
      WillByDefault(::testing::Return(std::make_optional(2)));
  ON_CALL(*nice_mock_multi_checker_ptr, failed_delta()).
      WillByDefault(::testing::Return(std::make_optional(1.3)));

  bart::convergence::FinalFluxOrN flux_tester(
      std::move(nice_mock_multi_checker_ptr),
      system_fluxes);

  flux_tester.SetMaxIterations(5).SetIteration(4);
  auto status = flux_tester.CheckFinalConvergence();
  EXPECT_TRUE(status.is_complete);
}

/* Checks for proper handling of the Multichecker returning a status of
 * complete when max iterations is reached, if converged. */
TEST_F(ConvergenceFinalFluxOrNTest, MaxIterConvergence) {
  EXPECT_CALL(*mock_multi_checker_ptr, CheckIfConverged(_,_)).
      WillOnce(::testing::Return(true));
  EXPECT_CALL(*mock_multi_checker_ptr, failed_delta()).
      WillOnce(::testing::Return(std::nullopt));
  EXPECT_CALL(*mock_multi_checker_ptr, failed_index()).
      WillOnce(::testing::Return(std::nullopt));

  bart::convergence::FinalFluxOrN flux_tester(std::move(mock_multi_checker_ptr),
                                              system_fluxes);

  flux_tester.SetMaxIterations(5).SetIteration(4);
  auto status = flux_tester.CheckFinalConvergence();
  EXPECT_TRUE(status.is_complete);
}

<|endoftext|>


<commit_before>/*
 * FileMode.hpp
 *
 * Copyright (C) 2009-12 by RStudio, PBC
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#ifndef CORE_SYSTEM_FILE_MODE_HPP
#define CORE_SYSTEM_FILE_MODE_HPP

#ifdef _WIN32
#error FileMode.hpp is is not supported on Windows
#endif

#include <sys/stat.h>
#include <sys/unistd.h>

#include <shared_core/Error.hpp>
#include <shared_core/FilePath.hpp>
#include <shared_core/SafeConvert.hpp>

namespace rstudio {
namespace core {
namespace system {

inline Error isFileReadable(const FilePath& filePath, bool* pReadable)
{
   int result = ::access(filePath.getAbsolutePath().c_str(), R_OK);
   if (result == 0)
   {
      // user has access
      *pReadable = true;
   }
   else if (errno == EACCES)
   {
      // this error is expected when the user doesn't have access to the path
      *pReadable = false;
   }
   else
   {
      // some other error (unexpected)
      return systemError(errno, ERROR_LOCATION);
   }
   return Success();
}

inline Error isFileWriteable(const FilePath& filePath, bool* pWriteable)
{
   int result = ::access(filePath.getAbsolutePath().c_str(), W_OK);
   if (result == 0)
   {
      // user has access
      *pWriteable = true;
   }
   else if (errno == EACCES)
   {
      *pWriteable = false;
   }
   else
   {
      return systemError(errno, ERROR_LOCATION);
   }
   return Success();
}

} // namespace system
} // namespace core
} // namespace rstudio

#endif // CORE_SYSTEM_FILE_MODE_HPP
<commit_msg>move the rest of the FileMode functions to FilePath<commit_after><|endoftext|>


<commit_before>#include <ros/ros.h>
#include <sensor_msgs/PointCloud2.h>
#include <nav_msgs/OccupancyGrid.h>
#include <pcl_conversions/pcl_conversions.h>
#include <pcl_ros/point_cloud.h>
#include <tf/transform_listener.h>
#include <pcl_ros/transforms.h>
#include <cmath>

typedef pcl::PointCloud<pcl::PointXYZ> PointCloudXYZ;

nav_msgs::OccupancyGrid nav_map;
ros::Publisher map_pub;
tf::TransformListener* tf_listener;
bool map_changed;

int x_origin, y_origin;

inline int round (const float a) { return int (a + 0.5); }

void setCellOccupancy(const int x, const int y, const int value)
{
	// only include this point if it falls within the map grid
	if(x < nav_map.info.width && x >= 0 &&
	   y < nav_map.info.height && y >= 0)
	{
		nav_map.data[y*nav_map.info.width + x] = value;
	}
}

void setCellOccupancy(const float x, const float y, const int value)
{
	int x_coord = (int)(x/nav_map.info.resolution) + x_origin;
	int y_coord = (int)(y/nav_map.info.resolution) + y_origin;

	setCellOccupancy(x_coord, y_coord, value);
}

int getCellOccupancy(const int x, const int y)
{
	if(x < nav_map.info.width && x >= 0 &&
	   y < nav_map.info.height && y >= 0)
	{
		return nav_map.data[y*nav_map.info.width + x];
	}

	return 50;
}

int getCellOccupancy(const float x, const float y)
{
	int x_coord = (int)(x/nav_map.info.resolution) + x_origin;
	int y_coord = (int)(y/nav_map.info.resolution) + y_origin;

	return getCellOccupancy(x_coord, y_coord);
}

void beamDDA(const tf::Vector3& beamStart, const tf::Vector3& beamEnd)
{
	int dx = (int)((beamEnd.getX() - beamStart.getX())/nav_map.info.resolution);
	int dy = (int)((beamEnd.getY() - beamStart.getY())/nav_map.info.resolution);
	int steps;

	float xIncrement, yIncrement;
	float x = beamStart.getX()/nav_map.info.resolution;
	float y = beamStart.getY()/nav_map.info.resolution;

	if(fabs(dx) > fabs(dy))
		steps = fabs(dx);
	else
		steps = fabs(dy);
	xIncrement = ((float)dx)/((float)steps);
	yIncrement = ((float)dy)/((float)steps);

/*	ROS_INFO("%3.3f, %3.3f, %3.3f, %3.3f, %d, %d, %d, %3.3f, %3.3f",
			 beamStart.getX(), beamStart.getY(),
			 beamEnd.getX(), beamEnd.getY(),
			 dx, dy, steps,
			 xIncrement, yIncrement);*/

	setCellOccupancy(x, y, 0);
	for(int k=0; k<steps-1; k++)
	{
		x += xIncrement;
		y += yIncrement;
		int new_value = getCellOccupancy(round(x)+x_origin, round(y)+y_origin) - 5;
		if(new_value < 0)
			new_value = 0;
		setCellOccupancy(round(x)+x_origin, round(y)+y_origin, new_value);
	}
}

void laserCallback(const sensor_msgs::PointCloud2::ConstPtr& ros_cloud)
{
	sensor_msgs::PointCloud2 map_ros_cloud;
	if(!tf_listener->waitForTransform(
		   "/map",
		   "/base_link",
		   ros_cloud->header.stamp,
		   ros::Duration(1.0)))
	{
		ROS_INFO("Transform from /map to /base_link failed");
		return; // if a transform isn't found within one second give up
	}
	pcl_ros::transformPointCloud("/map", *ros_cloud, map_ros_cloud, *tf_listener);
	// get the start point of the laser beam
	tf::StampedTransform laser_transform;
	if(!tf_listener->waitForTransform(
		   "/map",
		   "/head_hokuyo_frame",
		   ros_cloud->header.stamp,
		   ros::Duration(1.0)))
	{
		ROS_INFO("Transform from /map to /head_hokuyo_frame failed");
		return;
	}
	tf_listener->lookupTransform("/map", "/head_hokuyo_frame", ros_cloud->header.stamp, laser_transform);
	tf::Vector3 beam_start = laser_transform.getOrigin();
	beam_start.setZ(0);

	// convert to the PCL format
	PointCloudXYZ pcl_cloud;
	pcl::fromROSMsg(map_ros_cloud, pcl_cloud);

	for(pcl::PointCloud<pcl::PointXYZ>::const_iterator point = pcl_cloud.points.begin();
		point != pcl_cloud.points.end();
		point++)
	{
		if(point->z > 1.2 || point->z < .8)
			continue; // ignore points outside of the scan plane

		// get the vector in the map plane
		tf::Vector3 beam_end(point->x, point->y, 0);

		beamDDA(beam_start, beam_end);

		double beam_length = beam_end.distance(beam_start);
		// ignore the max distance results and results that come from
		// within the bounding cylinder of the robot
		if(fabs(beam_length - 30.0) < .03 || fabs(beam_length) < .5)
			continue; // skip points that are near the max sensor range

		int new_value = getCellOccupancy(point->x, point->y) + 25;
		if(new_value > 100)
			new_value = 100;
		setCellOccupancy(point->x, point->y, new_value);
	}

	map_changed = true;
}

int main(int argc, char** argv)
{
	ros::init(argc, argv, "map_creator_2d");
	ros::NodeHandle nh;

	ros::NodeHandle priv_nh("~");
	double map_resolution, x_offset, y_offset;
	int map_width, map_height;
	priv_nh.param<double>("resolution", map_resolution, 0.05);
	priv_nh.param<int>("width", map_width, 1000);
	priv_nh.param<int>("height", map_height, 1000);
	priv_nh.param<double>("x_offset", x_offset, .5);
	priv_nh.param<double>("y_offset", y_offset, .5);

	if(x_offset < 0 || x_offset > 1)
	{
		ROS_ERROR("Invalid x_offset. Must be in range [0, 1.0]");
		return 1;
	}

	if(y_offset < 0 || y_offset > 1)
	{
		ROS_ERROR("Invalid y_offset. Must be in range [0, 1.0]");
		return 1;
	}

	tf_listener = new tf::TransformListener();

	// set the nav_map frame
	nav_map.header.frame_id = "/map";

	// fill out the meta-data
	nav_map.info.map_load_time = ros::Time::now();
	nav_map.info.resolution = map_resolution;
	nav_map.info.width = map_width;
	nav_map.info.height = map_height;
	nav_map.info.origin.position.x = -nav_map.info.resolution*nav_map.info.width*x_offset;
	nav_map.info.origin.position.y = -nav_map.info.resolution*nav_map.info.height*y_offset;
	nav_map.info.origin.orientation.w = 1.0;

	// initialize to all unknown
	for(int i=0; i<nav_map.info.height; i++)
	{
		for(int j=0; j<nav_map.info.width; j++)
		{
			nav_map.data.push_back(50);
		}
	}

	// get the origin coordinates in the map grid
	x_origin = (int)(nav_map.info.width*x_offset);
	y_origin = (int)(nav_map.info.height*y_offset);

	// now that the datastructure is initialized set up the ROS stuff
	map_pub = nh.advertise<nav_msgs::OccupancyGrid>("/map", 1, true);
	ros::Subscriber laser_sub = nh.subscribe<sensor_msgs::PointCloud2>("laser/points", 10, &laserCallback);

	ros::Rate loop_rate(10);
	while(ros::ok())
	{
		if(map_changed)
		{
			nav_map.header.stamp = ros::Time::now();
			map_pub.publish(nav_map);
			map_changed = false;
		}

		ros::spinOnce();
		loop_rate.sleep();
	}

	delete tf_listener;
}
<commit_msg>printing the resolution, size and origin that the map creator will be using.<commit_after>#include <ros/ros.h>
#include <sensor_msgs/PointCloud2.h>
#include <nav_msgs/OccupancyGrid.h>
#include <pcl_conversions/pcl_conversions.h>
#include <pcl_ros/point_cloud.h>
#include <tf/transform_listener.h>
#include <pcl_ros/transforms.h>
#include <cmath>

typedef pcl::PointCloud<pcl::PointXYZ> PointCloudXYZ;

nav_msgs::OccupancyGrid nav_map;
ros::Publisher map_pub;
tf::TransformListener* tf_listener;
bool map_changed;

int x_origin, y_origin;

inline int round (const float a) { return int (a + 0.5); }

void setCellOccupancy(const int x, const int y, const int value)
{
	// only include this point if it falls within the map grid
	if(x < nav_map.info.width && x >= 0 &&
	   y < nav_map.info.height && y >= 0)
	{
		nav_map.data[y*nav_map.info.width + x] = value;
	}
}

void setCellOccupancy(const float x, const float y, const int value)
{
	int x_coord = (int)(x/nav_map.info.resolution) + x_origin;
	int y_coord = (int)(y/nav_map.info.resolution) + y_origin;

	setCellOccupancy(x_coord, y_coord, value);
}

int getCellOccupancy(const int x, const int y)
{
	if(x < nav_map.info.width && x >= 0 &&
	   y < nav_map.info.height && y >= 0)
	{
		return nav_map.data[y*nav_map.info.width + x];
	}

	return 50;
}

int getCellOccupancy(const float x, const float y)
{
	int x_coord = (int)(x/nav_map.info.resolution) + x_origin;
	int y_coord = (int)(y/nav_map.info.resolution) + y_origin;

	return getCellOccupancy(x_coord, y_coord);
}

void beamDDA(const tf::Vector3& beamStart, const tf::Vector3& beamEnd)
{
	int dx = (int)((beamEnd.getX() - beamStart.getX())/nav_map.info.resolution);
	int dy = (int)((beamEnd.getY() - beamStart.getY())/nav_map.info.resolution);
	int steps;

	float xIncrement, yIncrement;
	float x = beamStart.getX()/nav_map.info.resolution;
	float y = beamStart.getY()/nav_map.info.resolution;

	if(fabs(dx) > fabs(dy))
		steps = fabs(dx);
	else
		steps = fabs(dy);
	xIncrement = ((float)dx)/((float)steps);
	yIncrement = ((float)dy)/((float)steps);

/*	ROS_INFO("%3.3f, %3.3f, %3.3f, %3.3f, %d, %d, %d, %3.3f, %3.3f",
			 beamStart.getX(), beamStart.getY(),
			 beamEnd.getX(), beamEnd.getY(),
			 dx, dy, steps,
			 xIncrement, yIncrement);*/

	setCellOccupancy(x, y, 0);
	for(int k=0; k<steps-1; k++)
	{
		x += xIncrement;
		y += yIncrement;
		int new_value = getCellOccupancy(round(x)+x_origin, round(y)+y_origin) - 5;
		if(new_value < 0)
			new_value = 0;
		setCellOccupancy(round(x)+x_origin, round(y)+y_origin, new_value);
	}
}

void laserCallback(const sensor_msgs::PointCloud2::ConstPtr& ros_cloud)
{
	sensor_msgs::PointCloud2 map_ros_cloud;
	if(!tf_listener->waitForTransform(
		   "/map",
		   "/base_link",
		   ros_cloud->header.stamp,
		   ros::Duration(1.0)))
	{
		ROS_INFO("Transform from /map to /base_link failed");
		return; // if a transform isn't found within one second give up
	}
	pcl_ros::transformPointCloud("/map", *ros_cloud, map_ros_cloud, *tf_listener);
	// get the start point of the laser beam
	tf::StampedTransform laser_transform;
	if(!tf_listener->waitForTransform(
		   "/map",
		   "/head_hokuyo_frame",
		   ros_cloud->header.stamp,
		   ros::Duration(1.0)))
	{
		ROS_INFO("Transform from /map to /head_hokuyo_frame failed");
		return;
	}
	tf_listener->lookupTransform("/map", "/head_hokuyo_frame", ros_cloud->header.stamp, laser_transform);
	tf::Vector3 beam_start = laser_transform.getOrigin();
	beam_start.setZ(0);

	// convert to the PCL format
	PointCloudXYZ pcl_cloud;
	pcl::fromROSMsg(map_ros_cloud, pcl_cloud);

	for(pcl::PointCloud<pcl::PointXYZ>::const_iterator point = pcl_cloud.points.begin();
		point != pcl_cloud.points.end();
		point++)
	{
		if(point->z > 1.2 || point->z < .8)
			continue; // ignore points outside of the scan plane

		// get the vector in the map plane
		tf::Vector3 beam_end(point->x, point->y, 0);

		beamDDA(beam_start, beam_end);

		double beam_length = beam_end.distance(beam_start);
		// ignore the max distance results and results that come from
		// within the bounding cylinder of the robot
		if(fabs(beam_length - 30.0) < .03 || fabs(beam_length) < .5)
			continue; // skip points that are near the max sensor range

		int new_value = getCellOccupancy(point->x, point->y) + 25;
		if(new_value > 100)
			new_value = 100;
		setCellOccupancy(point->x, point->y, new_value);
	}

	map_changed = true;
}

int main(int argc, char** argv)
{
	ros::init(argc, argv, "map_creator_2d");
	ros::NodeHandle nh;

	ros::NodeHandle priv_nh("~");
	double map_resolution, x_offset, y_offset;
	int map_width, map_height;
	priv_nh.param<double>("resolution", map_resolution, 0.05);
	priv_nh.param<int>("width", map_width, 1000);
	priv_nh.param<int>("height", map_height, 1000);
	priv_nh.param<double>("x_offset", x_offset, .5);
	priv_nh.param<double>("y_offset", y_offset, .5);

	ROS_INFO("Map Resolution %3.3f", map_resolution);
	ROS_INFO("Map Size (%d, %d)", map_width, map_height);
	ROS_INFO("Map Origin Offset (%3.3f, %3.3f)", x_offset, y_offset);

	if(x_offset < 0 || x_offset > 1)
	{
		ROS_ERROR("Invalid x_offset. Must be in range [0, 1.0]");
		return 1;
	}

	if(y_offset < 0 || y_offset > 1)
	{
		ROS_ERROR("Invalid y_offset. Must be in range [0, 1.0]");
		return 1;
	}

	tf_listener = new tf::TransformListener();

	// set the nav_map frame
	nav_map.header.frame_id = "/map";

	// fill out the meta-data
	nav_map.info.map_load_time = ros::Time::now();
	nav_map.info.resolution = map_resolution;
	nav_map.info.width = map_width;
	nav_map.info.height = map_height;
	nav_map.info.origin.position.x = -nav_map.info.resolution*nav_map.info.width*x_offset;
	nav_map.info.origin.position.y = -nav_map.info.resolution*nav_map.info.height*y_offset;
	nav_map.info.origin.orientation.w = 1.0;

	// initialize to all unknown
	for(int i=0; i<nav_map.info.height; i++)
	{
		for(int j=0; j<nav_map.info.width; j++)
		{
			nav_map.data.push_back(50);
		}
	}

	// get the origin coordinates in the map grid
	x_origin = (int)(nav_map.info.width*x_offset);
	y_origin = (int)(nav_map.info.height*y_offset);

	// now that the datastructure is initialized set up the ROS stuff
	map_pub = nh.advertise<nav_msgs::OccupancyGrid>("/map", 1, true);
	ros::Subscriber laser_sub = nh.subscribe<sensor_msgs::PointCloud2>("laser/points", 10, &laserCallback);

	ros::Rate loop_rate(10);
	while(ros::ok())
	{
		if(map_changed)
		{
			nav_map.header.stamp = ros::Time::now();
			map_pub.publish(nav_map);
			map_changed = false;
		}

		ros::spinOnce();
		loop_rate.sleep();
	}

	delete tf_listener;
}
<|endoftext|>


<commit_before>/*
    This file is part of KAddressBook.
    Copyright (c) 2004 Tobias Koenig <tokoe@kde.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include <QLayout>
#include <QPushButton>
#include <QTimer>
//Added by qt3to4:
#include <QGridLayout>

#include <kabc/resource.h>
#include <kdialog.h>
#include <kglobal.h>
#include <kiconloader.h>
#include <kinputdialog.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kresources/configdialog.h>

#include "core.h"

#include "resourceselection.h"
#include <libkdepim/resourceabc.h>

class AddressBookWrapper : public KABC::AddressBook
{
  public:
    AddressBookWrapper( KABC::AddressBook* );

    KRES::Manager<KABC::Resource>* getResourceManager()
    {
      return resourceManager();
    }
};

class ResourceItem : public Q3CheckListItem
{
  public:
    ResourceItem( K3ListView *parent, KABC::Resource *resource )
      : Q3CheckListItem( parent, resource->resourceName(), CheckBox ),
        mResource( resource ), mChecked( false ),
        mIsSubresource( false ), mSubItemsCreated( false ),
        mResourceIdentifier()
    {
      setOn( resource->isActive() );
      setPixmap( 0, KGlobal::iconLoader()->loadIcon( "contents", K3Icon::Small ) );
      mChecked = isOn();
    }

    ResourceItem( KPIM::ResourceABC *resourceABC, ResourceItem* parent,
                  const QString& resourceIdent )
      : Q3CheckListItem( parent, resourceABC->subresourceLabel( resourceIdent ), CheckBox ),
        mResource( resourceABC ), mChecked( false ),
        mIsSubresource( true ), mSubItemsCreated( false ),
        mResourceIdentifier( resourceIdent )
    {
      KPIM::ResourceABC* res = static_cast<KPIM::ResourceABC *>( mResource );
      setOn( res->subresourceActive( mResourceIdentifier ) );
      setPixmap( 0, KGlobal::iconLoader()->loadIcon( "contents", K3Icon::Small ) );
      mChecked = isOn();
    }

    void createSubresourceItems();

    void setChecked( bool state ) { mChecked = state; }
    bool checked() const { return mChecked; }
    KABC::Resource *resource() const { return mResource; }
    QString resourceIdentifier() const { return mResourceIdentifier; }
    bool isSubResource() const { return mIsSubresource; }

    virtual void stateChange( bool active );

  private:
    KABC::Resource * const mResource;
    bool mChecked;
    const bool mIsSubresource;
    bool mSubItemsCreated;
    const QString mResourceIdentifier;
};

// Comes from korganizer/resourceview.cpp
void ResourceItem::createSubresourceItems()
{
  KPIM::ResourceABC* res = dynamic_cast<KPIM::ResourceABC *>( mResource );
  QStringList subresources;
  if ( res )
    subresources = res->subresources();
  if ( !subresources.isEmpty() ) {
    setOpen( true );
    setExpandable( true );
    // This resource has subresources
    QStringList::ConstIterator it;
    for ( it = subresources.begin(); it != subresources.end(); ++it ) {
      (void)new ResourceItem( res, this, *it );
    }
  }
  mSubItemsCreated = true;
}

// TODO: connect this to some signalResourceModified
// void ResourceItem::setGuiState()
// {
//   if ( mIsSubresource )
//     setOn( mResource->subresourceActive( mResourceIdentifier ) );
//   else
//     setOn( mResource->isActive() );
// }

void ResourceItem::stateChange( bool active )
{
  //kDebug(5720) << k_funcinfo << this << " " << text( 0 ) << " active=" << active << endl;
  if ( active && !mIsSubresource ) {
    if ( !mSubItemsCreated )
      createSubresourceItems();
  }

  setOpen( active && childCount() > 0 );
}

////

ResourceSelection::ResourceSelection( KAB::Core *core, QWidget *parent )
  : KAB::ExtensionWidget( core, parent ), mManager( 0 )
{
  initGUI();

  AddressBookWrapper *wrapper = static_cast<AddressBookWrapper*>( core->addressBook() );
  mManager = wrapper->getResourceManager();

  connect( mAddButton, SIGNAL( clicked() ), SLOT( add() ) );
  connect( mEditButton, SIGNAL( clicked() ), SLOT( edit() ) );
  connect( mRemoveButton, SIGNAL( clicked() ), SLOT( remove() ) );

  connect( mListView, SIGNAL( clicked( Q3ListViewItem* ) ),
           SLOT( currentChanged( Q3ListViewItem* ) ) );

  QTimer::singleShot( 0, this, SLOT( updateView() ) );
}

ResourceSelection::~ResourceSelection()
{
}

QString ResourceSelection::title() const
{
  return i18n( "Address Books" );
}

QString ResourceSelection::identifier() const
{
  return "resourceselection";
}

void ResourceSelection::add()
{
  QStringList types = mManager->resourceTypeNames();
  QStringList descs = mManager->resourceTypeDescriptions();

  bool ok = false;
  QString desc = KInputDialog::getItem( i18n( "Add Address Book" ),
                                        i18n( "Please select type of the new address book:" ),
                                        descs, 0, false, &ok, this );
  if ( !ok )
    return;

  QString type = types[ descs.indexOf( desc ) ];

  // Create new resource
  KABC::Resource *resource = mManager->createResource( type );
  if ( !resource ) {
    KMessageBox::error( this, i18n("<qt>Unable to create an address book of type %1.</qt>",
                                type ) );
    return;
  }

  resource->setResourceName( i18n( "%1 address book", type ) );

  KRES::ConfigDialog dlg( this, QString( "contact" ), resource );

  if ( dlg.exec() ) {
    core()->addressBook()->addResource( resource );
    resource->asyncLoad();

    mLastResource = resource->identifier();
    updateView();
  } else {
    delete resource;
    resource = 0;
  }
}

void ResourceSelection::edit()
{
  ResourceItem *item = selectedItem();
  if ( !item )
    return;

  KRES::ConfigDialog dlg( this, QString( "contact" ), item->resource() );

  if ( dlg.exec() ) {
    mManager->change( item->resource() );
    item->resource()->asyncLoad();

    mLastResource = item->resource()->identifier();
    updateView();
  }
}

void ResourceSelection::remove()
{
  ResourceItem *item = selectedItem();
  if ( !item )
    return;

  int result = KMessageBox::warningContinueCancel( this,
        i18n( "<qt>Do you really want to remove the address book %1?</qt>" ,
          item->resource()->resourceName() ), "",
        KGuiItem( i18n( "&Remove" ), "editdelete" ) );
  if ( result == KMessageBox::Cancel )
    return;

  mLastResource = item->resource()->identifier();

  core()->addressBook()->removeResource( item->resource() );
  core()->addressBook()->emitAddressBookChanged();

  updateView();
}

void ResourceSelection::currentChanged( Q3ListViewItem *item )
{
  ResourceItem *resItem = static_cast<ResourceItem*>( item );
  bool state = (resItem && !resItem->isSubResource() );

  mEditButton->setEnabled( state );
  mRemoveButton->setEnabled( state );

  if ( !resItem )
    return;

  KABC::Resource *resource = resItem->resource();

  if ( resItem->checked() != resItem->isOn() ) {
    resItem->setChecked( resItem->isOn() );
    if ( resItem->isSubResource() ) {
      KPIM::ResourceABC *res = dynamic_cast<KPIM::ResourceABC *>( resource );
      res->setSubresourceActive( resItem->resourceIdentifier(), resItem->isOn() );
      mManager->change( resource );
    } else {
      resource->setActive( resItem->isOn() );
      mManager->change( resource );

      if ( resItem->checked() ) {
        if ( !resource->addressBook() )
          resource->setAddressBook( core()->addressBook() );

        if ( !resource->isOpen() )
          resource->open();

        resource->asyncLoad();
      } else {
        resource->close();
      }
    }

    mLastResource = resource->identifier();
    core()->addressBook()->emitAddressBookChanged();
    //updateView();
  }
}

void ResourceSelection::updateView()
{
  if ( !mManager )
    return;

  mListView->clear();

  KRES::Manager<KABC::Resource>::Iterator it;
  for ( it = mManager->begin(); it != mManager->end(); ++it ) {

    new ResourceItem( mListView, *it );
    KPIM::ResourceABC* resource = dynamic_cast<KPIM::ResourceABC *>( *it );
    if ( resource ) {
      disconnect( resource, 0, this, 0 );
      connect( resource, SIGNAL( signalSubresourceAdded( KPIM::ResourceABC *,
                                                         const QString &, const QString & ) ),
               SLOT( slotSubresourceAdded( KPIM::ResourceABC *,
                                           const QString &, const QString & ) ) );

      connect( resource, SIGNAL( signalSubresourceRemoved( KPIM::ResourceABC *,
                                                           const QString &, const QString & ) ),
               SLOT( slotSubresourceRemoved( KPIM::ResourceABC *,
                                             const QString &, const QString & ) ) );
      //connect( resource, SIGNAL( resourceSaved( KPIM::ResourceABC * ) ),
      //         SLOT( closeResource( KPIM::ResourceABC * ) ) );
    }
  }

  Q3ListViewItemIterator itemIt( mListView );
  while ( itemIt.current() ) {
    ResourceItem *item = static_cast<ResourceItem*>( itemIt.current() );
    if ( item->resource()->identifier() == mLastResource ) {
      mListView->setSelected( item, true );
      mListView->ensureItemVisible( item );
      break;
    }
    ++itemIt;
  }

  core()->addressBook()->emitAddressBookChanged();
}

// Add a new entry
void ResourceSelection::slotSubresourceAdded( KPIM::ResourceABC *resource,
                                              const QString& /*type*/,
                                              const QString& subResource )
{
  kDebug(5720) << k_funcinfo << resource->resourceName() << " " << subResource << endl;
  Q3ListViewItem *i = mListView->findItem( resource->resourceName(), 0 );
  if ( !i )
    // Not found
    return;

  ResourceItem *item = static_cast<ResourceItem *>( i );
  (void)new ResourceItem( resource, item, subResource );
}

// Remove an entry
void ResourceSelection::slotSubresourceRemoved( KPIM::ResourceABC* resource,
                                                const QString& /*type*/,
                                                const QString& subResource )
{
  kDebug(5720) << k_funcinfo << resource->resourceName() << " " << subResource << endl;
  // TODO
  //delete findItemByIdentifier( resource );
  //emitResourcesChanged();
}

ResourceItem* ResourceSelection::selectedItem() const
{
  return static_cast<ResourceItem*>( mListView->selectedItem() );
}

void ResourceSelection::initGUI()
{
  QGridLayout *layout = new QGridLayout( this );
  layout->setSpacing( 5 );
  layout->setMargin( 2 );

  mListView = new K3ListView( this );
  mListView->addColumn( i18n( "Address Books" ) );
  mListView->setFullWidth( true );
  layout->addWidget( mListView, 0, 0, 1, 3 );

  mAddButton = new QPushButton( i18n( "Add..." ), this );
  mEditButton = new QPushButton( i18n( "Edit..." ), this );
  mEditButton->setEnabled( false );
  mRemoveButton = new QPushButton( i18n( "Remove" ), this );
  mRemoveButton->setEnabled( false );

  layout->addWidget( mAddButton, 1, 0 );
  layout->addWidget( mEditButton, 1, 1 );
  layout->addWidget( mRemoveButton, 1, 2 );
}

class ResourceSelectionFactory : public KAB::ExtensionFactory
{
  public:
    KAB::ExtensionWidget *extension( KAB::Core *core, QWidget *parent )
    {
      return new ResourceSelection( core, parent );
    }

    QString identifier() const
    {
      return "resourceselection";
    }
};

extern "C" {
  KDE_EXPORT void *init_libkaddrbk_resourceselection()
  {
    return ( new ResourceSelectionFactory );
  }
}

#include "resourceselection.moc"
<commit_msg>dynamic_cast without checking for the result doesn't make sense (CID 2070)<commit_after>/*
    This file is part of KAddressBook.
    Copyright (c) 2004 Tobias Koenig <tokoe@kde.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include <QLayout>
#include <QPushButton>
#include <QTimer>
//Added by qt3to4:
#include <QGridLayout>

#include <kabc/resource.h>
#include <kdialog.h>
#include <kglobal.h>
#include <kiconloader.h>
#include <kinputdialog.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kresources/configdialog.h>

#include "core.h"

#include "resourceselection.h"
#include <libkdepim/resourceabc.h>

class AddressBookWrapper : public KABC::AddressBook
{
  public:
    AddressBookWrapper( KABC::AddressBook* );

    KRES::Manager<KABC::Resource>* getResourceManager()
    {
      return resourceManager();
    }
};

class ResourceItem : public Q3CheckListItem
{
  public:
    ResourceItem( K3ListView *parent, KABC::Resource *resource )
      : Q3CheckListItem( parent, resource->resourceName(), CheckBox ),
        mResource( resource ), mChecked( false ),
        mIsSubresource( false ), mSubItemsCreated( false ),
        mResourceIdentifier()
    {
      setOn( resource->isActive() );
      setPixmap( 0, KGlobal::iconLoader()->loadIcon( "contents", K3Icon::Small ) );
      mChecked = isOn();
    }

    ResourceItem( KPIM::ResourceABC *resourceABC, ResourceItem* parent,
                  const QString& resourceIdent )
      : Q3CheckListItem( parent, resourceABC->subresourceLabel( resourceIdent ), CheckBox ),
        mResource( resourceABC ), mChecked( false ),
        mIsSubresource( true ), mSubItemsCreated( false ),
        mResourceIdentifier( resourceIdent )
    {
      KPIM::ResourceABC* res = static_cast<KPIM::ResourceABC *>( mResource );
      setOn( res->subresourceActive( mResourceIdentifier ) );
      setPixmap( 0, KGlobal::iconLoader()->loadIcon( "contents", K3Icon::Small ) );
      mChecked = isOn();
    }

    void createSubresourceItems();

    void setChecked( bool state ) { mChecked = state; }
    bool checked() const { return mChecked; }
    KABC::Resource *resource() const { return mResource; }
    QString resourceIdentifier() const { return mResourceIdentifier; }
    bool isSubResource() const { return mIsSubresource; }

    virtual void stateChange( bool active );

  private:
    KABC::Resource * const mResource;
    bool mChecked;
    const bool mIsSubresource;
    bool mSubItemsCreated;
    const QString mResourceIdentifier;
};

// Comes from korganizer/resourceview.cpp
void ResourceItem::createSubresourceItems()
{
  KPIM::ResourceABC* res = dynamic_cast<KPIM::ResourceABC *>( mResource );
  QStringList subresources;
  if ( res )
    subresources = res->subresources();
  if ( !subresources.isEmpty() ) {
    setOpen( true );
    setExpandable( true );
    // This resource has subresources
    QStringList::ConstIterator it;
    for ( it = subresources.begin(); it != subresources.end(); ++it ) {
      (void)new ResourceItem( res, this, *it );
    }
  }
  mSubItemsCreated = true;
}

// TODO: connect this to some signalResourceModified
// void ResourceItem::setGuiState()
// {
//   if ( mIsSubresource )
//     setOn( mResource->subresourceActive( mResourceIdentifier ) );
//   else
//     setOn( mResource->isActive() );
// }

void ResourceItem::stateChange( bool active )
{
  //kDebug(5720) << k_funcinfo << this << " " << text( 0 ) << " active=" << active << endl;
  if ( active && !mIsSubresource ) {
    if ( !mSubItemsCreated )
      createSubresourceItems();
  }

  setOpen( active && childCount() > 0 );
}

////

ResourceSelection::ResourceSelection( KAB::Core *core, QWidget *parent )
  : KAB::ExtensionWidget( core, parent ), mManager( 0 )
{
  initGUI();

  AddressBookWrapper *wrapper = static_cast<AddressBookWrapper*>( core->addressBook() );
  mManager = wrapper->getResourceManager();

  connect( mAddButton, SIGNAL( clicked() ), SLOT( add() ) );
  connect( mEditButton, SIGNAL( clicked() ), SLOT( edit() ) );
  connect( mRemoveButton, SIGNAL( clicked() ), SLOT( remove() ) );

  connect( mListView, SIGNAL( clicked( Q3ListViewItem* ) ),
           SLOT( currentChanged( Q3ListViewItem* ) ) );

  QTimer::singleShot( 0, this, SLOT( updateView() ) );
}

ResourceSelection::~ResourceSelection()
{
}

QString ResourceSelection::title() const
{
  return i18n( "Address Books" );
}

QString ResourceSelection::identifier() const
{
  return "resourceselection";
}

void ResourceSelection::add()
{
  QStringList types = mManager->resourceTypeNames();
  QStringList descs = mManager->resourceTypeDescriptions();

  bool ok = false;
  QString desc = KInputDialog::getItem( i18n( "Add Address Book" ),
                                        i18n( "Please select type of the new address book:" ),
                                        descs, 0, false, &ok, this );
  if ( !ok )
    return;

  QString type = types[ descs.indexOf( desc ) ];

  // Create new resource
  KABC::Resource *resource = mManager->createResource( type );
  if ( !resource ) {
    KMessageBox::error( this, i18n("<qt>Unable to create an address book of type %1.</qt>",
                                type ) );
    return;
  }

  resource->setResourceName( i18n( "%1 address book", type ) );

  KRES::ConfigDialog dlg( this, QString( "contact" ), resource );

  if ( dlg.exec() ) {
    core()->addressBook()->addResource( resource );
    resource->asyncLoad();

    mLastResource = resource->identifier();
    updateView();
  } else {
    delete resource;
    resource = 0;
  }
}

void ResourceSelection::edit()
{
  ResourceItem *item = selectedItem();
  if ( !item )
    return;

  KRES::ConfigDialog dlg( this, QString( "contact" ), item->resource() );

  if ( dlg.exec() ) {
    mManager->change( item->resource() );
    item->resource()->asyncLoad();

    mLastResource = item->resource()->identifier();
    updateView();
  }
}

void ResourceSelection::remove()
{
  ResourceItem *item = selectedItem();
  if ( !item )
    return;

  int result = KMessageBox::warningContinueCancel( this,
        i18n( "<qt>Do you really want to remove the address book %1?</qt>" ,
          item->resource()->resourceName() ), "",
        KGuiItem( i18n( "&Remove" ), "editdelete" ) );
  if ( result == KMessageBox::Cancel )
    return;

  mLastResource = item->resource()->identifier();

  core()->addressBook()->removeResource( item->resource() );
  core()->addressBook()->emitAddressBookChanged();

  updateView();
}

void ResourceSelection::currentChanged( Q3ListViewItem *item )
{
  ResourceItem *resItem = static_cast<ResourceItem*>( item );
  bool state = (resItem && !resItem->isSubResource() );

  mEditButton->setEnabled( state );
  mRemoveButton->setEnabled( state );

  if ( !resItem )
    return;

  KABC::Resource *resource = resItem->resource();

  if ( resItem->checked() != resItem->isOn() ) {
    resItem->setChecked( resItem->isOn() );
    if ( resItem->isSubResource() ) {
      KPIM::ResourceABC *res = static_cast<KPIM::ResourceABC *>( resource );
      res->setSubresourceActive( resItem->resourceIdentifier(), resItem->isOn() );
      mManager->change( resource );
    } else {
      resource->setActive( resItem->isOn() );
      mManager->change( resource );

      if ( resItem->checked() ) {
        if ( !resource->addressBook() )
          resource->setAddressBook( core()->addressBook() );

        if ( !resource->isOpen() )
          resource->open();

        resource->asyncLoad();
      } else {
        resource->close();
      }
    }

    mLastResource = resource->identifier();
    core()->addressBook()->emitAddressBookChanged();
    //updateView();
  }
}

void ResourceSelection::updateView()
{
  if ( !mManager )
    return;

  mListView->clear();

  KRES::Manager<KABC::Resource>::Iterator it;
  for ( it = mManager->begin(); it != mManager->end(); ++it ) {

    new ResourceItem( mListView, *it );
    KPIM::ResourceABC* resource = dynamic_cast<KPIM::ResourceABC *>( *it );
    if ( resource ) {
      disconnect( resource, 0, this, 0 );
      connect( resource, SIGNAL( signalSubresourceAdded( KPIM::ResourceABC *,
                                                         const QString &, const QString & ) ),
               SLOT( slotSubresourceAdded( KPIM::ResourceABC *,
                                           const QString &, const QString & ) ) );

      connect( resource, SIGNAL( signalSubresourceRemoved( KPIM::ResourceABC *,
                                                           const QString &, const QString & ) ),
               SLOT( slotSubresourceRemoved( KPIM::ResourceABC *,
                                             const QString &, const QString & ) ) );
      //connect( resource, SIGNAL( resourceSaved( KPIM::ResourceABC * ) ),
      //         SLOT( closeResource( KPIM::ResourceABC * ) ) );
    }
  }

  Q3ListViewItemIterator itemIt( mListView );
  while ( itemIt.current() ) {
    ResourceItem *item = static_cast<ResourceItem*>( itemIt.current() );
    if ( item->resource()->identifier() == mLastResource ) {
      mListView->setSelected( item, true );
      mListView->ensureItemVisible( item );
      break;
    }
    ++itemIt;
  }

  core()->addressBook()->emitAddressBookChanged();
}

// Add a new entry
void ResourceSelection::slotSubresourceAdded( KPIM::ResourceABC *resource,
                                              const QString& /*type*/,
                                              const QString& subResource )
{
  kDebug(5720) << k_funcinfo << resource->resourceName() << " " << subResource << endl;
  Q3ListViewItem *i = mListView->findItem( resource->resourceName(), 0 );
  if ( !i )
    // Not found
    return;

  ResourceItem *item = static_cast<ResourceItem *>( i );
  (void)new ResourceItem( resource, item, subResource );
}

// Remove an entry
void ResourceSelection::slotSubresourceRemoved( KPIM::ResourceABC* resource,
                                                const QString& /*type*/,
                                                const QString& subResource )
{
  kDebug(5720) << k_funcinfo << resource->resourceName() << " " << subResource << endl;
  // TODO
  //delete findItemByIdentifier( resource );
  //emitResourcesChanged();
}

ResourceItem* ResourceSelection::selectedItem() const
{
  return static_cast<ResourceItem*>( mListView->selectedItem() );
}

void ResourceSelection::initGUI()
{
  QGridLayout *layout = new QGridLayout( this );
  layout->setSpacing( 5 );
  layout->setMargin( 2 );

  mListView = new K3ListView( this );
  mListView->addColumn( i18n( "Address Books" ) );
  mListView->setFullWidth( true );
  layout->addWidget( mListView, 0, 0, 1, 3 );

  mAddButton = new QPushButton( i18n( "Add..." ), this );
  mEditButton = new QPushButton( i18n( "Edit..." ), this );
  mEditButton->setEnabled( false );
  mRemoveButton = new QPushButton( i18n( "Remove" ), this );
  mRemoveButton->setEnabled( false );

  layout->addWidget( mAddButton, 1, 0 );
  layout->addWidget( mEditButton, 1, 1 );
  layout->addWidget( mRemoveButton, 1, 2 );
}

class ResourceSelectionFactory : public KAB::ExtensionFactory
{
  public:
    KAB::ExtensionWidget *extension( KAB::Core *core, QWidget *parent )
    {
      return new ResourceSelection( core, parent );
    }

    QString identifier() const
    {
      return "resourceselection";
    }
};

extern "C" {
  KDE_EXPORT void *init_libkaddrbk_resourceselection()
  {
    return ( new ResourceSelectionFactory );
  }
}

#include "resourceselection.moc"
<|endoftext|>